diff --git a/admin/catalog.php b/admin/catalog.php index 0bf59942..c37ab67f 100644 --- a/admin/catalog.php +++ b/admin/catalog.php @@ -275,7 +275,7 @@ switch ($_REQUEST['action']) { $catalog->format(); require_once AmpConfig::get('prefix') . '/templates/show_edit_catalog.inc.php'; break; - case 'gather_album_art': + case 'gather_media_art': toggle_visible('ajax-loading'); ob_end_flush(); @@ -289,7 +289,7 @@ switch ($_REQUEST['action']) { $catalog->gather_art(); } $url = AmpConfig::get('web_path') . '/admin/catalog.php'; - $title = T_('Album Art Search Finished'); + $title = T_('Media Art Search Finished'); $body = ''; show_confirmation($title,$body,$url); break; diff --git a/bin/catalog_update.inc b/bin/catalog_update.inc index 5807f3f1..32c3bf92 100644 --- a/bin/catalog_update.inc +++ b/bin/catalog_update.inc @@ -127,8 +127,8 @@ while ($row = Dba::fetch_row($db_results)) { $catalog->add_to_catalog($options); echo "----------------\n\n"; } elseif ($artadd == 1) { - // Look for album art - echo T_('Starting Album Art Search'); + // Look for media art + echo T_('Starting Media Art Search'); echo "\n"; $catalog->gather_art(); echo "----------------\n\n"; diff --git a/bin/sort_files.inc b/bin/sort_files.inc index 32986d50..94fba5b2 100644 --- a/bin/sort_files.inc +++ b/bin/sort_files.inc @@ -65,7 +65,6 @@ while ($r = Dba::fetch_row($db_results)) { foreach ($songs as $song) { /* Find this poor song a home */ $song->format(); - $song->format_pattern(); $directory = sort_find_home($song,$catalog->sort_pattern,$catalog->path); $filename = $song->f_file; $fullpath = $directory . "/" . $filename; diff --git a/browse.php b/browse.php index 79a666d9..d7934b03 100644 --- a/browse.php +++ b/browse.php @@ -53,6 +53,8 @@ switch ($_REQUEST['action']) { case 'tvshow_season': case 'tvshow_episode': case 'movie': + case 'clip': + case 'personal_video': $browse->set_type($_REQUEST['action']); $browse->set_simple_browse(true); break; @@ -156,17 +158,12 @@ switch ($_REQUEST['action']) { $browse->show_objects(); break; case 'tvshow_episode': - if (AmpConfig::get('catalog_disable')) { - $browse->set_filter('catalog_enabled', '1'); - } - $browse->set_sort('title','ASC'); - $browse->show_objects(); - break; case 'movie': + case 'clip': + case 'personal_video': if (AmpConfig::get('catalog_disable')) { $browse->set_filter('catalog_enabled', '1'); } - $browse->set_sort('title','ASC'); $browse->show_objects(); break; default: diff --git a/config/ampache.cfg.php.dist b/config/ampache.cfg.php.dist index fdda165d..e1e6897e 100644 --- a/config/ampache.cfg.php.dist +++ b/config/ampache.cfg.php.dist @@ -7,7 +7,7 @@ ; if this config file is up to date ; this is compared against a value hard-coded ; into the init script -config_version = 16 +config_version = 17 ;################### ; Path Vars # @@ -128,7 +128,7 @@ catalog_file_pattern = "mp3|mpc|m4p|m4a|mp4|aac|ogg|rm|wma|asf|flac|spx|ra|ape|s ; 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" +catalog_video_pattern = "avi|mpg|flv|m4v|webm|mkv" ; Playlist Pattern ; This defines which playlist types Ampache will attempt to catalog @@ -266,7 +266,14 @@ getid3_tag_order = "id3v2,id3v1,vorbiscomment,quicktime,matroska,ape,asf,avi,mpe ; POSSIBLE VALUES (builtins): filename and getID3 ; POSSIBLE VALUES (plugins): MusicBrainz, plus any others you've installed. ; DEFAULT: getID3 filename -metadata_order = "getID3,filename,MusicBrainz,TMDb" +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. +; DEFAULT: filename getID3 +metadata_order_video = "filename,getID3" ; Un comment if don't want ampache to follow symlinks ; DEFAULT: false diff --git a/lib/class/artist.class.php b/lib/class/artist.class.php index 33b93d0b..80281741 100644 --- a/lib/class/artist.class.php +++ b/lib/class/artist.class.php @@ -102,7 +102,8 @@ class Artist extends database_object Dba::write('DELETE FROM `artist` USING `artist` LEFT JOIN `song` ON `song`.`artist` = `artist`.`id` ' . 'LEFT JOIN `song` AS `song2` ON `song2`.`album_artist` = `artist`.`id` ' . 'LEFT JOIN `wanted` ON `wanted`.`artist` = `artist`.`id` ' . - 'WHERE `song`.`id` IS NULL AND `song2`.`id` IS NULL AND `wanted`.`id` IS NULL'); + 'LEFT JOIN `clip` ON `clip`.`artist` = `artist`.`id` ' . + 'WHERE `song`.`id` IS NULL AND `song2`.`id` IS NULL AND `wanted`.`id` IS NULL AND `clip`.`id` IS NULL'); } /** diff --git a/lib/class/browse.class.php b/lib/class/browse.class.php index a0536d78..b0e2e008 100644 --- a/lib/class/browse.class.php +++ b/lib/class/browse.class.php @@ -245,11 +245,23 @@ class Browse extends Query break; case 'tvshow_episode': $box_title = T_('Episodes'); - $box_req = AmpConfig::get('prefix') . '/templates/show_tvshow_episodes.inc.php'; + $video_type = 'TVShow_Episode'; + $box_req = AmpConfig::get('prefix') . '/templates/show_videos.inc.php'; break; case 'movie': $box_title = T_('Movies'); - $box_req = AmpConfig::get('prefix') . '/templates/show_movies.inc.php'; + $video_type = 'Movie'; + $box_req = AmpConfig::get('prefix') . '/templates/show_videos.inc.php'; + break; + case 'clip': + $box_title = T_('Clips'); + $video_type = 'Clip'; + $box_req = AmpConfig::get('prefix') . '/templates/show_videos.inc.php'; + break; + case 'personal_video': + $box_title = T_('Personal Videos'); + $video_type = 'Personal_Video'; + $box_req = AmpConfig::get('prefix') . '/templates/show_videos.inc.php'; break; default: // Rien a faire diff --git a/lib/class/catalog.class.php b/lib/class/catalog.class.php index e53dbf5b..06d68d06 100644 --- a/lib/class/catalog.class.php +++ b/lib/class/catalog.class.php @@ -398,10 +398,9 @@ abstract class Catalog extends database_object */ public static function get_stats($catalog_id = null) { - $results = self::count_songs($catalog_id); + $results = self::count_medias($catalog_id); $results = array_merge(User::count(), $results); $results['tags'] = self::count_tags(); - $results['videos'] = self::count_videos($catalog_id); $hours = floor($results['time'] / 3600); @@ -431,6 +430,7 @@ abstract class Catalog extends database_object $type = $data['type']; $rename_pattern = $data['rename_pattern']; $sort_pattern = $data['sort_pattern']; + $gather_types = $data['gather_media']; $insert_id = 0; $filename = AmpConfig::get('prefix') . '/modules/catalog/' . $type . '.catalog.php'; @@ -438,12 +438,13 @@ abstract class Catalog extends database_object if ($include) { $sql = 'INSERT INTO `catalog` (`name`, `catalog_type`, ' . - '`rename_pattern`, `sort_pattern`) VALUES (?, ?, ?, ?)'; + '`rename_pattern`, `sort_pattern`, `gather_types`) VALUES (?, ?, ?, ?, ?)'; Dba::write($sql, array( $name, $type, $rename_pattern, - $sort_pattern + $sort_pattern, + $gather_types )); $insert_id = Dba::insert_id(); @@ -464,17 +465,17 @@ abstract class Catalog extends database_object return $insert_id; } - - public static function insert_video($id, $gtypes, $results) { - + + public static function insert_video($gtypes, $results) + { if (count($gtypes) > 0) { $gtype = $gtypes[0]; switch ($gtype) { case 'tvshow': - TVShow::insert($id, $results); + TVShow_Episode::insert($results); break; case 'movie': - Movie::insert($id, $results); + Movie::insert($results); break; default: // Do nothing, video entry already created and no additional data for now @@ -483,23 +484,6 @@ abstract class Catalog extends database_object } } - /** - * count_videos - * - * This returns the current number of video files in the database. - */ - public static function count_videos($id = null) - { - $sql = 'SELECT COUNT(`id`) FROM `video` '; - if ($id) { - $sql .= 'WHERE `catalog` = ?'; - } - $db_results = Dba::read($sql, $id ? array($id) : null); - - $row = Dba::fetch_assoc($db_results); - return $row[0]; - } - /** * count_tags * @@ -516,25 +500,32 @@ abstract class Catalog extends database_object } /** - * count_songs + * count_medias * - * This returns the current number of songs, albums, and artists + * This returns the current number of songs, videos, albums, and artists * in this catalog. */ - public static function count_songs($id = null) + public static function count_medias($id = null) { $where_sql = $id ? 'WHERE `catalog` = ?' : ''; $params = $id ? array($id) : null; $sql = 'SELECT COUNT(`id`), SUM(`time`), SUM(`size`) FROM `song` ' . $where_sql; - $db_results = Dba::read($sql, $params); $data = Dba::fetch_row($db_results); $songs = $data[0]; $time = $data[1]; $size = $data[2]; + $sql = 'SELECT COUNT(`id`), SUM(`time`), SUM(`size`) FROM `video` ' . + $where_sql; + $db_results = Dba::read($sql, $params); + $data = Dba::fetch_row($db_results); + $videos = $data[0]; + $time += $data[1]; + $size += $data[2]; + $sql = 'SELECT COUNT(DISTINCT(`album`)) FROM `song` ' . $where_sql; $db_results = Dba::read($sql, $params); $data = Dba::fetch_row($db_results); @@ -557,6 +548,7 @@ abstract class Catalog extends database_object $results = array(); $results['songs'] = $songs; + $results['videos'] = $videos; $results['albums'] = $albums; $results['artists'] = $artists; $results['playlists'] = $playlists; @@ -1094,7 +1086,7 @@ abstract class Catalog extends database_object return $info; } // update_song_from_tags - + public function get_gather_types($media_type) { $gtypes = $this->gather_types; @@ -1105,13 +1097,13 @@ abstract class Catalog extends database_object if ($media_type == "video") { unset($types['music']); } - + if ($media_type == "music") { unset($types['video']); unset($types['movie']); unset($types['tvshow']); } - + return $types; } @@ -1187,6 +1179,7 @@ abstract class Catalog extends database_object Song::gc(); Album::gc(); Artist::gc(); + Video::gc(); Art::gc(); Stats::gc(); Rating::gc(); diff --git a/lib/class/clip.class.php b/lib/class/clip.class.php new file mode 100644 index 00000000..343c8bd0 --- /dev/null +++ b/lib/class/clip.class.php @@ -0,0 +1,114 @@ +get_info($id); + foreach ($info as $key=>$value) { + $this->$key = $value; + } + + return true; + + } // Constructor + + /** + * gc + * + * This cleans out unused clips + */ + public static function gc() + { + $sql = "DELETE FROM `clip` USING `clip` LEFT JOIN `video` ON `video`.`id` = `clip`.`id` " . + "WHERE `video`.`id` IS NULL"; + Dba::write($sql); + } + + /** + * create + * This takes a key'd array of data as input and inserts a new clip entry, it returns the record id + */ + public static function insert($data) + { + $sql = "INSERT INTO `clip` (`id`,`artist`,`song`) " . + "VALUES (?, ?, ?)"; + Dba::write($sql, array($data['id'], $data['artist'], $data['song'])); + + return $data['id']; + + } // create + + /** + * update + * This takes a key'd array of data as input and updates a clip entry + */ + public static function update($data) + { + $sql = "UPDATE `clip` SET `artist` = ?, `song` = ? WHERE `id` = ?"; + Dba::write($sql, array($data['artist'], $data['song'], $data['id'])); + + return true; + + } // update + + /** + * format + * this function takes the object and reformats some values + */ + + public function format() + { + parent::format(); + + if ($this->artist) { + $artist = new Artist($this->artist); + $artist->format(); + $this->f_artist = $artist->f_link; + } + + if ($this->song) { + $song = new Song($this->song); + $song->format(); + $this->f_song = $song->f_link; + } + + return true; + + } //format + +} // Clip class diff --git a/lib/class/daap_api.class.php b/lib/class/daap_api.class.php index 52d57c61..d5931609 100644 --- a/lib/class/daap_api.class.php +++ b/lib/class/daap_api.class.php @@ -262,7 +262,7 @@ class Daap_Api $r = self::tlv('dmap.itemid', 1); $r .= self::tlv('dmap.itemname', 'Ampache'); - $counts = Catalog::count_songs(); + $counts = Catalog::count_medias(); $r .= self::tlv('dmap.itemcount', $counts['songs']); $r .= self::tlv('dmap.containercount', count(Playlist::get_playlists())); $r = self::tlv('dmap.listingitem', $r); diff --git a/lib/class/movie.class.php b/lib/class/movie.class.php index 5e5220f4..096a4c3a 100644 --- a/lib/class/movie.class.php +++ b/lib/class/movie.class.php @@ -27,9 +27,6 @@ class Movie extends Video public $year; public $video; - public $f_link; - public $f_date; - /** * Constructor * This pulls the movie information from the database and returns @@ -38,27 +35,39 @@ class Movie extends Video public function __construct($id) { parent::__construct($id); - + $info = $this->get_info($id); foreach ($info as $key=>$value) { $this->$key = $value; } - + return true; } // Constructor /** - * create - * This takes a key'd array of data as input and inserts a new movie entry, it returns the auto_inc id + * gc + * + * This cleans out unused movies */ - public static function create($data) + public static function gc() { - $sql = "INSERT INTO `movie` (`id`, `name`,`original_name`,`description`, `year`, `release_date`) " . - "VALUES (?, ?, ?, ?, ?, ?)"; - Dba::write($sql, array($data['id'], $data['name'], $data['original_name'], $data['description'], $data['year'], $data['release_date'])); + $sql = "DELETE FROM `movie` USING `movie` LEFT JOIN `video` ON `video`.`id` = `movie`.`id` " . + "WHERE `video`.`id` IS NULL"; + Dba::write($sql); + } - return $insert_id; + /** + * create + * This takes a key'd array of data as input and inserts a new movie entry, it returns the record id + */ + public static function insert($data) + { + $sql = "INSERT INTO `movie` (`id`,`original_name`,`description`, `year`) " . + "VALUES (?, ?, ?, ?)"; + Dba::write($sql, array($data['id'], $data['original_name'], $data['description'], $data['year'])); + + return $data['id']; } // create @@ -68,12 +77,12 @@ class Movie extends Video */ public static function update($data) { - $sql = "UPDATE `movie` SET `name` = ?, `original_name` = ?, `description` = ?, `year` = ?, `release_date` = ? WHERE `id` = ?"; - Dba::write($sql, array($data['name'], $data['original_name'], $data['description'], $data['year'], $data['release_date'], $data['id'])); + $sql = "UPDATE `movie` SET `original_name` = ?, `description` = ?, `year` = ? WHERE `id` = ?"; + Dba::write($sql, array($data['original_name'], $data['description'], $data['year'], $data['id'])); return true; - } // create + } // update /** * format @@ -83,8 +92,11 @@ class Movie extends Video public function format() { parent::format(); + + $this->f_link = '' . ($this->original_name ?: $this->f_title) . ''; + return true; } //format -} // License class +} // Movie class diff --git a/lib/class/personal_video.class.php b/lib/class/personal_video.class.php new file mode 100644 index 00000000..91df3396 --- /dev/null +++ b/lib/class/personal_video.class.php @@ -0,0 +1,103 @@ +get_info($id); + foreach ($info as $key=>$value) { + $this->$key = $value; + } + + return true; + + } // Constructor + + /** + * gc + * + * This cleans out unused personal videos + */ + public static function gc() + { + $sql = "DELETE FROM `personal_video` USING `personal_video` LEFT JOIN `video` ON `video`.`id` = `personal_video`.`id` " . + "WHERE `video`.`id` IS NULL"; + Dba::write($sql); + } + + /** + * create + * This takes a key'd array of data as input and inserts a new personal video entry, it returns the record id + */ + public static function insert($data) + { + $sql = "INSERT INTO `personal_video` (`id`,`location`,`description`) " . + "VALUES (?, ?, ?)"; + Dba::write($sql, array($data['id'], $data['location'], $data['description'])); + + return $data['id']; + + } // create + + /** + * update + * This takes a key'd array of data as input and updates a personal video entry + */ + public static function update($data) + { + $sql = "UPDATE `personal_video` SET `location` = ?, `description` = ? WHERE `id` = ?"; + Dba::write($sql, array($data['location'], $data['description'], $data['id'])); + + return true; + + } // update + + /** + * format + * this function takes the object and reformats some values + */ + + public function format() + { + parent::format(); + + $this->f_location = $this->location; + + return true; + + } //format + +} // Personal_Video class diff --git a/lib/class/preference.class.php b/lib/class/preference.class.php index fbf522cd..43153abf 100644 --- a/lib/class/preference.class.php +++ b/lib/class/preference.class.php @@ -363,7 +363,7 @@ class Preference extends database_object public static function fix_preferences($results) { $arrays = array('auth_methods', 'getid3_tag_order', - 'metadata_order', 'art_order', 'amazon_base_urls'); + 'metadata_order', 'metadata_order_video', 'art_order', 'amazon_base_urls'); foreach ($arrays as $item) { $results[$item] = trim($results[$item]) diff --git a/lib/class/query.class.php b/lib/class/query.class.php index 4de45e2e..ccee071a 100644 --- a/lib/class/query.class.php +++ b/lib/class/query.class.php @@ -310,7 +310,24 @@ class Query 'title', 'resolution', 'length', - 'codec' + 'codec', + 'release_date' + ), + 'clip' => array( + 'title', + 'artist', + 'resolution', + 'length', + 'codec', + 'release_date' + ), + 'personal_video' => array( + 'title', + 'location', + 'resolution', + 'length', + 'codec', + 'release_date' ) ); } @@ -652,6 +669,8 @@ class Query case 'tvshow_season': case 'tvshow_episode': case 'movie': + case 'personal_video': + case 'clip': // Set it $this->_state['type'] = $type; $this->set_base_sql(true, $custom_base); @@ -969,6 +988,14 @@ class Query $this->set_select("`movie`.`id`"); $sql = "SELECT %%SELECT%% FROM `movie` "; break; + case 'clip': + $this->set_select("`clip`.`id`"); + $sql = "SELECT %%SELECT%% FROM `clip` "; + break; + case 'personal_video': + $this->set_select("`personal_video`.`id`"); + $sql = "SELECT %%SELECT%% FROM `personal_video` "; + break; case 'playlist_song': case 'song': default: @@ -1720,17 +1747,8 @@ class Query break; case 'video': switch ($field) { - case 'title': - $sql = "`video`.`title`"; - break; - case 'resolution': - $sql = "`video`.`resolution_x`"; - break; - case 'length': - $sql = "`video`.`time`"; - break; - case 'codec': - $sql = "`video`.`video_codec`"; + default: + $sql = $this->sql_sort_video('video', $field); break; } // end switch break; @@ -1852,22 +1870,6 @@ class Query break; case 'tvshow_episode': switch ($field) { - case 'title': - $sql = "`video`.`title`"; - $this->set_join('left', '`video`', '`tvshow_episode`.`id`', '`video`.`id`', 100); - break; - case 'resolution': - $sql = "`video`.`resolution`"; - $this->set_join('left', '`video`', '`tvshow_episode`.`id`', '`video`.`id`', 100); - break; - case 'length': - $sql = "`video`.`length`"; - $this->set_join('left', '`video`', '`tvshow_episode`.`id`', '`video`.`id`', 100); - break; - case 'codec': - $sql = "`video`.`codec`"; - $this->set_join('left', '`video`', '`tvshow_episode`.`id`', '`video`.`id`', 100); - break; case 'season': $sql = "`tvshow_season`.`season_number`"; $this->set_join('left', '`tvshow_season`', '`tvshow_episode`.`season`', '`tvshow_season`.`id`', 100); @@ -1877,25 +1879,35 @@ class Query $this->set_join('left', '`tvshow_season`', '`tvshow_episode`.`season`', '`tvshow_season`.`id`', 100); $this->set_join('left', '`tvshow`', '`tvshow_season`.`tvshow`', '`tvshow`.`id`', 100); break; + default: + $sql = $this->sql_sort_video('tvshow_episode', $field); + break; } break; case 'movie': switch ($field) { - case 'title': - $sql = "`video`.`title`"; - $this->set_join('left', '`video`', '`movie`.`id`', '`video`.`id`', 100); + default: + $sql = $this->sql_sort_video('movie', $field); break; - case 'resolution': - $sql = "`video`.`resolution`"; - $this->set_join('left', '`video`', '`movie`.`id`', '`video`.`id`', 100); + } + break; + case 'clip': + switch ($field) { + case 'location': + $sql = "`clip`.`artist`"; break; - case 'length': - $sql = "`video`.`length`"; - $this->set_join('left', '`video`', '`movie`.`id`', '`video`.`id`', 100); + default: + $sql = $this->sql_sort_video('clip', $field); break; - case 'codec': - $sql = "`video`.`codec`"; - $this->set_join('left', '`video`', '`movie`.`id`', '`video`.`id`', 100); + } + break; + case 'personal_video': + switch ($field) { + case 'location': + $sql = "`personal_video`.`location`"; + break; + default: + $sql = $this->sql_sort_video('personal_video', $field); break; } break; @@ -1904,12 +1916,42 @@ class Query break; } // end switch - if (isset($sql)) { return "$sql $order,"; } + if (isset($sql) && !empty($sql)) { return "$sql $order,"; } return ""; } // sql_sort + private function sql_sort_video($field, $table) + { + $sql = ""; + switch ($field) { + case 'title': + $sql = "`video`.`title`"; + break; + case 'resolution': + $sql = "`video`.`resolution`"; + break; + case 'length': + $sql = "`video`.`length`"; + break; + case 'codec': + $sql = "`video`.`codec`"; + break; + case 'release_date': + $sql = "`video`.`release_date`"; + break; + } + + if (!empty($sql)) { + if ($table != 'video') { + $this->set_join('left', '`video`', '`' . $table . '`.`id`', '`video`.`id`', 100); + } + } + + return $sql; + } + /** * resort_objects * This takes the existing objects, looks at the current diff --git a/lib/class/song.class.php b/lib/class/song.class.php index 6bb06a8a..a2597803 100644 --- a/lib/class/song.class.php +++ b/lib/class/song.class.php @@ -901,12 +901,6 @@ class Song extends database_object implements media { $this->fill_ext_info(); - // Format the filename - preg_match("/^.*\/(.*?)$/", $this->file, $short); - if (is_array($short) && isset($short[1])) { - $this->f_file = htmlspecialchars($short[1]); - } - // Format the album name $this->f_album_full = $this->get_album_name(); $this->f_album = $this->f_album_full; @@ -927,7 +921,9 @@ class Song extends database_object implements media $this->f_link = "link) . "\" title=\"" . scrub_out($this->f_artist) . " - " . scrub_out($this->title) . "\"> " . scrub_out($this->f_title) . ""; $this->f_album_link = "album . "\" title=\"" . scrub_out($this->f_album_full) . "\"> " . scrub_out($this->f_album) . ""; $this->f_artist_link = "artist . "\" title=\"" . scrub_out($this->f_artist_full) . "\"> " . scrub_out($this->f_artist) . ""; - $this->f_album_artist_link = "album_artist . "\" title=\"" . scrub_out($this->f_album_artist_full) . "\"> " . scrub_out($this->f_album_artist_full) . ""; + if (!empty($this->album_artist)) { + $this->f_album_artist_link = "album_artist . "\" title=\"" . scrub_out($this->f_album_artist_full) . "\"> " . scrub_out($this->f_album_artist_full) . ""; + } // Format the Bitrate $this->f_bitrate = intval($this->bitrate/1000) . "-" . strtoupper($this->mode); @@ -952,48 +948,16 @@ class Song extends database_object implements media $this->f_lyrics = "title) . "\" href=\"" . AmpConfig::get('web_path') . "/song.php?action=show_lyrics&song_id=" . $this->id . "\">" . T_('Show Lyrics') . ""; + $this->f_file = $this->f_artist . ' - '; + if ($this->track) { + $this->f_file .= $this->track . ' - '; + } + $this->f_file .= $this->f_title . '.' . $this->type; + return true; } // format - /** - * format_pattern - * This reformats the song information based on the catalog - * rename patterns - */ - public function format_pattern() - { - $extension = ltrim(substr($this->file,strlen($this->file)-4,4),"."); - - $catalog = Catalog::create_from_id($this->catalog); - - // If we don't have a rename pattern then just return it - if (!trim($catalog->rename_pattern)) { - $this->f_pattern = $this->title; - $this->f_file = $this->title . '.' . $extension; - return; - } - - /* Create the filename that this file should have */ - $album = $this->f_album_full; - $artist = $this->f_artist_full; - $track = sprintf('%02d', $this->track); - $title = $this->title; - $year = $this->year; - - /* Start replacing stuff */ - $replace_array = array('%a','%A','%t','%T','%y','/','\\'); - $content_array = array($artist,$album,$title,$track,$year,'-','-'); - - $rename_pattern = str_replace($replace_array,$content_array,$catalog->rename_pattern); - - $rename_pattern = preg_replace("[\-\:\!]","_",$rename_pattern); - - $this->f_pattern = $rename_pattern; - $this->f_file = $rename_pattern . "." . $extension; - - } // format_pattern - /** * get_fields * This returns all of the 'data' fields for this object, we need to filter out some that we don't diff --git a/lib/class/song_preview.class.php b/lib/class/song_preview.class.php index 5048e98e..d86370b7 100644 --- a/lib/class/song_preview.class.php +++ b/lib/class/song_preview.class.php @@ -194,10 +194,6 @@ class Song_Preview extends database_object implements media */ public function format() { - // Format the filename - preg_match("/^.*\/(.*?)$/",$this->file, $short); - $this->f_file = htmlspecialchars($short[1]); - // Format the artist name if ($this->artist) { $this->f_artist_full = $this->get_artist_name(); diff --git a/lib/class/tvshow.class.php b/lib/class/tvshow.class.php index 3a235087..dcee9ba5 100644 --- a/lib/class/tvshow.class.php +++ b/lib/class/tvshow.class.php @@ -67,7 +67,9 @@ class TVShow extends database_object */ public static function gc() { - + $sql = "DELETE FROM `tvshow` USING `tvshow` LEFT JOIN `tvshow_season` ON `tvshow_season`.`tvshow` = `tvshow`.`id` " . + "WHERE `tvshow_season`.`id` IS NULL"; + Dba::write($sql); } /** @@ -131,7 +133,7 @@ class TVShow extends database_object return $results; } // get_episodes - + /** * _get_extra info * This returns the extra information for the tv show, this means totals etc @@ -142,12 +144,18 @@ class TVShow extends database_object if (parent::is_cached('tvshow_extra', $this->id) ) { $row = parent::get_from_cache('tvshow_extra', $this->id); } else { - $sql = "SELECT DISTINCT(`tvshow_season`.`id`), COUNT(`tvshow_season`.`id`) AS `season_count`, COUNT(`tvshow_episode`.`id`) AS `episode_count` FROM `tvshow_season` " . + $sql = "SELECT COUNT(`tvshow_episode`.`id`) AS `episode_count` FROM `tvshow_season` " . "LEFT JOIN `tvshow_episode` ON `tvshow_episode`.`season` = `tvshow_season`.`id` " . "WHERE `tvshow_season`.`tvshow` = ?"; - $db_results = Dba::read($sql, array($this->id)); $row = Dba::fetch_assoc($db_results); + + $sql = "SELECT COUNT(`tvshow_season`.`id`) AS `season_count` FROM `tvshow_season` " . + "WHERE `tvshow_season`.`tvshow` = ?"; + $db_results = Dba::read($sql, array($this->id)); + $row2 = Dba::fetch_assoc($db_results); + $row['season_count'] = $row2['season_count']; + parent::add_to_cache('tvshow_extra',$this->id,$row); } @@ -158,7 +166,7 @@ class TVShow extends database_object return $row; } // _get_extra_info - + /** * format * this function takes the object and reformats some values @@ -168,11 +176,11 @@ class TVShow extends database_object $this->f_name = $this->name; $this->link = AmpConfig::get('web_path') . '/tvshows.php?action=show&tvshow=' . $this->id; $this->f_link = '' . $this->f_name . ''; - + $this->_get_extra_info($this->catalog_id); $this->tags = Tag::get_top_tags('tvshow', $this->id); $this->f_tags = Tag::get_display($this->tags, true, 'tvshow'); - + return true; } diff --git a/lib/class/tvshow_episode.class.php b/lib/class/tvshow_episode.class.php index d4c8dae3..2369fb17 100644 --- a/lib/class/tvshow_episode.class.php +++ b/lib/class/tvshow_episode.class.php @@ -28,8 +28,9 @@ class TVShow_Episode extends Video public $description; public $f_link; - public $f_season; + public $f_season_link; public $f_tvshow; + public $f_tvshow_link; /** * Constructor @@ -39,30 +40,60 @@ class TVShow_Episode extends Video public function __construct($id) { parent::__construct($id); - + $info = $this->get_info($id); foreach ($info as $key=>$value) { $this->$key = $value; } - + return true; - } // Constructor + } + + /** + * gc + * + * This cleans out unused tv shows episodes + */ + public static function gc() + { + $sql = "DELETE FROM `tvshow_episode` USING `tvshow_episode` LEFT JOIN `video` ON `video`.`id` = `tvshow_episode`.`id` WHERE `video`.`id` IS NULL"; + Dba::write($sql); + } + + /** + * insert + * Insert a new tv show episode and related entities. + */ + public static function insert($data) + { + if (empty($data['tvshow'])) { + $data['tvshow'] = T_('Unknown'); + } + + $tvshow = TVShow::check($data['tvshow'], $data['tvshow_year']); + $tvshow_season = TVShow_Season::check($tvshow, $data['tvshow_season']); + + $sdata = $data; + // Replace relation name with db ids + $sdata['tvshow'] = $tvshow; + $sdata['tvshow_season'] = $tvshow_season; + return self::create($sdata); + } /** * create - * This takes a key'd array of data as input and inserts a new tv show episode entry, it returns the auto_inc id + * This takes a key'd array of data as input and inserts a new tv show episode entry, it returns the record id */ public static function create($data) { - $sql = "INSERT INTO `tvshow_episode` (`id`, `season`,`episode_number`,`description`) " . - "VALUES (?, ?, ?, ?)"; - Dba::write($sql, array($data['id'], $data['season'], $data['episode_number'], $data['description'])); - $insert_id = Dba::insert_id(); + $sql = "INSERT INTO `tvshow_episode` (`id`, `original_name`, `season`, `episode_number`, `description`) " . + "VALUES (?, ?, ?, ?, ?)"; + Dba::write($sql, array($data['id'], $data['original_name'], $data['tvshow_season'], $data['tvshow_episode'], $data['description'])); - return $insert_id; + return $data['id']; - } // create + } /** * update @@ -70,12 +101,12 @@ class TVShow_Episode extends Video */ public static function update($data) { - $sql = "UPDATE `tvshow_episode` SET `season` = ?, `episode_number` = ?, `description` = ? WHERE `id` = ?"; - Dba::write($sql, array($data['season'], $data['episode_number'], $data['description'], $data['id'])); + $sql = "UPDATE `tvshow_episode` SET `original_name` = ?, `season` = ?, `episode_number` = ?, `description` = ? WHERE `id` = ?"; + Dba::write($sql, array($data['original_name'], $data['tvshow_season'], $data['tvshow_episode'], $data['description'], $data['id'])); return true; - } // create + } /** * format @@ -84,14 +115,24 @@ class TVShow_Episode extends Video public function format() { parent::format(); - + $season = new TVShow_Season($this->season); $season->format(); - $this->f_season = $season->f_link; - $this->f_tvshow = $season->f_tvshow; - + + $this->f_title = ($this->original_name ?: $this->f_title); + $this->f_link = '' . $this->f_title . ''; + $this->f_season_link = $season->f_link; + $this->f_tvshow = $tvshow->f_tvshow; + $this->f_tvshow_link = $season->f_tvshow_link; + + $this->f_file = $this->f_tvshow; + if ($this->episode_number) { + $this->f_file .= ' - S'. sprintf('%02d', $season->season_number) . 'E'. sprintf('%02d', $this->episode_number); + } + $this->f_file .= ' - ' . $this->f_title; + return true; - } //format + } -} // License class +} diff --git a/lib/class/tvshow_season.class.php b/lib/class/tvshow_season.class.php index 00b6c810..f1715a05 100644 --- a/lib/class/tvshow_season.class.php +++ b/lib/class/tvshow_season.class.php @@ -29,6 +29,7 @@ class TVShow_Season extends database_object public $episodes; public $f_name; + public $f_tvshow; public $f_tvshow_link; public $link; public $f_link; @@ -64,7 +65,9 @@ class TVShow_Season extends database_object */ public static function gc() { - + $sql = "DELETE FROM `tvshow_season` USING `tvshow_season` LEFT JOIN `tvshow_episode` ON `tvshow_episode`.`season` = `tvshow_season`.`id` " . + "WHERE `tvshow_episode`.`id` IS NULL"; + Dba::write($sql); } /** @@ -93,7 +96,7 @@ class TVShow_Season extends database_object return $results; } // get_episodes - + /** * _get_extra info * This returns the extra information for the tv show season, this means totals etc @@ -118,7 +121,7 @@ class TVShow_Season extends database_object return $row; } // _get_extra_info - + /** * format * this function takes the object and reformats some values @@ -126,19 +129,75 @@ class TVShow_Season extends database_object public function format() { $this->f_name = T_('Season') . ' ' . $this->season_number; - + $tvshow = new TVShow($this->tvshow); $tvshow->format(); + $this->f_tvshow = $tvshow->f_name; $this->f_tvshow_link = $tvshow->f_link; - + $this->link = AmpConfig::get('web_path') . '/tvshow_seasons.php?action=show&season=' . $this->id; $this->f_link = '' . $this->f_name . ''; - + $this->_get_extra_info($this->catalog_id); - + return true; } + /** + * check + * + * Checks for an existing tv show season; if none exists, insert one. + */ + public static function check($tvshow, $season_number, $readonly = false) + { + $name = $tvshow . '_' . $season_number; + // null because we don't have any unique id like mbid for now + if (isset(self::$_mapcache[$name]['null'])) { + return self::$_mapcache[$name]['null']; + } + + $id = 0; + $exists = false; + + if (!$exists) { + $sql = 'SELECT `id` FROM `tvshow_season` WHERE `tvshow` = ? AND `season_number` = ?'; + $db_results = Dba::read($sql, array($tvshow, $season_number)); + + $id_array = array(); + while ($row = Dba::fetch_assoc($db_results)) { + $key = 'null'; + $id_array[$key] = $row['id']; + } + + if (count($id_array)) { + $id = array_shift($id_array); + $exists = true; + } + } + + if ($exists) { + self::$_mapcache[$name]['null'] = $id; + return $id; + } + + if ($readonly) { + return null; + } + + $sql = 'INSERT INTO `tvshow_season` (`tvshow`, `season_number`) ' . + 'VALUES(?, ?)'; + + $db_results = Dba::write($sql, array($tvshow, $season_number)); + if (!$db_results) { + return null; + } + $id = Dba::insert_id(); + + self::$_mapcache[$name]['null'] = $id; + return $id; + + } + /** * update * This takes a key'd array of data and updates the current tv show @@ -148,7 +207,7 @@ class TVShow_Season extends database_object $sql = 'UPDATE `tvshow_season` SET `season_number` = ? WHERE `id` = ?'; return Dba::write($sql, array($data['season_number'], $this->id)); } // update - + public static function update_tvshow($tvshow_id, $season_id) { $sql = "UPDATE `tvshow_season` SET `tvshow` = ? WHERE `id` = ?"; diff --git a/lib/class/update.class.php b/lib/class/update.class.php index 490ab661..639b9e5e 100644 --- a/lib/class/update.class.php +++ b/lib/class/update.class.php @@ -424,7 +424,7 @@ class Update $update_string = '- Add UPnP backend preference.
'; $version[] = array('version' => '370008','description' => $update_string); - + $update_string = '- Enhance video support with TVShows and Movies.
'; $version[] = array('version' => '370009','description' => $update_string); @@ -2656,7 +2656,6 @@ class Update Dba::write($sql); return true; } -<<<<<<< HEAD /** * update_370007 @@ -2702,10 +2701,10 @@ class Update $id = Dba::insert_id(); $sql = "INSERT INTO `user_preference` VALUES (-1,?,'0')"; Dba::write($sql, array($id)); - + return true; } - + /** * update_370009 * @@ -2715,12 +2714,12 @@ class Update { $sql = "ALTER TABLE `video` ADD `release_date` int(11) unsigned NULL AFTER `enabled`"; Dba::write($sql); - + $sql = "CREATE TABLE `people` (" . "`id` int(11) unsigned NOT NULL AUTO_INCREMENT," . "`name` varchar(256) NOT NULL," . "PRIMARY KEY (`id`)) ENGINE = MYISAM"; - + $sql = "CREATE TABLE `people_rel` (" . "`id` int(11) unsigned NOT NULL AUTO_INCREMENT," . "`object_id` int(11) unsigned NOT NULL," . @@ -2728,7 +2727,7 @@ class Update "`people_id` int(11) unsigned NOT NULL," . "`rel_type` varchar(32) NOT NULL," . "PRIMARY KEY (`id`)) ENGINE = MYISAM"; - + $sql = "CREATE TABLE `tvshow` (" . "`id` int(11) unsigned NOT NULL AUTO_INCREMENT," . "`name` varchar(80) NOT NULL," . @@ -2736,22 +2735,23 @@ class Update "`year` int(11) unsigned NULL," . "PRIMARY KEY (`id`)) ENGINE = MYISAM"; Dba::write($sql); - + $sql = "CREATE TABLE `tvshow_season` (" . "`id` int(11) unsigned NOT NULL AUTO_INCREMENT," . "`season_number` int(11) unsigned NOT NULL," . "`tvshow` int(11) unsigned NOT NULL," . "PRIMARY KEY (`id`)) ENGINE = MYISAM"; Dba::write($sql); - + $sql = "CREATE TABLE `tvshow_episode` (" . "`id` int(11) unsigned NOT NULL," . + "`original_name` varchar(80) NULL," . "`season` int(11) unsigned NOT NULL," . "`episode_number` int(11) unsigned NOT NULL," . "`description` varchar(256) NULL," . "PRIMARY KEY (`id`)) ENGINE = MYISAM"; Dba::write($sql); - + $sql = "CREATE TABLE `movie` (" . "`id` int(11) unsigned NOT NULL," . "`original_name` varchar(80) NULL," . @@ -2759,14 +2759,28 @@ class Update "`year` int(11) unsigned NULL," . "PRIMARY KEY (`id`)) ENGINE = MYISAM"; Dba::write($sql); - + + $sql = "CREATE TABLE `personal_video` (" . + "`id` int(11) unsigned NOT NULL," . + "`location` varchar(256) NULL," . + "`description` varchar(256) NULL," . + "PRIMARY KEY (`id`)) ENGINE = MYISAM"; + Dba::write($sql); + + $sql = "CREATE TABLE `clip` (" . + "`id` int(11) unsigned NOT NULL," . + "`artist` int(11) NULL," . + "`song` int(11) NULL," . + "PRIMARY KEY (`id`)) ENGINE = MYISAM"; + Dba::write($sql); + $sql = "INSERT INTO `preference` (`name`,`value`,`description`,`level`,`type`,`catagory`) " . "VALUES ('allow_video','1','Allow video features',25,'integer','system')"; Dba::write($sql); $id = Dba::insert_id(); $sql = "INSERT INTO `user_preference` VALUES (-1,?,'1')"; Dba::write($sql, array($id)); - + return true; } } diff --git a/lib/class/upnp_api.class.php b/lib/class/upnp_api.class.php index 1bbdb349..a9f1114c 100644 --- a/lib/class/upnp_api.class.php +++ b/lib/class/upnp_api.class.php @@ -298,7 +298,7 @@ class Upnp_Api case 'artists': switch (count($pathreq)) { case 1: - $counts = Catalog::count_songs(); + $counts = Catalog::count_medias(); $meta = array( 'id' => $root . '/artists', 'parentID' => $root, @@ -322,7 +322,7 @@ class Upnp_Api case 'albums': switch (count($pathreq)) { case 1: - $counts = Catalog::count_songs(); + $counts = Catalog::count_medias(); $meta = array( 'id' => $root . '/albums', 'parentID' => $root, @@ -346,7 +346,7 @@ class Upnp_Api case 'songs': switch (count($pathreq)) { case 1: - $counts = Catalog::count_songs(); + $counts = Catalog::count_medias(); $meta = array( 'id' => $root . '/songs', 'parentID' => $root, @@ -370,7 +370,7 @@ class Upnp_Api case 'playlists': switch (count($pathreq)) { case 1: - $counts = Catalog::count_songs(); + $counts = Catalog::count_medias(); $meta = array( 'id' => $root . '/playlists', 'parentID' => $root, @@ -394,7 +394,7 @@ class Upnp_Api case 'smartplaylists': switch (count($pathreq)) { case 1: - $counts = Catalog::count_songs(); + $counts = Catalog::count_medias(); $meta = array( 'id' => $root . '/smartplaylists', 'parentID' => $root, @@ -559,7 +559,7 @@ class Upnp_Api break; default: - $counts = Catalog::count_songs(); + $counts = Catalog::count_medias(); $mediaItems[] = self::_musicMetadata('artists'); $mediaItems[] = self::_musicMetadata('albums'); diff --git a/lib/class/vainfo.class.php b/lib/class/vainfo.class.php index 06899686..fac647c6 100644 --- a/lib/class/vainfo.class.php +++ b/lib/class/vainfo.class.php @@ -203,7 +203,7 @@ class vainfo /* Figure out what type of file we are dealing with */ $this->type = $this->_get_type(); - $enabled_sources = (array) AmpConfig::get('metadata_order'); + $enabled_sources = (array) $this->get_metadata_order(); if (in_array('filename', $enabled_sources)) { $this->tags['filename'] = $this->_parse_filename($this->filename); @@ -282,6 +282,8 @@ class vainfo $info['time'] = $info['time'] ?: intval($tags['time']); $info['channels'] = $info['channels'] ?: $tags['channels']; + // This because video title are almost always bad... + $info['original_name'] = $info['original_name'] ?: stripslashes(trim($tags['original_name'])); $info['title'] = $info['title'] ?: stripslashes(trim($tags['title'])); $info['year'] = $info['year'] ?: intval($tags['year']); @@ -328,6 +330,12 @@ class vainfo $info['resolution_y'] = $info['resolution_y'] ?: intval($tags['resolution_y']); $info['audio_codec'] = $info['audio_codec'] ?: trim($tags['audio_codec']); $info['video_codec'] = $info['video_codec'] ?: trim($tags['video_codec']); + + $info['tvshow'] = $info['tvshow'] ?: trim($tags['tvshow']); + $info['tvshow_year'] = $info['tvshow_year'] ?: trim($tags['tvshow_year']); + $info['tvshow_season'] = $info['tvshow_season'] ?: trim($tags['tvshow_season']); + $info['tvshow_episode'] = $info['tvshow_episode'] ?: trim($tags['tvshow_episode']); + $info['release_date'] = $info['release_date'] ?: trim($tags['release_date']); } // Some things set the disk number even though there aren't multiple @@ -442,6 +450,19 @@ class vainfo return $cleaned; } + private function get_metadata_order_key() + { + if (!in_array('music', $this->gather_types)) + return 'metadata_order_video'; + + return 'metadata_order'; + } + + private function get_metadata_order() + { + return (array) AmpConfig::get($this->get_metadata_order_key()); + } + /** * _get_plugin_tags * @@ -449,7 +470,7 @@ class vainfo */ private function _get_plugin_tags() { - $tag_order = AmpConfig::get('metadata_order'); + $tag_order = $this->get_metadata_order(); if (!is_array($tag_order)) { $tag_order = array($tag_order); } @@ -461,7 +482,7 @@ class vainfo $installed_version = Plugin::get_plugin_version($plugin->_plugin->name); if ($installed_version) { if ($plugin->load($GLOBALS['user'])) { - $this->tags[$tag_source] = $plugin->_plugin->get_metadata($this->gather_types, self::clean_tag_info($this->tags, self::get_tag_type($this->tags), $this->filename)); + $this->tags[$tag_source] = $plugin->_plugin->get_metadata($this->gather_types, self::clean_tag_info($this->tags, self::get_tag_type($this->tags, $this->get_metadata_order_key()), $this->filename)); } } } @@ -790,60 +811,202 @@ class vainfo $origin = $filename; $results = array(); - // Correctly detect the slash we need to use here - if (strpos($filename, '/') !== false) { - $slash_type = '/'; - $slash_type_preg = $slash_type; - } else { - $slash_type = '\\'; - $slash_type_preg = $slash_type . $slash_type; - } - - // Combine the patterns - $pattern = preg_quote($this->_dir_pattern) . $slash_type_preg . preg_quote($this->_file_pattern); - - // Remove first left directories from filename to match pattern - $cntslash = substr_count($pattern, $slash_type) + 1; - $filepart = explode($slash_type, $filename); - if (count($filepart) > $cntslash) { - $filename = implode($slash_type, array_slice($filepart, count($filepart) - $cntslash)); - } - - // Pull out the pattern codes into an array - preg_match_all('/\%\w/', $pattern, $elements); - - // Mangle the pattern by turning the codes into regex captures - $pattern = preg_replace('/\%[Ty]/', '([0-9]+?)', $pattern); - $pattern = preg_replace('/\%\w/', '(.+?)', $pattern); - $pattern = str_replace('/', '\/', $pattern); - $pattern = str_replace(' ', '\s', $pattern); - $pattern = '/' . $pattern . '\..+$/'; - - // Pull out our actual matches - preg_match($pattern, $filename, $matches); - - if ($matches != null) { - // The first element is the full match text - $matched = array_shift($matches); - debug_event('vainfo', $pattern . ' matched ' . $matched . ' on ' . $filename, 5); - - // Iterate over what we found - foreach ($matches as $key => $value) { - $new_key = translate_pattern_code($elements['0'][$key]); - if ($new_key) { - $results[$new_key] = $value; - } + if (in_array('music', $this->gather_types) || in_array('clip', $this->gather_types)) { + // Correctly detect the slash we need to use here + if (strpos($filename, '/') !== false) { + $slash_type = '/'; + $slash_type_preg = $slash_type; + } else { + $slash_type = '\\'; + $slash_type_preg = $slash_type . $slash_type; } - $results['title'] = $results['title'] ?: basename($filename); - if ($this->islocal) { - $results['size'] = filesize(Core::conv_lc_file($origin)); + // Combine the patterns + $pattern = preg_quote($this->_dir_pattern) . $slash_type_preg . preg_quote($this->_file_pattern); + + // Remove first left directories from filename to match pattern + $cntslash = substr_count($pattern, $slash_type) + 1; + $filepart = explode($slash_type, $filename); + if (count($filepart) > $cntslash) { + $filename = implode($slash_type, array_slice($filepart, count($filepart) - $cntslash)); + } + + // Pull out the pattern codes into an array + preg_match_all('/\%\w/', $pattern, $elements); + + // Mangle the pattern by turning the codes into regex captures + $pattern = preg_replace('/\%[Ty]/', '([0-9]+?)', $pattern); + $pattern = preg_replace('/\%\w/', '(.+?)', $pattern); + $pattern = str_replace('/', '\/', $pattern); + $pattern = str_replace(' ', '\s', $pattern); + $pattern = '/' . $pattern . '\..+$/'; + + // Pull out our actual matches + preg_match($pattern, $filename, $matches); + + if ($matches != null) { + // The first element is the full match text + $matched = array_shift($matches); + debug_event('vainfo', $pattern . ' matched ' . $matched . ' on ' . $filename, 5); + + // Iterate over what we found + foreach ($matches as $key => $value) { + $new_key = translate_pattern_code($elements['0'][$key]); + if ($new_key) { + $results[$new_key] = $value; + } + } + + $results['title'] = $results['title'] ?: basename($filename); + if ($this->islocal) { + $results['size'] = filesize(Core::conv_lc_file($origin)); + } + } + } + + if (in_array('tvshow', $this->gather_types)) { + $pathinfo = pathinfo($filename); + $filetitle = $pathinfo['filename']; + + $results = array_merge($results, $this->parseEpisodeName($filetitle)); + if (!$results['tvshow']) { + // Try to identify the show information from parent folder + $filetitle = basename($pathinfo['dirname']); + $results = array_merge($results, $this->parseEpisodeName($filetitle)); + + if (!$results['tvshow']) { + if ($results['tvshow_season'] && $results['tvshow_episode']) { + // We have season and episode, we assume parent folder is the tvshow name + $pathinfo = pathinfo($pathinfo['dirname']); + $filetitle = basename($pathinfo['dirname']); + $results['tvshow'] = $this->fixSerieName($filetitle); + } else { + // Or we assume each parent folder contains one missing information + if (preg_match('/[\/\\\\]([^\/\\\\]*)[\/\\\\]Season (\d{1,2})[\/\\\\]((E|Ep|Episode)\s?(\d{1,2})[\/\\\\])?/i', $filename, $matches)) { + $results['tvshow'] = $this->fixSerieName($matches[1]); + $results['tvshow_season'] = $matches[2]; + if (isset($matches[5])) { + $results['tvshow_episode'] = $matches[5]; + } + } + } + } + } + } + + if (in_array('movie', $this->gather_types)) { + $pathinfo = pathinfo($filename); + $filetitle = $pathinfo['filename']; + $results['title'] = $this->fixVideoReleaseName($filetitle); + if (!$results['title']) { + // Try to identify the movie information from parent folder + $filetitle = basename($pathinfo['dirname']); + $results['title'] = $this->fixVideoReleaseName($filetitle); } } return $results; } + private function parseEpisodeName($filetitle) + { + $patterns = array( + '/(.*)s(\d\d)e(\d\d)(\D.*)/i', + '/(.*)s(\d\d)(\D)(.*)/i', + '/(.*)\D(\d{1,2})x(\d\d)(\D)(.*)/i', + '/(.*)\D(\d{1,2})x(\d\d)$/i', + '/(\D*)[\.|\-|_](\d)(\d\d)([\.|\-|_]\D.*)/i', + '/(\D*)(\d)[^0-9](\d\d)(\D.*)/i' + ); + + $results = array(); + for ($i=0;$ifixSerieName($matches[1]); + if(empty($name)) + continue; + + $season = floatval($matches[2]); + if ($season == 0) + continue; + + $episode = floatval($matches[3]); + $leftover = $matches[4]; + + if ($episode == 0) { + // Some malformed string + $leftover = $filetitle; + } + + $results['tvshow'] = $name; + $results['tvshow_season'] = $season; + $results['tvshow_episode'] = $episode; + $results['title'] = $this->fixVideoReleaseName($leftover); + break; + } + } + + return $results; + } + + private function fixSerieName($name) + { + $name = str_replace('_', ' ', $name); + $name = str_replace('.', ' ', $name); + $name = str_replace(' ', ' ', $name); + $name = $this->removeStartingDashesAndSpaces($name); + $name = $this->removeEndingDashesAndSpaces($name); + + return ucwords($name); + } + + private function fixVideoReleaseName($name) + { + $commonabbr = array( + 'divx', 'xvid', 'dvdrip', 'hdtv', 'lol', 'axxo', 'repack', 'xor', + 'pdtv', 'real', 'vtv', 'caph', '2hd', 'proper', 'fqm', 'uncut', + 'topaz', 'tvt', 'notv', 'fpn', 'fov', 'orenji', '0tv', 'omicron', + 'dsr', 'ws', 'sys', 'crimson', 'wat', 'hiqt', 'internal', 'brrip', + 'boheme', 'vost', 'vostfr', 'fastsub', 'addiction' + ); + for ($i=0; $ifixSerieName($name); + } + + private function removeStartingDashesAndSpaces($name) + { + if (empty($name)) + return $name; + + while (strpos($name, ' ') === 0 || strpos($name, '-') === 0) { + $name = preg_replace('/^ /', '', $name); + $name = preg_replace('/^-/', '', $name); + } + return $name; + } + + private function removeEndingDashesAndSpaces($name) + { + if (empty($name)) + return $name; + + while (strrpos($name, ' ') === strlen($name) - 1 || strrpos($name, '-') === strlen($name) - 1) { + $name = preg_replace('/ $/', '', $name); + $name = preg_replace('/-$/', '', $name); + } + return $name; + } + /** * set_broken * diff --git a/lib/class/video.class.php b/lib/class/video.class.php index 373fc3d6..7da0c33c 100644 --- a/lib/class/video.class.php +++ b/lib/class/video.class.php @@ -44,16 +44,18 @@ class Video extends database_object implements media public $f_resolution; public $f_tags; public $f_length; + public $f_file; + public $f_release_date; /** * Constructor - * This pulls the shoutbox information from the database and returns - * a constructed object, uses user_shout table + * This pulls the information from the database and returns + * a constructed object */ public function __construct($id) { // Load the data from the database - $info = $this->get_info($id); + $info = $this->get_info($id, 'video'); foreach ($info as $key=>$value) { $this->$key = $value; } @@ -89,14 +91,21 @@ class Video extends database_object implements media { $this->f_title = scrub_out($this->title); $this->link = AmpConfig::get('web_path') . "/video.php?action=show_video&video_id=" . $this->id; + if (strtolower(get_class($this)) != 'video') { + $this->link .= '&type=' . get_class($this); + } $this->f_link = "link . "\" title=\"" . scrub_out($this->f_title) . "\"> " . scrub_out($this->f_title) . ""; $this->f_codec = $this->video_codec . ' / ' . $this->audio_codec; $this->f_resolution = $this->resolution_x . 'x' . $this->resolution_y; $this->f_tags = ''; $this->f_length = floor($this->time/60) . ' ' . T_('minutes'); + $this->f_file = $this->f_title . '.' . $this->type; + if ($this->release_date) { + $this->f_release_date = date('Y-m-d', $this->release_date); + } } // format - + /** * gc * @@ -104,9 +113,12 @@ class Video extends database_object implements media */ public static function gc() { - Dba::write('DELETE FROM `movie` USING `movie` LEFT JOIN `video` ON `video`.`id` = `movie`.`id` WHERE `video`.`id` IS NULL'); - Dba::write('DELETE FROM `tvshow_episode` USING `tvshow_episode` LEFT JOIN `video` ON `video`.`id` = `tvshow_episode`.`id` WHERE `video`.`id` IS NULL'); + Movie::gc(); + TVShow_Episode::gc(); + TVShow_Season::gc(); TVShow::gc(); + Personal_Video::gc(); + Clip::gc(); } public function get_stream_types() @@ -145,4 +157,17 @@ class Video extends database_object implements media return false; } + public static function validate_type($type) + { + switch (strtolower($type)) { + case 'tvshow_episode': + case 'movie': + case 'clip': + case 'personal_video': + return $type; + default: + return 'Video'; + } + } + } // end Video class diff --git a/lib/init.php b/lib/init.php index a43ec404..37c8181b 100644 --- a/lib/init.php +++ b/lib/init.php @@ -66,7 +66,7 @@ if (!empty($link)) { $results['load_time_begin'] = $load_time_begin; /** This is the version.... fluf nothing more... **/ $results['version'] = '3.7.1-develop'; -$results['int_config_version'] = '16'; +$results['int_config_version'] = '17'; if (!empty($results['force_ssl'])) { $http_type = 'https://'; diff --git a/lib/preferences.php b/lib/preferences.php index 5e719c82..a5d9616b 100644 --- a/lib/preferences.php +++ b/lib/preferences.php @@ -125,7 +125,7 @@ function create_preference_input($name,$value) } elseif ($value == '0') { echo "Disabled"; } else { - if (preg_match('/_pass$/', $name)) { + if (preg_match('/_pass$/', $name) || preg_match('/_api_key$/', $name)) { echo "******"; } else { echo $value; diff --git a/modules/catalog/dropbox.catalog.php b/modules/catalog/dropbox.catalog.php index 83026402..3801e0cd 100644 --- a/modules/catalog/dropbox.catalog.php +++ b/modules/catalog/dropbox.catalog.php @@ -280,10 +280,10 @@ class Catalog_dropbox extends Catalog $this->add_files($client, $this->path); echo "\n
" . - printf(T_('Catalog Update Finished. Total Songs: [%s]'), $this->count); + printf(T_('Catalog Update Finished. Total Media: [%s]'), $this->count); echo '
'; if ($this->count == 0) { - echo T_('No songs updated, do you respect the patterns?') . '
'; + echo T_('No media updated, do you respect the patterns?') . '
'; } echo '
'; } else { diff --git a/modules/catalog/local.catalog.php b/modules/catalog/local.catalog.php index 22bbc28a..61ee228a 100644 --- a/modules/catalog/local.catalog.php +++ b/modules/catalog/local.catalog.php @@ -362,13 +362,13 @@ class Catalog_local extends Catalog if (count($this->get_gather_types('music')) > 0) { $this->_insert_local_song($full_file, $file_size, $options); } else { - debug_event('read', $full_file] . " ignored, bad media type for this catalog.", 5); + debug_event('read', $full_file . " ignored, bad media type for this catalog.", 5); } } else { if (count($this->get_gather_types('video')) > 0) { $this->insert_local_video($full_file,$file_size); } else { - debug_event('read', $full_file] . " ignored, bad media type for this catalog.", 5); + debug_event('read', $full_file . " ignored, bad media type for this catalog.", 5); } } @@ -462,7 +462,7 @@ class Catalog_local extends Catalog UI::show_box_top(); echo "\n
" . - printf(T_('Catalog Update Finished. Total Time: [%s] Total Songs: [%s] Songs Per Second: [%s]'), + printf(T_('Catalog Update Finished. Total Time: [%s] Total Media: [%s] Media Per Second: [%s]'), date('i:s', $time_diff), $this->count, $rate); echo '

'; UI::show_box_bottom(); @@ -703,7 +703,7 @@ class Catalog_local extends Catalog $vainfo = new vainfo($file, $gtypes,'','','',$this->sort_pattern,$this->rename_pattern); $vainfo->get_info(); - $tag_name = vainfo::get_tag_type($vainfo->tags); + $tag_name = vainfo::get_tag_type($vainfo->tags, 'metadata_order_video'); $results = vainfo::clean_tag_info($vainfo->tags,$tag_name,$file); $rezx = intval($results['resolution_x']); @@ -715,8 +715,9 @@ class Catalog_local extends Catalog $params = array($file, $this->id, $results['title'], $results['video_codec'], $results['audio_codec'], $rezx, $rezy, $filesize, $results['time'], $results['mime'], $release_date); Dba::write($sql, $params); $vid = Dba::insert_id(); - - Catalog::insert_video($vid, $gtypes, $results); + + $results['id'] = $vid; + Catalog::insert_video($gtypes, $results); return true; diff --git a/modules/plugins/Bitly.plugin.php b/modules/plugins/Bitly.plugin.php index 0f444e57..ba32792d 100644 --- a/modules/plugins/Bitly.plugin.php +++ b/modules/plugins/Bitly.plugin.php @@ -25,14 +25,14 @@ class AmpacheBitly { public $name = 'Bit.ly'; public $description = 'Url shorteners on shared links with Bit.ly'; public $url = 'http://bitly.com/'; - public $version = '000001'; + public $version = '000002'; public $min_ampache = '360037'; public $max_ampache = '999999'; // These are internal settings used by this class, run this->load to // fill them out private $bitly_username; - private $bitly_api; + private $bitly_api_key; /** * Constructor @@ -54,8 +54,8 @@ class AmpacheBitly { // Check and see if it's already installed (they've just hit refresh, those dorks) if (Preference::exists('bitly_username')) { return false; } - Preference::insert('bitly_username','Bit.ly username','','25','string','plugins'); - Preference::insert('bitly_api','Bit.ly api key','','25','string','plugins'); + Preference::insert('bitly_username','Bit.ly username','','75','string','plugins'); + Preference::insert('bitly_api_key','Bit.ly api key','','75','string','plugins'); return true; @@ -69,7 +69,7 @@ class AmpacheBitly { public function uninstall() { Preference::delete('bitly_username'); - Preference::delete('bitly_api'); + Preference::delete('bitly_api_key'); } // uninstall @@ -83,14 +83,14 @@ class AmpacheBitly { public function shortener($url) { - if (empty($this->bitly_username) || empty($this->bitly_api)) { + if (empty($this->bitly_username) || empty($this->bitly_api_key)) { debug_event($this->name, 'Bit.ly username or api key missing', '3'); return false; } $shorturl = ''; - $apiurl = 'http://api.bit.ly/v3/shorten?login=' . $this->bitly_username . '&apiKey=' . $this->bitly_api . '&longUrl=' . urlencode($url) . '&format=json'; + $apiurl = 'http://api.bit.ly/v3/shorten?login=' . $this->bitly_username . '&apiKey=' . $this->bitly_api_key . '&longUrl=' . urlencode($url) . '&format=json'; try { debug_event($this->name, 'Bit.ly api call: ' . $apiurl, '5'); $request = Requests::get($apiurl); @@ -120,8 +120,8 @@ class AmpacheBitly { debug_event($this->name,'No Bit.ly username, shortener skipped','3'); return false; } - if (strlen(trim($data['bitly_api']))) { - $this->bitly_api = trim($data['bitly_api']); + if (strlen(trim($data['bitly_api_key']))) { + $this->bitly_api_key = trim($data['bitly_api_key']); } else { debug_event($this->name,'No Bit.ly api key, shortener skipped','3'); diff --git a/modules/plugins/Flickr.plugin.php b/modules/plugins/Flickr.plugin.php index 8faf9dae..6015ad6f 100644 --- a/modules/plugins/Flickr.plugin.php +++ b/modules/plugins/Flickr.plugin.php @@ -46,7 +46,7 @@ class Ampacheflickr { */ public function install() { if (Preference::exists('flickr_api_key')) { return false; } - Preference::insert('flickr_api_key','Flickr api key','','25','string','plugins'); + Preference::insert('flickr_api_key','Flickr api key','','75','string','plugins'); return true; } // install diff --git a/modules/plugins/MusicBrainz.plugin.php b/modules/plugins/MusicBrainz.plugin.php index a0721f7b..419a2cee 100644 --- a/modules/plugins/MusicBrainz.plugin.php +++ b/modules/plugins/MusicBrainz.plugin.php @@ -70,7 +70,7 @@ class AmpacheMusicBrainz { */ public function get_metadata($gather_types, $song_info) { // Music metadata only - if (!in_array($gather_types, 'music')) { + if (!in_array('music', $gather_types)) { return null; } diff --git a/modules/plugins/Tmdb.plugin.php b/modules/plugins/Tmdb.plugin.php new file mode 100644 index 00000000..3043a85c --- /dev/null +++ b/modules/plugins/Tmdb.plugin.php @@ -0,0 +1,159 @@ +load to + // fill them out + private $api_key; + + /** + * Constructor + * This function does nothing + */ + public function __construct() { + return true; + } + + /** + * install + * This is a required plugin function + */ + public function install() { + + if (Preference::exists('tmdb_api_url')) { return false; } + + Preference::insert('tmdb_api_key','Tmdb api key','','75','string','plugins'); + + return true; + } // install + + /** + * uninstall + * This is a required plugin function + */ + public function uninstall() { + + Preference::delete('tmdb_api_url'); + + return true; + } // uninstall + + /** + * load + * This is a required plugin function; here it populates the prefs we + * need for this object. + */ + public function load($user) { + + $user->set_preferences(); + $data = $user->prefs; + + if (strlen(trim($data['tmdb_api_key']))) { + $this->api_key = trim($data['tmdb_api_key']); + } + else { + debug_event($this->name,'No Tmdb api key, metadata plugin skipped','3'); + return false; + } + + return true; + } // load + + /** + * get_metadata + * Returns song metadata for what we're passed in. + */ + public function get_metadata($gather_types, $media_info) { + debug_event('tmdb', 'Getting metadata from Tmdb...', '5'); + + // TVShow / Movie metadata only + if (!in_array('tvshow', $gather_types) && !in_array('movie', $gather_types)) { + debug_event('tmdb', 'Not a valid media type, skipped.', '5'); + return null; + } + $token = new \Tmdb\ApiToken($this->api_key); + $client = new \Tmdb\Client($token); + + $title = $media_info['original_name'] ?: $media_info['title']; + + $results = array(); + try { + if (in_array('movie', $gather_types)) { + if (!empty($title)) { + $apires = $client->getSearchApi()->searchMovies($title); + if (count($apires['results']) > 0) { + $release = $apires['results'][0]; + $results['tmdb_id'] = $release['id']; + $results['original_name'] = $release['original_title']; + if (!empty($release['release_date'])) { + $results['release_date'] = strtotime($release['release_date']); + $results['year'] = date("Y", $results['release_date']); // Production year shouldn't be the release date + } + } + } + } + + if (in_array('tvshow', $gather_types)) { + if (!empty($media_info['tvshow'])) { + $apires = $client->getSearchApi()->searchTv($media_info['tvshow']); + if (count($apires['results']) > 0) { + // Get first match + $release = $apires['results'][0]; + $results['tmdb_tvshow_id'] = $release['id']; + $results['tvshow'] = $release['original_name']; + if (!empty($release['first_air_date'])) { + $results['tvshow_year'] = date("Y", strtotime($release['first_air_date'])); + } + + if ($media_info['tvshow_season'] && $media_info['tvshow_episode']) { + $release = $client->getTvEpisodeApi()->getEpisode($results['tmdb_tvshow_id'], $media_info['tvshow_season'], $media_info['tvshow_episode']); + if ($release['id']) { + $results['tmdb_id'] = $release['id']; + $results['tvshow_season'] = $release['season_number']; + $results['tvshow_episode'] = $release['episode_number']; + $results['original_name'] = $release['name']; + if (!empty($release['air_date'])) { + $results['release_date'] = strtotime($release['release_date']); + $results['year'] = date("Y", $results['release_date']); + } + $results['description'] = $release['overview']; + } + } + } + } + } + } catch (Exception $e) { + debug_event('tmdb', 'Error getting metadata: ' . $e->getMessage(), '1'); + } + + return $results; + } // get_metadata + +} // end AmpacheTmdb +?> diff --git a/modules/plugins/Yourls.plugin.php b/modules/plugins/Yourls.plugin.php index 86e58514..21dd219a 100644 --- a/modules/plugins/Yourls.plugin.php +++ b/modules/plugins/Yourls.plugin.php @@ -25,7 +25,7 @@ class AmpacheYourls { public $name = 'YOURLS'; public $description = 'Url shorteners on shared links with YOURLS'; public $url = 'http://yourls.org/'; - public $version = '000001'; + public $version = '000002'; public $min_ampache = '360037'; public $max_ampache = '999999'; @@ -33,7 +33,7 @@ class AmpacheYourls { // fill them out private $yourls_domain; private $yourls_use_idn; - private $yourls_api; + private $yourls_api_key; /** * Constructor @@ -55,9 +55,9 @@ class AmpacheYourls { // Check and see if it's already installed (they've just hit refresh, those dorks) if (Preference::exists('yourls_domain')) { return false; } - Preference::insert('yourls_domain','YOURLS domain name','','25','string','plugins'); - Preference::insert('yourls_use_idn','YOURLS use IDN','0','25','boolean','plugins'); - Preference::insert('yourls_api','YOURLS api key','','25','string','plugins'); + Preference::insert('yourls_domain','YOURLS domain name','','75','string','plugins'); + Preference::insert('yourls_use_idn','YOURLS use IDN','0','75','boolean','plugins'); + Preference::insert('yourls_api_key','YOURLS api key','','75','string','plugins'); return true; @@ -72,7 +72,7 @@ class AmpacheYourls { Preference::delete('yourls_domain'); Preference::delete('yourls_use_idn'); - Preference::delete('yourls_api'); + Preference::delete('yourls_api_key'); } // uninstall @@ -86,14 +86,14 @@ class AmpacheYourls { public function shortener($url) { - if (empty($this->yourls_domain) || empty($this->yourls_api)) { + if (empty($this->yourls_domain) || empty($this->yourls_api_key)) { debug_event($this->name, 'YOURLS domain or api key missing', '3'); return false; } $shorturl = ''; - $apiurl = 'http://' . $this->yourls_domain . '/yourls-api.php?signature=' . $this->yourls_api . '&action=shorturl&format=simple&url=' . urlencode($url); + $apiurl = 'http://' . $this->yourls_domain . '/yourls-api.php?signature=' . $this->yourls_api_key . '&action=shorturl&format=simple&url=' . urlencode($url); try { debug_event($this->name, 'YOURLS api call: ' . $apiurl, '5'); $request = Requests::get($apiurl); @@ -130,8 +130,8 @@ class AmpacheYourls { debug_event($this->name,'No YOURLS domain, shortener skipped','3'); return false; } - if (strlen(trim($data['yourls_api']))) { - $this->yourls_api = trim($data['yourls_api']); + if (strlen(trim($data['yourls_api_key']))) { + $this->yourls_api_key = trim($data['yourls_api_key']); } else { debug_event($this->name,'No YOURLS api key, shortener skipped','3'); diff --git a/play/index.php b/play/index.php index 62d7b7dc..beb7802b 100644 --- a/play/index.php +++ b/play/index.php @@ -295,7 +295,6 @@ if ($_GET['action'] == 'download' AND AmpConfig::get('download')) { debug_event('play', 'Downloading file...', 5); // STUPID IE - $media->format_pattern(); $media_name = str_replace(array('?','/','\\'),"_",$media->f_file); $browser->downloadHeaders($media_name,$media->mime,false,$media->size); diff --git a/stream.php b/stream.php index 052bbbe1..20452741 100644 --- a/stream.php +++ b/stream.php @@ -159,10 +159,17 @@ switch ($_REQUEST['action']) { $urls = array($democratic->play_url()); break; case 'download': - $media_ids[] = array( - 'object_type' => 'song', - 'object_id' => scrub_in($_REQUEST['song_id']) - ); + if (isset($_REQUEST['song_id'])) { + $media_ids[] = array( + 'object_type' => 'song', + 'object_id' => scrub_in($_REQUEST['song_id']) + ); + } else if (isset($_REQUEST['video_id'])) { + $media_ids[] = array( + 'object_type' => 'video', + 'object_id' => scrub_in($_REQUEST['video_id']) + ); + } break; case 'live_stream': $object = new Radio($_REQUEST['stream_id']); diff --git a/templates/footer.inc.php b/templates/footer.inc.php index a0bda7e0..c36d8552 100644 --- a/templates/footer.inc.php +++ b/templates/footer.inc.php @@ -27,7 +27,9 @@ playlist->get_items()); + if ($GLOBALS['user']->playlist) { + $count_temp_playlist = count($GLOBALS['user']->playlist->get_items()); + } } ?>