public function cmd($cmd, $item = NULL) { // TODO: check access // @see: http://www.musicpd.org/doc/protocol/playback_commands.html // validate commands switch ($cmd) { case 'update': $config = \Slim\Slim::getInstance()->config['mpd']; # TODO: move 'disallow_full_database_update' from config.ini to user-previleges if (!$item && $config['disallow_full_database_update'] == '0') { return $this->mpd($cmd); } if (is_string($item) === TRUE) { $item = $item; } if (is_array($item) === TRUE) { $item = join(DS, $item); } if (is_file($config['musicdir'] . $item) === FALSE && is_dir($config['musicdir'] . $item) === FALSE) { // error - invalid $item return FALSE; } \Slimpd\importer::queDirectoryUpdate($item); return $this->mpd('update "' . str_replace("\"", "\\\"", $item) . '"'); // tracks that hasnt been importet in mpd database have to get inserted befor playing // TODO: should this also trigger a mysql-db-insert of this track? // TODO: should we allow this also for directories or limit this function to single music files? // tracks that hasnt been importet in mpd database have to get inserted befor playing // TODO: should this also trigger a mysql-db-insert of this track? // TODO: should we allow this also for directories or limit this function to single music files? case 'updateMpdAndPlay': $config = \Slim\Slim::getInstance()->config['mpd']; # TODO: move 'disallow_full_database_update' from config.ini to user-previleges if (!$item && $config['disallow_full_database_update'] == '0') { return $this->mpd($cmd); } if (is_string($item) === TRUE) { $item = $item; } if (is_array($item) === TRUE) { $item = join(DS, $item); } if (is_file($config['musicdir'] . $item) === FALSE) { // error - invalid $item or $item is a directory # TODO: send warning to client? return FALSE; } // now we have to find the nearest parent directory that already exists in mpd-database $closestExistingItemInMpdDatabase = $this->findClosestExistingItem($item); // special case when we try to play a single new file (without parent-dir) out of mpd root if ($closestExistingItemInMpdDatabase === NULL && $config['disallow_full_database_update'] == '1') { # TODO: send warning to client? return FALSE; } if ($closestExistingItemInMpdDatabase !== $item) { $this->cmd('update', $closestExistingItemInMpdDatabase); // TODO: replace dirty sleep with mpd-status-poll and continue as soon as the item is imported sleep(1); } return $this->cmd('addSelect', $item); case 'seekPercent': $currentSong = $this->mpd('currentsong'); $cmd = 'seek ' . $currentSong['Pos'] . ' ' . round($item * ($currentSong['Time'] / 100)) . ''; $this->mpd($cmd); case 'status': case 'stats': case 'currentsong': return $this->mpd($cmd); case 'play': case 'pause': case 'stop': case 'previous': case 'next': $this->mpd($cmd); break; case 'toggleRepeat': $status = $this->mpd('status'); $this->mpd('repeat ' . (int) ($status['repeat'] xor 1)); break; case 'toggleRandom': $status = $this->mpd('status'); $this->mpd('random ' . (int) ($status['random'] xor 1)); break; case 'toggleConsume': $status = $this->mpd('status'); $this->mpd('consume ' . (int) ($status['consume'] xor 1)); break; case 'playlistStatus': $this->playlistStatus(); break; case 'addSelect': # TODO: general handling of position to add # TODO: general handling of playing immediately or simply appending to playlist $path = ''; if (is_string($item) === TRUE) { $path = $item; } if (is_numeric($item) === TRUE) { $path = \Slimpd\Track::getInstanceByAttributes(array('id' => $item))->getRelativePath(); } if (is_array($item) === TRUE) { $path = join(DS, $item); } if (is_file(\Slim\Slim::getInstance()->config['mpd']['musicdir'] . $path) === TRUE) { $this->mpd('addid "' . str_replace("\"", "\\\"", $path) . '" 0'); $this->mpd('play 0'); } else { // trailing slash on directories will not work - lets remove it if (substr($path, -1) === DS) { $path = substr($path, 0, -1); } $this->mpd('add "' . str_replace("\"", "\\\"", $path) . '"'); } break; case 'playIndex': $this->mpd('play ' . $item); break; case 'deleteIndex': $this->mpd('delete ' . $item); break; case 'clearPlaylist': $this->mpd('clear'); break; case 'clearPlaylistNotCurrent': $status = $this->mpd('status'); $songId = isset($status['songid']) ? $status['songid'] : 0; if ($songId > 0) { // move current song to first position $this->mpd('moveid ' . $songId . ' 0'); $playlistLength = isset($status['playlistlength']) ? $status['playlistlength'] : 0; if ($playlistLength > 1) { $this->mpd('delete 1:' . $playlistLength); } } break; case 'playSelect': // playSelect(); // playSelect(); case 'addSelect': // addSelect(); // addSelect(); case 'deleteIndexAjax': // deleteIndexAjax(); // deleteIndexAjax(); case 'deletePlayed': // deletePlayed(); // deletePlayed(); case 'volumeImageMap': // volumeImageMap(); // volumeImageMap(); case 'toggleMute': // toggleMute(); // toggleMute(); case 'loopGain': // loopGain(); // loopGain(); case 'playlistTrack': // playlistTrack(); die('sorry, not implemented yet'); break; default: die('unsupported'); break; } }
$image->dump($imagesize); }); } $app->get('/importer(/)', function () use($app, $config) { $config['action'] = 'importer'; $config['servertime'] = time(); $query = "SELECT * FROM importer ORDER BY jobStart DESC,id DESC LIMIT 30;"; $result = $app->db->query($query); while ($record = $result->fetch_assoc()) { $record['jobStatistics'] = unserialize($record['jobStatistics']); $config['itemlist'][] = $record; } $app->render('surrounding.twig', $config); }); $app->get('/importer/triggerUpdate', function () use($app, $config) { \Slimpd\importer::queStandardUpdate(); }); $app->get('/audiosvg/width/:width/:itemParam+', function ($width, $itemParam) use($app, $config) { $svgGenerator = new \Slimpd\Svggenerator($itemParam); $svgGenerator->generateSvg($width); }); $app->get('/filebrowser', function () use($app, $config) { $config['action'] = 'filebrowser'; $fileBrowser = new \Slimpd\filebrowser(); $fileBrowser->getDirectoryContent($config['mpd']['musicdir']); $config['breadcrumb'] = $fileBrowser->breadcrumb; $config['subDirectories'] = $fileBrowser->subDirectories; $config['files'] = $fileBrowser->files; $config['hotlinks'] = $config['filebrowser-hotlinks']; $app->render('surrounding.twig', $config); });