astrXbian/www/jukebox/player/mpd/filetree.php

344 lines
14 KiB
PHP

<?php
class fileCollector extends base_mpd_player {
public function doFileBrowse($path, $prefix) {
logger::mark("DIRBROWSER", "Browsing",$path);
$parts = true;
$foundfile = false;
$filedata = array();
$dircount = 0;
$this->send_command('lsinfo "'.format_for_mpd($path).'"');
while(!feof($this->connection) && $parts) {
$parts = $this->getline();
if (is_array($parts)) {
$s = trim($parts[1]);
if (substr($s,0,1) != ".") {
switch ($parts[0]) {
case "file":
if (!$foundfile) {
$foundfile = true;
} else {
if (!array_key_exists('Title', $filedata) || substr($filedata['Title'], 0, 12) != "[unplayable]") {
printFileItem($this->getFormatName($filedata), $filedata['file'], $filedata['Time']);
}
$filedata = array();
}
$filedata[$parts[0]] = $parts[1];
break;
case "playlist":
if ($path != "") {
// Ignore playlists located at the root. This is cleaner and makes more sense
printPlaylistItem(basename($parts[1]), $parts[1]);
}
break;
case "directory":
printDirectoryItem($parts[1], basename($parts[1]), $prefix, $dircount, false);
$dircount++;
break;
case "Title":
case "Time":
case "Artist":
case "Album":
$filedata[$parts[0]] = $parts[1];
break;
}
}
}
}
if (array_key_exists('file', $filedata)) {
if (!array_key_exists('Title', $filedata) || substr($filedata['Title'], 0, 12) != "[unplayable]") {
printFileItem($this->getFormatName($filedata), $filedata['file'], $filedata['Time']);
}
}
}
private function getFormatName($filedata) {
if ($this->player_type == "mopidy" && !preg_match('/local:track:/', $filedata['file'])) {
if (array_key_exists('Title', $filedata) && array_key_exists('Artist', $filedata)) {
return concatenate_artist_names(array_unique(explode(';',$filedata['Artist']))).' - '.$filedata['Title'];
}
if (array_key_exists('Title', $filedata)) {
return $filedata['Title'];
}
if (array_key_exists('Album', $filedata)) {
return "Album: ".$filedata['Album'];
}
}
return basename(rawurldecode($filedata['file']));
}
// Semi-Hacky way of doing a search and displaying the results as a file tree
// It's not neat, but then I don't understand why anyone would want to display
// search results this way in RompR.
public function doFileSearch($cmd, $domains) {
global $dbterms;
$tree = new mpdlistthing(null);
$parts = true;
$fcount = 0;
$filedata = array();
$foundfile = false;
if (count($domains) == 0) {
$domains = null;
}
$this->send_command($cmd);
while(!feof($this->connection) && $parts) {
$parts = $this->getline();
if (is_array($parts)) {
switch($parts[0]) {
case "file":
if (!$foundfile) {
$foundfile = true;
} else {
if ($dbterms['tags'] !== null || $dbterms['rating'] !== null) {
// If this is a search and we have tags or ratings to search for, check them here.
if (check_url_against_database($filedata['file'], $dbterms['tags'], $dbterms['rating']) == true) {
if (!is_array($domains) || in_array(getDomain($filedata['file']),$domains)) {
$tree->newItem($filedata);
$fcount++;
}
}
} else {
if (!is_array($domains) || in_array(getDomain($filedata['file']),$domains)) {
$tree->newItem($filedata);
$fcount++;
}
}
$filedata = array();
}
$filedata[$parts[0]] = trim($parts[1]);
break;
case "playlist":
$filedata[$parts[0]] = trim($parts[1]);
if ($dbterms['tags'] === null && $dbterms['rating'] === null) {
$tree->newItem($filedata);
$fcount++;
}
$filedata = array();
break;
case "Title":
case "Time":
case "AlbumArtist":
case "Album":
case "Artist":
if (in_array($parts[0], MPD_ARRAY_PARAMS)) {
$filedata[$parts[0]] = array_unique(explode(';',trim($parts[1])));
} else {
$filedata[$parts[0]] = explode(';',trim($parts[1]))[0];
}
break;
}
}
}
if (array_key_exists('file', $filedata)) {
if (!is_array($domains) || in_array(getDomain($filedata['file']),$domains)) {
$tree->newItem($filedata);
$fcount++;
}
}
printFileSearch($tree, $fcount);
}
}
function printFileSearch(&$tree, $fcount) {
$prefix = "sdirholder";
print '<div class="menuitem">';
print "<h3>".get_int_text("label_searchresults")."</h3>";
print "</div>";
print '<div style="margin-bottom:4px">
<table width="100%" class="playlistitem">
<tr><td align="left">'.$fcount.' '.get_int_text('label_files').'</td></tr>
</table>
</div>';
$tree->getHTML($prefix);
}
function printFileItem($displayname, $fullpath, $time) {
global $prefs;
$ext = strtolower(pathinfo($fullpath, PATHINFO_EXTENSION));
print '<div class="clickable clicktrack playable ninesix draggable indent containerbox padright line brick_wide" name="'.
rawurlencode($fullpath).'">';
print '<i class="'.audioClass($ext, getDomain($fullpath)).' fixed collectionicon"></i>';
print '<div class="expand">'.$displayname.'</div>';
if ($time > 0) {
print '<div class="fixed playlistrow2 tracktime">'.format_time($time).'</div>';
}
print '</div>';
}
function printPlaylistItem($displayname, $fullpath) {
print '<div class="clickable clickcue playable ninesix draggable indent containerbox padright line" name="'.
rawurlencode($fullpath).'">';
print '<i class="icon-doc-text fixed collectionitem"></i>';
print '<div class="expand">'.$displayname.'</div>';
print '</div>';
}
class mpdlistthing {
// Note: This is for displaying SEARCH RESULTS ONLY as a file tree.
// Directory clicking only works on this when the entire results set
// is loaded into the browser at once. Don't fuck with it, it's got teeth.
public function __construct($name, $parent = null, $filedata = null) {
$this->children = array();
$this->name = $name;
$this->parent = $parent;
$this->filedata = $filedata;
$this->dircount = 0;
}
public function newItem($filedata) {
global $prefs;
// This should only be called from outside the tree.
// This is the root object's pre-parser
if (array_key_exists('playlist', $filedata)) {
$decodedpath = $filedata['playlist'];
$filedata['file_display_name'] = basename($decodedpath);
} else {
$decodedpath = rawurldecode($filedata['file']);
}
if (substr($decodedpath, 0, 12) == "[unplayable]") {
return;
}
// All the different fixups for all the different mopidy backends
// and their various random ways of doing things.
if (preg_match('/podcast\+http:\/\//', $decodedpath)) {
$filedata['file_display_name'] = (array_key_exists('Title', $filedata)) ?
$filedata['Title'] : basename($decodedpath);
$filedata['file_display_name'] =
preg_replace('/Album: /','',$filedata['file_display_name']);
$decodedpath = preg_replace('/podcast\+http:\/\//','podcast/',$decodedpath);
} else if (preg_match('/:artist:/', $decodedpath)) {
$filedata['file_display_name'] = concatenate_artist_names($filedata['Artist']);
$decodedpath = preg_replace('/(.+?):(.+?):/','$1/$2/',$decodedpath);
} else if (preg_match('/:album:/', $decodedpath)) {
$matches = array();
$a = preg_match('/(.*?):(.*?):(.*)/',$decodedpath,$matches);
if ($filedata['AlbumArtist'] === null) {
$filedata['AlbumArtist'] = $filedata['Artist'] ? $filedata['Artist'] : "Unknown";
}
$decodedpath = $matches[1]."/".$matches[2]."/".
concatenate_artist_names($filedata['AlbumArtist'])."/".$matches[3];
$filedata['file_display_name'] = $filedata['Album'];
} else if (preg_match('/local:track:/', $decodedpath)) {
$filedata['file_display_name'] = basename($decodedpath);
$decodedpath = preg_replace('/:track:/','/',$decodedpath);
} else if (preg_match('/:track:/', $decodedpath)) {
$matches = array();
$a = preg_match('/(.*?):(.*?):(.*)/',$decodedpath,$matches);
$decodedpath = $matches[1]."/".$matches[2]."/".
concatenate_artist_names($filedata['Artist'])."/".
$filedata['Album']."/".$matches[3];
$filedata['file_display_name'] = $filedata['Title'];
} else if (preg_match('/soundcloud:song\//', $decodedpath)) {
$filedata['file_display_name'] = (array_key_exists('Title', $filedata)) ?
$filedata['Title'] : basename($decodedpath);
$decodedpath = preg_replace('/soundcloud:song/','soundcloud/'.
concatenate_artist_names($filedata['Artist']),$decodedpath);
} else if (preg_match('/^internetarchive:/', $decodedpath)) {
$filedata['file_display_name'] = $filedata['Album'];
$decodedpath = preg_replace('/internetarchive:/','internetarchive/',$decodedpath);
} else if (preg_match('/youtube:video\//', $decodedpath)) {
$filedata['file_display_name'] = (array_key_exists('Title', $filedata)) ?
$filedata['Title'] : basename($decodedpath);
$decodedpath = preg_replace('/youtube:video/','youtube',$decodedpath);
} else if (preg_match('/tunein:station/', $decodedpath)) {
$filedata['file_display_name'] = (array_key_exists('Album', $filedata)) ?
$filedata['Album'] : basename($decodedpath);
$decodedpath = 'tunein/';
if (array_key_exists('Artist', $filedata)) {
$decodedpath .= concatenate_artist_names($filedata['Artist']).'/';
}
} else {
if ($prefs['player_backend'] == "mopidy") {
$filedata['file_display_name'] = (array_key_exists('Title', $filedata)) ?
$filedata['Title'] : basename($decodedpath);
} else {
$filedata['file_display_name'] = basename($filedata['file']);
}
}
$pathbits = explode('/', $decodedpath);
$name = array_shift($pathbits);
if (!array_key_exists($name, $this->children)) {
$this->children[$name] = new mpdlistthing($name, $this);
}
$this->children[$name]->newChild($pathbits, $filedata);
}
public function newChild($pathbits, $filedata) {
$name = array_shift($pathbits);
if (count($pathbits) == 0) {
$this->children[$name] = new mpdlistthing($filedata['file_display_name'], $this, $filedata);
} else {
if (!array_key_exists($name, $this->children)) {
$this->children[$name] = new mpdlistthing($name, $this);
}
$this->children[$name]->newChild($pathbits, $filedata);
}
}
public function getHTML($prefix) {
if ($this->name !== null) {
if (count($this->children) > 0) {
// Must be a directory
printDirectoryItem($this->parent->getName($this->name), $this->name, $prefix, $this->dircount, true);
$this->parent->dircount++;
foreach ($this->children as $child) {
$child->getHTML($prefix.$this->dircount.'_');
}
print '</div>';
} else {
if (array_key_exists('playlist', $this->filedata)) {
printPlaylistItem($this->filedata['file_display_name'],$this->filedata['file']);
} else {
printFileItem($this->filedata['file_display_name'], $this->filedata['file'], $this->filedata['Time']);
}
}
} else {
foreach ($this->children as $child) {
$child->getHTML($prefix.$this->dircount.'_');
}
}
}
public function getName($name) {
if ($this->name !== null) {
$name = $this->name."/".$name;
}
if ($this->parent !== null) {
$name = $this->parent->getName($name);
}
return $name;
}
}
?>