292 lines
12 KiB
PHP
292 lines
12 KiB
PHP
<?php
|
|
chdir('../..');
|
|
require_once ("includes/vars.php");
|
|
require_once ("includes/functions.php");
|
|
require_once ("player/".$prefs['player_backend']."/player.php");
|
|
require_once ("collection/collection.php");
|
|
require_once ('backends/sql/backend.php');
|
|
$mpd_status = array();
|
|
$playlist_movefrom = null;
|
|
$playlist_moveto = null;
|
|
$playlist_moving_within = null;
|
|
$playlist_tracksadded = 0;
|
|
$expected_state = null;
|
|
$do_resume_seek = false;
|
|
$do_resume_seek_id = false;
|
|
$moveallto = null;
|
|
$current_playlist_length = 0;
|
|
$player = new $PLAYER_TYPE();
|
|
|
|
if ($player->is_connected()) {
|
|
|
|
$cmd_status = true;
|
|
|
|
$cmds = array();
|
|
|
|
//
|
|
// Assemble and format the command list and perform any command-specific backend actions
|
|
//
|
|
|
|
$json = json_decode(file_get_contents("php://input"));
|
|
|
|
if ($json) {
|
|
|
|
foreach ($json as $cmd) {
|
|
|
|
logger::trace("POSTCOMMAND", "RAW command : ".implode(' ', $cmd));
|
|
|
|
switch ($cmd[0]) {
|
|
case "addtoend":
|
|
logger::trace("POSTCOMMAND", "Addtoend ".$cmd[1]);
|
|
$cmds = array_merge($cmds, playAlbumFromTrack($cmd[1]));
|
|
break;
|
|
|
|
case 'playlisttoend':
|
|
logger::trace("POSTCOMMAND", "Playing playlist ".$cmd[1]." from position ".$cmd[2]." to end");
|
|
foreach($player->get_stored_playlist_tracks($cmd[1], $cmd[2]) as list($class, $uri, $filedata)) {
|
|
if ($class == 'clicktrack') {
|
|
$cmds[] = 'add "'.$uri.'"';
|
|
} else {
|
|
$cmds[] = 'load "'.$uri.'"';
|
|
}
|
|
}
|
|
break;
|
|
|
|
case "additem":
|
|
logger::trace("POSTCOMMAND", "Adding Item ".$cmd[1]);
|
|
$cmds = array_merge($cmds, getItemsToAdd($cmd[1], null));
|
|
break;
|
|
|
|
case "addartist":
|
|
logger::trace("MPD", "Getting tracks for Artist ".$cmd[1]);
|
|
$cmds = array_merge($cmds, $player->get_tracks_for_spotify_artist($cmd[1]));
|
|
break;
|
|
|
|
case "loadstreamplaylist":
|
|
require_once ("player/".$prefs['player_backend']."/streamplaylisthandler.php");
|
|
require_once ("utils/getInternetPlaylist.php");
|
|
$cmds = array_merge($cmds, load_internet_playlist($cmd[1], $cmd[2], $cmd[3]));
|
|
break;
|
|
|
|
case "addremoteplaylist":
|
|
logger::log("POSTCOMMAND", "Remote Playlist URL is",$cmd[1]);
|
|
// First, see if we can just 'load' the remote playlist. This is better with MPD
|
|
// as it parses track names from the playlist
|
|
if (check_track_load_command($cmd[1]) == 'load') {
|
|
logger::log("POSTCOMMAND", "Loading remote playlist");
|
|
$cmds[] = join_command_string(array('load', $cmd[1]));
|
|
} else {
|
|
// Always use the MPD version of the stream playlist handler, since that parses
|
|
// all tracks (Mopidy's version doesn't because we use Mopidy's playlist parser instead).
|
|
// Perversely, we need to use this because we can't use 'load' on a remote playlist with Mopidy,
|
|
// and 'add' only adds the first track. As user remtote playlists can have multiple types of
|
|
// thing in them, including streams, we need to 'add' every track - unless we're using mpd and
|
|
// the 'track' is a playlist we need to load..... Crikey.
|
|
logger::log("POSTCOMMAND", "Adding remote playlist (track by track)");
|
|
require_once ("player/mpd/streamplaylisthandler.php");
|
|
require_once ("utils/getInternetPlaylist.php");
|
|
$tracks = load_internet_playlist($cmd[1], '', '', true);
|
|
foreach ($tracks as $track) {
|
|
$cmd = check_track_load_command($track['TrackUri']);
|
|
$cmds[] = join_command_string(array($cmd, $track['TrackUri']));
|
|
}
|
|
}
|
|
break;
|
|
|
|
case "rename":
|
|
require_once ('utils/imagefunctions.php');
|
|
$oldimage = new albumImage(array('artist' => 'PLAYLIST', 'album' => $cmd[1]));
|
|
$oldimage->change_name($cmd[2]);
|
|
$cmds[] = join_command_string($cmd);
|
|
break;
|
|
|
|
case "playlistadd":
|
|
if (preg_match('/[ab]album\d+|[ab]artist\d+/', $cmd[2])) {
|
|
$lengthnow = count($cmds);
|
|
$cmds = array_merge($cmds, getItemsToAdd($cmd[2], $cmd[0].' "'.format_for_mpd($cmd[1]).'"'));
|
|
check_playlist_add_move($cmd, (count($cmds) - $lengthnow));
|
|
} else {
|
|
$cmds[] = join_command_string(array($cmd[0], $cmd[1], $cmd[2]));
|
|
check_playlist_add_move($cmd, 1);
|
|
}
|
|
break;
|
|
|
|
case "moveallto":
|
|
$moveallto = $cmd[1];
|
|
$temp_status = $player->get_status();
|
|
if (array_key_exists('playlistlength', $temp_status)) {
|
|
$current_playlist_length = $temp_status['playlistlength'];
|
|
}
|
|
break;
|
|
|
|
case "playlistadddir":
|
|
$thing = array('searchaddpl',$cmd[1],'base',$cmd[2]);
|
|
$cmds[] = join_command_string($thing);
|
|
break;
|
|
|
|
case "resume":
|
|
logger::log("POSTCOMMAND", "Adding Track ".$cmd[1]);
|
|
logger::log("POSTCOMMAND", " .. and seeking position ".$cmd[3]." to ".$cmd[2]);
|
|
$cmds[] = join_command_string(array('add', rawurldecode($cmd[1])));
|
|
$cmds[] = join_command_string(array('play', $cmd[3]));
|
|
$expected_state = 'play';
|
|
$do_resume_seek = array($cmd[3], $cmd[2]);
|
|
break;
|
|
|
|
case "seekpodcast":
|
|
$expected_state = 'play';
|
|
$do_resume_seek_id = array($cmd[1], $cmd[2]);
|
|
break;
|
|
|
|
case 'save':
|
|
case 'rm':
|
|
case "load":
|
|
$cmds[] = join_command_string($cmd);
|
|
break;
|
|
|
|
case "clear":
|
|
$cmds[] = join_command_string($cmd);
|
|
break;
|
|
|
|
case "play":
|
|
case "playid":
|
|
$expected_state = 'play';
|
|
// Fall through
|
|
default:
|
|
$cmds[] = join_command_string($cmd);
|
|
break;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// If we added tracks to a STORED playlist, move them into the correct position
|
|
//
|
|
|
|
while ($playlist_tracksadded > 0 && $playlist_movefrom !== null && $playlist_moveto !== null) {
|
|
$cmds[] = join_command_string(array('playlistmove', $playlist_moving_within, $playlist_movefrom, $playlist_moveto));
|
|
$playlist_moveto++;
|
|
$playlist_movefrom++;
|
|
$playlist_tracksadded--;
|
|
}
|
|
|
|
//
|
|
// Send the command list to mpd
|
|
//
|
|
|
|
$cmd_status = $player->do_command_list($cmds);
|
|
|
|
//
|
|
// If we added tracks to the playlist, move them into position if we need to
|
|
//
|
|
|
|
if ($moveallto !== null) {
|
|
logger::trace("MPD", "Moving Tracks into position");
|
|
$temp_status = $player->get_status();
|
|
$new_playlist_length = $temp_status['playlistlength'];
|
|
$player->do_command_list(array(join_command_string(array('move', $current_playlist_length.':'.$new_playlist_length, $moveallto))));
|
|
}
|
|
|
|
//
|
|
// Wait for the player to start playback if that's what it's supposed to be doing
|
|
//
|
|
|
|
$player->wait_for_state($expected_state);
|
|
|
|
//
|
|
// Work around mopidy play/seek command list bug
|
|
//
|
|
|
|
if ($do_resume_seek !== false) {
|
|
$player->do_command_list(array(join_command_string(array('seek', $do_resume_seek[0], $do_resume_seek[1]))));
|
|
}
|
|
if ($do_resume_seek_id !== false) {
|
|
$player->do_command_list(array(join_command_string(array('seekid', $do_resume_seek_id[0], $do_resume_seek_id[1]))));
|
|
}
|
|
|
|
//
|
|
// Query mpd's status
|
|
//
|
|
|
|
$mpd_status = $player->get_status();
|
|
|
|
//
|
|
// If we got an error from the command list and NOT from 'status',
|
|
// make sure we report the command list error back
|
|
//
|
|
|
|
if (is_array($cmd_status) && !array_key_exists('error', $mpd_status) && array_key_exists('error', $cmd_status)) {
|
|
logger::warn("POSTCOMMAND", "Command List Error",$cmd_status['error']);
|
|
$mpd_status = array_merge($mpd_status, $cmd_status);
|
|
}
|
|
|
|
//
|
|
// Add current song and replay gain status to mpd_status
|
|
// We use currentsong for streams. It is NOT merged with database data as the playlist data is
|
|
// so should not be used for metadata at any other point except for filename.
|
|
//
|
|
|
|
if (array_key_exists('song', $mpd_status) && !array_key_exists('error', $mpd_status)) {
|
|
$songinfo = $player->get_current_song();
|
|
if (is_array($songinfo)) {
|
|
$mpd_status = array_merge($mpd_status, $songinfo);
|
|
}
|
|
}
|
|
|
|
$mpd_status = array_merge($mpd_status, $player->get_replay_gain_state());
|
|
|
|
//
|
|
// Clear any player error now we've caught it
|
|
//
|
|
|
|
if (array_key_exists('error', $mpd_status)) {
|
|
logger::log("MPD", "Clearing Player Error ".$mpd_status['error']);
|
|
$player->clear_error();
|
|
}
|
|
|
|
//
|
|
// Disable 'single' if we're stopped or paused (single is used for 'Stop After Current Track')
|
|
//
|
|
|
|
if (array_key_exists('single', $mpd_status) && $mpd_status['single'] == 1 && array_key_exists('state', $mpd_status) &&
|
|
($mpd_status['state'] == "pause" || $mpd_status['state'] == "stop")) {
|
|
logger::trace("MPD", "Cancelling Single Mode");
|
|
$player->cancel_single_quietly();
|
|
$mpd_status['single'] = 0;
|
|
}
|
|
|
|
//
|
|
// Format any error message more nicely
|
|
//
|
|
|
|
if (array_key_exists('error', $mpd_status)) {
|
|
$mpd_status['error'] = preg_replace('/ACK \[.*?\]\s*/','',$mpd_status['error']);
|
|
}
|
|
|
|
} else {
|
|
$mpd_status['error'] = "Unable to Connect to ".$prefs['currenthost'];
|
|
}
|
|
|
|
$p = $prefs['currenthost'];
|
|
$mpd_status['radiomode'] = $prefs['multihosts']->{$p}->radioparams->radiomode;
|
|
$mpd_status['radioparam'] = $prefs['multihosts']->{$p}->radioparams->radioparam;
|
|
$mpd_status['radiomaster'] = $prefs['multihosts']->{$p}->radioparams->radiomaster;
|
|
$mpd_status['radioconsume'] = $prefs['multihosts']->{$p}->radioparams->radioconsume;
|
|
|
|
header('Content-Type: application/json');
|
|
echo json_encode($mpd_status);
|
|
|
|
function check_playlist_add_move($cmd, $incvalue) {
|
|
global $playlist_moving_within, $playlist_movefrom, $playlist_moveto, $playlist_tracksadded;
|
|
if ($cmd[3] == 0 || $cmd[3]) {
|
|
if ($playlist_moving_within === null) $playlist_moving_within = $cmd[1];
|
|
if ($playlist_movefrom === null) $playlist_movefrom = $cmd[4];
|
|
if ($playlist_moveto === null) $playlist_moveto = $cmd[3];
|
|
$playlist_tracksadded += $incvalue;
|
|
}
|
|
}
|
|
|
|
|
|
?>
|