Skip to content

Instantly share code, notes, and snippets.

@neckro
Created September 2, 2014 20:03
Show Gist options
  • Save neckro/b10684b4e018da2b96fa to your computer and use it in GitHub Desktop.
Save neckro/b10684b4e018da2b96fa to your computer and use it in GitHub Desktop.
MP3 playlist generator
<?php
class Config {
public static $MusicFolder = "music";
public static $MusicTypes = array("mp3", "mpeg3", "flac", "m4a", "aiff");
public static $FolderImage = array("folder.jpg", "folder.png", "folder.gif");
public static $AllowSymlinks = false;
}
$baseurl = explode("?", "http://" . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']);
$baseurl = array_shift($baseurl);
$baseurl = explode("/", $baseurl);
array_pop($baseurl);
$baseurl = implode('/', $baseurl) . '/';
if (array_key_exists('m', $_GET)) {
$mode = $_GET['m'];
} else {
$mode = 'browse';
}
if (array_key_exists('f', $_GET)) {
$folder = cleanPath($_GET['f']);
} else {
$folder = "";
}
$shuffle = false;
switch ($mode) {
case 'browse':
$pl = new FolderIndex($folder);
$pl->display($baseurl . Config::$MusicFolder . '/');
break;
case 'shuffle':
$shuffle = true;
case 'play':
$pl = new Playlist($folder);
if ($shuffle) $pl->shuffle();
$pl->display($baseurl);
break;
}
function cleanPath($path) {
// prevent shenanigans, hopefully
$path = str_replace("..\\", "", $path);
$path = str_replace("../", "", $path);
$path = trim($path, '/\\.');
return $path;
}
class RecursivePlaylistFilterIterator extends RecursiveFilterIterator {
public function accept() {
return ($this->current()->isDir() || in_array(strtolower($this->current()->getExtension()), Config::$MusicTypes, true));
}
}
class FolderListFilterIterator extends FilterIterator {
public function accept() {
return ($this->current()->isDir() || in_array(strtolower($this->current()->getExtension()), Config::$MusicTypes, true));
}
}
class FileList {
protected $iteratorMode = RecursiveIteratorIterator::SELF_FIRST;
public $filelist = array();
protected $iterator;
protected $filter;
protected $folder;
protected $basefolder;
public function __construct($folder) {
$this->folder = $folder;
$this->basefolder = Config::$MusicFolder . '/';
$this->buildIterator();
}
public function shuffle() {
$this->filelist = iterator_to_array($this->filelist);
shuffle($this->filelist);
}
protected function buildIterator() {
$this->iterator = new DirectoryIterator($this->basefolder . $this->folder);
$this->filter = new FolderListFilterIterator($this->iterator);
$this->filelist = new IteratorIterator($this->filter, $this->iteratorMode);
}
}
class RecursiveFileList extends FileList {
protected $iteratorMode = RecursiveIteratorIterator::LEAVES_ONLY;
protected function buildIterator() {
$this->iterator = new RecursiveDirectoryIterator($this->basefolder . $this->folder, Config::$AllowSymlinks ? RecursiveDirectoryIterator::FOLLOW_SYMLINK : 0);
$this->filter = new RecursivePlaylistFilterIterator($this->iterator);
$this->filelist = new RecursiveIteratorIterator($this->filter, $this->iteratorMode);
}
}
class Playlist extends RecursiveFileList {
public function display($base = '') {
header('Content-Type: audio/mpegurl');
foreach($this->filelist as $f) {
// Skip all dot files
if (strpos($f, '/.') > -1) continue;
//echo "#EXTINF:<duration>,<title>\n";
echo $base . str_replace("\\", '/', $f) . "\n";
}
}
}
class FolderIndex extends FileList {
public function display($base = '') {
echo "<html>\n<head><title>" . $this->folder . "</title></head>\n<body style=\"font-family: sans-serif; font-size: 10pt;\">\n";
$eol = "<br />\n";
if (!empty($this->folder)) {
echo '<b>' . $this->folder . '</b>' . $eol;
echo '<a href="?f=' . urlencode(dirname($this->folder)) . '">Parent Directory</a>' . $eol;
}
echo '<a href="?m=play&f=' . urlencode($this->folder) . '"><b>Play All</b></a>' . $eol;
echo '<a href="?m=shuffle&f=' . urlencode($this->folder) . '"><b>Shuffle All</b></a>' . $eol;
foreach ($this->filelist as $f) {
if (substr($f, 0, 1) == '.') continue;
$fe = urlencode($this->folder . "/" . $f);
if($f->isDir()) {
echo '<a href="?m=browse&f=' . $fe . '">' . $f . $eol;
} else {
echo '<a href="' . $base . $this->folder . '/' . $f . '">' . $f . "</a>$eol";
}
}
echo "</body></html>\n";
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment