diff --git a/config/ampache.cfg.php.dist b/config/ampache.cfg.php.dist index 4406e580b2..befd61f1ff 100644 --- a/config/ampache.cfg.php.dist +++ b/config/ampache.cfg.php.dist @@ -120,15 +120,15 @@ auth_methods = "mysql" ; This defines which file types Ampache will attempt to catalog ; You can specify any file extension you want in here separating them ; with a | -; DEFAULT: mp3|mpc|m4p|m4a|mp4|aac|ogg|rm|wma|asf|flac|spx|ra|ape|shn|wv -catalog_file_pattern = "mp3|mpc|m4p|m4a|mp4|aac|ogg|rm|wma|asf|flac|spx|ra|ape|shn|wv" +; DEFAULT: mp3|mpc|m4p|m4a|aac|ogg|oga|wav|aif|aiff|rm|wma|asf|flac|spx|ra|ape|shn|wv +catalog_file_pattern = "mp3|mpc|m4p|m4a|aac|ogg|oga|wav|aif|aiff|rm|wma|asf|flac|spx|ra|ape|shn|wv" ; Video Pattern ; This defines which video file types Ampache will attempt to catalog ; You can specify any file extension you want in here seperating them with ; a | but ampache may not be able to parse them -; DEAFULT: avi|mpg|flv|m4v|webm -catalog_video_pattern = "avi|mpg|flv|m4v|webm|mkv" +; DEAFULT: avi|mpg|mpeg|flv|m4v|mp4|webm|mkv|wmv|ogv|mov|divx|m2ts +catalog_video_pattern = "avi|mpg|mpeg|flv|m4v|mp4|webm|mkv|wmv|ogv|mov|divx|m2ts" ; Playlist Pattern ; This defines which playlist types Ampache will attempt to catalog @@ -271,10 +271,15 @@ metadata_order = "getID3,filename" ; This determines the order in which metadata sources are used (and in the ; case of plugins, checked) for video files ; POSSIBLE VALUES (builtins): filename and getID3 -; POSSIBLE VALUES (plugins): Tmdb, plus any others you've installed. +; POSSIBLE VALUES (plugins): Tmdb,Omdb plus any others you've installed. ; DEFAULT: filename getID3 metadata_order_video = "filename,getID3" +; This determines if a preview image should be retrieved from video files +; It requires encode_get_image transcode settings. +; DEFAULT: false +;generate_video_preview = "true" + ; Un comment if don't want ampache to follow symlinks ; DEFAULT: false ;no_symlinks = "false" @@ -645,17 +650,41 @@ refresh_limit = "60" ; (e.g. if you store everything in FLAC, but don't want to ever stream that.) ; transcode_TYPE = {allowed|required|false} ; DEFAULT: false +;;; Audio ;transcode_m4a = allowed ;transcode_flac = required ;transcode_mpc = required ;transcode_ogg = required +;transcode_oga = required ;transcode_wav = required +;transcode_wma = required +;transcode_aif = required +;transcode_aiff = required +;transcode_ape = required +;transcode_shn = required ;transcode_mp3 = allowed - -; Default output format +;;; Video +;transcode_avi = allowed +;transcode_mkv = allowed +;transcode_mpg = allowed +;transcode_mpeg = allowed +;transcode_m4v = allowed +;transcode_mp4 = allowed +;transcode_mov = allowed +;transcode_wmv = allowed +;transcode_ogv = allowed +;transcode_divx = allowed +;transcode_m2ts = allowed +;transcode_webm = allowed + +; Default audio output format ; DEFAULT: none ;encode_target = mp3 +; Default video output format +; DEFAULT: none +;encode_video_target = flv + ; Override the default output format on a per-type basis ; encode_target_TYPE = TYPE ; DEFAULT: none @@ -697,6 +726,11 @@ transcode_player_customize = true ;encode_args_ogg = "-vn -b:a %SAMPLE%K -c:a libvorbis -f ogg pipe:1" ;encode_args_m4a = "-vn -b:a %SAMPLE%K -c:a libfdk_aac -f adts pipe:1" ;encode_args_wav = "-vn -b:a %SAMPLE%K -c:a pcm_s16le -f wav pipe:1" +;encode_args_flv = "-b:a %SAMPLE%K -ar 44100 -ac 2 -v 0 -f flv -c:v libx264 -preset superfast -threads 0 pipe:1" + +; Encoding arguments to retrieve an image from a single frame +; DEFAULT: none +;encode_get_image = "-ss %TIME% -f image2 -vframes 1 pipe:1" ;###################################################### ; these options allow you to configure your rss-feed diff --git a/image.php b/image.php index 7c7f626285..26e39bc5ab 100644 --- a/image.php +++ b/image.php @@ -52,6 +52,7 @@ /* Decide what size this image is */ $size = Art::get_thumb_size($_GET['thumb']); +$kind = isset($_GET['kind']) ? $_GET['kind'] : 'default'; $image = ''; $mime = ''; @@ -78,7 +79,7 @@ $item = new $type($_GET['object_id']); $filename = $item->name ?: $item->title; - $art = new Art($item->id, $type); + $art = new Art($item->id, $type, $kind); $art->get_db(); $etag = $art->id; diff --git a/lib/class/album.class.php b/lib/class/album.class.php index 349ae816ad..27155a88fb 100644 --- a/lib/class/album.class.php +++ b/lib/class/album.class.php @@ -484,7 +484,7 @@ public function get_fullname() public function get_parent() { if ($album->artist_count == 1) { - return array('artist', $album->artist_id); + return array('type' => 'artist', 'id' => $album->artist_id); } return null; @@ -500,6 +500,11 @@ public function get_user_owner() return null; } + public function get_default_art_kind() + { + return 'default'; + } + /** * get_random_songs * gets a random number, and a random assortment of songs from this album diff --git a/lib/class/art.class.php b/lib/class/art.class.php index d8752dd4fd..2e0372a8aa 100644 --- a/lib/class/art.class.php +++ b/lib/class/art.class.php @@ -37,6 +37,7 @@ class Art extends database_object public $uid; // UID of the object not ID because it's not the ART.ID public $raw; // Raw art data public $raw_mime; + public $kind; public $thumb; public $thumb_mime; @@ -48,12 +49,13 @@ class Art extends database_object * Art constructor, takes the UID of the object and the * object type. */ - public function __construct($uid, $type = 'album') + public function __construct($uid, $type = 'album', $kind = 'default') { if (!Catalog::is_library_item($type)) return false; $this->type = $type; $this->uid = $uid; + $this->kind = $kind; } // constructor @@ -196,8 +198,8 @@ public function get($raw=false) */ public function get_db() { - $sql = "SELECT `id`, `image`, `mime`, `size` FROM `image` WHERE `object_type` = ? AND `object_id` = ?"; - $db_results = Dba::read($sql, array($this->type, $this->uid)); + $sql = "SELECT `id`, `image`, `mime`, `size` FROM `image` WHERE `object_type` = ? AND `object_id` = ? AND `kind` = ?"; + $db_results = Dba::read($sql, array($this->type, $this->uid, $this->kind)); while ($results = Dba::fetch_assoc($db_results)) { if ($results['size'] == 'original') { @@ -230,10 +232,10 @@ public function get_db() } // get_db - public static function has_db($object_id, $object_type) + public static function has_db($object_id, $object_type, $kind = 'default') { - $sql = "SELECT COUNT(`id`) AS `nb_img` FROM `image` WHERE `object_type` = ? AND `object_id` = ?"; - $db_results = Dba::read($sql, array($object_type, $object_id)); + $sql = "SELECT COUNT(`id`) AS `nb_img` FROM `image` WHERE `object_type` = ? AND `object_id` = ? AND `kind` = ?"; + $db_results = Dba::read($sql, array($object_type, $object_id, $kind)); $nb_img = 0; if ($results = Dba::fetch_assoc($db_results)) { $nb_img = $results['nb_img']; @@ -269,18 +271,12 @@ public function insert($source, $mime) // Default to image/jpeg if they don't pass anything $mime = $mime ? $mime : 'image/jpeg'; - - $image = Dba::escape($source); - $mime = Dba::escape($mime); - $uid = Dba::escape($this->uid); - $type = Dba::escape($this->type); - // Blow it away! $this->reset(); // Insert it! - $sql = "INSERT INTO `image` (`image`, `mime`, `size`, `object_type`, `object_id`) VALUES('$image', '$mime', 'original', '$type', '$uid')"; - Dba::write($sql); + $sql = "INSERT INTO `image` (`image`, `mime`, `size`, `object_type`, `object_id`, `kind`) VALUES(?, ?, 'original', ?, ?, ?)"; + Dba::write($sql, array($source, $mime, $this->type, $this->uid, $this->kind)); return true; @@ -292,8 +288,8 @@ public function insert($source, $mime) */ public function reset() { - $sql = "DELETE FROM `image` WHERE `object_id` = ? AND `object_type` = ?"; - Dba::write($sql, array($this->uid, $this->type)); + $sql = "DELETE FROM `image` WHERE `object_id` = ? AND `object_type` = ? AND `kind` = ?"; + Dba::write($sql, array($this->uid, $this->type, $this->kind)); } // reset /** @@ -308,17 +304,11 @@ public function save_thumb($source, $mime, $size) return false; } - $source = Dba::escape($source); - $mime = Dba::escape($mime); - $size = Dba::escape($size); - $uid = Dba::escape($this->uid); - $type = Dba::escape($this->type); - - $sql = "DELETE FROM `image` WHERE `object_id`='$uid' AND `object_type`='$type' AND `size`='$size'"; - Dba::write($sql); + $sql = "DELETE FROM `image` WHERE `object_id` = ? AND `object_type` = ? AND `size` = ? AND `kind` = ?"; + Dba::write($sql, array($this->uid, $this->type, $size, $this->kind)); - $sql = "INSERT INTO `image` (`image`, `mime`, `size`, `object_type`, `object_id`) VALUES('$source', '$mime', '$size', '$type', '$uid')"; - Dba::write($sql); + $sql = "INSERT INTO `image` (`image`, `mime`, `size`, `object_type`, `object_id`, `kind`) VALUES(?, ?, ?, ?, ?, ?)"; + Dba::write($sql, array($source, $mime, $size, $this->type, $this->uid, $this->kind)); } // save_thumb /** @@ -329,12 +319,8 @@ public function save_thumb($source, $mime, $size) public function get_thumb($size) { $sizetext = $size['width'] . 'x' . $size['height']; - $sizetext = Dba::escape($sizetext); - $type = Dba::escape($this->type); - $uid = Dba::escape($this->uid); - - $sql = "SELECT `image`, `mime` FROM `image` WHERE `size`='$sizetext' AND `object_type`='$type' AND `object_id`='$uid'"; - $db_results = Dba::read($sql); + $sql = "SELECT `image`, `mime` FROM `image` WHERE `size` = ? AND `object_type` = ? AND `object_id` = ? AND `kind` = ?"; + $db_results = Dba::read($sql, array($sizetext, $this->type, $this->uid, $this->kind)); $results = Dba::fetch_assoc($db_results); if (count($results)) { @@ -469,8 +455,8 @@ public static function get_from_source($data, $type = 'album') $uid = Dba::escape($data['db']); $type = Dba::escape($type); - $sql = "SELECT * FROM `image` WHERE `object_type`='$type' AND `object_id`='$uid' AND `size`='original'"; - $db_results = Dba::read($sql); + $sql = "SELECT * FROM `image` WHERE `object_type` = ? AND `object_id` =? AND `size`='original'"; + $db_results = Dba::read($sql, array($type, $data['db'])); $row = Dba::fetch_assoc($db_results); return $row['art']; } // came from the db @@ -600,58 +586,19 @@ public static function gc() * gather * This tries to get the art in question */ - public function gather($options = array(), $limit = false) + public function gather($options = array(), $limit = false, $gather_parent = false) { // Define vars $results = array(); + $type = $this->type; + if (isset($options['type'])) { + $type = $options['type']; + } if (count($options) == 0) { - switch ($this->type) { - case 'album': - $album = new Album($this->uid); - $album->format(); - $options['artist'] = $album->f_artist; - $options['album'] = $album->f_name; - $options['keyword'] = $options['artist'] . ' ' . $options['album']; - break; - case 'artist': - $artist = new Artist($this->uid); - $artist->format(); - $options['artist'] = $album->f_artist; - $options['keyword'] = $options['artist']; - break; - case 'tvshow': - $tvshow = new TVShow($this->uid); - $tvshow->format(); - $options['tvshow'] = $tvshow->f_name; - $options['keyword'] = $options['tvshow']; - break; - case 'tvshow_season': - $season = new TVShow_Season($this->uid); - $season->format(); - $options['tvshow'] = $season->f_tvshow; - $options['tvshow_season'] = $season->f_name; - $options['keyword'] = $options['tvshow']; - break; - case 'tvshow_episode': - $video = new TVShow_Episode($this->uid); - $video->format(); - $options['tvshow'] = $video->f_tvshow; - $options['tvshow_season'] = $video->f_tvshow_season; - $options['tvshow_episode'] = $video->episode_number; - $options['keyword'] = $options['tvshow'] . " " . $video->f_title; - break; - case 'video': - case 'clip': - case 'movie': - case 'personal_video': - $video = new Video($this->uid); - $video->format(); - $options['keyword'] = $video->f_title; - break; - } + debug_event('Art', 'No options for art search, skipped.', 3); + return array(); } - $config = AmpConfig::get('art_order'); $methods = get_class_methods('Art'); @@ -676,7 +623,7 @@ public function gather($options = array(), $limit = false) $installed_version = Plugin::get_plugin_version($plugin->_plugin->name); if ($installed_version) { if ($plugin->load($GLOBALS['user'])) { - $data = $plugin->_plugin->gather_arts($this->type, $options, $limit); + $data = $plugin->_plugin->gather_arts($type, $options, $limit); } } } else if (in_array($method_name, $methods)) { @@ -1246,6 +1193,11 @@ public static function get_thumb_size($thumb) $size['height'] = 300; $size['width'] = 200; break; + case '8': + /* Video preview size */ + $size['height'] = 200; + $size['width'] = 470; + break; default: $size['height'] = '275'; $size['width'] = '275'; @@ -1260,12 +1212,21 @@ public static function display_item($item, $thumb, $link = null) return self::display($item->type, $item->id, $item->get_fullname(), $thumb, $link); } - public static function display($object_type, $object_id, $name, $thumb, $link = null) + public static function display($object_type, $object_id, $name, $thumb, $link = null, $show_default = true, $kind = 'default') { + if (!$show_default) { + // Don't show any image if not available + if (!self::has_db($object_id, $object_type, $kind)) { + return false; + } + } $size = self::get_thumb_size($thumb); $prettyPhoto = ($link == null); if ($link == null) { $link = AmpConfig::get('web_path') . "/image.php?object_id=" . $object_id . "&object_type=" . $object_type . "&auth=" . session_id(); + if ($kind != 'default') { + $link .= '&kind=' . $kind; + } } echo "
"; echo ""; $imgurl = AmpConfig::get('web_path') . "/image.php?object_id=" . $object_id . "&object_type=" . $object_type . "&thumb=" . $thumb; + if ($kind != 'default') { + $imgurl .= '&kind=' . $kind; + } echo "\"""; if ($prettyPhoto) { echo "
"; @@ -1293,6 +1257,8 @@ public static function display($object_type, $object_id, $name, $thumb, $link = } echo "\n"; echo "
"; + + return true; } } // Art diff --git a/lib/class/artist.class.php b/lib/class/artist.class.php index ac12e55140..36b359c074 100644 --- a/lib/class/artist.class.php +++ b/lib/class/artist.class.php @@ -375,6 +375,11 @@ public function get_user_owner() return $this->user; } + public function get_default_art_kind() + { + return 'default'; + } + /** * check * diff --git a/lib/class/broadcast.class.php b/lib/class/broadcast.class.php index 7bf008024f..b2e1fb219c 100644 --- a/lib/class/broadcast.class.php +++ b/lib/class/broadcast.class.php @@ -143,6 +143,11 @@ public function get_user_owner() return $this->user; } + public function get_default_art_kind() + { + return 'default'; + } + public static function get_broadcast_list_sql() { $sql = "SELECT `id` FROM `broadcast` WHERE `started` = '1' "; @@ -220,13 +225,9 @@ public static function get_broadcasts($user_id) return $broadcasts; } - /* - * - * @SuppressWarnings(PHPMD.UnusedFormalParameter) - */ - public static function play_url($oid, $additional_params='') + public static function gc() { - return $oid; + } } // end of broadcast class diff --git a/lib/class/browse.class.php b/lib/class/browse.class.php index c6173b3354..9bc22d3fdf 100644 --- a/lib/class/browse.class.php +++ b/lib/class/browse.class.php @@ -191,7 +191,7 @@ public function show_objects($object_ids = null, $argument = null) break; case 'catalog': $box_title = T_('Catalogs'); - $box_req = AmpConfig::get('prefix') . '/templates/show_searches.inc.php'; + $box_req = AmpConfig::get('prefix') . '/templates/show_catalogs.inc.php'; break; case 'shoutbox': $box_title = T_('Shoutbox Records'); diff --git a/lib/class/catalog.class.php b/lib/class/catalog.class.php index cab1e631ee..ddec5666e2 100644 --- a/lib/class/catalog.class.php +++ b/lib/class/catalog.class.php @@ -432,6 +432,9 @@ public static function create($data) $sort_pattern = $data['sort_pattern']; $gather_types = $data['gather_media']; + // Should it be an array? Not now. + if (!in_array($gather_types, array('music', 'clip', 'tvshow', 'movie', 'personal_video'))) return false; + $insert_id = 0; $filename = AmpConfig::get('prefix') . '/modules/catalog/' . $type . '.catalog.php'; $include = require_once $filename; @@ -802,6 +805,73 @@ public static function get_albums_by_artist($size = 0, $offset = 0, $catalogs = return $results; } + public function gather_art_item($type, $id) + { + debug_event('gather_art', 'Gathering art for ' . $type . '/' . $id . '...', 5); + + // Should be more generic ! + if ($type == 'video') { + $libitem = Video::create_from_id($id); + } else { + $libitem = new $type($id); + } + $options = array(); + $libitem->format(); + if ($libitem->id) { + if (count($options) == 0) { + // Only search on items with default art kind as `default`. + if ($libitem->get_default_art_kind() == 'default') { + $keywords = $libitem->get_keywords(); + $keyword = ''; + foreach ($keywords as $key => $word) { + $options[$key] = $word['value']; + if ($word['important']) { + if (!empty($word['value'])) { + $keyword .= ' ' . $word['value']; + } + } + } + $options['keyword'] = $keyword; + } + + $parent = $libitem->get_parent(); + if ($parent != null) { + if (!Art::has_db($parent['id'], $parent['type'])) { + $this->gather_art_item($parent['type'], $parent['id']); + } + } + } + } + + $art = new Art($id, $type); + $results = $art->gather($options, 1, true); + + if (count($results)) { + // Pull the string representation from the source + $image = Art::get_from_source($results[0], $type); + if (strlen($image) > '5') { + $art->insert($image, $results[0]['mime']); + // If they've enabled resizing of images generate a thumbnail + if (AmpConfig::get('resize_images')) { + $thumb = $art->generate_thumb($image, array( + 'width' => 275, + 'height' => 275), + $results[0]['mime']); + if (is_array($thumb)) { + $art->save_thumb($thumb['thumb'], $thumb['thumb_mime'], '275x275'); + } + } + + } else { + debug_event('gather_art', 'Image less than 5 chars, not inserting', 3); + } + } + + if ($type == 'video' && AmpConfig::get('generate_video_preview')) { + Video::generate_preview($id); + } + } + /** * gather_art * @@ -850,31 +920,7 @@ public function gather_art($songs = null, $videos = null) // Run through items and get the art! foreach ($searches as $key => $values) { foreach ($values as $id) { - $art = new Art($id, $key); - - debug_event('gather_art', 'Gathering art for ' . $key . '/' . $id . '...', 5); - $results = $art->gather(array(), 1); - - if (count($results)) { - // Pull the string representation from the source - $image = Art::get_from_source($results[0], $key); - if (strlen($image) > '5') { - $art->insert($image, $results[0]['mime']); - // If they've enabled resizing of images generate a thumbnail - if (AmpConfig::get('resize_images')) { - $thumb = $art->generate_thumb($image, array( - 'width' => 275, - 'height' => 275), - $results[0]['mime']); - if (is_array($thumb)) { - $art->save_thumb($thumb['thumb'], $thumb['thumb_mime'], '275x275'); - } - } - - } else { - debug_event('gather_art', 'Image less than 5 chars, not inserting', 3); - } - } + $this->gather_art_item($key, $id); // Stupid little cutesie thing $search_count++; @@ -882,8 +928,6 @@ public function gather_art($songs = null, $videos = null) UI::update_text('count_art_' . $this->id, $search_count); UI::update_text('read_art_' . $this->id, scrub_out($album->name)); } - - unset($found); } } @@ -1211,14 +1255,13 @@ public function get_gather_types($media_type) $gtypes = "music"; } $types = explode(',', $gtypes); + if ($media_type == "video") { - unset($types['music']); + $types = array_diff($types, array('music')); } if ($media_type == "music") { - unset($types['video']); - unset($types['movie']); - unset($types['tvshow']); + $types = array_diff($types, array('personal_video', 'movie', 'tvshow')); } return $types; diff --git a/lib/class/channel.class.php b/lib/class/channel.class.php index e480879be8..bbb42779e7 100644 --- a/lib/class/channel.class.php +++ b/lib/class/channel.class.php @@ -211,6 +211,11 @@ public function get_user_owner() return null; } + public function get_default_art_kind() + { + return 'default'; + } + public function get_target_object() { $object = null; diff --git a/lib/class/clip.class.php b/lib/class/clip.class.php index 954df491a1..6dea7c06b4 100644 --- a/lib/class/clip.class.php +++ b/lib/class/clip.class.php @@ -126,7 +126,7 @@ public function get_keywords() public function get_parent() { if ($this->artist) { - return array('artist', $this->artist); + return array('type' => 'artist', 'id' => $this->artist); } return null; diff --git a/lib/class/library_item.interface.php b/lib/class/library_item.interface.php index f087dd453f..c04fa1bf7a 100644 --- a/lib/class/library_item.interface.php +++ b/lib/class/library_item.interface.php @@ -45,6 +45,8 @@ public function get_childrens(); public function get_user_owner(); + public function get_default_art_kind(); + public function update($data); public static function gc(); diff --git a/lib/class/live_stream.class.php b/lib/class/live_stream.class.php index 8dd4766102..724ff03b7f 100644 --- a/lib/class/live_stream.class.php +++ b/lib/class/live_stream.class.php @@ -101,6 +101,11 @@ public function get_user_owner() return null; } + public function get_default_art_kind() + { + return 'default'; + } + /** * update * This is a static function that takes a key'd array for input @@ -203,6 +208,11 @@ public static function play_url($oid, $additional_params='',$sid='',$force_http= } // play_url + public function get_stream_name() + { + return $this->get_fullname(); + } + /** * get_transcode_settings * @@ -237,4 +247,9 @@ public static function get_all_radios($catalog = null) return $radios; } + public static function gc() + { + + } + } //end of radio class diff --git a/lib/class/media.interface.php b/lib/class/media.interface.php index 192c1eb6a3..b7c24e2ee6 100644 --- a/lib/class/media.interface.php +++ b/lib/class/media.interface.php @@ -54,4 +54,10 @@ public static function play_url($oid, $additional_params=''); */ public function get_transcode_settings($target = null); + /** + * get_stream_name + * Get the complete name to display for the stream. + */ + public function get_stream_name(); + } // end interface diff --git a/lib/class/movie.class.php b/lib/class/movie.class.php index 05c8c720f0..2db33e9fbd 100644 --- a/lib/class/movie.class.php +++ b/lib/class/movie.class.php @@ -103,4 +103,20 @@ public function format() } //format + public function get_keywords() + { + $keywords = parent::get_keywords(); + $keywords['type'] = array('important' => false, + 'label' => null, + 'value' => 'movie' + ); + + return $keywords; + } + + public function get_default_art_kind() + { + return 'default'; + } + } // Movie class diff --git a/lib/class/playlist.class.php b/lib/class/playlist.class.php index 7b2e71e5b0..18c4254cb9 100644 --- a/lib/class/playlist.class.php +++ b/lib/class/playlist.class.php @@ -61,7 +61,9 @@ public function __construct($id) */ public static function gc() { - Dba::write("DELETE FROM `playlist_data` USING `playlist_data` LEFT JOIN `song` ON `song`.`id` = `playlist_data`.`object_id` WHERE `song`.`file` IS NULL AND `playlist_data`.`object_type`='song'"); + foreach (array('song', 'video') as $object_type) { + Dba::write("DELETE FROM `playlist_data` USING `playlist_data` LEFT JOIN `" . $object_type . "` ON `song`.`id` = `playlist_data`.`object_id` WHERE `song`.`file` IS NULL AND `playlist_data`.`object_type`='" . $object_type . "'"); + } Dba::write("DELETE FROM `playlist` USING `playlist` LEFT JOIN `playlist_data` ON `playlist_data`.`playlist` = `playlist`.`id` WHERE `playlist_data`.`object_id` IS NULL"); } @@ -158,6 +160,11 @@ public function get_user_owner() return $this->user; } + public function get_default_art_kind() + { + return 'default'; + } + /** * get_track * Returns the single item on the playlist and all of it's information, restrict @@ -176,8 +183,8 @@ public function get_track($track_id) /** * get_items - * This returns an array of playlist songs that are in this playlist. - * Because the same song can be on the same playlist twice they are + * This returns an array of playlist medias that are in this playlist. + * Because the same meda can be on the same playlist twice they are * keyed by the uid from playlist_data */ public function get_items() @@ -235,7 +242,7 @@ public function get_songs() { $results = array(); - $sql = "SELECT * FROM `playlist_data` WHERE `playlist` = ? ORDER BY `track`"; + $sql = "SELECT * FROM `playlist_data` WHERE `playlist` = ? AND `object_type` = 'song' ORDER BY `track`"; $db_results = Dba::read($sql, array($this->id)); while ($r = Dba::fetch_assoc($db_results)) { diff --git a/lib/class/rating.class.php b/lib/class/rating.class.php index d63b8d4509..a67fe841f9 100644 --- a/lib/class/rating.class.php +++ b/lib/class/rating.class.php @@ -53,7 +53,7 @@ public function __construct($id, $type) */ public static function gc() { - foreach (array('song', 'album', 'artist', 'video', 'tvshow', 'tvshow_season', 'tvshow_episode', 'movie') as $object_type) { + foreach (array('song', 'album', 'artist', 'video', 'tvshow', 'tvshow_season') as $object_type) { Dba::write("DELETE FROM `rating` USING `rating` LEFT JOIN `$object_type` ON `$object_type`.`id` = `rating`.`object_id` WHERE `object_type` = '$object_type' AND `$object_type`.`id` IS NULL"); } } diff --git a/lib/class/search.class.php b/lib/class/search.class.php index b3d38b29be..90b7a763c1 100644 --- a/lib/class/search.class.php +++ b/lib/class/search.class.php @@ -656,6 +656,11 @@ public function get_user_owner() return $this->user; } + public function get_default_art_kind() + { + return 'default'; + } + /** * get_items * diff --git a/lib/class/share.class.php b/lib/class/share.class.php index a7296e6a86..b8503d4ba6 100644 --- a/lib/class/share.class.php +++ b/lib/class/share.class.php @@ -261,7 +261,7 @@ public function create_fake_playlist() case 'album': case 'playlist': $object = new $this->object_type($this->object_id); - $songs = $object->get_songs(); + $songs = $object->get_songs('song'); foreach ($songs as $id) { $medias[] = array( 'object_type' => 'song', diff --git a/lib/class/song.class.php b/lib/class/song.class.php index 1cb1114b34..945bfa037f 100644 --- a/lib/class/song.class.php +++ b/lib/class/song.class.php @@ -976,7 +976,7 @@ public function get_fullname() public function get_parent() { - return array('album', $this->album); + return array('type' => 'album', 'id' => $this->album); } public function get_childrens() @@ -986,9 +986,18 @@ public function get_childrens() public function get_user_owner() { + if ($this->user_upload) { + return $this->user_upload; + } + return null; } + public function get_default_art_kind() + { + return 'default'; + } + /** * get_fields * This returns all of the 'data' fields for this object, we need to filter out some that we don't @@ -1055,41 +1064,52 @@ public function get_rel_path($file_path=0,$catalog_id=0) } // get_rel_path - /** - * play_url - * This function takes all the song information and correctly formats a - * a stream URL taking into account the downsmapling mojo and everything - * else, this is the true function - */ - public static function play_url($oid, $additional_params='') + public static function generic_play_url($object_type, $object_id, $additional_params) { - $song = new Song($oid); - $user_id = $GLOBALS['user']->id ? scrub_out($GLOBALS['user']->id) : '-1'; - $type = $song->type; + $media = new $object_type($object_id); + if (!$media->id) return null; + + $uid = $GLOBALS['user']->id ? scrub_out($GLOBALS['user']->id) : '-1'; + $type = $media->type; - // Checking if the song is gonna be transcoded into another type + // Checking if the media is gonna be transcoded into another type // Some players doesn't allow a type streamed into another without giving the right extension $transcode_cfg = AmpConfig::get('transcode'); $transcode_mode = AmpConfig::get('transcode_' . $type); if ($transcode_cfg == 'always' || ($transcode_cfg != 'never' && $transcode_mode == 'required')) { - $transcode_settings = $song->get_transcode_settings(null); + $transcode_settings = $media->get_transcode_settings(null); if ($transcode_settings) { - debug_event("song.class.php", "Changing play url type from {".$type."} to {".$transcode_settings['format']."} due to encoding settings...", 5); + debug_event("media", "Changing play url type from {".$type."} to {".$transcode_settings['format']."} due to encoding settings...", 5); $type = $transcode_settings['format']; } } - $song_name = $song->get_artist_name() . " - " . $song->title . "." . $type; - $song_name = str_replace("/", "-", $song_name); - $song_name = str_replace("?", "", $song_name); - $song_name = str_replace("#", "", $song_name); - $song_name = rawurlencode($song_name); + $media_name = $media->get_stream_name() . "." . $type; + $media_name = str_replace("/", "-", $media_name); + $media_name = str_replace("?", "", $media_name); + $media_name = str_replace("#", "", $media_name); + $media_name = rawurlencode($media_name); - $url = Stream::get_base_url() . "type=song&oid=" . $song->id . "&uid=" . $user_id . $additional_params . "&name=" . $song_name; + $url = Stream::get_base_url() . "type=" . $object_type . "&oid=" . $object_id . "&uid=" . $uid . $additional_params . "&name=" . $media_name; return Stream_URL::format($url); + } + + /** + * play_url + * This function takes all the song information and correctly formats a + * a stream URL taking into account the downsmapling mojo and everything + * else, this is the true function + */ + public static function play_url($oid, $additional_params='') + { + return self::generic_play_url('song', $oid, $additional_params); + } - } // play_url + public function get_stream_name() + { + return $this->get_artist_name() . " - " . $this->title; + } /** * get_recently_played @@ -1134,7 +1154,7 @@ public static function get_recently_played($user_id='') public function get_stream_types() { return Song::get_stream_types_for_type($this->type); - } // end stream_types + } public static function get_stream_types_for_type($type) { @@ -1149,37 +1169,45 @@ public static function get_stream_types_for_type($type) } return $types; - } // end stream_types + } - public function get_transcode_settings($target = null) + public static function get_transcode_settings_for_media($source, $target = null, $media_type = 'song') { - $source = $this->type; + $setting_target = 'encode_target'; + if ($media_type != 'song') { + $setting_target = 'encode_' . $media_type . '_target'; + } if ($target) { - debug_event('song.class.php', 'Explicit format request {'.$target.'}', 5); + debug_event('media', 'Explicit format request {' . $target . '}', 5); } else if ($target = AmpConfig::get('encode_target_' . $source)) { - debug_event('song.class.php', 'Defaulting to configured target format for ' . $source, 5); - } else if ($target = AmpConfig::get('encode_target')) { - debug_event('song.class.php', 'Using default target format', 5); + debug_event('media', 'Defaulting to configured target format for ' . $source, 5); + } else if ($target = AmpConfig::get($setting_target)) { + debug_event('media', 'Using default target format', 5); } else { $target = $source; - debug_event('song.class.php', 'No default target for ' . $source . ', choosing to resample', 5); + debug_event('media', 'No default target for ' . $source . ', choosing to resample', 5); } - debug_event('song.class.php', 'Transcode settings: from ' . $source . ' to ' . $target, 5); + debug_event('media', 'Transcode settings: from ' . $source . ' to ' . $target, 5); $cmd = AmpConfig::get('transcode_cmd_' . $source) ?: AmpConfig::get('transcode_cmd'); $args = AmpConfig::get('encode_args_' . $target); if (!$args) { - debug_event('song.class.php', 'Target format ' . $target . ' is not properly configured', 2); + debug_event('media', 'Target format ' . $target . ' is not properly configured', 2); return false; } - debug_event('song.class.php', 'Command: ' . $cmd . ' Arguments: ' . $args, 5); + debug_event('media', 'Command: ' . $cmd . ' Arguments: ' . $args, 5); return array('format' => $target, 'command' => $cmd . ' ' . $args); } + public function get_transcode_settings($target = null) + { + return Song::get_transcode_settings_for_media($this->type, $target, 'song'); + } + public function get_lyrics() { if ($this->lyrics) { diff --git a/lib/class/song_preview.class.php b/lib/class/song_preview.class.php index d86370b79e..4a4b8452d7 100644 --- a/lib/class/song_preview.class.php +++ b/lib/class/song_preview.class.php @@ -255,6 +255,11 @@ public function get_transcode_settings($target = null) return false; } + public function get_stream_name() + { + return $this->title; + } + public static function get_song_previews($album_mbid) { $songs = array(); diff --git a/lib/class/stream.class.php b/lib/class/stream.class.php index 4176f1c80c..542c256b55 100644 --- a/lib/class/stream.class.php +++ b/lib/class/stream.class.php @@ -102,13 +102,13 @@ public static function get_allowed_bitrate($song) * start_transcode * * This is a rather complex function that starts the transcoding or - * resampling of a song and returns the opened file handle. + * resampling of a media and returns the opened file handle. */ - public static function start_transcode($song, $type = null, $bitrate=0) + public static function start_transcode($media, $type = null, $bitrate=0) { - debug_event('stream.class.php', 'Starting transcode for {'.$song->file.'}. Type {'.$type.'}. Bitrate {'.$bitrate.'}...', 5); + debug_event('stream.class.php', 'Starting transcode for {'.$media->file.'}. Type {'.$type.'}. Bitrate {'.$bitrate.'}...', 5); - $transcode_settings = $song->get_transcode_settings($type); + $transcode_settings = $media->get_transcode_settings($type); // Bail out early if we're unutterably broken if ($transcode_settings == false) { debug_event('stream', 'Transcode requested, but get_transcode_settings failed', 2); @@ -116,7 +116,7 @@ public static function start_transcode($song, $type = null, $bitrate=0) } if ($bitrate == 0) { - $sample_rate = self::get_allowed_bitrate($song); + $sample_rate = self::get_allowed_bitrate($media); debug_event('stream', 'Configured bitrate is ' . $sample_rate, 5); // Validate the bitrate $sample_rate = self::validate_bitrate($sample_rate); @@ -124,15 +124,15 @@ public static function start_transcode($song, $type = null, $bitrate=0) $sample_rate = $bitrate; } - // Never upsample a song - if ($song->type == $transcode_settings['format'] && ($sample_rate * 1000) > $song->bitrate) { + // Never upsample a media + if ($media->type == $transcode_settings['format'] && ($sample_rate * 1000) > $media->bitrate) { debug_event('stream', 'Clamping bitrate to avoid upsampling to ' . $sample_rate, 5); - $sample_rate = self::validate_bitrate($song->bitrate / 1000); + $sample_rate = self::validate_bitrate($media->bitrate / 1000); } debug_event('stream', 'Final transcode bitrate is ' . $sample_rate, 5); - $song_file = scrub_arg($song->file); + $song_file = scrub_arg($media->file); // Finalise the command line $command = $transcode_settings['command']; @@ -145,11 +145,51 @@ public static function start_transcode($song, $type = null, $bitrate=0) foreach ($string_map as $search => $replace) { $command = str_replace($search, $replace, $command, $ret); if (!$ret) { - debug_event('downsample', "$search not in downsample command", 5); + debug_event('stream', "$search not in transcode command", 5); } } - debug_event('downsample', "Downsample command: $command", 3); + return self::start_process($command, array($transcode_settings['format'])); + } + + public static function get_image_preview($media) + { + $image = null; + $sec = ($media->time >= 30) ? 30 : intval($media->time / 2); + $frame = '00:00:' . sprintf("%02d", $sec) . '.0'; + + if (AmpConfig::get('transcode_cmd') && AmpConfig::get('encode_get_image')) { + + $command = AmpConfig::get('transcode_cmd') . ' ' . AmpConfig::get('encode_get_image'); + $string_map = array( + '%FILE%' => scrub_arg($media->file), + '%TIME%' => $frame + ); + foreach ($string_map as $search => $replace) { + $command = str_replace($search, $replace, $command, $ret); + if (!$ret) { + debug_event('stream', "$search not in transcode command", 5); + } + } + $proc = self::start_process($command); + + if (is_resource($proc['handle'])) { + $image = ''; + do { + $image .= fread($proc['handle'], 1024); + } while (!feof($proc['handle'])); + fclose($proc['handle']); + } + } else { + debug_event('stream', 'Missing transcode_cmd / encode_get_image parameters to generate media preview.', 3); + } + + return $image; + } + + private static function start_process($command, $settings = array()) + { + debug_event('stream', "Transcode command: " . $command, 3); $descriptors = array(1 => array('pipe', 'w')); if (strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN') { @@ -158,12 +198,13 @@ public static function start_transcode($song, $type = null, $bitrate=0) } $process = proc_open($command, $descriptors, $pipes); - return array( + $parray = array( 'process' => $process, 'handle' => $pipes[1], - 'stderr' => $pipes[2], - 'format' => $transcode_settings['format'] + 'stderr' => $pipes[2] ); + + return array_merge($parray, $settings); } /** diff --git a/lib/class/stream_playlist.class.php b/lib/class/stream_playlist.class.php index 106ba3b6e0..5206bb1103 100644 --- a/lib/class/stream_playlist.class.php +++ b/lib/class/stream_playlist.class.php @@ -143,7 +143,7 @@ public static function media_to_urlarray($media, $additional_params='') $url['title'] = 'Video - ' . $object->title; $url['author'] = $object->f_artist_full; break; - case 'radio': + case 'live_stream': $url['title'] = 'Radio - ' . $object->name; if (!empty($object->site_url)) { $url['title'] .= ' (' . $object->site_url . ')'; diff --git a/lib/class/tag.class.php b/lib/class/tag.class.php index 9f8236b75e..c5181babbf 100644 --- a/lib/class/tag.class.php +++ b/lib/class/tag.class.php @@ -654,4 +654,9 @@ public function get_user_owner() return null; } + public function get_default_art_kind() + { + return 'default'; + } + } // end of Tag class diff --git a/lib/class/tvshow.class.php b/lib/class/tvshow.class.php index 8ad0f74729..857af18ddc 100644 --- a/lib/class/tvshow.class.php +++ b/lib/class/tvshow.class.php @@ -190,6 +190,10 @@ public function get_keywords() $keywords['tvshow'] = array('important' => true, 'label' => T_('TV Show'), 'value' => $this->f_name); + $keywords['type'] = array('important' => false, + 'label' => null, + 'value' => 'tvshow' + ); return $keywords; } @@ -214,6 +218,11 @@ public function get_user_owner() return null; } + public function get_default_art_kind() + { + return 'default'; + } + /** * check * diff --git a/lib/class/tvshow_episode.class.php b/lib/class/tvshow_episode.class.php index 29713741ef..9bd8765435 100644 --- a/lib/class/tvshow_episode.class.php +++ b/lib/class/tvshow_episode.class.php @@ -172,13 +172,17 @@ public function get_keywords() 'label' => T_('Episode'), 'value' => $this->episode_number); } + $keywords['type'] = array('important' => false, + 'label' => null, + 'value' => 'tvshow' + ); return $keywords; } public function get_parent() { - return array('tvshow_season', $this->season); + return array('type' => 'tvshow_season', 'id' => $this->season); } } diff --git a/lib/class/tvshow_season.class.php b/lib/class/tvshow_season.class.php index b7c8c81f9a..ff66fe7383 100644 --- a/lib/class/tvshow_season.class.php +++ b/lib/class/tvshow_season.class.php @@ -152,6 +152,10 @@ public function get_keywords() $keywords['tvshow_season'] = array('important' => false, 'label' => T_('Season'), 'value' => $this->season_number); + $keywords['type'] = array('important' => false, + 'label' => null, + 'value' => 'tvshow' + ); return $keywords; } @@ -163,7 +167,7 @@ public function get_fullname() public function get_parent() { - return array('tvshow', $this->tvshow); + return array('type' => 'tvshow', 'id' => $this->tvshow); } public function get_childrens() @@ -176,6 +180,11 @@ public function get_user_owner() return null; } + public function get_default_art_kind() + { + return 'default'; + } + /** * check * diff --git a/lib/class/update.class.php b/lib/class/update.class.php index 9a9837e3cb..e3a261d39c 100644 --- a/lib/class/update.class.php +++ b/lib/class/update.class.php @@ -2768,6 +2768,9 @@ public static function update_370009() $sql = "INSERT INTO `user_preference` VALUES (-1,?,'1')"; Dba::write($sql, array($id)); + $sql = "ALTER TABLE `image` ADD `kind` VARCHAR( 32 ) NULL DEFAULT 'default' AFTER `object_id`"; + Dba::write($sql); + return true; } } diff --git a/lib/class/userflag.class.php b/lib/class/userflag.class.php index 021462c832..044b23cabc 100644 --- a/lib/class/userflag.class.php +++ b/lib/class/userflag.class.php @@ -91,7 +91,7 @@ public static function build_cache($type, $ids, $user_id = null) */ public static function gc() { - foreach (array('song', 'album', 'artist', 'video', 'tvshow', 'tvshow_season', 'tvshow_episode', 'movie') as $object_type) { + foreach (array('song', 'album', 'artist', 'video', 'tvshow', 'tvshow_season') as $object_type) { Dba::write("DELETE FROM `user_flag` USING `user_flag` LEFT JOIN `$object_type` ON `$object_type`.`id` = `user_flag`.`object_id` WHERE `object_type` = '$object_type' AND `$object_type`.`id` IS NULL"); } } diff --git a/lib/class/video.class.php b/lib/class/video.class.php index f91c354222..bcae4ec133 100644 --- a/lib/class/video.class.php +++ b/lib/class/video.class.php @@ -168,6 +168,11 @@ public function get_user_owner() return null; } + public function get_default_art_kind() + { + return 'preview'; + } + /** * gc * @@ -185,38 +190,30 @@ public static function gc() public function get_stream_types() { - return array('native'); - - } // native_stream + return Song::get_stream_types_for_type($this->type); + } /** * play_url * This returns a "PLAY" url for the video in question here, this currently feels a little * like a hack, might need to adjust it in the future */ - public static function play_url($oid, $additional_params='',$sid='',$force_http='') + public static function play_url($oid, $additional_params='') { - $video = new Video($oid); - - if (!$video->id) { return false; } - - $uid = $GLOBALS['user']->id ? scrub_out($GLOBALS['user']->id) : '-1'; - $oid = intval($video->id); - - $url = Stream::get_base_url() . "type=video&uid=" . $uid . "&oid=" . $oid; - - return Stream_URL::format($url . $additional_params); + return Song::generic_play_url('video', $oid, $additional_params); + } - } // play_url + public function get_stream_name() + { + return $this->title; + } /** * get_transcode_settings - * - * FIXME: Video transcoding is not implemented */ public function get_transcode_settings($target = null) { - return false; + return Song::get_transcode_settings_for_media($this->type, $target, 'video'); } private static function get_derived_types() @@ -249,6 +246,7 @@ public static function type_to_mime($type) case 'avi': return 'video/avi'; case 'ogg': + case 'ogv': return 'application/ogg'; case 'wmv': return 'audio/x-ms-wmv'; @@ -257,6 +255,19 @@ public static function type_to_mime($type) return 'video/mp4'; case 'mkv': return 'video/x-matroska'; + case 'mkv': + return 'video/x-matroska'; + case 'mov': + return 'video/quicktime'; + case 'divx': + return 'video/x-divx'; + case 'webm': + return 'video/webm'; + case 'flv': + return 'video/x-flv'; + case 'mpg': + case 'mpeg': + case 'm2ts': default: return 'video/mpeg'; } @@ -328,4 +339,18 @@ public function update($data) } // update + /* + * generate_preview + * Generate video preview image from a video file + */ + public static function generate_preview($video_id, $overwrite = false) + { + if ($overwrite || !Art::has_db($video_id, 'video', 'preview')) { + $artp = new Art($video_id, 'video', 'preview'); + $video = new Video($video_id); + $image = Stream::get_image_preview($video); + $artp->insert($image, 'image/png'); + } + } + } // end Video class diff --git a/lib/class/webplayer.class.php b/lib/class/webplayer.class.php index 04f2c13c99..661651bdcd 100644 --- a/lib/class/webplayer.class.php +++ b/lib/class/webplayer.class.php @@ -83,24 +83,24 @@ protected static function get_types($item, $force_type='') } } - $song = null; + $media = null; $urlinfo = Stream_URL::parse($item->url); - if ($urlinfo['id'] && $urlinfo['type'] == 'song') { - $song = new Song($urlinfo['id']); + if ($urlinfo['id'] && Catalog::is_media($urlinfo['type'])) { + $media = new $urlinfo['type']($urlinfo['id']); } else if ($urlinfo['id'] && $urlinfo['type'] == 'song_preview') { - $song = new Song_Preview($urlinfo['id']); + $media = new Song_Preview($urlinfo['id']); } else if (isset($urlinfo['demo_id'])) { $democratic = new Democratic($urlinfo['demo_id']); if ($democratic->id) { $song_id = $democratic->get_next_object(); if ($song_id) { - $song = new Song($song_id); + $media = new Song($song_id); } } } - if ($song != null) { - $ftype = $song->type; + if ($media != null) { + $ftype = $media->type; $transcode = false; $transcode_cfg = AmpConfig::get('transcode'); @@ -110,12 +110,12 @@ protected static function get_types($item, $force_type='') if ($transcode_cfg == 'always' || !empty($force_type) || $ftype_transcode == 'required' || ($types['real'] != $ftype && !AmpConfig::get('webplayer_flash'))) { if ($transcode_cfg == 'always' || ($transcode_cfg != 'never' && in_array('transcode', $valid_types))) { // Transcode only if excepted type available - $transcode_settings = $song->get_transcode_settings($types['real']); + $transcode_settings = $media->get_transcode_settings($types['real']); if ($transcode_settings && AmpConfig::get('transcode_player_customize')) { $transcode = true; } else { if (!in_array('native', $valid_types)) { - $transcode_settings = $song->get_transcode_settings(null); + $transcode_settings = $media->get_transcode_settings(null); if ($transcode_settings) { $types['real'] = $transcode_settings['format']; $transcode = true; @@ -128,16 +128,16 @@ protected static function get_types($item, $force_type='') if (!$transcode) { $types['real'] = $ftype; } - if ($types['real'] == "flac" || $types['real'] == "ogg") $types['player'] = "oga"; - else if ($types['real'] == "mp4") $types['player'] = "m4a"; - } else if ($urlinfo['id'] && $urlinfo['type'] == 'video') { - $video = new Video($urlinfo['id']); - $types['real'] = pathinfo($video->file, PATHINFO_EXTENSION); - - if ($types['real'] == "ogg") $types['player'] = "ogv"; - else if ($types['real'] == "webm") $types['player'] = "webmv"; - else if ($types['real'] == "mp4") $types['player'] = "m4v"; - } else if ($item->type == 'radio') { + + if ($urlinfo['type'] == 'song') { + if ($types['real'] == "flac" || $types['real'] == "ogg") $types['player'] = "oga"; + else if ($types['real'] == "mp4") $types['player'] = "m4a"; + } else if ($urlinfo['type'] == 'video') { + if ($types['real'] == "ogg") $types['player'] = "ogv"; + else if ($types['real'] == "webm") $types['player'] = "webmv"; + else if ($types['real'] == "mp4") $types['player'] = "m4v"; + } + } else if ($item->type == 'live_stream') { $types['real'] = $item->codec; if ($types['real'] == "flac" || $types['real'] == "ogg") $types['player'] = "oga"; } else { diff --git a/lib/install.lib.php b/lib/install.lib.php index 163ccd8eb1..1d8c79186d 100644 --- a/lib/install.lib.php +++ b/lib/install.lib.php @@ -399,13 +399,21 @@ function install_config_transcode_mode($mode) 'transcode_flac' => 'required', 'transcode_mpc' => 'required', 'transcode_ogg' => 'allowed', - 'transcode_wav' => 'required' + 'transcode_wav' => 'required', + 'transcode_avi' => 'allowed', + 'transcode_mpg' => 'allowed', + 'transcode_mkv' => 'allowed', ); if ($mode == 'ffmpeg' || $mode == 'avconv') { $trconfig['transcode_cmd'] = $mode . ' -i %FILE%'; $trconfig['encode_args_mp3'] = '-vn -b:a %SAMPLE%K -c:a libmp3lame -f mp3 pipe:1'; $trconfig['encode_args_ogg'] = '-vn -b:a %SAMPLE%K -c:a libvorbis -f ogg pipe:1'; $trconfig['encode_args_wav'] = '-vn -b:a %SAMPLE%K -c:a pcm_s16le -f wav pipe:1'; + $trconfig['encode_args_flv'] = '-b:a %SAMPLE%K -ar 44100 -ac 2 -v 0 -f flv -c:v libx264 -preset superfast pipe:1'; + $trconfig['encode_get_image'] = '-ss %TIME% -f image2 -vframes 1 pipe:1'; + $trconfig['waveform'] = 'true'; + $trconfig['generate_video_preview'] = 'true'; + AmpConfig::set_by_array($trconfig, true); } } diff --git a/modules/catalog/local.catalog.php b/modules/catalog/local.catalog.php index 19cc989482..93e5a716f0 100644 --- a/modules/catalog/local.catalog.php +++ b/modules/catalog/local.catalog.php @@ -362,14 +362,14 @@ public function add_files($path, $options) } // if it's a playlist else { - if ($is_audio_file) { - if (count($this->get_gather_types('music')) > 0) { - $this->insert_local_song($full_file, $options); + if (count($this->get_gather_types('music')) > 0) { + if ($is_audio_file) { + $this->insert_local_song($full_file, $options); } else { debug_event('read', $full_file . " ignored, bad media type for this catalog.", 5); } - } else { - if (count($this->get_gather_types('video')) > 0) { + } else if (count($this->get_gather_types('video')) > 0) { + if ($is_video_file) { $this->insert_local_video($full_file, $options); } else { debug_event('read', $full_file . " ignored, bad media type for this catalog.", 5); @@ -377,7 +377,7 @@ public function add_files($path, $options) } $this->count++; - $file = str_replace(array('(',')','\''),'',$full_file); + $file = str_replace(array('(', ')', '\''), '', $full_file); if (UI::check_ticker()) { UI::update_text('add_count_' . $this->id, $this->count); UI::update_text('add_dir_' . $this->id, scrub_out($file)); @@ -720,6 +720,10 @@ public function insert_local_video($file, $options = array()) if ($results['art']) { $art = new Art($id, 'video'); $art->insert_url($results['art']); + + if (AmpConfig::get('generate_video_preview')) { + Video::generate_preview($id); + } } else { $this->added_videos_to_gather[] = $id; } diff --git a/modules/localplay/httpq.controller.php b/modules/localplay/httpq.controller.php index 71291493ce..ac25067abd 100644 --- a/modules/localplay/httpq.controller.php +++ b/modules/localplay/httpq.controller.php @@ -478,7 +478,7 @@ public function get() $filename = Dba::escape($entry['file']); $sql = "SELECT `id`,'song' AS `type` FROM `song` WHERE `file` LIKE '%$filename' " . "UNION ALL " . - "SELECT `id`,'radio' AS `type` FROM `live_stream` WHERE `url`='$filename' "; + "SELECT `id`,'live_stream' AS `type` FROM `live_stream` WHERE `url`='$filename' "; $db_results = Dba::read($sql); if ($row = Dba::fetch_assoc($db_results)) { @@ -489,7 +489,7 @@ public function get() $data['name'] = $media->f_title . ' - ' . $media->f_album . ' - ' . $media->f_artist; $data['link'] = $media->f_link; break; - case 'radio': + case 'live_stream': $frequency = $media->frequency ? '[' . $media->frequency . ']' : ''; $site_url = $media->site_url ? '(' . $media->site_url . ')' : ''; $data['name'] = "$media->name $frequency $site_url"; diff --git a/modules/localplay/mpd.controller.php b/modules/localplay/mpd.controller.php index 190da01df4..08fec64b73 100644 --- a/modules/localplay/mpd.controller.php +++ b/modules/localplay/mpd.controller.php @@ -479,7 +479,7 @@ public function get() $filename = Dba::escape($entry['file']); $sql = "SELECT `id`,'song' AS `type` FROM `song` WHERE `file` LIKE '%$filename' " . "UNION ALL " . - "SELECT `id`,'radio' AS `type` FROM `live_stream` WHERE `url`='$filename' "; + "SELECT `id`,'live_stream' AS `type` FROM `live_stream` WHERE `url`='$filename' "; $db_results = Dba::read($sql); if ($row = Dba::fetch_assoc($db_results)) { @@ -490,7 +490,7 @@ public function get() $data['name'] = $media->f_title . ' - ' . $media->f_album . ' - ' . $media->f_artist; $data['link'] = $media->f_link; break; - case 'radio': + case 'live_stream': $frequency = $media->frequency ? '[' . $media->frequency . ']' : ''; $site_url = $media->site_url ? '(' . $media->site_url . ')' : ''; $data['name'] = "$media->name $frequency $site_url"; diff --git a/modules/plugins/Tmdb.plugin.php b/modules/plugins/Tmdb.plugin.php index 732b4a4b4d..9702e082f0 100644 --- a/modules/plugins/Tmdb.plugin.php +++ b/modules/plugins/Tmdb.plugin.php @@ -187,6 +187,7 @@ public function get_metadata($gather_types, $media_info) { public function gather_arts($type, $options = array(), $limit = 5) { + debug_event('Tmdb', 'gather_arts for type `' . $type . '`', 5); return Art::gather_metadata_plugin($this, $type, $options); } diff --git a/play/index.php b/play/index.php index beb7802bba..b42ce4fcd0 100644 --- a/play/index.php +++ b/play/index.php @@ -33,12 +33,8 @@ /* These parameters had better come in on the url. */ $uid = scrub_in($_REQUEST['uid']); -$oid = $_REQUEST['oid'] - // FIXME: Any place that doesn't use oid should be fixed - ? scrub_in($_REQUEST['oid']) - : scrub_in($_REQUEST['song']); +$oid = scrub_in($_REQUEST['oid']); $sid = scrub_in($_REQUEST['ssid']); -$video = make_bool($_REQUEST['video']); $type = scrub_in($_REQUEST['type']); if (AmpConfig::get('transcode_player_customize')) { @@ -50,13 +46,7 @@ } $share_id = scrub_in($_REQUEST['share_id']); -if ($video) { - // FIXME: Compatibility hack, should eventually be removed - $type = 'video'; -} - if (!$type) { - // FIXME: Compatibility hack, should eventually be removed $type = 'song'; } @@ -222,6 +212,7 @@ $media = new Song_Preview($oid); $media->format(); } else { + $type = 'video'; $media = new Video($oid); $media->format(); } @@ -230,18 +221,18 @@ // Build up the catalog for our current object $catalog = Catalog::create_from_id($media->catalog); - /* If the song is disabled */ + /* If the media is disabled */ if (!make_bool($media->enabled)) { debug_event('Play', "Error: $media->file is currently disabled, song skipped", '5'); // Check to see if this is a democratic playlist, if so remove it completely - if ($demo_id && isset($democratic)) { $democratic->delete_from_oid($oid, 'song'); } + if ($demo_id && isset($democratic)) { $democratic->delete_from_oid($oid, $type); } header('HTTP/1.1 404 File Disabled'); exit; } - // If we are running in Legalize mode, don't play songs already playing + // If we are running in Legalize mode, don't play medias already playing if (AmpConfig::get('lock_songs')) { - if (!Stream::check_lock_media($media->id,get_class($media))) { + if (!Stream::check_lock_media($media->id, $type)) { exit; } } @@ -255,7 +246,7 @@ if ($media == null) { // Handle democratic removal if ($demo_id && isset($democratic)) { - $democratic->delete_from_oid($oid, 'song'); + $democratic->delete_from_oid($oid, $type); } exit; } @@ -264,24 +255,24 @@ if (!$media->file || !Core::is_readable(Core::conv_lc_file($media->file))) { // We need to make sure this isn't democratic play, if it is then remove - // the song from the vote list + // the media from the vote list if (is_object($tmp_playlist)) { $tmp_playlist->delete_track($oid); } // FIXME: why are these separate? - // Remove the song votes if this is a democratic song - if ($demo_id && isset($democratic)) { $democratic->delete_from_oid($oid, 'song'); } + // Remove the media votes if this is a democratic song + if ($demo_id && isset($democratic)) { $democratic->delete_from_oid($oid, $type); } - debug_event('play', "Song $media->file ($media->title) does not have a valid filename specified", 2); - header('HTTP/1.1 404 Invalid song, file not found or file unreadable'); + debug_event('play', "Media $media->file ($media->title) does not have a valid filename specified", 2); + header('HTTP/1.1 404 Invalid media, file not found or file unreadable'); exit; } -// don't abort the script if user skips this song because we need to update now_playing +// don't abort the script if user skips this media because we need to update now_playing ignore_user_abort(true); -// Format the song name -$media_name = $media->f_artist_full . " - " . $media->title . "." . $media->type; +// Format the media name +$media_name = $media->get_stream_name() . "." . $media->type; header('Access-Control-Allow-Origin: *'); @@ -345,7 +336,7 @@ $cpaction = $_REQUEST['custom_play_action']; // Determine whether to transcode $transcode = false; -// transcode_to should only have an effect if the song is the wrong format +// transcode_to should only have an effect if the media is the wrong format $transcode_to = $transcode_to == $media->type ? null : $transcode_to; debug_event('play', 'Custom play action {'.$cpaction.'}', 5); @@ -393,8 +384,7 @@ if ($transcode) { // Content-length guessing if required by the player. // Otherwise it shouldn't be used as we are not really sure about final length when transcoding - // Should also support video, but video implementation as to be reviewed first! - if (get_class($media) == 'Song' && $_REQUEST['content_length'] == 'required') { + if ($_REQUEST['content_length'] == 'required') { $max_bitrate = Stream::get_allowed_bitrate($media); if ($media->time > 0 && $max_bitrate > 0) { $stream_size = ($media->time * $max_bitrate * 1000) / 8; @@ -416,7 +406,7 @@ header('ETag: ' . $media->id); // Put this song in the now_playing table only if it's a song for now... -if (get_class($media) == 'Song') { +if ($type == 'song') { Stream::insert_now_playing($media->id, $uid, $media->time, $sid, get_class($media)); } @@ -490,7 +480,7 @@ debug_event('play', 'Content-Range doesn\'t start from 0, stats should already be registered previously; not collecting stats', 5); } else if ($real_bytes_streamed > 0) { // FIXME: support other media types - if (get_class($media) == 'Song' && empty($share_id)) { + if ($type == 'song' && empty($share_id)) { if ($_SERVER['REQUEST_METHOD'] != 'HEAD') { debug_event('play', 'Registering stats for {'.$media->title.'}...', '5'); $sessionkey = Stream::$session; @@ -505,7 +495,7 @@ // If this is a democratic playlist remove the entry. // We do this regardless of play amount. -if ($demo_id && isset($democratic)) { $democratic->delete_from_oid($oid,'song'); } +if ($demo_id && isset($democratic)) { $democratic->delete_from_oid($oid, $type); } if ($transcode && isset($transcoder)) { if (strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN') { diff --git a/server/ajax.server.php b/server/ajax.server.php index 22b8b325db..03019e77cd 100644 --- a/server/ajax.server.php +++ b/server/ajax.server.php @@ -168,7 +168,7 @@ $object = new Live_Stream($_REQUEST['id']); // Confirm its a valid ID if ($object->name) { - $GLOBALS['user']->playlist->add_object($object->id,'radio'); + $GLOBALS['user']->playlist->add_object($object->id, 'live_stream'); } break; case 'video': diff --git a/templates/rightbar.inc.php b/templates/rightbar.inc.php index 87fdc8241a..4c62febeea 100644 --- a/templates/rightbar.inc.php +++ b/templates/rightbar.inc.php @@ -105,7 +105,7 @@ $objects = array_slice($objects, 0, 100, true); } - $normal_array = array('radio', 'song', 'video', 'random', 'song_preview'); + $normal_array = array('live_stream', 'song', 'video', 'random', 'song_preview'); foreach ($objects as $uid=>$object_data) { $type = array_shift($object_data); diff --git a/templates/show_add_catalog.inc.php b/templates/show_add_catalog.inc.php index 8684334d20..c31868b974 100644 --- a/templates/show_add_catalog.inc.php +++ b/templates/show_add_catalog.inc.php @@ -72,7 +72,7 @@ - + diff --git a/templates/show_channels.inc.php b/templates/show_channels.inc.php index 5aacf177b4..6e8bff3214 100644 --- a/templates/show_channels.inc.php +++ b/templates/show_channels.inc.php @@ -54,7 +54,7 @@ - + diff --git a/templates/show_edit_live_stream_row.inc.php b/templates/show_edit_live_stream_row.inc.php index bdc7679700..5b6a4289b9 100644 --- a/templates/show_edit_live_stream_row.inc.php +++ b/templates/show_edit_live_stream_row.inc.php @@ -21,7 +21,7 @@ */ ?>
-
+ diff --git a/templates/show_get_art.inc.php b/templates/show_get_art.inc.php index 29ef864625..f6322661b3 100644 --- a/templates/show_get_art.inc.php +++ b/templates/show_get_art.inc.php @@ -25,7 +25,7 @@
$word) { - if ($key != 'keyword') { + if ($key != 'keyword' && $word['label']) { ?> - - @@ -41,7 +40,7 @@ $libitem->format(); ?> - + @@ -54,7 +53,6 @@ - diff --git a/templates/show_tvshow.inc.php b/templates/show_tvshow.inc.php index 428538b88a..413705c967 100644 --- a/templates/show_tvshow.inc.php +++ b/templates/show_tvshow.inc.php @@ -65,10 +65,6 @@ id . '&append=true', T_('Play all last'),'addplay_tvshow_text_' . $tvshow->id); ?> -
  • - id,'add', T_('Add all to temporary playlist'),'add_' . $tvshow->id); ?> - id, T_('Add all to temporary playlist'),'add_text_' . $tvshow->id); ?> -
  • diff --git a/templates/show_tvshow_row.inc.php b/templates/show_tvshow_row.inc.php index fe3b847f0a..794bb49f58 100644 --- a/templates/show_tvshow_row.inc.php +++ b/templates/show_tvshow_row.inc.php @@ -39,14 +39,6 @@ - diff --git a/templates/show_tvshow_season.inc.php b/templates/show_tvshow_season.inc.php index 84982d5c58..c9131dccb2 100644 --- a/templates/show_tvshow_season.inc.php +++ b/templates/show_tvshow_season.inc.php @@ -60,10 +60,6 @@ id . '&append=true', T_('Play all last'),'addplay_season_text_' . $season->id); ?> -
  • - id,'add', T_('Add all to temporary playlist'),'add_' . $season->id); ?> - id, T_('Add all to temporary playlist'),'add_text_' . $season->id); ?> -
  • diff --git a/templates/show_tvshow_season_row.inc.php b/templates/show_tvshow_season_row.inc.php index 51dbd96972..c5a3c090d7 100644 --- a/templates/show_tvshow_season_row.inc.php +++ b/templates/show_tvshow_season_row.inc.php @@ -39,14 +39,6 @@ - diff --git a/templates/show_tvshow_seasons.inc.php b/templates/show_tvshow_seasons.inc.php index 927eb1a6a5..c010b41ed8 100644 --- a/templates/show_tvshow_seasons.inc.php +++ b/templates/show_tvshow_seasons.inc.php @@ -32,7 +32,6 @@ - @@ -70,7 +69,6 @@ - diff --git a/templates/show_tvshows.inc.php b/templates/show_tvshows.inc.php index b7a723eff1..6325d3ade5 100644 --- a/templates/show_tvshows.inc.php +++ b/templates/show_tvshows.inc.php @@ -34,7 +34,6 @@ - @@ -75,7 +74,6 @@ - diff --git a/templates/show_video.inc.php b/templates/show_video.inc.php index a45c63d8b4..e74acde1c7 100644 --- a/templates/show_video.inc.php +++ b/templates/show_video.inc.php @@ -24,7 +24,9 @@ f_title . ' ' . T_('Details'), 'box box_video_details'); ?>
    id, $video->f_title, 7); +if (!Art::display('video', $video->id, $video->f_title, 7, null, false)) { + Art::display('video', $video->id, $video->f_title, 8, null, false, 'preview'); +} ?>
    @@ -54,7 +56,6 @@ id . '&append=true','play_add', T_('Play last'),'addplay_video_' . $video->id); ?> - id,'add', T_('Add to temporary playlist'),'add_video_' . $video->id); ?> diff --git a/templates/show_video_row.inc.php b/templates/show_video_row.inc.php index a0fad8ccec..4b37d19fa9 100644 --- a/templates/show_video_row.inc.php +++ b/templates/show_video_row.inc.php @@ -41,14 +41,9 @@
    - diff --git a/templates/show_videos.inc.php b/templates/show_videos.inc.php index a2293cd888..c442ddd39e 100644 --- a/templates/show_videos.inc.php +++ b/templates/show_videos.inc.php @@ -31,7 +31,6 @@ - -
    @@ -61,6 +61,7 @@ + diff --git a/templates/show_live_stream_row.inc.php b/templates/show_live_stream_row.inc.php index cbde48763a..61918a59c2 100644 --- a/templates/show_live_stream_row.inc.php +++ b/templates/show_live_stream_row.inc.php @@ -29,16 +29,11 @@ f_name_link; ?> - - id,'add', T_('Add to temporary playlist'),'add_radio_' . $libitem->id); ?> - - f_url_link; ?> codec; ?> - + diff --git a/templates/show_live_streams.inc.php b/templates/show_live_streams.inc.php index a4225e6ef3..5bfd5c6484 100644 --- a/templates/show_live_streams.inc.php +++ b/templates/show_live_streams.inc.php @@ -28,7 +28,6 @@
    id . '&sort=name', T_('Name'),'live_stream_sort_name'); ?> id . '&sort=codec', T_('Codec'),'live_stream_codec'); ?>
    id . '&sort=name', T_('Name'),'live_stream_sort_name'); ?> id . '&sort=codec', T_('Codec'),'live_stream_codec_bottom'); ?> f_link; ?> - - id,'add', T_('Add to temporary playlist'),'add_artist_' . $libitem->id); ?> - - - - - episodes; ?> seasons; ?> f_tags; ?>f_link; ?> - - id,'add', T_('Add to temporary playlist'),'add_season_' . $libitem->id); ?> - - - - - f_tvshow_link; ?> episodes; ?> id . '&sort=season', T_('Season'),'season_sort_season'); ?> id . '&sort=tvshow', T_('TV Show'),'season_sort_tvshow'); ?> id . '&sort=season', T_('Season'),'season_sort_name_bottom'); ?> id . '&sort=tvshow', T_('TV Show'),'season_sort_artist_bottom'); ?> id . '&type=tvshow&sort=name', T_('TV Show'),'tvshow_sort_name'); ?> id . '&type=tvshow&sort=name', T_('TV Show'),'tvshow_sort_name'); ?> f_link; ?> - - id,'add', T_('Add to temporary playlist'),'add_video_' . $libitem->id); ?> - - f_codec; ?> id . '&type=video&sort=title', T_('Title'),'sort_video_title'); ?> id . '&type=video&sort=title', T_('Title'),'sort_video_title'); ?>