1954 lines
70 KiB
PHP
1954 lines
70 KiB
PHP
|
<?php
|
||
|
|
||
|
include ("backends/sql/connect.php");
|
||
|
require_once ("skins/".$skin."/ui_elements.php");
|
||
|
connect_to_database($romonitor_hack);
|
||
|
$find_track = null;
|
||
|
$update_track = null;
|
||
|
$transaction_open = false;
|
||
|
$numdone = 0;
|
||
|
$doing_search = false;
|
||
|
$nodata = array (
|
||
|
'isSearchResult' => 4,
|
||
|
'Rating' => 0,
|
||
|
'Tags' => array()
|
||
|
);
|
||
|
|
||
|
// So what are Hidden tracks?
|
||
|
// These are used to count plays from online sources when those tracks are not in the collection.
|
||
|
// Doing this does increase the size of the database. Quite a lot. But without it the stats for charts
|
||
|
// and fave artists etc don't make a lot of sense in a world where a proportion of your listening
|
||
|
// is in response to searches of Spotify or youtube etc.
|
||
|
|
||
|
// Wishlist items have Uri as NULL. Each wishlist track is in a distinct album - this makes stuff
|
||
|
// easier for the wishlist viewer
|
||
|
|
||
|
// Assumptions are made in the code that Wishlist items will not be hidden tracks and that hidden
|
||
|
// tracks have no metadata apart from a Playcount. Always be aware of this.
|
||
|
|
||
|
// For tracks, LastModified controls whether a collection update will update any of its data.
|
||
|
// Tracks added by hand (by tagging or rating, via userRatings.php) must have LastModified as NULL
|
||
|
// - this is how we prevent the collection update from removing them.
|
||
|
|
||
|
// Search:
|
||
|
// Tracktable.isSearchResult is set to:
|
||
|
// 1 on any existing track that comes up in the search
|
||
|
// 2 for any track that comes up the search and has to be added - i.e it's not part of the main collection.
|
||
|
// 3 for any hidden track that comes up in search so it can be re-hidden later.
|
||
|
// Note that there is arithmetical logic to the values used here, they're not arbitrary flags
|
||
|
|
||
|
// Collection:
|
||
|
// justAdded is automatically set to 1 for any track that has just been added
|
||
|
// when updating the collection we set them all to 0 and then set to 1 on any existing track we find,
|
||
|
// then we can easily remove old tracks.
|
||
|
|
||
|
function create_new_track(&$data) {
|
||
|
|
||
|
// create_new_track
|
||
|
// Creates a new track, along with artists and album if necessary
|
||
|
// Returns: TTindex
|
||
|
|
||
|
global $mysqlc;
|
||
|
|
||
|
if ($data['albumai'] == null) {
|
||
|
// Does the albumartist exist?
|
||
|
$data['albumai'] = check_artist($data['albumartist']);
|
||
|
}
|
||
|
|
||
|
// Does the track artist exist?
|
||
|
if ($data['trackai'] == null) {
|
||
|
if ($data['artist'] != $data['albumartist']) {
|
||
|
$data['trackai'] = check_artist($data['artist']);
|
||
|
} else {
|
||
|
$data['trackai'] = $data['albumai'];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ($data['albumai'] == null || $data['trackai'] == null) {
|
||
|
logger::fail("MYSQL", "Trying to create new track but failed to get an artist index");
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
if ($data['albumindex'] == null) {
|
||
|
// Does the album exist?
|
||
|
if ($data['album'] == null) {
|
||
|
$data['album'] = 'rompr_wishlist_'.microtime('true');
|
||
|
}
|
||
|
$data['albumindex'] = check_album($data);
|
||
|
if ($data['albumindex'] == null) {
|
||
|
logger::fail("MYSQL", "Trying to create new track but failed to get an album index");
|
||
|
return null;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
$data['sourceindex'] = null;
|
||
|
if ($data['uri'] === null && array_key_exists('streamuri', $data) && $data['streamuri'] !== null) {
|
||
|
$data['sourceindex'] = check_radio_source($data);
|
||
|
}
|
||
|
|
||
|
if (sql_prepare_query(true, null, null, null,
|
||
|
"INSERT INTO
|
||
|
Tracktable
|
||
|
(Title, Albumindex, Trackno, Duration, Artistindex, Disc, Uri, LastModified, Hidden, isSearchResult, Sourceindex, isAudiobook)
|
||
|
VALUES
|
||
|
(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
|
||
|
$data['title'], $data['albumindex'], $data['trackno'], $data['duration'], $data['trackai'],
|
||
|
$data['disc'], $data['uri'], $data['lastmodified'], $data['hidden'], $data['searchflag'], $data['sourceindex'], $data['isaudiobook']))
|
||
|
{
|
||
|
return $mysqlc->lastInsertId();
|
||
|
}
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
function check_radio_source($data) {
|
||
|
global $mysqlc;
|
||
|
$index = simple_query('Sourceindex', 'WishlistSourcetable', 'SourceUri', $data['streamuri'], null);
|
||
|
if ($index === null) {
|
||
|
logger::log("SQL", "Creating Wishlist Source",$data['streamname']);
|
||
|
if (sql_prepare_query(true, null, null, null,
|
||
|
"INSERT INTO WishlistSourcetable (SourceName, SourceImage, SourceUri) VALUES (?, ?, ?)",
|
||
|
$data['streamname'], $data['streamimage'], $data['streamuri']))
|
||
|
{
|
||
|
$index = $mysqlc->lastInsertId();
|
||
|
}
|
||
|
}
|
||
|
return $index;
|
||
|
}
|
||
|
|
||
|
function check_artist($artist) {
|
||
|
|
||
|
// check_artist:
|
||
|
// Checks for the existence of an artist by name in the Artisttable and creates it if necessary
|
||
|
// Returns: Artistindex
|
||
|
|
||
|
$index = sql_prepare_query(false, null, 'Artistindex', null, "SELECT Artistindex FROM Artisttable WHERE LOWER(Artistname) = LOWER(?)", $artist);
|
||
|
if ($index === null) {
|
||
|
$index = create_new_artist($artist);
|
||
|
}
|
||
|
return $index;
|
||
|
}
|
||
|
|
||
|
function create_new_artist($artist) {
|
||
|
|
||
|
// create_new_artist
|
||
|
// Creates a new artist
|
||
|
// Returns: Artistindex
|
||
|
|
||
|
global $mysqlc;
|
||
|
$retval = null;
|
||
|
if (sql_prepare_query(true, null, null, null, "INSERT INTO Artisttable (Artistname) VALUES (?)", $artist)) {
|
||
|
$retval = $mysqlc->lastInsertId();
|
||
|
logger::trace("MYSQL", "Created artist",$artist,"with Artistindex",$retval);
|
||
|
}
|
||
|
return $retval;
|
||
|
}
|
||
|
|
||
|
function best_value($a, $b) {
|
||
|
|
||
|
// best_value
|
||
|
// Used by check_album to determine the best value to use when updating album details
|
||
|
// Returns: value
|
||
|
|
||
|
if ($b == null || $b == "") {
|
||
|
return $a;
|
||
|
} else {
|
||
|
return $b;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function check_album(&$data) {
|
||
|
|
||
|
// check_album:
|
||
|
// Checks for the existence of an album and creates it if necessary
|
||
|
// Returns: Albumindex
|
||
|
|
||
|
global $prefs, $trackbytrack, $doing_search;
|
||
|
$index = null;
|
||
|
$year = null;
|
||
|
$img = null;
|
||
|
$mbid = null;
|
||
|
$result = sql_prepare_query(false, PDO::FETCH_OBJ, null, null,
|
||
|
"SELECT
|
||
|
Albumindex,
|
||
|
Year,
|
||
|
Image,
|
||
|
AlbumUri,
|
||
|
mbid
|
||
|
FROM
|
||
|
Albumtable
|
||
|
WHERE
|
||
|
LOWER(Albumname) = LOWER(?)
|
||
|
AND AlbumArtistindex = ?
|
||
|
AND Domain = ?", $data['album'], $data['albumai'], $data['domain']);
|
||
|
$obj = array_shift($result);
|
||
|
|
||
|
if ($prefs['preferlocalfiles'] && $trackbytrack && !$doing_search && $data['domain'] == 'local' && !$obj) {
|
||
|
// Does the album exist on a different, non-local, domain? The checks above ensure we only do this
|
||
|
// during a collection update
|
||
|
$result = sql_prepare_query(false, PDO::FETCH_OBJ, null, null,
|
||
|
"SELECT
|
||
|
Albumindex,
|
||
|
Year,
|
||
|
Image,
|
||
|
AlbumUri,
|
||
|
mbid,
|
||
|
Domain
|
||
|
FROM
|
||
|
Albumtable
|
||
|
WHERE
|
||
|
LOWER(Albumname) = LOWER(?)
|
||
|
AND AlbumArtistindex = ?", $data['album'], $data['albumai']);
|
||
|
$obj = array_shift($result);
|
||
|
if ($obj) {
|
||
|
logger::log("MYSQL", "Album ".$data['album']." was found on domain ".$obj->Domain.". Changing to local");
|
||
|
$index = $obj->Albumindex;
|
||
|
if (sql_prepare_query(true, null, null, null, "UPDATE Albumtable SET AlbumUri=NULL, Domain=?, justUpdated=? WHERE Albumindex=?", 'local', 1, $index)) {
|
||
|
$obj->AlbumUri = null;
|
||
|
logger::debug("MYSQL", " ...Success");
|
||
|
} else {
|
||
|
logger::fail("MYSQL", " Album ".$data['album']." update FAILED");
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ($obj) {
|
||
|
$index = $obj->Albumindex;
|
||
|
$year = best_value($obj->Year, $data['date']);
|
||
|
$img = best_value($obj->Image, $data['image']);
|
||
|
$uri = best_value($obj->AlbumUri, $data['albumuri']);
|
||
|
$mbid = best_value($obj->mbid, $data['ambid']);
|
||
|
if ($year != $obj->Year || $img != $obj->Image || $uri != $obj->AlbumUri || $mbid != $obj->mbid) {
|
||
|
|
||
|
if ($prefs['debug_enabled'] > 6) {
|
||
|
logger::log("BACKEND", "Updating Details For Album ".$data['album']." (index ".$index.")" );
|
||
|
logger::log("BACKEND", " Old Date : ".$obj->Year);
|
||
|
logger::log("BACKEND", " New Date : ".$year);
|
||
|
logger::log("BACKEND", " Old Image : ".$obj->Image);
|
||
|
logger::log("BACKEND", " New Image : ".$img);
|
||
|
logger::log("BACKEND", " Old Uri : ".$obj->AlbumUri);
|
||
|
logger::log("BACKEND", " New Uri : ".$uri);
|
||
|
logger::log("BACKEND", " Old MBID : ".$obj->mbid);
|
||
|
logger::log("BACKEND", " New MBID : ".$mbid);
|
||
|
}
|
||
|
|
||
|
if (sql_prepare_query(true, null, null, null, "UPDATE Albumtable SET Year=?, Image=?, AlbumUri=?, mbid=?, justUpdated=1 WHERE Albumindex=?",$year, $img, $uri, $mbid, $index)) {
|
||
|
logger::debug("BACKEND", " ...Success");
|
||
|
} else {
|
||
|
logger::fail("BACKEND", " Album ".$data['album']." update FAILED");
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
$index = create_new_album($data);
|
||
|
}
|
||
|
return $index;
|
||
|
}
|
||
|
|
||
|
function create_new_album($data) {
|
||
|
|
||
|
// create_new_album
|
||
|
// Creates an album
|
||
|
// Returns: Albumindex
|
||
|
|
||
|
global $mysqlc;
|
||
|
$retval = null;
|
||
|
$im = array(
|
||
|
'searched' => $data['image'] ? 1: 0,
|
||
|
'image' => $data['image']
|
||
|
);
|
||
|
if (sql_prepare_query(true, null, null, null,
|
||
|
"INSERT INTO
|
||
|
Albumtable
|
||
|
(Albumname, AlbumArtistindex, AlbumUri, Year, Searched, ImgKey, mbid, Domain, Image)
|
||
|
VALUES
|
||
|
(?, ?, ?, ?, ?, ?, ?, ?, ?)",
|
||
|
$data['album'], $data['albumai'], $data['albumuri'], $data['date'], $im['searched'], $data['imagekey'], $data['ambid'], $data['domain'], $im['image'])) {
|
||
|
$retval = $mysqlc->lastInsertId();
|
||
|
logger::log("BACKEND", "Created Album ".$data['album']." with Albumindex ".$retval);
|
||
|
}
|
||
|
return $retval;
|
||
|
}
|
||
|
|
||
|
function remove_ttid($ttid) {
|
||
|
|
||
|
// Remove a track from the database.
|
||
|
// Doesn't do any cleaning up - call remove_cruft afterwards to remove orphaned artists and albums
|
||
|
|
||
|
// Deleting tracks will delete their associated playcounts. While it might seem like a good idea
|
||
|
// to hide them instead, in fact this results in a situation where we have tracks in our database
|
||
|
// that no longer exist in physical form - eg if local tracks are removed. This is really bad if we then
|
||
|
// later play those tracks from an online source and rate them. romprmetadata::find_item will return the hidden local track,
|
||
|
// which will get rated and appear back in the collection. So now we have an unplayable track in our collection.
|
||
|
// There's no real way round it, (without creating some godwaful lookup table of backends it's safe to do this with)
|
||
|
// so we just delete the track and lose the playcount information.
|
||
|
|
||
|
// If it's a search result, it must be a manually added track (we can't delete collection tracks)
|
||
|
// and we might still need it in the search, so set it to a 2 instead of deleting it.
|
||
|
|
||
|
logger::log("BACKEND", "Removing track ".$ttid);
|
||
|
$result = false;
|
||
|
if (generic_sql_query("DELETE FROM Tracktable WHERE isSearchResult != 1 AND TTindex = '".$ttid."'",true)) {
|
||
|
if (generic_sql_query("UPDATE Tracktable SET isSearchResult = 2 WHERE isSearchResult = 1 AND TTindex = '".$ttid."'", true)) {
|
||
|
$result = true;;
|
||
|
}
|
||
|
}
|
||
|
return $result;
|
||
|
}
|
||
|
|
||
|
function list_tags() {
|
||
|
|
||
|
// list_tags
|
||
|
// Return a sorted lst of tag names. Used by the UI for creating the tag menu
|
||
|
|
||
|
$tags = array();
|
||
|
$result = generic_sql_query("SELECT Name FROM Tagtable ORDER BY LOWER(Name)");
|
||
|
foreach ($result as $r) {
|
||
|
$tags[] = $r['Name'];
|
||
|
}
|
||
|
return $tags;
|
||
|
}
|
||
|
|
||
|
function get_rating_headers($sortby) {
|
||
|
|
||
|
$ratings = array();
|
||
|
|
||
|
switch ($sortby) {
|
||
|
|
||
|
case 'Rating':
|
||
|
$ratings = generic_sql_query("SELECT Rating AS Name, COUNT(TTindex) AS NumTracks FROM Ratingtable GROUP BY Rating ORDER BY Rating");
|
||
|
break;
|
||
|
|
||
|
case 'Tag':
|
||
|
$ratings = generic_sql_query('SELECT Name, COUNT(TTindex) AS NumTracks FROM Tagtable JOIN TagListtable USING (Tagindex) GROUP BY Name ORDER BY Name');
|
||
|
break;
|
||
|
|
||
|
case 'AlbumArtist':
|
||
|
// It's actually Track Artist, but sod changing it now.
|
||
|
$qstring = "SELECT DISTINCT Artistname AS Name, COUNT(DISTINCT TTindex) AS NumTracks
|
||
|
FROM
|
||
|
Artisttable AS a JOIN Tracktable AS tt USING (Artistindex)
|
||
|
LEFT JOIN Ratingtable USING (TTindex)
|
||
|
LEFT JOIN `TagListtable` USING (TTindex)
|
||
|
LEFT JOIN Tagtable AS t USING (Tagindex)
|
||
|
WHERE Hidden = 0 AND isSearchResult < 2 AND (Rating IS NOT NULL OR t.Name IS NOT NULL)
|
||
|
GROUP BY Artistname
|
||
|
ORDER BY ";
|
||
|
$qstring .= sort_artists_by_name();
|
||
|
$ratings = generic_sql_query($qstring);
|
||
|
break;
|
||
|
|
||
|
case 'Tags':
|
||
|
$ratings = generic_sql_query("SELECT DISTINCT ".SQL_TAG_CONCAT." AS Name, 0 AS NumTracks FROM
|
||
|
(SELECT Tagindex, TTindex FROM TagListtable ORDER BY Tagindex) AS tagorder
|
||
|
JOIN Tagtable AS t USING (Tagindex)
|
||
|
GROUP BY TTindex
|
||
|
ORDER By Name");
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
$ratings = array('INTERNAL ERROR!');
|
||
|
break;
|
||
|
|
||
|
}
|
||
|
|
||
|
return $ratings;
|
||
|
}
|
||
|
|
||
|
function sortletter_mangler() {
|
||
|
global $prefs;
|
||
|
$qstring = '';
|
||
|
if (count($prefs['nosortprefixes']) > 0) {
|
||
|
$qstring .= "CASE ";
|
||
|
foreach($prefs['nosortprefixes'] AS $p) {
|
||
|
$phpisshitsometimes = strlen($p)+2;
|
||
|
$qstring .= "WHEN LOWER(a.Artistname) LIKE '".strtolower($p).
|
||
|
" %' THEN UPPER(SUBSTR(a.Artistname,".$phpisshitsometimes.",1)) ";
|
||
|
}
|
||
|
$qstring .= "ELSE UPPER(SUBSTR(a.Artistname,1,1)) END AS SortLetter";
|
||
|
} else {
|
||
|
$qstring .= "UPPER(SUBSTR(a.Artistname,1,1)) AS SortLetter";
|
||
|
}
|
||
|
return $qstring;
|
||
|
}
|
||
|
|
||
|
function get_rating_info($sortby, $value) {
|
||
|
|
||
|
global $prefs;
|
||
|
|
||
|
// Tuned SQL queries for each type, for speed, otherwise it's unuseable
|
||
|
|
||
|
switch ($sortby) {
|
||
|
case 'Rating':
|
||
|
$qstring = "SELECT
|
||
|
r.Rating AS Rating,
|
||
|
IFNULL(".SQL_TAG_CONCAT.", 'No Tags') AS Tags,
|
||
|
tr.TTindex,
|
||
|
tr.TrackNo,
|
||
|
tr.Title,
|
||
|
tr.Duration,
|
||
|
tr.Uri,
|
||
|
a.Artistname,
|
||
|
aa.Artistname AS AlbumArtist,
|
||
|
al.Albumname,
|
||
|
al.Image, ";
|
||
|
$qstring .= sortletter_mangler();
|
||
|
|
||
|
$qstring .= " FROM
|
||
|
Ratingtable AS r
|
||
|
JOIN Tracktable AS tr ON tr.TTindex = r.TTindex
|
||
|
LEFT JOIN TagListtable AS tl ON tr.TTindex = tl.TTindex
|
||
|
LEFT JOIN Tagtable AS t USING (Tagindex)
|
||
|
JOIN Albumtable AS al USING (Albumindex)
|
||
|
JOIN Artisttable AS a ON (tr.Artistindex = a.Artistindex)
|
||
|
JOIN Artisttable AS aa ON (al.AlbumArtistindex = aa.Artistindex)
|
||
|
WHERE r.Rating = ".$value." AND tr.isSearchResult < 2 AND tr.Uri IS NOT NULL";
|
||
|
break;
|
||
|
|
||
|
case 'Tag':
|
||
|
$qstring = "SELECT
|
||
|
IFNULL(r.Rating, 0) AS Rating,
|
||
|
IFNULL(".SQL_TAG_CONCAT.", 'No Tags') AS Tags,
|
||
|
tr.TTindex,
|
||
|
tr.TrackNo,
|
||
|
tr.Title,
|
||
|
tr.Duration,
|
||
|
tr.Uri,
|
||
|
a.Artistname,
|
||
|
aa.Artistname AS AlbumArtist,
|
||
|
al.Albumname,
|
||
|
al.Image, ";
|
||
|
$qstring .= sortletter_mangler();
|
||
|
|
||
|
$qstring .= " FROM
|
||
|
Tracktable AS tr
|
||
|
LEFT JOIN Ratingtable AS r ON tr.TTindex = r.TTindex
|
||
|
LEFT JOIN TagListtable AS tl ON tr.TTindex = tl.TTindex
|
||
|
LEFT JOIN Tagtable AS t USING (Tagindex)
|
||
|
JOIN Albumtable AS al USING (Albumindex)
|
||
|
JOIN Artisttable AS a ON (tr.Artistindex = a.Artistindex)
|
||
|
JOIN Artisttable AS aa ON (al.AlbumArtistindex = aa.Artistindex)
|
||
|
WHERE tr.isSearchResult < 2 AND tr.Uri IS NOT NULL AND tr.TTindex IN (SELECT TTindex FROM TagListtable JOIN Tagtable USING (Tagindex) WHERE Name = '".$value."')";
|
||
|
break;
|
||
|
|
||
|
case 'AlbumArtist':
|
||
|
// It's actually Track Artist, but sod changing it now.
|
||
|
$qstring = "SELECT
|
||
|
IFNULL(r.Rating, 0) AS Rating,
|
||
|
IFNULL(".SQL_TAG_CONCAT.", 'No Tags') AS Tags,
|
||
|
tr.TTindex,
|
||
|
tr.TrackNo,
|
||
|
tr.Title,
|
||
|
tr.Duration,
|
||
|
tr.Uri,
|
||
|
a.Artistname,
|
||
|
aa.Artistname AS AlbumArtist,
|
||
|
al.Albumname,
|
||
|
al.Image ";
|
||
|
|
||
|
$qstring .= " FROM
|
||
|
Tracktable AS tr
|
||
|
LEFT JOIN Ratingtable AS r ON tr.TTindex = r.TTindex
|
||
|
LEFT JOIN TagListtable AS tl ON tr.TTindex = tl.TTindex
|
||
|
LEFT JOIN Tagtable AS t USING (Tagindex)
|
||
|
JOIN Albumtable AS al USING (Albumindex)
|
||
|
JOIN Artisttable AS a ON (tr.Artistindex = a.Artistindex)
|
||
|
JOIN Artisttable AS aa ON (al.AlbumArtistindex = aa.Artistindex)
|
||
|
WHERE (r.Rating IS NOT NULL OR t.Name IS NOT NULL) AND tr.Uri IS NOT NULL AND tr.isSearchResult < 2 AND a.Artistname = '".$value."'";
|
||
|
break;
|
||
|
|
||
|
case 'Tags':
|
||
|
$qstring = "SELECT
|
||
|
IFNULL(r.Rating, 0) AS Rating,
|
||
|
".SQL_TAG_CONCAT." AS Tags,
|
||
|
tr.TTindex,
|
||
|
tr.TrackNo,
|
||
|
tr.Title,
|
||
|
tr.Duration,
|
||
|
tr.Uri,
|
||
|
a.Artistname,
|
||
|
aa.Artistname AS AlbumArtist,
|
||
|
al.Albumname,
|
||
|
COUNT(tr.TTindex) AS count,
|
||
|
al.Image, ";
|
||
|
$qstring .= sortletter_mangler();
|
||
|
|
||
|
$qstring .= " FROM
|
||
|
TagListtable AS tl
|
||
|
JOIN Tracktable AS tr USING (TTindex)
|
||
|
JOIN Tagtable AS t USING (Tagindex)
|
||
|
LEFT JOIN Ratingtable AS r ON tr.TTindex = r.TTindex
|
||
|
JOIN Albumtable AS al USING (Albumindex)
|
||
|
JOIN Artisttable AS a ON (tr.Artistindex = a.Artistindex)
|
||
|
JOIN Artisttable AS aa ON (al.AlbumArtistindex = aa.Artistindex)
|
||
|
WHERE ";
|
||
|
$tags = explode(', ',$value);
|
||
|
foreach ($tags as $i => $t) {
|
||
|
$tags[$i] = "tr.TTindex IN (SELECT TTindex FROM TagListtable JOIN Tagtable USING (Tagindex) WHERE Name='".$t."')";
|
||
|
}
|
||
|
$qstring .= implode(' AND ', $tags);
|
||
|
$qstring .= " AND tr.isSearchResult < 2 AND tr.Uri IS NOT NULL";
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
$qstring .= " GROUP BY tr.TTindex ORDER BY ";
|
||
|
$qstring .= sort_artists_by_name();
|
||
|
$qstring .= ", al.Albumname, tr.TrackNo";
|
||
|
|
||
|
$t = microtime(true);
|
||
|
$ratings = generic_sql_query($qstring);
|
||
|
$took = microtime(true) - $t;
|
||
|
logger::debug("TIMINGS", " :: Getting rating data took ".$took." seconds");
|
||
|
// Our query for Tags (Tag List) will get eg if we're looking for 'tag1' it'll get tracks with 'tag1' and 'tag2'
|
||
|
// So we check how many tags there are in each result and only use the ones that match the number of tags we're looking for
|
||
|
if ($sortby == 'Tags') {
|
||
|
$temp = array();
|
||
|
$c = count($tags);
|
||
|
foreach ($ratings as $rat) {
|
||
|
if ($rat['count'] == $c) {
|
||
|
$temp[] = $rat;
|
||
|
}
|
||
|
}
|
||
|
$ratings = $temp;
|
||
|
}
|
||
|
|
||
|
return $ratings;
|
||
|
|
||
|
}
|
||
|
|
||
|
function clear_wishlist() {
|
||
|
return generic_sql_query("DELETE FROM Tracktable WHERE Uri IS NULL", true);
|
||
|
}
|
||
|
|
||
|
function num_collection_tracks($albumindex) {
|
||
|
// Returns the number of tracks this album contains that were added by a collection update
|
||
|
// (i.e. not added manually). We do this because editing year or album artist for those albums
|
||
|
// won't hold across a collection update, so we just forbid it.
|
||
|
return generic_sql_query("SELECT COUNT(TTindex) AS cnt FROM Tracktable WHERE Albumindex = ".$albumindex." AND LastModified IS NOT NULL AND Hidden = 0 AND Uri IS NOT NULL AND isSearchResult < 2", false, null, 'cnt', 0);
|
||
|
|
||
|
}
|
||
|
|
||
|
function get_all_data($ttid) {
|
||
|
|
||
|
// Misleadingly named function which should be used to get ratings and tags
|
||
|
// (and whatever else we might add) based on a TTindex
|
||
|
global $nodata;
|
||
|
$data = $nodata;
|
||
|
$result = generic_sql_query("SELECT
|
||
|
IFNULL(r.Rating, 0) AS Rating,
|
||
|
IFNULL(p.Playcount, 0) AS Playcount,
|
||
|
".sql_to_unixtime('p.LastPlayed')." AS LastTime,
|
||
|
".sql_to_unixtime('tr.DateAdded')." AS DateAdded,
|
||
|
IFNULL(".SQL_TAG_CONCAT.", '') AS Tags,
|
||
|
tr.isSearchResult,
|
||
|
tr.Hidden
|
||
|
FROM
|
||
|
Tracktable AS tr
|
||
|
LEFT JOIN Ratingtable AS r ON tr.TTindex = r.TTindex
|
||
|
LEFT JOIN Playcounttable AS p ON tr.TTindex = p.TTindex
|
||
|
LEFT JOIN TagListtable AS tl ON tr.TTindex = tl.TTindex
|
||
|
LEFT JOIN Tagtable AS t USING (Tagindex)
|
||
|
WHERE tr.TTindex = ".$ttid."
|
||
|
GROUP BY tr.TTindex
|
||
|
ORDER BY t.Name"
|
||
|
);
|
||
|
if (count($result) > 0) {
|
||
|
$data = array_shift($result);
|
||
|
$data['Tags'] = ($data['Tags'] == '') ? array() : explode(', ', $data['Tags']);
|
||
|
if ($data['LastTime'] != null && $data['LastTime'] != 0 && $data['LastTime'] != '0') {
|
||
|
$data['Last'] = $data['LastTime'];
|
||
|
}
|
||
|
}
|
||
|
return $data;
|
||
|
}
|
||
|
|
||
|
// Looking up this way is hugely faster than looking up by Uri
|
||
|
function get_extra_track_info(&$filedata) {
|
||
|
$data = array();;
|
||
|
$result = sql_prepare_query(false, PDO::FETCH_ASSOC, null, null,
|
||
|
'SELECT Uri, TTindex, Disc, Artistname AS AlbumArtist, Albumtable.Image AS "X-AlbumImage", mbid AS MUSICBRAINZ_ALBUMID, Searched, IFNULL(Playcount, 0) AS Playcount
|
||
|
FROM
|
||
|
Tracktable
|
||
|
JOIN Albumtable USING (Albumindex)
|
||
|
JOIN Artisttable ON Albumtable.AlbumArtistindex = Artisttable.Artistindex
|
||
|
LEFT JOIN Playcounttable USING (TTindex)
|
||
|
WHERE Title = ?
|
||
|
AND TrackNo = ?
|
||
|
AND Albumname = ?',
|
||
|
$filedata['Title'], $filedata['Track'], $filedata['Album']
|
||
|
);
|
||
|
foreach ($result as $tinfo) {
|
||
|
if ($tinfo['Uri'] == $filedata['file']) {
|
||
|
logger::trace("EXTRAINFO", "Found Track In Collection");
|
||
|
$data = array_filter($tinfo, function($v) {
|
||
|
if ($v === null || $v == '') {
|
||
|
return false;
|
||
|
}
|
||
|
return true;
|
||
|
});
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
if (count($data) == 0) {
|
||
|
$result = sql_prepare_query(false, PDO::FETCH_ASSOC, null, null,
|
||
|
'SELECT Albumtable.Image AS "X-AlbumImage", mbid AS MUSICBRAINZ_ALBUMID, Searched
|
||
|
FROM
|
||
|
Albumtable
|
||
|
JOIN Artisttable ON Albumtable.AlbumArtistindex = Artisttable.Artistindex
|
||
|
WHERE Albumname = ?
|
||
|
AND Artistname = ?',
|
||
|
$filedata['Album'], concatenate_artist_names($filedata['AlbumArtist'])
|
||
|
);
|
||
|
foreach ($result as $tinfo) {
|
||
|
logger::trace("EXTRAINFO", "Found Album In Collection");
|
||
|
$data = array_filter($tinfo, function($v) {
|
||
|
if ($v === null || $v == '') {
|
||
|
return false;
|
||
|
}
|
||
|
return true;
|
||
|
});
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
return $data;
|
||
|
}
|
||
|
|
||
|
function get_imagesearch_info($key) {
|
||
|
|
||
|
// Used by getalbumcover.php to get album and artist names etc based on an Image Key
|
||
|
|
||
|
$retval = array('artist' => null, 'album' => null, 'mbid' => null, 'albumpath' => null, 'albumuri' => null);
|
||
|
$result = generic_sql_query(
|
||
|
"SELECT DISTINCT
|
||
|
Artisttable.Artistname,
|
||
|
Albumname,
|
||
|
mbid,
|
||
|
Albumindex,
|
||
|
AlbumUri,
|
||
|
isSearchResult
|
||
|
FROM
|
||
|
Albumtable
|
||
|
JOIN Artisttable ON AlbumArtistindex = Artisttable.Artistindex
|
||
|
JOIN Tracktable USING (Albumindex)
|
||
|
WHERE ImgKey = '".$key."' AND isSearchResult < 2 AND Hidden = 0", false, PDO::FETCH_OBJ
|
||
|
);
|
||
|
// This can come back with multiple results if we have the same album on multiple backends
|
||
|
// So we make sure we combine the data to get the best possible set
|
||
|
foreach ($result as $obj) {
|
||
|
if ($retval['artist'] == null) {
|
||
|
$retval['artist'] = $obj->Artistname;
|
||
|
}
|
||
|
if ($retval['album'] == null) {
|
||
|
$retval['album'] = $obj->Albumname;
|
||
|
}
|
||
|
if ($retval['mbid'] == null || $retval['mbid'] == "") {
|
||
|
$retval['mbid'] = $obj->mbid;
|
||
|
}
|
||
|
if ($retval['albumpath'] == null) {
|
||
|
$retval['albumpath'] = get_album_directory($obj->Albumindex, $obj->AlbumUri);
|
||
|
}
|
||
|
if ($retval['albumuri'] == null || $retval['albumuri'] == "") {
|
||
|
$retval['albumuri'] = $obj->AlbumUri;
|
||
|
}
|
||
|
logger::log("GETALBUMCOVER", "Found album",$retval['album'],",in collection");
|
||
|
}
|
||
|
|
||
|
$result = generic_sql_query(
|
||
|
"SELECT DISTINCT
|
||
|
Artisttable.Artistname,
|
||
|
Albumname,
|
||
|
mbid,
|
||
|
Albumindex,
|
||
|
AlbumUri,
|
||
|
isSearchResult
|
||
|
FROM
|
||
|
Albumtable
|
||
|
JOIN Artisttable ON AlbumArtistindex = Artisttable.Artistindex
|
||
|
JOIN Tracktable USING (Albumindex)
|
||
|
WHERE ImgKey = '".$key."' AND isSearchResult > 1", false, PDO::FETCH_OBJ
|
||
|
);
|
||
|
// This can come back with multiple results if we have the same album on multiple backends
|
||
|
// So we make sure we combine the data to get the best possible set
|
||
|
foreach ($result as $obj) {
|
||
|
if ($retval['artist'] == null) {
|
||
|
$retval['artist'] = $obj->Artistname;
|
||
|
}
|
||
|
if ($retval['album'] == null) {
|
||
|
$retval['album'] = $obj->Albumname;
|
||
|
}
|
||
|
if ($retval['mbid'] == null || $retval['mbid'] == "") {
|
||
|
$retval['mbid'] = $obj->mbid;
|
||
|
}
|
||
|
if ($retval['albumpath'] == null) {
|
||
|
$retval['albumpath'] = get_album_directory($obj->Albumindex, $obj->AlbumUri);
|
||
|
}
|
||
|
if ($retval['albumuri'] == null || $retval['albumuri'] == "") {
|
||
|
$retval['albumuri'] = $obj->AlbumUri;
|
||
|
}
|
||
|
logger::log("GETALBUMCOVER", "Found album",$retval['album'],"in search results or hidden tracks");
|
||
|
}
|
||
|
return $retval;
|
||
|
}
|
||
|
|
||
|
function get_albumlink($albumindex) {
|
||
|
return simple_query('AlbumUri', 'Albumtable', 'Albumindex', $albumindex, "");
|
||
|
}
|
||
|
|
||
|
function get_album_directory($albumindex, $uri) {
|
||
|
global $prefs;
|
||
|
$retval = null;
|
||
|
// Get album directory by using the Uri of one of its tracks, making sure we choose only local tracks
|
||
|
if (getDomain($uri) == 'local') {
|
||
|
$result = generic_sql_query("SELECT Uri FROM Tracktable WHERE Albumindex = ".$albumindex." LIMIT 1");
|
||
|
foreach ($result as $obj2) {
|
||
|
$retval = dirname($obj2['Uri']);
|
||
|
$retval = preg_replace('#^local:track:#', '', $retval);
|
||
|
$retval = preg_replace('#^file://#', '', $retval);
|
||
|
$retval = preg_replace('#^beetslocal:\d+:'.$prefs['music_directory_albumart'].'/#', '', $retval);
|
||
|
logger::log("SQL", "Got album directory using track Uri :",$retval);
|
||
|
}
|
||
|
}
|
||
|
return $retval;
|
||
|
}
|
||
|
|
||
|
function update_image_db($key, $found, $imagefile) {
|
||
|
$val = ($found) ? $imagefile : null;
|
||
|
if (sql_prepare_query(true, null, null, null, "UPDATE Albumtable SET Image = ?, Searched = 1 WHERE ImgKey = ?", $val, $key)) {
|
||
|
logger::log("MYSQL", " Database Image URL Updated");
|
||
|
} else {
|
||
|
logger::fail("MYSQL", " Failed To Update Database Image URL",$val,$key);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function track_is_hidden($ttid) {
|
||
|
$h = simple_query('Hidden', 'Tracktable', 'TTindex', $ttid, 0);
|
||
|
return ($h != 0) ? true : false;
|
||
|
}
|
||
|
|
||
|
function track_is_searchresult($ttid) {
|
||
|
// This is for detecting tracks that were added as part of a search, or un-hidden as part of a search
|
||
|
$h = simple_query('isSearchResult', 'Tracktable', 'TTindex', $ttid, 0);
|
||
|
return ($h > 1) ? true : false;
|
||
|
}
|
||
|
|
||
|
function track_is_wishlist($ttid) {
|
||
|
$u = simple_query('Uri', 'Tracktable', 'TTindex', $ttid, '');
|
||
|
if ($u === null) {
|
||
|
logger::mark("USERRATING", "Track",$ttid,"is wishlist. Discarding");
|
||
|
generic_sql_query("DELETE FROM Playcounttable WHERE TTindex=".$ttid, true);
|
||
|
generic_sql_query("DELETE FROM Tracktable WHERE TTindex=".$ttid, true);
|
||
|
return true;
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
function check_for_wishlist_track(&$data) {
|
||
|
$result = sql_prepare_query(false, PDO::FETCH_ASSOC, null, null, "SELECT TTindex FROM Tracktable JOIN Artisttable USING (Artistindex)
|
||
|
WHERE Artistname=? AND Title=? AND Uri IS NULL",$data['artist'],$data['title']);
|
||
|
foreach ($result as $obj) {
|
||
|
logger::mark("USERRATING", "Wishlist Track",$obj['TTindex'],"matches the one we're adding");
|
||
|
$meta = get_all_data($obj['TTindex']);
|
||
|
$data['attributes'] = array();
|
||
|
$data['attributes'][] = array('attribute' => 'Rating', 'value' => $meta['Rating']);
|
||
|
$data['attributes'][] = array('attribute' => 'Tags', 'value' => $meta['Tags']);
|
||
|
generic_sql_query("DELETE FROM Tracktable WHERE TTindex=".$obj['TTindex'], true);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function sort_artists_by_name() {
|
||
|
global $prefs;
|
||
|
$qstring = '';
|
||
|
foreach ($prefs['artistsatstart'] as $a) {
|
||
|
$qstring .= "CASE WHEN LOWER(a.Artistname) = LOWER('".$a."') THEN 1 ELSE 2 END, ";
|
||
|
}
|
||
|
if (count($prefs['nosortprefixes']) > 0) {
|
||
|
$qstring .= "(CASE ";
|
||
|
foreach($prefs['nosortprefixes'] AS $p) {
|
||
|
$phpisshitsometimes = strlen($p)+2;
|
||
|
$qstring .= "WHEN LOWER(a.Artistname) LIKE '".strtolower($p).
|
||
|
" %' THEN LOWER(SUBSTR(a.Artistname,".$phpisshitsometimes.")) ";
|
||
|
}
|
||
|
$qstring .= "ELSE LOWER(a.Artistname) END)";
|
||
|
} else {
|
||
|
$qstring .= "LOWER(a.Artistname)";
|
||
|
}
|
||
|
return $qstring;
|
||
|
}
|
||
|
|
||
|
function albumartist_sort_query($flag) {
|
||
|
// This query gives us album artists only. It also makes sure we only get artists for whom we
|
||
|
// have actual tracks (no album artists who appear only on the wishlist or who have only hidden tracks)
|
||
|
// Using GROUP BY is faster than using SELECT DISTINCT
|
||
|
// USING IN is faster than the double JOIN
|
||
|
global $prefs;
|
||
|
switch ($flag) {
|
||
|
case 'a':
|
||
|
$sflag = "AND isSearchResult < 2 AND isAudiobook = 0";
|
||
|
break;
|
||
|
|
||
|
case 'b':
|
||
|
$sflag = "AND isSearchResult > 0 AND isAudiobook = 0";
|
||
|
break;
|
||
|
|
||
|
case 'z':
|
||
|
$sflag = "AND isSearchResult < 2 AND isAudiobook = 1";
|
||
|
break;
|
||
|
|
||
|
case 'c':
|
||
|
// Special case for album art manager
|
||
|
$sflag = "AND isSearchResult < 2";
|
||
|
break;
|
||
|
|
||
|
}
|
||
|
|
||
|
$qstring = "SELECT Artistname, Artistindex
|
||
|
FROM Artisttable AS a
|
||
|
WHERE
|
||
|
Artistindex IN
|
||
|
(SELECT AlbumArtistindex FROM Albumtable JOIN Tracktable USING (Albumindex)
|
||
|
WHERE Uri IS NOT NULL
|
||
|
AND Hidden = 0
|
||
|
".track_date_check($prefs['collectionrange'], $flag)."
|
||
|
".$sflag."
|
||
|
GROUP BY AlbumArtistindex)
|
||
|
ORDER BY ";
|
||
|
$qstring .= sort_artists_by_name();
|
||
|
return $qstring;
|
||
|
}
|
||
|
|
||
|
function do_artists_from_database($why, $what, $who) {
|
||
|
global $divtype;
|
||
|
$singleheader = array();
|
||
|
logger::trace("DUMPALBUMS", "Generating artist",$why.$what.$who,"from database");
|
||
|
$singleheader['type'] = 'insertAfter';
|
||
|
$singleheader['where'] = 'fothergill';
|
||
|
$count = 0;
|
||
|
$t = microtime(true);
|
||
|
$result = generic_sql_query(albumartist_sort_query($why), false, PDO::FETCH_ASSOC);
|
||
|
$at = microtime(true) - $t;
|
||
|
logger::debug("TIMINGS", " -- Album Artist SQL query took ".$at." seconds");
|
||
|
$t = microtime(true);
|
||
|
foreach($result as $obj) {
|
||
|
if ($who == "root") {
|
||
|
print artistHeader($why.$what.$obj['Artistindex'], $obj['Artistname']);
|
||
|
$count++;
|
||
|
} else {
|
||
|
if ($obj['Artistindex'] != $who) {
|
||
|
$singleheader['type'] = 'insertAfter';
|
||
|
$singleheader['where'] = $why.$what.$obj['Artistindex'];
|
||
|
} else {
|
||
|
$singleheader['html'] = artistHeader($why.$what.$obj['Artistindex'], $obj['Artistname']);
|
||
|
$singleheader['id'] = $who;
|
||
|
$at = microtime(true) - $t;
|
||
|
logger::debug("TIMINGS", " -- Generating Artist Header took ".$at." seconds");
|
||
|
return $singleheader;
|
||
|
}
|
||
|
}
|
||
|
$divtype = ($divtype == "album1") ? "album2" : "album1";
|
||
|
}
|
||
|
$at = microtime(true) - $t;
|
||
|
logger::debug("TIMINGS", " -- Generating Artist List took ".$at." seconds");
|
||
|
return $count;
|
||
|
}
|
||
|
|
||
|
function get_list_of_artists() {
|
||
|
return generic_sql_query(albumartist_sort_query("c"));
|
||
|
}
|
||
|
|
||
|
function album_sort_query($why, $what, $who) {
|
||
|
global $prefs;
|
||
|
$sflag = ($why == "b") ? "AND Tracktable.isSearchResult > 0" : "AND Tracktable.isSearchResult < 2";
|
||
|
$sflag .= ($why == 'z') ? " AND Tracktable.isAudiobook = 1" : " AND Tracktable.isAudiobook = 0";
|
||
|
|
||
|
$qstring = "SELECT Albumtable.*, Artisttable.Artistname FROM Albumtable JOIN Artisttable ON
|
||
|
(Albumtable.AlbumArtistindex = Artisttable.Artistindex) WHERE ";
|
||
|
|
||
|
if ($who != "root") {
|
||
|
$qstring .= "AlbumArtistindex = '".$who."' AND ";
|
||
|
}
|
||
|
$qstring .= "Albumindex IN (SELECT Albumindex FROM Tracktable WHERE
|
||
|
Tracktable.Albumindex = Albumtable.Albumindex AND ";
|
||
|
|
||
|
$qstring .= "Tracktable.Uri IS NOT NULL AND Tracktable.Hidden = 0 ".track_date_check($prefs['collectionrange'], $why)." ".$sflag.")";
|
||
|
$qstring .= " ORDER BY ";
|
||
|
if ($prefs['sortcollectionby'] == "albumbyartist" && $who == "root") {
|
||
|
foreach ($prefs['artistsatstart'] as $a) {
|
||
|
$qstring .= "CASE WHEN LOWER(Artisttable.Artistname) = LOWER('".$a."') THEN 1 ELSE 2 END, ";
|
||
|
}
|
||
|
if (count($prefs['nosortprefixes']) > 0) {
|
||
|
$qstring .= "(CASE ";
|
||
|
foreach($prefs['nosortprefixes'] AS $p) {
|
||
|
$phpisshitsometimes = strlen($p)+2;
|
||
|
$qstring .= "WHEN LOWER(Artisttable.Artistname) LIKE '".strtolower($p).
|
||
|
" %' THEN LOWER(SUBSTR(Artisttable.Artistname,".$phpisshitsometimes.")) ";
|
||
|
}
|
||
|
$qstring .= "ELSE LOWER(Artisttable.Artistname) END),";
|
||
|
} else {
|
||
|
$qstring .= "LOWER(Artisttable.Artistname),";
|
||
|
}
|
||
|
}
|
||
|
$qstring .= " CASE WHEN Albumname LIKE '".get_int_text('label_allartist')."%' THEN 1 ELSE 2 END,";
|
||
|
if ($prefs['sortbydate']) {
|
||
|
if ($prefs['notvabydate']) {
|
||
|
$qstring .= " CASE WHEN Artisttable.Artistname = 'Various Artists' THEN LOWER(Albumname) ELSE Year END,";
|
||
|
} else {
|
||
|
$qstring .= ' Year,';
|
||
|
}
|
||
|
}
|
||
|
$qstring .= ' LOWER(Albumname)';
|
||
|
return $qstring;
|
||
|
}
|
||
|
|
||
|
function do_artist_banner($why, $what, $who) {
|
||
|
logger::debug("BACKEND", "Creating Banner ".$why." ".$what." ".$who);
|
||
|
$singleheader['type'] = 'insertAfter';
|
||
|
$singleheader['where'] = 'fothergill';
|
||
|
$qstring = album_sort_query($why, $what, 'root');
|
||
|
$result = generic_sql_query($qstring, false, PDO::FETCH_OBJ);
|
||
|
foreach ($result as $obj) {
|
||
|
if ($obj->AlbumArtistindex != $who) {
|
||
|
$singleheader['where'] = 'aalbum'.$obj->Albumindex;
|
||
|
$singleheader['type'] = 'insertAfter';
|
||
|
} else {
|
||
|
$singleheader['html'] = artistBanner($obj->Artistname, $obj->AlbumArtistindex, $why);
|
||
|
$singleheader['id'] = $obj->AlbumArtistindex;
|
||
|
return $singleheader;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function do_albums_from_database($why, $what, $who, $fragment = false, $use_artistindex = false, $force_artistname = false, $do_controlheader = true) {
|
||
|
global $prefs;
|
||
|
$singleheader = array();
|
||
|
$singleheader['why'] = $why;
|
||
|
if ($prefs['sortcollectionby'] == "artist") {
|
||
|
$singleheader['type'] = 'insertAtStart';
|
||
|
$singleheader['where'] = $why.'artist'.$who;
|
||
|
} else {
|
||
|
$singleheader['type'] = 'insertAfter';
|
||
|
$singleheader['where'] = 'fothergill';
|
||
|
}
|
||
|
logger::log("DUMPALBUMS", "Generating albums for",$why.$what.$who,"from database");
|
||
|
|
||
|
$qstring = album_sort_query($why, $what, $who);
|
||
|
logger::debug("DUMPALBUMS", "Query String Is ".$qstring);
|
||
|
|
||
|
$count = 0;
|
||
|
$currart = "";
|
||
|
$currban = "";
|
||
|
$result = generic_sql_query($qstring);
|
||
|
if ($do_controlheader && count($result) > 0) {
|
||
|
print albumControlHeader($fragment, $why, $what, $who, $result[0]['Artistname']);
|
||
|
}
|
||
|
foreach ($result as $obj) {
|
||
|
$artistbanner = ($prefs['sortcollectionby'] == 'albumbyartist' && $prefs['showartistbanners']) ? $obj['Artistname'] : null;
|
||
|
$obj['Artistname'] = ($force_artistname || $prefs['sortcollectionby'] == "album") ? $obj['Artistname'] : null;
|
||
|
$obj['why'] = $why;
|
||
|
$obj['id'] = $why.$what.$obj['Albumindex'];
|
||
|
$obj['class'] = 'album';
|
||
|
if ($fragment === false) {
|
||
|
if ($artistbanner !== null && $artistbanner !== $currban) {
|
||
|
print artistBanner($artistbanner, $obj['AlbumArtistindex'], $why);
|
||
|
}
|
||
|
print albumHeader($obj);
|
||
|
} else {
|
||
|
if ($obj['Albumindex'] != $fragment) {
|
||
|
$singleheader['where'] = $why.'album'.$obj['Albumindex'];
|
||
|
$singleheader['type'] = 'insertAfter';
|
||
|
} else {
|
||
|
$singleheader['html'] = albumHeader($obj);
|
||
|
$singleheader['id'] = $fragment;
|
||
|
return $singleheader;
|
||
|
}
|
||
|
}
|
||
|
$currart = $obj['Artistname'];
|
||
|
$currban = $artistbanner;
|
||
|
$count++;
|
||
|
}
|
||
|
logger::log("DUMPALBUMS", "... Found ".$count." albums");
|
||
|
if ($count == 0 && !($why == 'a' && $who == 'root')) {
|
||
|
noAlbumsHeader();
|
||
|
}
|
||
|
return $count;
|
||
|
}
|
||
|
|
||
|
function artistBanner($a, $i, $why) {
|
||
|
return '<div class="configtitle artistbanner brick brick_wide" id="'.$why.'artist'.$i.'"><b>'.$a.'</b></div>';
|
||
|
}
|
||
|
|
||
|
function remove_album_from_database($albumid) {
|
||
|
generic_sql_query("DELETE FROM Tracktable WHERE Albumindex = ".$albumid, true);
|
||
|
generic_sql_query("DELETE FROM Albumtable WHERE Albumindex = ".$albumid, true);
|
||
|
}
|
||
|
|
||
|
function get_list_of_albums($aid) {
|
||
|
$qstring = "SELECT * FROM Albumtable WHERE AlbumArtistindex = '".$aid."' AND ";
|
||
|
$qstring .= "Albumindex IN (SELECT Albumindex FROM Tracktable WHERE Tracktable.Albumindex =
|
||
|
Albumtable.Albumindex AND Tracktable.Uri IS NOT NULL AND Tracktable.Hidden = 0 AND
|
||
|
Tracktable.isSearchResult < 2)";
|
||
|
$qstring .= ' ORDER BY LOWER(Albumname)';
|
||
|
return generic_sql_query($qstring);
|
||
|
}
|
||
|
|
||
|
function get_album_tracks_from_database($index, $cmd, $flag) {
|
||
|
global $prefs;
|
||
|
$retarr = array();
|
||
|
$qstring = null;
|
||
|
$cmd = ($cmd === null) ? 'add' : $cmd;
|
||
|
switch ($flag) {
|
||
|
// Really need to make these flags simpler, but it does work.
|
||
|
case "b":
|
||
|
// b - tracks from search results
|
||
|
$action = "SELECT";
|
||
|
$sflag = "AND isSearchResult > 0";
|
||
|
$rflag = "";
|
||
|
break;
|
||
|
|
||
|
case "r":
|
||
|
// r - only tracks with ratings
|
||
|
$action = "SELECT";
|
||
|
$sflag = "AND isSearchResult < 2 AND (LinkChecked = 0 OR LinkChecked = 2)";
|
||
|
$rflag = " JOIN Ratingtable USING (TTindex)";
|
||
|
break;
|
||
|
|
||
|
case "t":
|
||
|
// t - only tracks with tags
|
||
|
$action = "SELECT DISTINCT";
|
||
|
$sflag = "AND isSearchResult < 2 AND (LinkChecked = 0 OR LinkChecked = 2)";
|
||
|
$rflag = " JOIN TagListtable USING (TTindex)";
|
||
|
break;
|
||
|
|
||
|
case "y":
|
||
|
// y = only tracks with tags and ratings
|
||
|
$action = "SELECT DISTINCT";
|
||
|
$sflag = "AND isSearchResult < 2 AND (LinkChecked = 0 OR LinkChecked = 2)";
|
||
|
$rflag = " JOIN Ratingtable USING (TTindex)";
|
||
|
$rflag .= " JOIN TagListtable USING (TTindex)";
|
||
|
break;
|
||
|
|
||
|
case "u":
|
||
|
// u - only tracks with tags or ratings
|
||
|
$qstring = "SELECT Uri, Disc, Trackno FROM
|
||
|
Tracktable JOIN Ratingtable USING (TTindex)
|
||
|
WHERE Albumindex = '".$index.
|
||
|
"' AND Uri IS NOT NULL
|
||
|
AND Hidden = 0
|
||
|
AND (LinkChecked = 0 OR LinkChecked = 2)
|
||
|
AND isSearchResult <2 "
|
||
|
.track_date_check($prefs['collectionrange'], $flag).
|
||
|
"UNION SELECT Uri, Disc, TrackNo FROM
|
||
|
Tracktable JOIN TagListtable USING (TTindex)
|
||
|
WHERE Albumindex = '".$index.
|
||
|
"' AND Uri IS NOT NULL
|
||
|
AND Hidden = 0
|
||
|
AND (LinkChecked = 0 OR LinkChecked = 2)
|
||
|
AND isSearchResult <2 "
|
||
|
.track_date_check($prefs['collectionrange'], $flag).
|
||
|
"ORDER BY Disc, TrackNo;";
|
||
|
break;
|
||
|
|
||
|
case "z":
|
||
|
// z - Audiobooks
|
||
|
$action = "SELECT";
|
||
|
$sflag = "AND isSearchResult < 2 AND isAudiobook = 1";
|
||
|
$rflag = "";
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
// anything else - tracks from collection
|
||
|
$action = "SELECT";
|
||
|
$sflag = "AND isSearchResult < 2 AND isAudiobook = 0";
|
||
|
$rflag = "";
|
||
|
break;
|
||
|
}
|
||
|
logger::log("GET TRACKS", "Getting Album Tracks for Albumindex",$index);
|
||
|
if ($qstring === null) {
|
||
|
$qstring = $action." Uri FROM Tracktable".$rflag." WHERE Albumindex = '".$index."' AND Uri IS NOT NULL AND Hidden = 0 ".track_date_check($prefs['collectionrange'], $flag)." ".$sflag." ORDER BY Disc, TrackNo";
|
||
|
}
|
||
|
$result = generic_sql_query($qstring);
|
||
|
foreach($result as $a) {
|
||
|
$retarr[] = $cmd.' "'.$a['Uri'].'"';
|
||
|
}
|
||
|
return $retarr;
|
||
|
}
|
||
|
|
||
|
function get_artist_tracks_from_database($index, $cmd, $flag) {
|
||
|
global $prefs;
|
||
|
$retarr = array();
|
||
|
logger::log("GET TRACKS", "Getting Tracks for AlbumArtist",$index);
|
||
|
$qstring = "SELECT Albumindex FROM Albumtable JOIN Artisttable ON
|
||
|
(Albumtable.AlbumArtistindex = Artisttable.Artistindex) WHERE AlbumArtistindex = ".$index." ORDER BY";
|
||
|
if ($prefs['sortbydate']) {
|
||
|
if ($prefs['notvabydate']) {
|
||
|
$qstring .= " CASE WHEN Artistname = 'Various Artists' THEN LOWER(Albumname) ELSE Year END,";
|
||
|
} else {
|
||
|
$qstring .= ' Year,';
|
||
|
}
|
||
|
}
|
||
|
$qstring .= ' LOWER(Albumname)';
|
||
|
$result = generic_sql_query($qstring);
|
||
|
foreach ($result as $a) {
|
||
|
$retarr = array_merge($retarr, get_album_tracks_from_database($a['Albumindex'], $cmd, $flag));
|
||
|
}
|
||
|
return $retarr;
|
||
|
}
|
||
|
|
||
|
function do_tracks_from_database($why, $what, $whom, $fragment = false) {
|
||
|
// This function can accept multiple album ids ($whom can be an array)
|
||
|
// in which case it will combine them all into one 'virtual album' - see browse_album()
|
||
|
global $prefs;
|
||
|
$who = getArray($whom);
|
||
|
logger::log("GET TRACKS", "Generating tracks for album(s)",$who,"from database");
|
||
|
if ($fragment) {
|
||
|
ob_start();
|
||
|
}
|
||
|
$t = ($why == "b") ? "AND isSearchResult > 0" : "AND isSearchResult < 2";
|
||
|
$trackarr = generic_sql_query(
|
||
|
// This looks like a wierd way of doing it but the obvious way doesn't work with mysql
|
||
|
// due to table aliases being used.
|
||
|
"SELECT
|
||
|
".SQL_TAG_CONCAT." AS tags,
|
||
|
r.Rating AS rating,
|
||
|
pr.Progress AS progress,
|
||
|
tr.TTindex AS ttid,
|
||
|
tr.Title AS title,
|
||
|
tr.TrackNo AS trackno,
|
||
|
tr.Duration AS time,
|
||
|
tr.LastModified AS lm,
|
||
|
tr.Disc AS disc,
|
||
|
tr.Uri AS uri,
|
||
|
tr.LinkChecked AS playable,
|
||
|
ta.Artistname AS artist,
|
||
|
tr.Artistindex AS trackartistindex,
|
||
|
al.AlbumArtistindex AS albumartistindex
|
||
|
FROM
|
||
|
(Tracktable AS tr, Artisttable AS ta, Albumtable AS al)
|
||
|
LEFT JOIN TagListtable AS tl ON tr.TTindex = tl.TTindex
|
||
|
LEFT JOIN Tagtable AS t USING (Tagindex)
|
||
|
LEFT JOIN Ratingtable AS r ON tr.TTindex = r.TTindex
|
||
|
LEFT JOIN Progresstable AS pr ON tr.TTindex = pr.TTindex
|
||
|
WHERE (".implode(' OR ', array_map('do_fiddle', $who)).")
|
||
|
AND uri IS NOT NULL
|
||
|
AND tr.Hidden = 0
|
||
|
".track_date_check($prefs['collectionrange'], $why)."
|
||
|
".$t."
|
||
|
AND tr.Artistindex = ta.Artistindex
|
||
|
AND al.Albumindex = tr.Albumindex
|
||
|
GROUP BY tr.TTindex
|
||
|
ORDER BY CASE WHEN title LIKE 'Album: %' THEN 1 ELSE 2 END, disc, trackno"
|
||
|
);
|
||
|
$numtracks = count($trackarr);
|
||
|
$numdiscs = get_highest_disc($trackarr);
|
||
|
$currdisc = -1;
|
||
|
trackControlHeader($why, $what, $who[0], get_album_details($who[0]));
|
||
|
foreach ($trackarr as $arr) {
|
||
|
if ($numdiscs > 1 && $arr['disc'] != $currdisc && $arr['disc'] > 0) {
|
||
|
$currdisc = $arr['disc'];
|
||
|
print '<div class="clickable clickdisc playable draggable discnumber indent">'.ucfirst(strtolower(get_int_text("musicbrainz_disc"))).' '.$currdisc.'</div>';
|
||
|
}
|
||
|
if ($currdisc > 0) {
|
||
|
$arr['discclass'] = ' disc'.$currdisc;
|
||
|
} else {
|
||
|
$arr['discclass'] = '';
|
||
|
}
|
||
|
$arr['numtracks'] = $numtracks;
|
||
|
$tracktype = albumTrack($arr);
|
||
|
}
|
||
|
if ($tracktype == 1) {
|
||
|
logger::mark("GET TRACKS", "Album",$who,"has no tracks, just an artist link");
|
||
|
print '<input type="hidden" class="expandartist"/>';
|
||
|
} else if ($tracktype == 2) {
|
||
|
logger::mark("GET TRACKS", "Album",$who,"has no tracks, just an album link");
|
||
|
print '<input type="hidden" class="expandalbum"/>';
|
||
|
}
|
||
|
if ($fragment) {
|
||
|
$s = ob_get_contents();
|
||
|
ob_end_clean();
|
||
|
return $s;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function get_highest_disc($tracks) {
|
||
|
$n = 1;
|
||
|
foreach ($tracks as $t) {
|
||
|
if ($t['disc'] > $n) {
|
||
|
$n = $t['disc'];
|
||
|
}
|
||
|
}
|
||
|
return $n;
|
||
|
}
|
||
|
|
||
|
function do_fiddle($a) {
|
||
|
return 'tr.Albumindex = '.$a;
|
||
|
}
|
||
|
|
||
|
function get_album_details($albumindex) {
|
||
|
return generic_sql_query(
|
||
|
"SELECT Albumname, Artistname, Image, AlbumUri
|
||
|
FROM Albumtable
|
||
|
JOIN Artisttable ON Albumtable.AlbumArtistindex = Artisttable.Artistindex
|
||
|
WHERE Albumindex = ".$albumindex );
|
||
|
}
|
||
|
|
||
|
function get_artist_charts() {
|
||
|
$artists = array();
|
||
|
$query = "SELECT SUM(Playcount) AS playtot, Artistindex, Artistname FROM
|
||
|
Playcounttable JOIN Tracktable USING (TTindex) JOIN Artisttable USING (Artistindex)";
|
||
|
$query .= " GROUP BY Artistindex ORDER BY playtot DESC LIMIT 40";
|
||
|
$result = generic_sql_query($query, false, PDO::FETCH_OBJ);
|
||
|
foreach ($result as $obj) {
|
||
|
$artists[] = array( 'label_artist' => $obj->Artistname, 'soundcloud_plays' => $obj->playtot);
|
||
|
}
|
||
|
return $artists;
|
||
|
}
|
||
|
|
||
|
function get_album_charts() {
|
||
|
$albums = array();
|
||
|
$query = "SELECT SUM(Playcount) AS playtot, Albumname, Artistname, AlbumUri, Albumindex
|
||
|
FROM Playcounttable JOIN Tracktable USING (TTindex) JOIN Albumtable USING (Albumindex)
|
||
|
JOIN Artisttable ON Albumtable.AlbumArtistindex = Artisttable.Artistindex";
|
||
|
$query .= " GROUP BY Albumindex ORDER BY playtot DESC LIMIT 40";
|
||
|
$result = generic_sql_query($query, false, PDO::FETCH_OBJ);
|
||
|
foreach ($result as $obj) {
|
||
|
$albums[] = array( 'label_artist' => $obj->Artistname,
|
||
|
'label_album' => $obj->Albumname,
|
||
|
'soundcloud_plays' => $obj->playtot, 'uri' => $obj->AlbumUri);
|
||
|
}
|
||
|
return $albums;
|
||
|
}
|
||
|
|
||
|
function get_track_charts($limit = 40) {
|
||
|
$tracks = array();
|
||
|
$query = "SELECT Title, Playcount, Artistname, Uri FROM Tracktable JOIN Playcounttable USING (TTIndex)
|
||
|
JOIN Artisttable USING (Artistindex)";
|
||
|
$query .= " ORDER BY Playcount DESC LIMIT ".$limit;
|
||
|
$result = generic_sql_query($query, false, PDO::FETCH_OBJ);
|
||
|
foreach ($result as $obj) {
|
||
|
$tracks[] = array( 'label_artist' => $obj->Artistname,
|
||
|
'label_track' => $obj->Title,
|
||
|
'soundcloud_plays' => $obj->Playcount, 'uri' => $obj->Uri);
|
||
|
}
|
||
|
return $tracks;
|
||
|
}
|
||
|
|
||
|
function find_justadded_artists() {
|
||
|
return sql_get_column("SELECT DISTINCT AlbumArtistindex FROM Albumtable JOIN Tracktable USING (Albumindex) WHERE justAdded = 1", 0);
|
||
|
}
|
||
|
|
||
|
function find_justadded_albums() {
|
||
|
return sql_get_column("SELECT DISTINCT Albumindex FROM Tracktable WHERE justAdded = 1", 0);
|
||
|
}
|
||
|
|
||
|
function get_user_radio_streams() {
|
||
|
return generic_sql_query("SELECT * FROM RadioStationtable WHERE IsFave = 1 ORDER BY Number, StationName");
|
||
|
}
|
||
|
|
||
|
function remove_user_radio_stream($x) {
|
||
|
generic_sql_query("UPDATE RadioStationtable SET IsFave = 0, Number = 65535 WHERE Stationindex = ".$x, true);
|
||
|
}
|
||
|
|
||
|
function save_radio_order($order) {
|
||
|
foreach ($order as $i => $o) {
|
||
|
generic_sql_query("UPDATE RadioStationtable SET Number = ".$i." WHERE Stationindex = ".$o, true);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function check_radio_station($playlisturl, $stationname, $image) {
|
||
|
global $mysqlc;
|
||
|
$index = null;
|
||
|
$index = sql_prepare_query(false, null, 'Stationindex', false, "SELECT Stationindex FROM RadioStationtable WHERE PlaylistUrl = ?", $playlisturl);
|
||
|
if ($index === false) {
|
||
|
logger::shout("RADIO", "Adding New Radio Station");
|
||
|
logger::mark("RADIO", " Name :",$stationname);
|
||
|
logger::mark("RADIO", " Image :",$image);
|
||
|
logger::mark("RADIO", " URL :",$playlisturl);
|
||
|
if (sql_prepare_query(true, null, null, null, "INSERT INTO RadioStationtable (IsFave, StationName, PlaylistUrl, Image) VALUES (?, ?, ?, ?)",
|
||
|
0, trim($stationname), trim($playlisturl), trim($image))) {
|
||
|
$index = $mysqlc->lastInsertId();
|
||
|
logger::log("RADIO", "Created new radio station with index ".$index);
|
||
|
}
|
||
|
} else {
|
||
|
sql_prepare_query(true, null, null, null, "UPDATE RadioStationtable SET StationName = ?, Image = ? WHERE Stationindex = ?",
|
||
|
trim($stationname), trim($image), $index);
|
||
|
logger::shout("RADIO", "Found radio station",$stationname,"with index",$index);
|
||
|
}
|
||
|
return $index;
|
||
|
}
|
||
|
|
||
|
function check_radio_tracks($stationid, $tracks) {
|
||
|
generic_sql_query("DELETE FROM RadioTracktable WHERE Stationindex = ".$stationid, true);
|
||
|
foreach ($tracks as $track) {
|
||
|
$index = sql_prepare_query(false, null, 'Stationindex', false, "SELECT Stationindex FROM RadioTracktable WHERE TrackUri = ?", trim($track['TrackUri']));
|
||
|
if ($index !== false) {
|
||
|
logger::log("RADIO", " Track already exists for stationindex",$index);
|
||
|
$stationid = $index;
|
||
|
} else {
|
||
|
logger::mark("RADIO", " Adding New Track",$track['TrackUri'],"to station",$stationid);
|
||
|
sql_prepare_query(true, null, null, null, "INSERT INTO RadioTracktable (Stationindex, TrackUri, PrettyStream) VALUES (?, ?, ?)",
|
||
|
$stationid, trim($track['TrackUri']), trim($track['PrettyStream']));
|
||
|
}
|
||
|
}
|
||
|
return $stationid;
|
||
|
}
|
||
|
|
||
|
function add_fave_station($info) {
|
||
|
if (array_key_exists('streamid', $info) && $info['streamid']) {
|
||
|
logger::shout("RADIO", "Updating StationIndex",$info['streamid'],"to be fave");
|
||
|
generic_sql_query("UPDATE RadioStationtable SET IsFave = 1 WHERE Stationindex = ".$info['streamid'], true);
|
||
|
return true;
|
||
|
}
|
||
|
$stationindex = check_radio_station($info['location'],$info['album'],$info['image']);
|
||
|
$stationindex = check_radio_tracks($stationindex, array(array('TrackUri' => $info['location'], 'PrettyStream' => $info['stream'])));
|
||
|
generic_sql_query("UPDATE RadioStationtable SET IsFave = 1 WHERE Stationindex = ".$stationindex, true);
|
||
|
}
|
||
|
|
||
|
function update_radio_station_name($info) {
|
||
|
if ($info['streamid']) {
|
||
|
logger::shout("RADIO", "Updating Stationindex",$info['streamid'],"with new name",$info['name']);
|
||
|
sql_prepare_query(true, null, null, null, "UPDATE RadioStationtable SET StationName = ? WHERE Stationindex = ?",$info['name'],$info['streamid']);
|
||
|
} else {
|
||
|
$stationid = check_radio_station($info['uri'], $info['name'], '');
|
||
|
check_radio_tracks($stationid, array(array('TrackUri' => $info['uri'], 'PrettyStream' => '')));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function find_stream_name_from_index($index) {
|
||
|
return simple_query('StationName', 'RadioStationtable', 'StationIndex', $index, '');
|
||
|
}
|
||
|
|
||
|
function update_stream_image($stream, $image) {
|
||
|
sql_prepare_query(true, null, null, null, "UPDATE RadioStationtable SET Image = ? WHERE StationName = ?",$image,$stream);
|
||
|
}
|
||
|
|
||
|
function update_podcast_image($podid, $image) {
|
||
|
logger::log("PODCASTS", "Setting Image to",$image,"for podid",$podid);
|
||
|
sql_prepare_query(true, null, null, null, 'UPDATE Podcasttable SET Image = ? WHERE PODindex = ?',$image, $podid);
|
||
|
}
|
||
|
|
||
|
function find_radio_track_from_url($url) {
|
||
|
return sql_prepare_query(false, PDO::FETCH_OBJ, null, null,
|
||
|
"SELECT
|
||
|
Stationindex, PlaylistUrl, StationName, Image, PrettyStream
|
||
|
FROM
|
||
|
RadioStationtable JOIN RadioTracktable USING (Stationindex)
|
||
|
WHERE TrackUri = ?",$url);
|
||
|
}
|
||
|
|
||
|
function find_podcast_track_from_url($url) {
|
||
|
return sql_prepare_query(false, PDO::FETCH_OBJ, null, null,
|
||
|
"SELECT
|
||
|
PodcastTracktable.Title AS title,
|
||
|
PodcastTracktable.Artist AS artist,
|
||
|
PodcastTracktable.Duration AS duration,
|
||
|
PodcastTracktable.Description AS comment,
|
||
|
Podcasttable.Title AS album,
|
||
|
Podcasttable.Artist AS albumartist,
|
||
|
Podcasttable.Image AS image
|
||
|
FROM PodcastTracktable JOIN Podcasttable USING (PODindex)
|
||
|
WHERE PodcastTracktable.Link=?
|
||
|
OR PodcastTracktable.Localfilename=?",
|
||
|
$url,
|
||
|
preg_replace('#http://.*?/#', '/', $url));
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Database Global Stats and Version Control
|
||
|
//
|
||
|
|
||
|
function update_track_stats() {
|
||
|
logger::log("BACKEND", "Updating Track Stats");
|
||
|
$t = microtime(true);
|
||
|
$ac = get_artist_count(ADDED_ALL_TIME, 0);
|
||
|
update_stat('ArtistCount',$ac);
|
||
|
|
||
|
$ac = get_album_count(ADDED_ALL_TIME, 0);
|
||
|
update_stat('AlbumCount',$ac);
|
||
|
|
||
|
$ac = get_track_count(ADDED_ALL_TIME, 0);
|
||
|
update_stat('TrackCount',$ac);
|
||
|
|
||
|
$ac = get_duration_count(ADDED_ALL_TIME, 0);
|
||
|
update_stat('TotalTime',$ac);
|
||
|
$at = microtime(true) - $t;
|
||
|
logger::debug("TIMINGS", "Updating Track Stats took ".$at." seconds");
|
||
|
}
|
||
|
|
||
|
function update_stat($item, $value) {
|
||
|
generic_sql_query("UPDATE Statstable SET Value='".$value."' WHERE Item='".$item."'", true);
|
||
|
}
|
||
|
|
||
|
function get_stat($item) {
|
||
|
return simple_query('Value', 'Statstable', 'Item', $item, 0);
|
||
|
}
|
||
|
|
||
|
function get_artist_count($range, $iab) {
|
||
|
$ac = generic_sql_query(
|
||
|
"SELECT COUNT(*) AS NumArtists FROM (SELECT AlbumArtistindex FROM Albumtable
|
||
|
INNER JOIN Tracktable USING (Albumindex) WHERE Uri IS NOT NULL
|
||
|
AND Hidden = 0 AND isSearchResult < 2 AND isAudiobook = ".$iab." ".track_date_check($range, 'a')." GROUP BY AlbumArtistindex) AS t", false, null, 'NumArtists', 0);
|
||
|
return $ac;
|
||
|
}
|
||
|
|
||
|
function get_album_count($range, $iab) {
|
||
|
$ac = generic_sql_query(
|
||
|
"SELECT COUNT(*) AS NumAlbums FROM (SELECT Albumindex FROM Tracktable WHERE Uri IS NOT NULL
|
||
|
AND Hidden = 0 AND isSearchResult < 2 AND isAudiobook = ".$iab." ".track_date_check($range, 'a')." GROUP BY Albumindex) AS t", false, null, 'NumAlbums', 0);
|
||
|
return $ac;
|
||
|
}
|
||
|
|
||
|
function get_track_count($range, $iab) {
|
||
|
$ac = generic_sql_query("SELECT COUNT(*) AS NumTracks FROM Tracktable WHERE Uri IS NOT NULL AND Hidden=0 AND isAudiobook = ".$iab." ".track_date_check($range, 'a')." AND isSearchResult < 2", false, null, 'NumTracks', 0);
|
||
|
return $ac;
|
||
|
}
|
||
|
|
||
|
function get_duration_count($range, $iab) {
|
||
|
$ac = generic_sql_query("SELECT SUM(Duration) AS TotalTime FROM Tracktable WHERE Uri IS NOT NULL AND Hidden=0 AND isAudiobook = ".$iab." ".track_date_check($range, 'a')." AND isSearchResult < 2", false, null, 'TotalTime', 0);
|
||
|
if ($ac == '') {
|
||
|
$ac = 0;
|
||
|
}
|
||
|
return $ac;
|
||
|
}
|
||
|
|
||
|
function dumpAlbums($which) {
|
||
|
|
||
|
global $divtype, $prefs;
|
||
|
|
||
|
$a = preg_match('/(a|b|z)(.*?)(\d+|root)/', $which, $matches);
|
||
|
if (!$a) {
|
||
|
print '<h3>'.get_int_text("label_general_error").'</h3>';
|
||
|
logger::fail("DUMPALBUMS", "Artist dump failed - regexp failed to match",$which);
|
||
|
return false;
|
||
|
}
|
||
|
$why = $matches[1];
|
||
|
$what = $matches[2];
|
||
|
$who = $matches[3];
|
||
|
$count = null;
|
||
|
|
||
|
switch ($who) {
|
||
|
case 'root':
|
||
|
print '<div class="sizer"></div>';
|
||
|
switch ($why) {
|
||
|
case 'a':
|
||
|
print collectionStats();
|
||
|
break;
|
||
|
|
||
|
case 'b':
|
||
|
searchStats();
|
||
|
break;
|
||
|
|
||
|
case 'z':
|
||
|
print audiobookStats();
|
||
|
break;
|
||
|
|
||
|
}
|
||
|
$divtype = "album1";
|
||
|
switch ($what) {
|
||
|
case 'artist':
|
||
|
$count = do_artists_from_database($why, $what, $who);
|
||
|
break;
|
||
|
|
||
|
case 'album':
|
||
|
case 'albumbyartist':
|
||
|
$count = do_albums_from_database($why, 'album', $who, false, false, false);
|
||
|
break;
|
||
|
|
||
|
}
|
||
|
if ($count == 0) {
|
||
|
switch ($why) {
|
||
|
case 'a':
|
||
|
emptyCollectionDisplay();
|
||
|
break;
|
||
|
|
||
|
case 'b':
|
||
|
emptySearchDisplay();
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
switch ($what) {
|
||
|
case 'artist':
|
||
|
do_albums_from_database($why, 'album', $who, false, false, false);
|
||
|
break;
|
||
|
case 'album':
|
||
|
do_tracks_from_database($why, $what, $who, false);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
function collectionStats() {
|
||
|
global $prefs;
|
||
|
$html = '<div id="fothergill" class="brick brick_wide">';
|
||
|
if ($prefs['collectionrange'] == ADDED_ALL_TIME) {
|
||
|
$html .= alistheader(get_stat('ArtistCount'),
|
||
|
get_stat('AlbumCount'),
|
||
|
get_stat('TrackCount'),
|
||
|
format_time(get_stat('TotalTime'))
|
||
|
);
|
||
|
} else {
|
||
|
$html .= alistheader(get_artist_count($prefs['collectionrange'], 0),
|
||
|
get_album_count($prefs['collectionrange'], 0),
|
||
|
get_track_count($prefs['collectionrange'], 0),
|
||
|
format_time(get_duration_count($prefs['collectionrange'], 0)));
|
||
|
}
|
||
|
$html .= '</div>';
|
||
|
return $html;
|
||
|
}
|
||
|
|
||
|
function audiobookStats() {
|
||
|
global $prefs;
|
||
|
$html = '<div class="brick brick_wide">';
|
||
|
$html .= alistheader(get_artist_count($prefs['collectionrange'], 1),
|
||
|
get_album_count($prefs['collectionrange'], 1),
|
||
|
get_track_count($prefs['collectionrange'], 1),
|
||
|
format_time(get_duration_count($prefs['collectionrange'], 1)));
|
||
|
$html .= "</div>";
|
||
|
return $html;
|
||
|
}
|
||
|
|
||
|
function searchStats() {
|
||
|
$numartists = generic_sql_query(
|
||
|
"SELECT COUNT(*) AS NumArtists FROM (SELECT DISTINCT AlbumArtistIndex FROM Albumtable
|
||
|
INNER JOIN Tracktable USING (Albumindex) WHERE Albumname IS NOT NULL AND Uri IS NOT
|
||
|
NULL AND Hidden = 0 AND isSearchResult > 0) AS t", false, null, 'NumArtists', 0);
|
||
|
|
||
|
$numalbums = generic_sql_query(
|
||
|
"SELECT COUNT(*) AS NumAlbums FROM (SELECT DISTINCT Albumindex FROM Albumtable
|
||
|
INNER JOIN Tracktable USING (Albumindex) WHERE Albumname IS NOT NULL AND Uri IS NOT
|
||
|
NULL AND Hidden = 0 AND isSearchResult > 0) AS t", false, null, 'NumAlbums', 0);
|
||
|
|
||
|
$numtracks = generic_sql_query(
|
||
|
"SELECT COUNT(*) AS NumTracks FROM Tracktable WHERE Uri IS NOT NULL
|
||
|
AND Hidden=0 AND isSearchResult > 0", false, null, 'NumTracks', 0);
|
||
|
|
||
|
$numtime = generic_sql_query(
|
||
|
"SELECT SUM(Duration) AS TotalTime FROM Tracktable WHERE Uri IS NOT NULL AND
|
||
|
Hidden=0 AND isSearchResult > 0", false, null, 'TotalTime', 0);
|
||
|
|
||
|
print '<div class="brick brick_wide">';
|
||
|
print alistheader($numartists, $numalbums, $numtracks, format_time($numtime));
|
||
|
print '</div>';
|
||
|
|
||
|
}
|
||
|
|
||
|
function getItemsToAdd($which, $cmd = null) {
|
||
|
$a = preg_match('/(a|b|r|t|y|u|z)(.*?)(\d+|root)/', $which, $matches);
|
||
|
if (!$a) {
|
||
|
logger::fail("GETITEMSTOADD", "Regexp failed to match",$which);
|
||
|
return array();
|
||
|
}
|
||
|
$why = $matches[1];
|
||
|
$what = $matches[2];
|
||
|
$who = $matches[3];
|
||
|
switch ($what) {
|
||
|
case "artist":
|
||
|
return get_artist_tracks_from_database($who, $cmd, $why);
|
||
|
break;
|
||
|
|
||
|
case "album":
|
||
|
return get_album_tracks_from_database($who, $cmd, $why);
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
logger::fail("GETITEMSTOADD", "Unknown type",$which);
|
||
|
return array();
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function playAlbumFromTrack($uri) {
|
||
|
$retval = array('add "'.$uri.'"');
|
||
|
$result = sql_prepare_query(false, PDO::FETCH_OBJ, null, null, "SELECT Albumindex, TrackNo, Disc, isSearchResult FROM Tracktable WHERE Uri = ?", $uri);
|
||
|
$album = array_shift($result);
|
||
|
if ($album) {
|
||
|
$newsr = ($album->isSearchResult == 0) ? 2 : 3;
|
||
|
$retval = array();
|
||
|
$result = sql_prepare_query(false, PDO::FETCH_OBJ, null, null, "SELECT Uri FROM Tracktable WHERE Albumindex = ? AND ((Disc = ? AND TrackNo >= ?) OR (Disc > ?)) AND Hidden = 0 AND isSearchResult < ? ORDER BY Disc, TrackNo",
|
||
|
$album->Albumindex, $album->Disc, $album->TrackNo, $album->Disc, $newsr);
|
||
|
foreach ($result as $obj) {
|
||
|
$retval[] = 'add "'.$obj->Uri.'"';
|
||
|
}
|
||
|
|
||
|
}
|
||
|
return $retval;
|
||
|
}
|
||
|
|
||
|
function check_url_against_database($url, $itags, $rating) {
|
||
|
global $mysqlc;
|
||
|
if ($mysqlc === null) connect_to_database();
|
||
|
$qstring = "SELECT COUNT(t.TTindex) AS num FROM Tracktable AS t ";
|
||
|
$tags = array();
|
||
|
if ($itags !== null) {
|
||
|
$qstring .= "JOIN (SELECT DISTINCT TTindex FROM TagListtable JOIN Tagtable AS tag USING (Tagindex) WHERE";
|
||
|
$tagterms = array();
|
||
|
foreach ($itags as $tag) {
|
||
|
$tags[] = trim($tag);
|
||
|
$tagterms[] = " tag.Name LIKE ?";
|
||
|
}
|
||
|
$qstring .= implode(" OR",$tagterms);
|
||
|
$qstring .=") AS j ON j.TTindex = t.TTindex ";
|
||
|
}
|
||
|
if ($rating !== null) {
|
||
|
$qstring .= "JOIN (SELECT * FROM Ratingtable WHERE Rating >= ".$rating.") AS rat ON rat.TTindex = t.TTindex ";
|
||
|
}
|
||
|
$tags[] = $url;
|
||
|
$qstring .= "WHERE t.Uri = ?";
|
||
|
$count = sql_prepare_query(false, null, 'num', 0, $qstring, $tags);
|
||
|
if ($count > 0) {
|
||
|
return true;
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
function cleanSearchTables() {
|
||
|
// Clean up the database tables before performing a new search or updating the collection
|
||
|
|
||
|
logger::trace("MYSQL", "Cleaning Search Results");
|
||
|
// Any track that was previously hidden needs to be re-hidden
|
||
|
generic_sql_query("UPDATE Tracktable SET Hidden = 1, isSearchResult = 0 WHERE isSearchResult = 3", true);
|
||
|
|
||
|
// Any track that was previously a '2' (added to database as search result) but now
|
||
|
// has a playcount needs to become a zero and be hidden.
|
||
|
hide_played_tracks();
|
||
|
|
||
|
// remove any remaining '2's
|
||
|
generic_sql_query("DELETE FROM Tracktable WHERE isSearchResult = 2", true);
|
||
|
|
||
|
// Set '1's back to '0's
|
||
|
generic_sql_query("UPDATE Tracktable SET isSearchResult = 0 WHERE isSearchResult = 1", true);
|
||
|
|
||
|
// This may leave some orphaned albums and artists
|
||
|
remove_cruft();
|
||
|
|
||
|
//
|
||
|
// remove_cruft creates some temporary tables and we need to remove them because
|
||
|
// remove cruft will be called again later on if we're doing a collection update.
|
||
|
// Sadly, DROP TABLE runs into locking problems, at least with SQLite, so instead
|
||
|
// we close the DB connection and start again.
|
||
|
// So this function must be called BEFORE prepareCollectionUpdate, as that creates
|
||
|
// temporary tables of its own.
|
||
|
//
|
||
|
|
||
|
close_database();
|
||
|
sleep(1);
|
||
|
connect_to_database();
|
||
|
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Stuff to do with creating the database from a music collection (collection.php)
|
||
|
//
|
||
|
|
||
|
function collectionUpdateRunning() {
|
||
|
$cur = simple_query('Value', 'Statstable', 'Item', 'Updating', null);
|
||
|
switch ($cur) {
|
||
|
case null:
|
||
|
logger::warn('COLLECTION', 'Got null response to update lock check');
|
||
|
case '0':
|
||
|
generic_sql_query("UPDATE Statstable SET Value = 1 WHERE Item = 'Updating'", true);
|
||
|
return false;
|
||
|
|
||
|
case '1':
|
||
|
logger::warn('COLLECTION', 'Multiple collection updates attempted');
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function clearUpdateLock() {
|
||
|
generic_sql_query("UPDATE Statstable SET Value = 0 WHERE Item = 'Updating'", true);
|
||
|
}
|
||
|
|
||
|
function prepareCollectionUpdate() {
|
||
|
create_foundtracks();
|
||
|
prepare_findtracks();
|
||
|
open_transaction();
|
||
|
}
|
||
|
|
||
|
function prepare_findtracks() {
|
||
|
global $find_track, $update_track;
|
||
|
if ($find_track = sql_prepare_query_later(
|
||
|
"SELECT TTindex, Disc, LastModified, Hidden, isSearchResult, Uri, isAudiobook FROM Tracktable WHERE Title=? AND ((Albumindex=? AND TrackNo=? AND Disc=?) OR (Artistindex=? AND Uri IS NULL))")) {
|
||
|
} else {
|
||
|
show_sql_error();
|
||
|
exit(1);
|
||
|
}
|
||
|
|
||
|
if ($update_track = sql_prepare_query_later(
|
||
|
"UPDATE Tracktable SET LinkChecked=0, Trackno=?, Duration=?, Disc=?, LastModified=?, Uri=?, Albumindex=?, isSearchResult=?, isAudiobook=?, Hidden=0, justAdded=1 WHERE TTindex=?")) {
|
||
|
} else {
|
||
|
show_sql_error();
|
||
|
exit(1);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function remove_findtracks() {
|
||
|
global $find_track, $update_track;
|
||
|
$find_track = null;
|
||
|
$update_track = null;
|
||
|
}
|
||
|
|
||
|
function tidy_database() {
|
||
|
// Find tracks that have been removed
|
||
|
logger::debug("TIMINGS", "Starting Cruft Removal");
|
||
|
$now = time();
|
||
|
logger::trace("MYSQL", "Finding tracks that have been deleted");
|
||
|
generic_sql_query("DELETE FROM Tracktable WHERE LastModified IS NOT NULL AND Hidden = 0 AND justAdded = 0", true);
|
||
|
remove_cruft();
|
||
|
update_stat('ListVersion',ROMPR_COLLECTION_VERSION);
|
||
|
update_track_stats();
|
||
|
$dur = format_time(time() - $now);
|
||
|
logger::debug("TIMINGS", "Cruft Removal Took ".$dur);
|
||
|
logger::debug("TIMINGS", "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
|
||
|
close_transaction();
|
||
|
}
|
||
|
|
||
|
function create_foundtracks() {
|
||
|
// The order of these is VERY IMPORTANT!
|
||
|
// Also the WHERE (thing) = 1 is important otherwise, at least with MySQL, it sets EVERY ROW to 0
|
||
|
// whether or not it's already 0. That takes a very long time
|
||
|
generic_sql_query("UPDATE Tracktable SET justAdded = 0 WHERE justAdded = 1", true);
|
||
|
generic_sql_query("UPDATE Albumtable SET justUpdated = 0 WHERE justUpdated = 1", true);
|
||
|
}
|
||
|
|
||
|
function remove_cruft() {
|
||
|
logger::log("MYSQL", "Removing orphaned albums");
|
||
|
$t = microtime(true);
|
||
|
generic_sql_query("DELETE FROM Albumtable WHERE Albumindex NOT IN (SELECT DISTINCT Albumindex FROM Tracktable)", true);
|
||
|
$at = microtime(true) - $t;
|
||
|
logger::debug("TIMINGS", " -- Removing orphaned albums took ".$at." seconds");
|
||
|
|
||
|
logger::log("MYSQL", "Removing orphaned artists");
|
||
|
$t = microtime(true);
|
||
|
delete_orphaned_artists();
|
||
|
$at = microtime(true) - $t;
|
||
|
logger::debug("TIMINGS", " -- Removing orphaned artists took ".$at." seconds");
|
||
|
|
||
|
logger::log("MYSQL", "Tidying Metadata");
|
||
|
$t = microtime(true);
|
||
|
generic_sql_query("DELETE FROM Ratingtable WHERE Rating = '0'", true);
|
||
|
generic_sql_query("DELETE FROM Ratingtable WHERE TTindex NOT IN (SELECT TTindex FROM Tracktable WHERE Hidden = 0)", true);
|
||
|
generic_sql_query("DELETE FROM TagListtable WHERE TTindex NOT IN (SELECT TTindex FROM Tracktable WHERE Hidden = 0)", true);
|
||
|
// Temporary table needed because we can't use an IN clause as it conflicts with a trigger
|
||
|
generic_sql_query("CREATE TEMPORARY TABLE used_tags AS SELECT DISTINCT Tagindex FROM TagListtable", true);
|
||
|
generic_sql_query("DELETE FROM Tagtable WHERE Tagindex NOT IN (SELECT Tagindex FROM used_tags)", true);
|
||
|
generic_sql_query("DELETE FROM Playcounttable WHERE Playcount = '0'", true);
|
||
|
generic_sql_query("DELETE FROM Playcounttable WHERE TTindex NOT IN (SELECT TTindex FROM Tracktable)", true);
|
||
|
$at = microtime(true) - $t;
|
||
|
logger::debug("TIMINGS", " -- Tidying metadata took ".$at." seconds");
|
||
|
}
|
||
|
|
||
|
function do_track_by_track($trackobject) {
|
||
|
|
||
|
// Tracks must have disc and albumartist tags to be handled by this method.
|
||
|
// Loads of static variables to speed things up - we don't have to look things up every time.
|
||
|
|
||
|
static $current_albumartist = null;
|
||
|
static $current_album = null;
|
||
|
static $current_domain = null;
|
||
|
static $current_albumlink= null;
|
||
|
static $albumobj = null;
|
||
|
|
||
|
if ($trackobject === null) {
|
||
|
if ($albumobj !== null) {
|
||
|
$albumobj->check_database();
|
||
|
$albumobj = null;
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
$artistname = $trackobject->get_sort_artist();
|
||
|
|
||
|
if ($albumobj === null ||
|
||
|
$current_albumartist != $artistname ||
|
||
|
$current_album != $trackobject->tags['Album'] ||
|
||
|
$current_domain != $trackobject->tags['domain'] ||
|
||
|
($trackobject->tags['X-AlbumUri'] != null && $trackobject->tags['X-AlbumUri'] != $current_albumlink)) {
|
||
|
if ($albumobj !== null) {
|
||
|
$albumobj->check_database();
|
||
|
}
|
||
|
$albumobj = new album($trackobject);
|
||
|
} else {
|
||
|
$albumobj->newTrack($trackobject);
|
||
|
}
|
||
|
|
||
|
$current_albumartist = $artistname;
|
||
|
$current_album = $albumobj->name;
|
||
|
$current_domain = $albumobj->domain;
|
||
|
$current_albumlink = $albumobj->uri;
|
||
|
|
||
|
}
|
||
|
|
||
|
function check_and_update_track($trackobj, $albumindex, $artistindex, $artistname) {
|
||
|
global $find_track, $update_track, $numdone, $prefs, $doing_search;
|
||
|
static $current_trackartist = null;
|
||
|
static $trackartistindex = null;
|
||
|
$ttid = null;
|
||
|
$lastmodified = null;
|
||
|
$hidden = 0;
|
||
|
$disc = 0;
|
||
|
$uri = null;
|
||
|
$issearchresult = 0;
|
||
|
$isaudiobook = 0;
|
||
|
|
||
|
// Why are we not checking by URI? That should be unique, right?
|
||
|
// Well, er. no. They're not.
|
||
|
// Especially Spotify returns the same URI multiple times if it's in mutliple playlists
|
||
|
// We CANNOT HANDLE that. Nor do we want to.
|
||
|
|
||
|
// The other advantage of this is that we can put an INDEX on Albumindex, TrackNo, and Title,
|
||
|
// which we can't do with Uri cos it's too long - this speeds the whole process up by a factor
|
||
|
// of about 32 (9 minutes when checking by URI vs 15 seconds this way, on my collection)
|
||
|
// Also, URIs might change if the user moves his music collection.
|
||
|
|
||
|
if ($prefs['collection_type'] == "sqlite") {
|
||
|
// Lord knows why, but we have to re-prepare these every single bloody time!
|
||
|
prepare_findtracks();
|
||
|
}
|
||
|
|
||
|
if ($find_track->execute(array($trackobj->tags['Title'], $albumindex, $trackobj->tags['Track'],$trackobj->tags['Disc'],$artistindex))) {
|
||
|
while ($obj = $find_track->fetch(PDO::FETCH_OBJ)) {
|
||
|
$ttid = $obj->TTindex;
|
||
|
$lastmodified = $obj->LastModified;
|
||
|
$hidden = $obj->Hidden;
|
||
|
$disc = $obj->Disc;
|
||
|
$issearchresult = $obj->isSearchResult;
|
||
|
$uri = $obj->Uri;
|
||
|
$isaudiobook = $obj->isAudiobook;
|
||
|
break;
|
||
|
}
|
||
|
} else {
|
||
|
show_sql_error();
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
// NOTE: It is imperative that the search results have been tidied up -
|
||
|
// i.e. there are no 1s or 2s in the database before we do a collection update
|
||
|
|
||
|
// When doing a search, we MUST NOT change lastmodified of any track, because this will cause
|
||
|
// user-added tracks to get a lastmodified date, and lastmodified == NULL
|
||
|
// is how we detect user-added tracks and prevent them being deleted on collection updates
|
||
|
|
||
|
// Note the use of === to detect LastModified, because == doesn't tell the difference between 0 and null
|
||
|
// - so if we have a manually added track and then add a collection track over it from a backend that doesn't
|
||
|
// give us LastModified (eg Spotify-Web), we don't update lastModified and the track remains manually added.
|
||
|
|
||
|
if ($ttid) {
|
||
|
if ((!$doing_search && $trackobj->tags['Last-Modified'] !== $lastmodified) ||
|
||
|
($doing_search && $issearchresult == 0) ||
|
||
|
($trackobj->tags['Disc'] != $disc && $trackobj->tags['Disc'] !== '') ||
|
||
|
$hidden != 0 ||
|
||
|
($trackobj->tags['type'] == 'audiobook' && $isaudiobook == 0) ||
|
||
|
($trackobj->tags['type'] != 'audiobook' && $isaudiobook == 1) ||
|
||
|
$trackobj->tags['file'] != $uri) {
|
||
|
|
||
|
//
|
||
|
// Lots of debug output
|
||
|
//
|
||
|
|
||
|
if ($prefs['debug_enabled'] > 6) {
|
||
|
logger::log("MYSQL", " Updating track with ttid $ttid because :");
|
||
|
|
||
|
if (!$doing_search && $lastmodified === null) logger::log("MYSQL", " LastModified is not set in the database");
|
||
|
if (!$doing_search && $trackobj->tags['Last-Modified'] === null) logger::log("MYSQL", " TrackObj LastModified is NULL too!");
|
||
|
if (!$doing_search && $lastmodified !== $trackobj->tags['Last-Modified']) logger::log("MYSQL", " LastModified has changed: We have ".$lastmodified." but track has ".$trackobj->tags['Last-Modified']);
|
||
|
if ($disc != $trackobj->tags['Disc']) logger::log("MYSQL", " Disc Number has changed: We have ".$disc." but track has ".$trackobj->tags['Disc']);
|
||
|
if ($hidden != 0) logger::log("MYSQL", " It is hidden");
|
||
|
if ($trackobj->tags['type'] == 'audiobook' && $isaudiobook == 0) logger::log("MYSQL", " It needs to be marked as an Auidiobook");
|
||
|
if ($trackobj->tags['type'] != 'audiobook' && $isaudiobook == 1) logger::log("MYSQL", " It needs to be un-marked as an Audiobook");
|
||
|
if ($trackobj->tags['file'] != $uri) {
|
||
|
logger::log("MYSQL", " Uri has changed from : ".$uri);
|
||
|
logger::log("MYSQL", " to : ".$trackobj->tags['file']);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// End of debug output
|
||
|
//
|
||
|
|
||
|
$newsearchresult = 0;
|
||
|
if ($doing_search) {
|
||
|
// Sometimes spotify search returns the same track with multiple URIs. This means we update the track
|
||
|
// when we get the second one and isSearchResult gets set to zero unless we do this.
|
||
|
$newsearchresult = $issearchresult;
|
||
|
}
|
||
|
$newlastmodified = $trackobj->tags['Last-Modified'];
|
||
|
if ($issearchresult == 0 && $doing_search) {
|
||
|
$newsearchresult = ($hidden != 0) ? 3 : 1;
|
||
|
logger::log("MYSQL", " It needs to be marked as a search result : Value ".$newsearchresult);
|
||
|
$newlastmodified = $lastmodified;
|
||
|
}
|
||
|
$newisaudiobook = $trackobj->tags['type'] == 'audiobook' ? 1 : 0;
|
||
|
if ($update_track->execute(array($trackobj->tags['Track'], $trackobj->tags['Time'], $trackobj->tags['Disc'],
|
||
|
$newlastmodified, $trackobj->tags['file'], $albumindex, $newsearchresult, $newisaudiobook, $ttid))) {
|
||
|
$numdone++;
|
||
|
} else {
|
||
|
show_sql_error();
|
||
|
}
|
||
|
} else {
|
||
|
generic_sql_query("UPDATE Tracktable SET justAdded = 1 WHERE TTindex = ".$ttid, true);
|
||
|
}
|
||
|
} else {
|
||
|
$a = $trackobj->get_artist_string();
|
||
|
if ($a != $current_trackartist || $trackartistindex == null) {
|
||
|
if ($artistname != $a && $a != null) {
|
||
|
$trackartistindex = check_artist($a);
|
||
|
} else {
|
||
|
$trackartistindex = $artistindex;
|
||
|
}
|
||
|
}
|
||
|
if ($trackartistindex == null) {
|
||
|
logger::error("MYSQL_TBT", "ERROR! Trackartistindex is still null!");
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
$current_trackartist = $a;
|
||
|
$sflag = ($doing_search) ? 2 : 0;
|
||
|
$params = array(
|
||
|
'title' => $trackobj->tags['Title'],
|
||
|
'artist' => null,
|
||
|
'trackno' => $trackobj->tags['Track'],
|
||
|
'duration' => $trackobj->tags['Time'],
|
||
|
'albumartist' => null,
|
||
|
'albumuri' => null,
|
||
|
'image' => null,
|
||
|
'album' => null,
|
||
|
'date' => null,
|
||
|
'uri' => $trackobj->tags['file'],
|
||
|
'trackai' => $trackartistindex,
|
||
|
'albumai' => $artistindex,
|
||
|
'albumindex' => $albumindex,
|
||
|
'searched' => null,
|
||
|
'imagekey' => null,
|
||
|
'lastmodified' => $trackobj->tags['Last-Modified'],
|
||
|
'disc' => $trackobj->tags['Disc'],
|
||
|
'ambid' => null,
|
||
|
'domain' => null,
|
||
|
'hidden' => 0,
|
||
|
'searchflag' => $sflag,
|
||
|
'isaudiobook' => $trackobj->tags['type'] == 'audiobook' ? 1 : 0
|
||
|
);
|
||
|
$ttid = create_new_track($params);
|
||
|
$numdone++;
|
||
|
}
|
||
|
check_transaction();
|
||
|
if ($ttid == null) {
|
||
|
logger::error("MYSQL", "ERROR! No ttid for track ".$trackobj->tags['file']);
|
||
|
logger::error("MYSQL", "Parameters were : ");
|
||
|
logger::error("MYSQL", " Title : ".$trackobj->tags['Title']);
|
||
|
logger::error("MYSQL", " Track : ".$trackobj->tags['Track']);
|
||
|
logger::error("MYSQL", " Time : ".$trackobj->tags['Time']);
|
||
|
logger::error("MYSQL", " file : ".$trackobj->tags['file']);
|
||
|
logger::error("MYSQL", " trackartistindex : ".$trackartistindex);
|
||
|
logger::error("MYSQL", " artistindex : ".$artistindex);
|
||
|
logger::error("MYSQL", " albumindex : ".$albumindex);
|
||
|
logger::error("MYSQL", " Last-Modified : ".$trackobj->tags['Last-Modified']);
|
||
|
logger::error("MYSQL", " Disc : ".$trackobj->tags['Disc']);
|
||
|
logger::error("MYSQL", " sflag : ".$sflag);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
?>
|