Searches the Project Gutenberg catalog and shows which works have been recorded in Librivox. Some recordings do not show up, so double-check against the official LibriVox catalog to be sure. Click on column headings to sort.
if ($_GET['author'] != null ||
$_GET['title'] != null ||
$_GET['author_gid'] != null ||
$_GET['cat_search'] != null ||
$_GET['lcsh'] != null ) {
$db_gb = new PDO ('sqlite:./gutenberg-catalog-sqlite-master/data/catalog.sqlite');
$db_gb -> setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$db_lv = new PDO ('sqlite:./librivox.sqlite3');
$db_lv -> setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$stmt;
if ($_GET['author'] !='') {
// TODO: insert three character limit on searches
$contributors = array(); // need to keep track so as to be able to combine ids for those that are both author and contributor
$stmt_co = $db_gb->prepare ("select * from contributors where name like :author_name order by name");
$stmt_co->bindValue (':author_name', '%' . $_GET['author'] . '%');
$stmt_co->execute();
while ($row = $stmt_co->fetch(PDO::FETCH_ASSOC) ) {
$contributors[$row['id']] = $row['name'];;
$n++;
}
$stmt = $db_gb->prepare ("select * from creators where name like :author_name order by name");
$stmt->bindValue (':author_name', '%' . $_GET['author'] . '%');
$stmt->execute();
echo "
Author |
";
$n=0;
while ($row = $stmt->fetch(PDO::FETCH_ASSOC) ) {
$co_id = array_search ($row['name'], $contributors); // returns contributor key if it exists for this name, otherwise returns false
if ( $co_id == false ) {
$co_id = null; // no contributor, so putting blank for parameter
} else {
unset ($contributors[$co_id]); // we now have this persons id in $co_id, now remove from the $contributors array so they don't come up again in the contributors-only table
}
echo "" . $row['name'] . " |
";
$n++;
}
if ( $n == 0 ) echo "No authors found like '". $_GET['author'].".'";
echo "
";
// finding as contributors
echo "
Contributor |
";
$n=0;
foreach ( $contributors as $co_id=>$co_name ) {
echo "" . $co_name . " |
";
$n++;
}
if ( $n == 0 ) echo "No contributors found like '". $_GET['author'].".' |
";
echo "
";
/* */
} // end author
if ($_GET['lcsh'] != '' ) {
$stmt = $db_gb->prepare ("SELECT * from lcsh_subjects WHERE id=:lcsh_id");
$stmt->bindValue(':lcsh_id', $_GET['lcsh']);
$stmt->execute();
$category = "not found";
if ($row = $stmt->fetch(PDO::FETCH_ASSOC) ) {
$category = $row['name'];
}
$stmt = $db_gb->prepare ("SELECT b.mtype_id, c.name, c.id, b.etext_id, b.data FROM books AS b JOIN lcsh2books AS l2b ON l2b.book_id = b.id JOIN creators AS c ON c2b.creator_id = c.id JOIN creators2books AS c2b ON c2b.book_id = b.id WHERE l2b.lcsh_id=:lcsh_id AND b.rights='G'");
$stmt->bindValue(':lcsh_id', $_GET['lcsh']);
$stmt->execute();
$first = true;
while ($row = $stmt->fetch(PDO::FETCH_ASSOC) ) {
if ( $first ) {
echo "Category:
$category
";
echo " ";
echo "Author | Title | LibriVox Recordings | Est. Read Time |
";
$first = false;
}
if ( $row['mtype_id'] != '') continue; // audiobooks
$title = $row ['data'];
$title = substr ( $title, strpos ( $title, '{"title":["') + 11 ); // sqlite database title capped to 255 chars but 'data' field isn't, so need to get title from data field
$title = substr ( $title, 0, strpos ( $title, "\"]") );
$title = str_replace ( '\n', " - ", $title);
$title = str_replace ( '\"', "\"", $title);
// echo "" . $row['name'] . " | " . $title . " | ";
echo " |
" . $row['name'] . " | " . $title . " | "; // to see gutenberg ids
$recording_urls = getLVRecordingsByTitle ($title, $row['name']);
if ( ! empty ($recording_urls) ) {
$n = 1;
foreach ( $recording_urls as $recording_url ) {
echo "[" . $n . "] ";
$n++;
}
} else echo "None found";
$times = getReadTimeForEtext ($row['etext_id']);
echo " | ";
echo $times['readable'] . " |
" ;
}
echo "
";
}
if ($_GET['title'] != '' ) {
} // end title
if ($_GET['cat_search'] != '' ) {
echo "
Categories like ".$_GET['cat_search']." |
";
$stmt = $db_gb->prepare ( "select * from lcsh_subjects where name like :subject");
$stmt->bindValue ( ':subject', "%" . $_GET['cat_search'] . "%" );
$stmt->execute ();
$n = 0;
while ($row = $stmt->fetch(PDO::FETCH_ASSOC) ) {
echo "" . $row['name']. " |
";
$n++;
}
echo "
";
if ( $n == 0 ) echo "No categories found like
'". $_GET['cat_search'].".'";
}
if ( $_GET['author_gid'] !='' || $_GET['contrib_gid'] !='' ) { // getting all books for a gutenberg author id
if ( $_GET['author_gid'] !='' ) {
$stmt = $db_gb->prepare ("SELECT b.mtype_id, c.name, b.id, b.etext_id, b.data FROM books AS b JOIN creators2books AS c2b ON c2b.book_id = b.id JOIN creators AS c ON c2b.creator_id = c.id WHERE c2b.creator_id=:gid AND b.rights='G'");
$stmt->bindValue (':gid', $_GET['author_gid']);
$stmt->execute();
$first = true;
while ($row = $stmt->fetch(PDO::FETCH_ASSOC) ) {
if ( $row['mtype_id'] != '') continue; // audiobooks and other nonbook media
if ( $first ) {
echo "
";
echo "Titles by ".$row['name']." | LibriVox recordings | Est. Read Time | ";
// echo "etext_id | ";
echo "
";
$first = false;
if (strpos ( $row['name'], "," ) == false) {
$author_last = $row['name'];
} else {
$author_last = substr ( $row['name'], 0, strpos ( $row['name'], "," ) );
}
$librivox_retval = file_get_contents ('https://librivox.org/api/feed/audiobooks?author=' . $author_last . '&format=serialized&fields={id,title,authors,url_text_source,url_librivox}' );
$librivox_array = unserialize ($librivox_retval);
$librivox_entries = $librivox_array['books'];
}
$title = $row ['data'];
$title = substr ( $title, strpos ( $title, '{"title":["') + 11 ); // sqlite database title capped to 255 chars but 'data' field isn't, so need to get title from data field
$title = substr ( $title, 0, strpos ( $title, "\"]") );
$title = str_replace ( '\n', " - ", $title);
$title = str_replace ( '\"', "\"", $title);
// echo "$title (".$row['etext_id'].") | ";
// " . $title . "
echo " |
" . $title . " | ";
$recording_urls = getLVRecordingsForGID ( $librivox_entries, $row['etext_id'], $title );
if ( ! empty ($recording_urls) ) {
$n = 1;
foreach ( $recording_urls as $recording_url ) {
echo "[" . $n . "] ";
$n++;
}
} else echo "None found";
$times = getReadTimeForEtext ($row['etext_id']);
echo " | ";
echo $times['readable'] . " |
";
}
echo "
";
} // end author table
if ( $_GET['contrib_gid'] !='' ) {
$stmt = $db_gb->prepare ("SELECT b.mtype_id, c.name, b.id, b.etext_id, b.data FROM books AS b JOIN contributors2books AS c2b ON c2b.book_id = b.id JOIN contributors AS c ON c2b.contributor_id = c.id WHERE c2b.contributor_id=:cid");
$stmt->bindValue (':cid', $_GET['contrib_gid']);
$stmt->execute();
$first = true;
while ($row = $stmt->fetch(PDO::FETCH_ASSOC) ) {
if ( $row['mtype_id'] != '') continue; // audiobooks and other nonbook media
if ( $first ) {
echo "
";
echo "".$row['name']." as contributor | LibriVox recordings | Est. Read Time |
";
$first = false;
if (strpos ( $row['name'], "," ) == false) {
$author_last = $row['name'];
} else {
$author_last = substr ( $row['name'], 0, strpos ( $row['name'], "," ) );
}
$librivox_retval = file_get_contents ('https://librivox.org/api/feed/audiobooks?author=' . $author_last . '&format=serialized&fields={id,title,authors,url_text_source,url_librivox}' );
$librivox_array = unserialize ($librivox_retval);
$librivox_entries = $librivox_array['books'];
// echo "Entries for $author_last: "; print_r ( $librivox_entries ); echo "
"; // for API testing
}
$title = $row ['data'];
$title = substr ( $title, strpos ( $title, '{"title":["') + 11 ); // sqlite database title capped to 255 chars but 'data' field isn't, so need to get title from data field
$title = substr ( $title, 0, strpos ( $title, "\"]") );
$title = str_replace ( '\n', " - ", $title);
$title = str_replace ( '\"', "\"", $title);
echo "" . $title . " | ";
$recording_urls = getLVRecordingsForGID ( $librivox_entries, $row['etext_id'], $row['title'] );
if ( ! empty ($recording_urls) ) {
$n = 1;
foreach ( $recording_urls as $recording_url ) {
echo "[" . $n . "] ";
$n++;
}
} else echo "None found";
$times = getReadTimeForEtext ($row['etext_id']);
echo " | ";
echo $times['readable'] . " |
" ;
}
echo "
";
} // end contrib table
} // end author/contrib_gid if
}
/**
$librovox_list is associative array from librivox API
$ebook_id is Project Gutenberg ebook id
$gb_title is Project Gutenberg title
@return array of librivox recording URLs for the book with the $ebook_id
*/
function getLVRecordingsForGID ( $librivox_list, $ebook_id, $gb_title ) {
global $db_lv;
$recordings = array ();
// echo " -- Checking ebook_id: " . $ebook_id . " against " . count ( $librivox_list ) . " entries -- ";
foreach ( $librivox_list as $librivox_entry ) { // want to move this to sqlite
$text_url = $librivox_entry['url_text_source'];
if ( $text_url != null ) {
$text_url = str_replace ( 'ebooks', 'etext', $text_url );
$lv_ebook_id = substr ( $text_url, strpos ( $text_url, '/etext/') + 7 );
if ( $lv_ebook_id == $ebook_id ) $recordings['$ebook_id'] = $librivox_entry['url_librivox'];
}
}
$stmt = $db_lv->prepare ("select s.author,s.title,s.parent_id,a.url_librivox from sections AS s JOIN audiobooks as a ON s.parent_id=a.id WHERE s.title=:title COLLATE NOCASE" );
$stmt->bindValue ( ':title', $gb_title );
$stmt->execute();
while ($row = $stmt->fetch(PDO::FETCH_ASSOC) ) {
$recordings[$row['parent_id']] = $row['url_librivox'];
// if ( ! array_key_exists ($row['parent_id'], $recordings) ) $recordings[$row['parent_id']] = $row['url_librivox'];
}
return $recordings;
}
function getLVRecordingsByTitle ( $title, $author ) {
global $db_lv;
$recordings = array ();
$author_last = substr ( $title, 0, strpos ($author, ','));
$stmt = $db_lv->prepare ( "SELECT id, url_librivox FROM audiobooks WHERE title=:title COLLATE NOCASE;" );
$stmt->bindValue ( ':title', $title );
$stmt->execute();
while ($row = $stmt->fetch(PDO::FETCH_ASSOC) ) {
$recordings[$row['id']] = $row['url_librivox'];
// need to do some kind of author based checking here
}
$stmt = $db_lv->prepare ("SELECT s.author,s.title,s.parent_id,a.url_librivox FROM sections AS s JOIN audiobooks AS a ON s.parent_id=a.id WHERE s.title=:title COLLATE NOCASE" );
$stmt->bindValue ( ':title', $title );
$stmt->execute();
while ($row = $stmt->fetch(PDO::FETCH_ASSOC) ) {
$recordings[$row['parent_id']] = $row['url_librivox'];
// need to do some kind of author based checking here
}
return $recordings;
}
function getReadTimeForEtext ( $etext_id ) {
global $db_gb;
$retval = array();
$stmt = $db_gb->prepare ("SELECT * FROM files WHERE etext_id=:id" );
$stmt->bindValue (':id', $etext_id);
$stmt->execute();
$file_size = -1;
while ($row = $stmt->fetch(PDO::FETCH_ASSOC) ) {
if ( endsWith ( $row['url'], 'txt' ) ) $file_size = $row['size'];
}
$file_size -= 18233; // Not counting gutenberg license
if ( $file_size < 0 ) $file_size = 0;
$retval['filesize'] = $file_size;
// return ( round ($file_size/1421) . " mins" );
// if ( $file_size < 85260 ) return ( (round ($file_size/1421) ) . " mins");
$hours = floor ( ($file_size/900)/60 );
$minutes = (round ( $file_size/900) ) % 60;
$retval['readable'] = "$hours h $minutes min";
if ( $file_size == 0 ) $retval['readable'] = "Unknown";
return $retval;
}
function endsWith($haystack, $needle)
{
$length = strlen($needle);
if ($length == 0) {
return true;
}
return (substr($haystack, -$length) === $needle);
}
?>
About | Source code | Email | Librivox data: October 3, 2016 | Gutenberg data: April 2014