astrXbian/www/jukebox/player/mopidy/player.php

381 lines
15 KiB
PHP

<?php
require_once ('player/mpd/mpdinterface.php');
$PLAYER_TYPE = 'mopidyPlayer';
class mopidyPlayer extends base_mpd_player {
private $monitor;
public function check_track_load_command($uri) {
return 'add';
}
function musicCollectionUpdate() {
global $prefs;
logger::blurt("MOPIDY", "Starting Music Collection Update");
$collection = new musicCollection();
$this->monitor = fopen('prefs/monitor','w');
$dirs = $prefs['mopidy_collection_folders'];
while (count($dirs) > 0) {
$dir = array_shift($dirs);
if ($dir == "Spotify Playlists") {
$this->musicCollectionSpotifyPlaylistHack();
} else {
fwrite($this->monitor, "\n<b>".get_int_text('label_scanningf', array($dir))."</b><br />".get_int_text('label_fremaining', array(count($dirs))));
foreach ($this->parse_list_output('lsinfo "'.format_for_mpd($this->local_media_check($dir)).'"', $dirs, false) as $filedata) {
$collection->newTrack($filedata);
}
$collection->tracks_to_database();
}
}
saveCollectionPlayer('mopidy');
fwrite($this->monitor, "\nUpdating Database");
}
private function musicCollectionSpotifyPlaylistHack() {
$dirs = array();
$playlists = $this->do_mpd_command("listplaylists", true, true);
if (is_array($playlists) && array_key_exists('playlist', $playlists)) {
$collection = new musicCollection();
foreach ($playlists['playlist'] as $pl) {
if (preg_match('/\(by spotify\)/', $pl)) {
logger::log("COLLECTION", "Ignoring Playlist ".$pl);
} else {
logger::log("COLLECTION", "Scanning Playlist ".$pl);
fwrite($this->monitor, "\n<b>".get_int_text('label_scanningp', array($pl))."</b>");
foreach ($this->parse_list_output('listplaylistinfo "'.format_for_mpd($pl).'"', $dirs, false) as $filedata) {
$collection->newTrack($filedata);
}
$collection->tracks_to_database();
}
}
}
}
public function collectionUpdateDone() {
fwrite($this->monitor, "\nRompR Is Done");
fclose($this->monitor);
}
private function local_media_check($dir) {
if ($dir == "Local media") {
// Mopidy-Local-SQlite contains a virtual tree sorting things by various keys
// If we scan the whole thing we scan every file about 8 times. This is stoopid.
// Check to see if 'Local media/Albums' is browseable and use that instead if it is.
// Using Local media/Folders causes every file to be re-scanned every time we update
// the collection, which takes ages and also includes m3u and pls stuff that we don't want
$r = $this->do_mpd_command('lsinfo "'.$dir.'/Albums"', false, false);
if ($r === false) {
return $dir;
} else {
return $dir.'/Albums';
}
}
return $dir;
}
protected function player_specific_fixups(&$filedata) {
global $prefs;
if (strpos($filedata['file'], ':artist:') !== false) {
$filedata['X-AlbumUri'] = $filedata['file'];
$filedata['Album'] = get_int_text("label_allartist").concatenate_artist_names($filedata['Artist']);
$filedata['Disc'] = 0;
$filedata['Track'] = 0;
} else if (strpos($filedata['file'], ':album:') !== false) {
$filedata['X-AlbumUri'] = $filedata['file'];
$filedata['Disc'] = 0;
$filedata['Track'] = 0;
}
switch($filedata['domain']) {
case 'local':
// mopidy-local-sqlite sets album URIs for local albums, but sometimes it gets it very wrong
// We don't need Album URIs for local tracks, since we can already add an entire album
$filedata['X-AlbumUri'] = null;
$this->check_undefined_tags($filedata);
$filedata['folder'] = dirname($filedata['unmopfile']);
if ($prefs['audiobook_directory'] != '') {
$f = rawurldecode($filedata['folder']);
if (strpos($f, $prefs['audiobook_directory']) === 0) {
$filedata['type'] = 'audiobook';
}
}
break;
case 'http':
case 'https':
case 'mms':
case 'mmsh':
case 'mmst':
case 'mmsu':
case 'gopher':
case 'rtp':
case 'rtsp':
case 'rtmp':
case 'rtmpt':
case 'rtmps':
case 'dirble':
case 'tunein':
case 'radio-de':
case 'audioaddict':
case 'oe1':
case 'bassdrive':
$this->preprocess_stream($filedata);
break;
case "soundcloud":
$this->preprocess_soundcloud($filedata);
break;
case "youtube":
$filedata['folder'] = $filedata['file'];
$filedata['Artist'] = ($filedata['Artist'] == null) ? munge_youtube_track_into_artist($filedata['Title']) : $filedata['Artist'];
$filedata['Album'] = $this->munge_youtube_track_into_album($filedata['Title']);
$filedata['Title'] = $this->munge_youtube_track_into_title($filedata['Title']);
$filedata['AlbumArtist'] = $filedata['Artist'];
$filedata['X-AlbumUri'] = $filedata['file'];
break;
case "spotify":
$filedata['folder'] = $filedata['X-AlbumUri'];
break;
case "internetarchive":
$this->check_undefined_tags($filedata);
$filedata['X-AlbumUri'] = $filedata['file'];
$filedata['folder'] = $filedata['file'];
$filedata['AlbumArtist'] = "Internet Archive";
break;
case "podcast":
$filedata['folder'] = $filedata['X-AlbumUri'];
if ($filedata['Artist'] !== null) {
$filedata['AlbumArtist'] = $filedata['Artist'];
}
if ($filedata['AlbumArtist'] === null) {
$filedata['AlbumArtist'] = array("Podcasts");
}
if (is_array($filedata['Artist']) &&
($filedata['Artist'][0] == "http" ||
$filedata['Artist'][0] == "https" ||
$filedata['Artist'][0] == "ftp" ||
$filedata['Artist'][0] == "file" ||
substr($filedata['Artist'][0],0,7) == "podcast")) {
$filedata['Artist'] = $filedata['AlbumArtist'];
}
$filedata['type'] = 'podcast';
break;
default:
check_undefined_tags($filedata);
$filedata['folder'] = dirname($filedata['unmopfile']);
break;
}
}
private function munge_youtube_track_into_artist($t) {
// Risky, but mopidy-youtube doesn't return artists (for obvious reasons)
if (preg_match('/^(.*?)\s*[-|\|+]\s*/', $t, $matches)) {
if ($matches[1] !== "") {
return array($matches[1]);
} else {
return array("Youtube");
}
} else {
return array("Youtube");
}
}
private function munge_youtube_track_into_album($t) {
// Even riskier, but mopidy-youtube doesn't return albums except 'Youtube' (for obvious reasons)
if (preg_match('/^.*?\s*[-|\|+]\s*(.*?)\s+[-|\|+]\s+/', $t, $matches)) {
if ($matches[1] !== "") {
return $matches[1];
}
}
if (preg_match('/^.*?\s*[-|\|+]\s*(.*?)\s+[\(|\[]*full album[\)|\]]*/i', $t, $matches)) {
if ($matches[1] !== "") {
return $matches[1];
}
}
return "Youtube";
}
private function munge_youtube_track_into_title($t) {
// Risky as fuck!
if (preg_match('/^.*?\s*[-|\|+]\s*.*?\s+[-|\|+]\s+(.*?)$/', $t, $matches)) {
return $matches[1];
} else {
return $t;
}
}
private function preprocess_stream(&$filedata) {
$filedata['Track'] = null;
list ( $filedata['Title'],
$filedata['Time'],
$filedata['Artist'],
$filedata['Album'],
$filedata['folder'],
$filedata['type'],
$filedata['X-AlbumImage'],
$filedata['station'],
$filedata['stream'],
$filedata['AlbumArtist'],
$filedata['StreamIndex'],
$filedata['Comment'],
$filedata['ImgKey']) = $this->check_radio_and_podcasts($filedata);
if (strrpos($filedata['file'], '#') !== false) {
# Fave radio stations added by Cantata/MPDroid
$filedata['Album'] = substr($filedata['file'], strrpos($filedata['file'], '#')+1, strlen($filedata['file']));
}
if (strpos($filedata['file'], 'bassdrive.com') !== false) {
$filedata['Album'] = 'Bassdrive';
}
// Mopidy's podcast backend
if ($filedata['Genre'] == "Podcast") {
$filedata['type'] = "podcast";
}
}
private function preprocess_soundcloud(&$filedata) {
$filedata['folder'] = concatenate_artist_names($filedata['Artist']);
$filedata['AlbumArtist'] = $filedata['Artist'];
$filedata['X-AlbumUri'] = $filedata['file'];
$filedata['Album'] = $filedata['Title'];
$filedata['X-AlbumImage'] = 'getRemoteImage.php?url='.$filedata['X-AlbumImage'];
}
private function check_radio_and_podcasts($filedata) {
$url = $filedata['file'];
// Do podcasts first. Podcasts played fro TuneIn get added as radio stations, and then if we play that track again
// via podcasts we want to make sure we pick up the details.
$result = find_podcast_track_from_url($url);
foreach ($result as $obj) {
logger::log("STREAMHANDLER", "Found PODCAST",$obj->title);
return array(
($obj->title == '') ? $filedata['Title'] : $obj->title,
// Mopidy's estimate of the duration is frequently more accurate than that supplied in the RSS
(array_key_exists('Time', $filedata) && $filedata['Time'] > 0) ? $filedata['Time'] : $obj->duration,
($obj->artist == '') ? $filedata['Artist'] : array($obj->artist),
($obj->album == '') ? $filedata['Album'] : $obj->album,
md5($obj->album),
'podcast',
$obj->image,
null,
'',
($obj->albumartist == '') ? $filedata['AlbumArtist'] : array($obj->albumartist),
null,
format_text(fixup_links($obj->comment)),
null
);
}
$result = find_radio_track_from_url($url);
foreach ($result as $obj) {
logger::log("STREAMHANDLER", "Found Radio Station ".$obj->StationName);
// Munge munge munge to make it looks pretty
if ($obj->StationName != '') {
logger::log("STREAMHANDLER", " Setting Album name from database ".$obj->StationName);
$album = $obj->StationName;
} else if ($filedata['Name'] && $filedata['Name'] != 'no name' && strpos($filedata['Name'], ' ') !== false) {
logger::log("STREAMHANDLER", " Setting Album from Name ".$filedata['Name']);
$album = $filedata['Name'];
} else if ($filedata['Name'] == null && $filedata['Title'] != null && $filedata['Title'] != 'no name' &&
$filedata['Artist'] == null && $filedata['Album'] == null && strpos($filedata['Title'], ' ') !== false) {
logger::log("STREAMHANDLER", " Setting Album from Title ".$filedata['Title']);
$album = $filedata['Title'];
$filedata['Title'] = null;
} else {
logger::log("STREAMHANDLER", " No information to set Album field");
$album = ROMPR_UNKNOWN_STREAM;
}
return array (
$filedata['Title'] === null ? '' : $filedata['Title'],
0,
$filedata['Artist'],
$album,
$obj->PlaylistUrl,
"stream",
($obj->Image == '') ? $filedata['X-AlbumImage'] : $obj->Image,
getDummyStation($url),
$obj->PrettyStream,
$filedata['AlbumArtist'],
$obj->Stationindex,
array_key_exists('Comment', $filedata) ? $filedata['Comment'] : '',
null
);
}
logger::fail("STREAMHANDLER", "Stream Track",$filedata['file'],"from",$filedata['domain'],"was not found in database");
if ($filedata['Album']) {
$album = $filedata['Album'];
} else if ($filedata['Name']) {
logger::log("STREAMHANDLER", " Setting Album from Name ".$filedata['Name']);
$album = $filedata['Name'];
if ($filedata['Pos'] !== null) {
update_radio_station_name(array('streamid' => null,'uri' => $filedata['file'], 'name' => $album));
}
} else if ($filedata['Name'] == null && $filedata['Title'] != null && $filedata['Artist'] == null && $filedata['Album'] == null) {
logger::log("STREAMHANDLER", " Setting Album from Title ".$filedata['Title']);
$album = $filedata['Title'];
$filedata['Title'] = null;
if ($filedata['Pos'] !== null) {
update_radio_station_name(array('streamid' => null,'uri' => $filedata['file'], 'name' => $album));
}
} else {
logger::log("STREAMHANDLER", " No information to set Album field");
$album = ROMPR_UNKNOWN_STREAM;
}
return array(
$filedata['Title'],
0,
$filedata['Artist'],
$album,
getStreamFolder(unwanted_array($url)),
"stream",
($filedata['X-AlbumImage'] == null) ? '' : $filedata['X-AlbumImage'],
getDummyStation(unwanted_array($url)),
null,
$filedata['AlbumArtist'],
null,
array_key_exists('Comment', $filedata) ? $filedata['Comment'] : '',
null
);
}
public function get_checked_url($url) {
return array('clicktrack', $url);
}
public function get_replay_gain_state() {
return array();
}
public static function is_personal_playlist($pl) {
if (preg_match('/ \(by/i', $pl)) {
// Don't permit deletion of tracks from other peple's playlists (Spotify)
return false;
}
return true;
}
}
?>