diff options
author | Karl 'vollmerk' Vollmer <vollmer@ampache.org> | 2005-06-09 16:34:40 +0000 |
---|---|---|
committer | Karl 'vollmerk' Vollmer <vollmer@ampache.org> | 2005-06-09 16:34:40 +0000 |
commit | bcad40a05ab2dc2a341a3227e30b96668bce4500 (patch) | |
tree | 6fca27588d53a1b24705bd2834e9e643bb729bd1 /modules/class/catalog.php | |
download | ampache-bcad40a05ab2dc2a341a3227e30b96668bce4500.tar.gz ampache-bcad40a05ab2dc2a341a3227e30b96668bce4500.tar.bz2 ampache-bcad40a05ab2dc2a341a3227e30b96668bce4500.zip |
New Import
Diffstat (limited to 'modules/class/catalog.php')
-rw-r--r-- | modules/class/catalog.php | 1934 |
1 files changed, 1934 insertions, 0 deletions
diff --git a/modules/class/catalog.php b/modules/class/catalog.php new file mode 100644 index 00000000..9affc95a --- /dev/null +++ b/modules/class/catalog.php @@ -0,0 +1,1934 @@ +<? +/* + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +/*! + @header Catalog Class + This class handles all actual work in regards to the catalog, it contains functions for creating/listing/updated the catalogs. +*/ + +class Catalog { + + var $name; + var $last_update; + var $last_add; + var $id3_set_command; + var $rename_pattern; + var $sort_pattern; + var $catalog_type; + + // Used in functions + var $albums = array(); + var $artists = array(); + var $genres = array(); + + /*! + @function Catalog + @discussion Catalog class constructor, pulls catalog information + @param $catalog_id The ID of the catalog you want to build information from + */ + function Catalog($catalog_id = 0) { + + /* If we have passed an id then do something */ + if ($catalog_id) { + /* Assign id for use in get_info() */ + $this->id = $catalog_id; + + /* Get the information from the db */ + $info = $this->get_info(); + + /* Assign Vars */ + $this->path = $info->path; + $this->name = $info->name; + $this->last_update = $info->last_update; + $this->last_add = $info->last_add; + $this->id3_set_command = $info->id3_set_command; + $this->rename_pattern = $info->rename_pattern; + $this->sort_pattern = $info->sort_pattern; + $this->catalog_type = $info->catalog_type; + } //catalog_id + + } //constructor + + + /*! + @function get_info + @discussion get's the vars for $this out of the database + @param $this->id Taken from the object + */ + function get_info() { + + /* Grab the basic information from the catalog and return it */ + $sql = "SELECT * FROM catalog WHERE id='$this->id'"; + $db_results = mysql_query($sql, dbh()); + + $results = mysql_fetch_object($db_results); + + return $results; + + } //get_info + + + /*! + @function get_catalogs + @discussion Pull all the current catalogs + */ + function get_catalogs() { + + $sql = "SELECT id FROM catalog"; + $db_results = mysql_query($sql, dbh()); + + while ($r = mysql_fetch_object($db_results)) { + $results[] = new Catalog($r->id); + } + + return $results; + + } // get_catalogs + + + /*! + @function get_catalog_stats + @discussion Pulls information about number of songs etc for a specifc catalog, or all catalogs + calls many other internal functions, returns an object containing results + @param $catalog_id If set tells us to pull from a single catalog, rather than all catalogs + */ + function get_catalog_stats($catalog_id=0) { + + $results->songs = $this->count_songs($catalog_id); + $results->albums = $this->count_albums($catalog_id); + $results->artists = $this->count_artists($catalog_id); + $results->size = $this->get_song_size($catalog_id); + $results->time = $this->get_song_time($catalog_id); + + } // get_catalog_stats + + + /*! + @function get_song_time + @discussion Get the total amount of time (song wise) in all or specific catalog + @param $catalog_id If set tells ut to pick a specific catalog + */ + function get_song_time($catalog_id=0) { + + $sql = "SELECT SUM(song.time) FROM song"; + if ($catalog_id) { + $sql .= " WHERE catalog='$catalog_id'"; + } + + $db_results = mysql_query($sql, dbh()); + + $results = mysql_fetch_field($db_results); + + /* Do some conversion to get Hours Min Sec */ + + + return $results; + + } // get_song_time + + + /*! + @function get_song_size + @discussion Get the total size of songs in all or a specific catalog + @param $catalog_id If set tells us to pick a specific catalog + */ + function get_song_size($catalog_id=0) { + + $sql = "SELECT SUM(song.size) FROM song"; + if ($catalog_id) { + $sql .= " WHERE catalog='$catalog_id'"; + } + + $db_results = mysql_query($sql, dbh()); + + $results = mysql_fetch_field($db_results); + + /* Convert it into MB */ + $results = ($results / 1048576); + + return $results; + + } // get_song_size + + + /*! + @function count_artists + @discussion Count the number of artists in all catalogs or in a specific one + @param $catalog_id If set tells us to pick a specific catalog + */ + function count_artists($catalog_id=0) { + + $sql = "SELECT DISTINCT(song.artist) FROM song"; + if ($catalog_id) { + $sql .= " WHERE catalog='$catalog_id'"; + } + + $db_results = mysql_query($sql,dbh()); + + $results = mysql_num_rows($db_results); + + return $results; + + } // count_artists + + + /*! + @function count_albums + @discussion Count the number of albums in all catalogs or in a specific one + @param $catalog_id If set tells us to pick a specific catalog + */ + function count_albums($catalog_id=0) { + + $sql = "SELECT DISTINCT(song.album) FROM song"; + if ($catalog_id) { + $sql .=" WHERE catalog='$catalog_id'"; + } + + $db_results = mysql_query($sql, dbh()); + + $results = mysql_num_rows($db_results); + + return $results; + + } // count_albums + + + /*! + @function count_songs + @discussion Count the number of songs in all catalogs, or a specific one + @param $catalog_id If set tells us to pick a specific catalog + */ + function count_songs($catalog_id=0) { + + $sql = "SELECT count(*) FROM song"; + if ($catalog_id) { + $sql .= " WHERE catalog='$catalog_id'"; + } + + $db_results = mysql_query($sql, dbh()); + $results = mysql_fetch_field($db_results); + + return $results; + + } // count_songs + + /*! + @function add_file + @discussion adds a single file + */ + function add_file($filename) { + + $file_size = @filesize($filename); + $pattern = "/\.[" . conf('catalog_file_pattern') . "]$/i"; + + if ( preg_match($pattern ,$filename) && ($file_size > 0) && (!preg_match('/\.AppleDouble/', $filename)) ) { + if(!$this->check_local_mp3($filename,$gather_type)) { + $this->insert_local_song($filename,$file_size); + } + } // if valid file + + + } // add_file + + + /*! + @function add_files + @discussion Recurses throught $this->path and pulls out all mp3s and returns the full + path in an array. Passes gather_type to determin if we need to check id3 + information against the db. + @param $path The root path you want to start grabing files from + @param $gather_type=0 Determins if we need to check the id3 tags of the file or not + */ + function add_files($path,$gather_type=0,$parse_m3u=0) { + /* Strip existing escape slashes and then add them again + This is done because we keep adding to the dir (slashed) + (non slashed) + and a double addslashes would pooch things + */ + + /* Open up the directory */ + $handle = opendir(stripslashes($path)); + + if (!is_resource($handle)) { + if (conf('debug')) { log_event($_SESSION['userdata']['username'],'read',"Unable to Open $path",'ampache-catalog'); } + echo "<font class=\"error\">" . _("Error: Unable to open") . " $path</font><br />\n"; + } + + /* Recurse through this dir and create the files array */ + while ( false !== ( $file = readdir($handle) ) ) { + + // Fix Found by Naund + // Needed to protect from ' in filenames + $file = sql_escape($file); + + // Prevent the script from timing out + set_time_limit(0); + + /* if not .. or . */ + if ($file != "." AND $file != "..") { + + if (conf('debug')) { + log_event($_SESSION['userdata']['username'],'read',"Starting work on $file inside $path",'ampache-catalog'); + } + + /* Change the dir so is_dir works correctly */ + if (!@chdir(stripslashes($path))) { + if (conf('debug')) { log_event($_SESSION['userdata']['username'],'read',"Unable to chdir $path",'ampache-catalog'); } + echo "<font class=\"error\">" . _("Error: Unable to change to directory") . " $path</font><br />\n"; + } + + /* Create the new path */ + $full_file = stripslashes($path."/".$file); + $full_file = str_replace("//","/",$full_file); + + if (conf('no_symlinks')) { + if (is_link($full_file)) { $failed_check = 1; } + } + + /* If it's a dir run this function again! */ + if (is_dir($full_file) AND !$failed_check) { + $this->add_files($full_file,$gather_type,$parse_m3u); + unset($failed_check); + } //it's a directory + + /* If it's not a dir let's roll with it */ + else { + /* Get the file information */ + $file_size = @filesize($full_file); + + if (!$file_size && $file_size != '0') { + echo "<font class=\"error\">" . _("Error: Unable to get filesize for") . " $full_file <br />"; + if (conf('debug')) { log_event($GLOBALS['user']->username,' read ',"Error: Unable to get filesize for $full_file",'ampache-catalog'); } + } // if no filesize + + $pattern = "/\.(" . conf('catalog_file_pattern'); + if ($parse_m3u) { + $pattern .= "|m3u)$/i"; + } + else { + $pattern .= ")$/i"; + } + + /* see if this is an mp3 file and if it is greater than 0 bytes */ + if ( preg_match($pattern ,$file) && ($file_size > 0) && (!preg_match('/\.AppleDouble/', $file)) ) { + + if (is_readable($full_file)) { + + if (substr($file,-3,3) == 'm3u') { + if ($this->import_m3u($full_file)) { + echo " " . _("Added Playlist From") . " $file . . . .<br />\n"; + flush(); + } + } // if it's an m3u + + else { + + /* see if the current song is in the catalog */ + $found = $this->check_local_mp3($full_file,$gather_type); + + /* If not found then insert, gets id3 information + * and then inserts it into the database + */ + if (!$found) { + $this->insert_local_song($full_file,$file_size); + + /* Stupid little cutesie thing */ + $this->count++; + if ( !($this->count%conf('catalog_echo_count')) ) { + echo _("Added") . " $this->count. . . . <br />\n"; + flush(); + } //echos song count + + } // not found + + } // if it's not an m3u + + } // is readable + else { + // not readable, warn user + if (conf('debug')) { log_event($_SESSION['userdata']['username'],'read',"$full_file is not readable by ampache",'ampache-catalog'); } + echo "$full_file " . _("is not readable by ampache") . ".<br />\n"; + + } + + } //if it's a mp3 and is greater than 0 bytes + + else { + if (conf('debug')) { + log_event($_SESSION['userdata']['username'],'read',"$full_file ignored, non audio file or 0 bytes",'ampache-catalog'); + } + } // else not an audio file or 0 size + + } //else it's not a directory + + } //end if not . or .. + + } //end while + + if (conf('debug')) { + log_event($_SESSION['userdata']['username'],' closedir ',"Finished reading $path closing handle",'ampache-catalog'); + } + + /* Close the dir handle */ + @closedir($handle); + + } //add_files + + /*! + @function get_albums + @discussion This gets albums for all songs passed in an array + */ + function get_albums($songs=array()) { + + foreach ($songs as $song_id) { + $sql = "SELECT album FROM song WHERE id='$song_id'"; + $db_results = mysql_query($sql, dbh()); + $results = mysql_fetch_array($db_results); + $albums[] = new Album($results[0]); + } // files + + return $albums; + + } // get_albums + + /*! + @function get_album_art + @discussion This runs through all of the albums and trys to find the + art for them from the mp3s + //FIXME: Make the display a table so it all lines up + */ + function get_album_art($catalog_id=0,$methods=array()) { + + if (!$catalog_id) { $catalog_id = $this->id; } + + // Get all of the albums in this catalog + $albums = $this->get_catalog_albums($catalog_id); + + // Run through them an get the art! + foreach ($albums as $album) { + flush(); + if ($debug) { echo " " . $album->name . " -- "; } + + if ($methods['id3']) { + $found = $album->get_id3_art(); + if ($found && $debug) { echo _("Found in ID3") . "<br />\n"; } + } + if ($methods['amazon'] && !$found) { + $found = $album->get_amazon_art(); + if ($found && $debug) { echo _("Found on Amazon") . "<br />\n"; } + } + if ($methods['folder'] && !$found) { + $found = $album->get_folder_art(); + if ($found && $debug) { echo _("Found in Folder") . "<br />\n"; } + } + if (count($methods) == '0' && !$found) { + $found = $album->get_art(); + if ($found && $debug) { echo _("Found") . "<br />\n"; } + } + + if (!$found && $debug) { echo "<font class=\"error\">" . _("Not Found") . "</font><br />\n"; } + + if ($found) { $art_found++; } + + + /* Stupid little cutesie thing */ + $search_count++; + if ( !($search_count%conf('catalog_echo_count')) ) { + echo _("Searched") . " $search_count. . . . <br />\n"; + flush(); + } //echos song count + + + // Prevent the script from timing out + set_time_limit(0); + + unset($found); + + } // foreach albums + + echo "$art_found album's with art. . .<br />\n"; + flush(); + + } // get_album_art + + /*! + @function get_catalog_albums() + @discussion Returns an array of the albums from a catalog + */ + function get_catalog_albums($catalog_id=0) { + + $results = array(); + + /* Use $this->id if nothing is passed */ + if (!$catalog_id) { $catalog_id = $this->id; } + + $sql = "SELECT DISTINCT(album.id) FROM album,song WHERE song.catalog='$catalog_id' AND song.album=album.id"; + $db_results = mysql_query($sql, dbh()); + + while ($r = mysql_fetch_object($db_results)) { + $results[] = new Album($r->id); + } + + return $results; + + } // get_catalog_albums + + + /*! + @function get_catalog_files + @discussion Returns an array of song objects from a catalog + @param $catalog_id=0 Specify the catalog ID you want to get the files of + */ + function get_catalog_files($catalog_id=0) { + + $results = array(); + + /* Use $this->id if nothing passed */ + if (!$catalog_id) { $catalog_id = $this->id; } + + $sql = "SELECT id FROM song WHERE catalog='$catalog_id' AND status='enabled'"; + $db_results = mysql_query($sql, dbh()); + + $results = array(); // return an emty array instead of nothing if no objects + while ($r = mysql_fetch_object($db_results)) { + $results[] = new Song($r->id); + } //end while + + return $results; + + } //get_catalog_files + + + /*! + @function get_disabled + @discussion Gets an array of the disabled songs for all catalogs + and returns full song objects with them + */ + function get_disabled() { + global $conf; + + $results = array(); + + $sql = "SELECT id FROM song WHERE status='disabled'"; + $db_results = mysql_query($sql, dbh()); + + while ($r = mysql_fetch_array($db_results)) { + $results[] = new Song($r['id']); + } + + return $results; + + } // get_disabled + + + /*! + @function get_files + @discussion Get's an array of .mp3s and returns the filenames + @param $path Get files starting at root $path + */ + function get_files($path) { + + /* Set it as an empty array */ + $files = array(); + + $path = stripslashes($path); + + /* Open up the directory */ + $handle = @opendir($path); + + if (!is_resource($handle)) { echo "<font class=\"error\">" . _("Error: Unable to open") . " $path</font><br />\n"; } + + /* Change dir so we can tell if it's a directory */ + if (!@chdir($path)) { + echo "<font class=\"error\">Error: Unable to change to $path directory</font><br />\n"; + } + + /* Recurse through this dir and create the files array */ + while ( FALSE !== ($file = @readdir($handle)) ) { + + $full_file = stripslashes($path . "/" . $file); + $full_file = str_replace("//","/",$full_file); + + if (conf('no_symlinks')) { + if (is_link($full_file)) { $failed_check = true; } + } + + /* It's a dir */ + if (is_dir($full_file) AND $file != "." AND $file != ".." AND !$failed_check) { + /* Merge the results of the get_files with the current results */ + $files = array_merge($files,$this->get_files($full_file)); + } //isdir + + /* Get the file information */ + $file_info = filesize($full_file); + + $pattern = "/\.[" . conf('catalog_file_pattern') . "]$/i"; + + if ( preg_match($pattern ,$file) && ($file_info > 0) && (!preg_match("/\.AppleDouble/", $file)) ) { + $files[] = $full_file; + } //is mp3 of at least some size + + } //end while + + /* Close the dir handle */ + @closedir($handle); + + /* Return the files array */ + return $files; + + } //get_files + + /*! + @function dump_album_art (Added by Cucumber 20050216) + @discussion This runs through all of the albums and trys to dump the + art for them into the 'folder.jpg' file in the appropriate dir + */ + function dump_album_art($catalog_id=0,$methods=array()) { + if (!$catalog_id) { $catalog_id = $this->id; } + + // Get all of the albums in this catalog + $albums = $this->get_catalog_albums($catalog_id); + + echo "<br /><b>" . _("Starting Dump Album Art") . ". . .</b><br><br />\n"; + + // Run through them an get the art! + foreach ($albums as $album) { + flush(); + if ($image = $album->get_db_art()) { + /* Get the first song in the album */ + $songs = $album->get_songs(1); + $song = $songs[0]; + $dir = dirname($song->file); + $extension = substr($image->art_mime,strlen($image->art_mime)-3,3); + + $preferred_filename = conf('album_art_preferred_filename'); + if (!$preferred_filename) { $preferred_filename = "folder.$extension"; } + + $file = "$dir/$preferred_filename"; + if ($file_handle = @fopen($file,"w")) { + if (fwrite($file_handle, $image->art)) { + $i++; + if ( !($i%conf('catalog_echo_count')) ) { + echo _("Written") . " $i. . . <br />\n"; + flush(); + } //echos song count + if (conf('debug')) { log_event($_SESSION['userdata']['username'],'art_write',"$album->name Art written to $file"); } + } + fclose($file_handle); + } // end if fopen + else { + if (conf('debug')) { log_event($_SESSION['userdata']['username'],'art_write',"Unable to open $file for writting"); } + echo "<font class=\"error\">" . _("Error unable to open file for writting") . " [$file] </font><br />\n"; + } + + } // end if image + + } // end foreach + + echo "<br /><b>" . _("Album Art Dump Complete") . "</b> "; + echo "<a href=\"" . conf('web_path') . "/admin/catalog.php" . "\">[" . _("Return") . "]</a>"; + + flush(); + + } // dump_album_art + + /*! + @function update_last_update + @discussion updates the last_update of the catalog + */ + function update_last_update() { + + $date = time(); + $sql = "UPDATE catalog SET last_update='$date' WHERE id='$this->id'"; + $db_results = mysql_query($sql, dbh()); + + } // update_last_update + + + /*! + @function update_last_add + @discussion updates the last_add of the catalog + */ + function update_last_add() { + + $date = time(); + $sql = "UPDATE catalog SET last_add='$date' WHERE id='$this->id'"; + $db_results = mysql_query($sql, dbh()); + + } // update_last_add + + + /*! + @function new_catalog + @discussion The Main array for making a new catalog calls many other child functions within this class + @param $path Root path to start from for catalog + @param $name Name of the new catalog + */ + function new_catalog($path,$name, $id3cmd=0, $ren=0, $sort=0, $type=0,$gather_art=0,$parse_m3u=0,$art=array()) { + + /* Record the time.. time the catalog gen */ + $start_time = time(); + + /* Flush anything that has happened so they don't think it's locked */ + flush(); + + /* + * Step one Add this to the catalog table if it's not + * already there returns the new catalog_id + */ + $catalog_id = $this->check_catalog($path); + + if (!$catalog_id) { + $catalog_id = $this->create_catalog_entry($path,$name,$id3cmd, $ren, $sort, $type); + } + + /* Setup the $this with the new information */ + $this->id = $catalog_id; + $this->path = $path; + $this->name = $name; + $this->id3_set_command = ($id3cmd)?$id3cmd:''; + $this->rename_pattern = ($ren)?$ren:''; + $this->sort_pattern = ($sort)?$sort:''; + $this->catalog_type = $type; + + /* Fluf */ + echo _("Starting Catalog Build") . " [$name]<br />\n"; + flush(); + + + if ($this->catalog_type == 'remote') { + echo _("Running Remote Sync") . ". . .<br /><br />"; + flush(); + $this->get_remote_catalog($type=0); + return true; + } + /* Get the songs and then insert them into the db */ + $this->add_files($this->path,$type,$parse_m3u); + + /* Now Adding Album Art? */ + if ($gather_art) { + echo "<br />\n<b>" . _("Starting Album Art Search") . ". . .</b><br />\n"; + flush(); + $this->get_album_art(0,$art); + } // if we want to gather album art + + /* Do a little stats mojo here */ + $current_time = time(); + + $time_diff = $current_time - $start_time; + if ($time_diff) { $song_per_sec = intval($this->count/$time_diff); } + echo _("Catalog Finished") . ". . . " . _("Total Time") . " [" . date("i:s",$time_diff) . "] " . _("Total Songs") . " [" . $this->count . "] " . + _("Songs Per Seconds") . " [" . $song_per_sec . "]<br />\n"; + + return $catalog_id; + + } //new_catalog + + /*! + @function update_single_item + @discussion updates a single album,artist,song + */ + function update_single_item($type,$id) { + + $songs = array(); + + switch ($type) { + case 'album': + $album = new Album($id); + $songs = $album->get_songs(); + break; + case 'artist': + $artist = new Artist($id); + $songs = $artist->get_songs(); + break; + case 'song': + $songs[0] = new Song($id); + break; + } // end switch type + + foreach($songs as $song) { + + $info = $this->update_song_from_tags($song); + + if ($info['change']) { + echo "<dl>\n\t<li>"; + echo "<b>$song->file " . _("Updated") . "</b>\n"; + echo $info['text']; + echo "\t</li>\n</dl><hr align=\"left\" width=\"50%\" />"; + flush(); + } // if change + else { + echo"<dl>\n\t<li>"; + echo "<b>$song->file</b><br />" . _("No Update Needed") . "\n"; + echo "\t</li>\n</dl><hr align=\"left\" width=\"50%\" />"; + flush(); + } + } // foreach songs + + } // update_single_item + + /*! + @function update_song_from_tags + @discussion updates the song info based on tags + */ + function update_song_from_tags($song) { + + $info = new Audioinfo(); + $results = $info->Info($song->file); + + /* Find the correct key */ + $key = get_tag_type($results); + + /* Fill Missing Information */ + $results = $song->fill_info($results,$this->sort_pattern . "/" . $this->rename_pattern, $this->id, $key); + + /* Clean up the tags */ + $results = clean_tag_info($results,$key,$song->file); + + /* Setup the vars */ + $new_song = new Song(); + $new_song->file = $results['file']; + $new_song->title = $results['title']; + $new_song->year = $results['year']; + $new_song->comment = $results['comment']; + $new_song->bitrate = $results['bitrate']; + $new_song->rate = $results['rate']; + $new_song->mode = $results['mode']; + $new_song->size = $results['size']; + $new_song->time = $results['time']; + $new_song->track = $results['track']; + $artist = $results['artist']; + $album = $results['album']; + $genre = $results['genre']; + + /* Clean up Old Vars */ + unset($results,$key,$info); + + /* + * We have the artist/genre/album name need to check it in the tables + * If found then add & return id, else return id + */ + $new_song->artist = $this->check_artist($artist); + $new_song->f_artist = $artist; + $new_song->genre = $this->check_genre($genre); + $new_song->f_genre = $genre; + $new_song->album = $this->check_album($album,$new_song->year); + $new_song->f_album = $album . " - " . $new_song->year; + $new_song->title = $this->check_title($new_song->title,$new_song->file); + + $info = $song->compare_song_information($song,$new_song); + + if ($info['change']) { + $song->update_song($song->id,$new_song); + } + + return $info; + + } // update_song_from_tags + + /*! + @function add_to_catalog + @discussion this function adds new files to an + existing catalog + */ + function add_to_catalog($type=0) { + + echo _("Starting New Song Search on") . " <b>[$this->name]</b> " . _("catalog") . "<br /><br />\n"; + flush(); + + if ($this->catalog_type == 'remote') { + echo _("Running Remote Update") . ". . .<br /><br />"; + flush(); + $this->get_remote_catalog($type=0); + return true; + } + + /* Set the Start time */ + $start_time = time(); + + /* Get the songs and then insert them into the db */ + $this->add_files($this->path,$type); + + /* Do a little stats mojo here */ + $current_time = time(); + + if ($type != "fast_add") { + echo "<b>" . _("Starting Album Art Search") . ". . .</b><br />\n"; + flush(); + $this->get_album_art(); + } + + /* Update the Catalog last_update */ + $this->update_last_add(); + + $time_diff = $current_time - $start_time; + if ($time_diff) { + $song_per_sec = intval($this->count/$time_diff); + } + if (!$song_per_sec) { + $song_per_sec = "N/A"; + } + if (!$this->count) { + $this->count = 0; + } + + echo "\n<br />" . _("Catalog Update Finished") . "... " . _("Total Time") . " [" . date("i:s",$time_diff) . "] " . + _("Total Songs") . " [" . $this->count . "] " . _("Songs Per Seconds") . " [" . $song_per_sec . "]<br /><br />"; + + } // add_to_catalog + + + /*! + @function get_remote_catalog + @discussion get a remote catalog and runs update if needed + */ + function get_remote_catalog($type=0) { + + if (!class_exists('xmlrpc_client')) { + if (conf('debug')) { log_event($_SESSION['userdata']['username'],'xmlrpc',"Unable to load XMLRPC library"); } + echo "<font class=\"error\"><b>" . _("Error") . "</b>: " . _("Unable to load XMLRPC library, make sure XML-RPC is enabled") . "<br />\n"; + return false; + } + + // first, glean out the information from the path about the server and remote path + preg_match("/http:\/\/([^\/]+)\/*(.*)/", $this->path, $match); + $server = $match[1]; + $path = $match[2]; + + if ( ! $path ) { + $client = new xmlrpc_client("/server.php", $server, 80); + } + else { + $client = new xmlrpc_client("/$path/server.php", $server, 80); + } + + $f = new xmlrpcmsg('remote_server_query', array(new xmlrpcval( conf('web_path'), "string")) ); + //if (conf('debug')) { $client->setDebug(1); } + $response = $client->send($f); + $value = $response->value(); + + if ( !$response->faultCode() ) { + $data = old_xmlrpc_decode($value); + + // Print out the catalogs we are going to sync + //FIXME: We should add catalog level access control + foreach ($data as $vars) { + $catalog_name = $vars[0]; + print("<b>Reading Remote Catalog: $catalog_name</b> [$this->path]<br />\n"); + } + } + else { + $error_msg = _("Error connecting to") . " " . $server . " " . _("Code") . ": " . $response->faultCode() . " " . _("Reason") . ": " . $response->faultString(); + log_event($_SESSION['userdata']['username'],'xmlrpc',$error_msg); + echo "<p class=\"error\">$error_msg</p>"; + return; + } + + $f = new xmlrpcmsg('remote_song_query', array(new xmlrpcval( 'song', "string")) ); + $response = $client->send($f); + $value = $response->value(); + + if ( !$response->faultCode() ) { + $data = old_xmlrpc_decode($value); + $this->update_remote_catalog($data,$this->path); + } + else { + $error_msg = _("Error connecting to") . " " . $server . " " . _("Code") . ": " . $response->faultCode() . " " . _("Reason") . ": " . $response->faultString(); + log_event($_SESSION['userdata']['username'],'xmlrpc',$error_msg); + echo "<p class=\"error\">$error_msg</p>"; + } + + echo "<p>" . _("Completed updating remote catalog(s)") . ".</p><hr>\n"; + + + } // get_remote_catalog + + /*! + @function update_remote_catalog + @discussion actually updates from the remote data + */ + function update_remote_catalog($songs,$root_path) { + global $settings, $dbh, $artists; + + + /* + We need to check the incomming songs + to see which ones need to be added + */ + foreach ($songs as $song) { + + // Prevent a timeout + set_time_limit(0); + + $song = base64_decode($song); + + $data = explode("::", $song); + + $new_song->artist = $this->check_artist($data[0]); + $new_song->album = $this->check_album($data[1],$data[4]); + $new_song->title = $data[2]; + $new_song->comment = $data[3]; + $new_song->year = $data[4]; + $new_song->bitrate = $data[5]; + $new_song->rate = $data[6]; + $new_song->mode = $data[7]; + $new_song->size = $data[8]; + $new_song->time = $data[9]; + $new_song->track = $data[10]; + $new_song->genre = $this->check_genre($data[11]); + $new_song->file = $root_path . "/play/index.php?song=" . $data[12] . "uid=$md5_ip"; + $new_song->catalog = $this->id; + + if (!$song_id = $this->check_remote_song($new_song->file)) { + $this->insert_remote_song($new_song); + } + + } // foreach new Songs + + //FIXME: Delete Songs that were not updated (gone) + + // now delete invalid entries + $this->clean_albums(); + $this->clean_stats(); + $this->clean_artists(); + $this->clean_flagged(); + + } // update_remote_catalog + + + /*! + @function clean_catalog + @discussion Cleans the Catalog of files that no longer exist grabs from $this->id or $id passed + Doesn't actually delete anything, disables errored files, and returns them in an array + @param $catalog_id=0 Take the ID of the catalog you want to clean + @param $action=0 Delete/Disable, default is disable + */ + function clean_catalog($catalog_id=0,$action=0) { + + /* Define the Arrays we will need */ + $dead_files = array(); + + if (!$catalog_id) { $catalog_id = $this->id; } + + echo "Cleaning the <b>[" . $this->name . "]</b> Catalog...<br /><br />"; + flush(); + + /* Get all songs in this catalog */ + $sql = "SELECT id,file FROM song WHERE catalog='$catalog_id' AND status='enabled'"; + $db_results = mysql_query($sql, dbh()); + + /* Recurse through files, put @ to prevent errors poping up */ + while ($results = mysql_fetch_object($db_results)) { + + /* Remove slashes while we are checking for its existance */ + $results->file = stripslashes($results->file); + + /* Stupid little cutesie thing */ + $this->count++; + if ( !($this->count%conf('catalog_echo_count')) ) { + echo _("Checking") . " $this->count. . . . <br />\n"; + flush(); + } //echos song count + + /* Also check the file information */ + $file_info = @filesize($results->file); + + /* If it errors somethings splated, or the files empty */ + if (!file_exists($results->file) OR $file_info < 1) { + + /* Add Error */ + echo "<font class=\"error\">Error File Not Found or 0 Bytes: " . $results->file . "</font><br />"; + flush(); + + /* Add this file to the list for removal from the db */ + $dead_files[] = $results; + } //if error + + } //while gettings songs + + /* Incase there's been a snafo with a mount point on something + * don't actually delete from DB here, simply disable and list + */ + if (count($dead_files)) { + foreach ($dead_files as $data) { + + //FIXME: Until I fix the form, assume delete + //if ($action === 'delete_dead') { + $sql = "DELETE FROM song WHERE id='$data->id'"; + //} + // + //else { + // $sql = "UPDATE song SET status='disabled' WHERE id='$data->id'"; + //} + + $db_results = mysql_query($sql, dbh()); + + /* DB Error occured */ + if (!$db_results) { + /* Add Error */ + } //if error + + } //end foreach + + } // end if dead files + + /* Step two find orphaned Arists/Albums + * This finds artists and albums that no + * longer have any songs associated with them + */ + $this->clean_albums(); + $this->clean_artists(); + $this->clean_stats(); + $this->clean_playlists(); + $this->clean_flagged(); + + /* Return dead files, so they can be listed */ + echo "<b>" . _("Catalog Clean Done") . " [" . count($dead_files) . "] " . _("files removed") . "</b><br />\n"; + flush(); + return $dead_files; + + } //clean_catalog + + + /*! + @function clean_albums + @discussion This function cleans out unused albums + @param $this->id Depends on the current object + */ + function clean_albums() { + + /* Mysql 3.23 doesn't support our cool query so we have to do it a different way */ + if (preg_match("/^3\./",mysql_get_server_info())) { + $sql = "SELECT album.id FROM album LEFT JOIN song ON song.album = album.id WHERE song.id IS NULL"; + $db_results = mysql_query($sql, dbh()); + + $results = array(); + + while ($r = mysql_fetch_row($db_results)) { + $results[] = $r; + } + + foreach ($results as $dead) { + + $sql = "DELETE FROM album WHERE id='$dead[0]'"; + $db_results = mysql_query($sql,dbh()); + } + return true; + } + + /* Do a complex delete to get albums where there are no songs */ + $sql = "DELETE FROM album USING album LEFT JOIN song ON song.album = album.id WHERE song.id IS NULL"; + $db_results = mysql_query($sql, dbh()); + + } //clean_albums + + /*! + @function clean_flagged + @discussion This functions cleans ou unused flagged items + */ + function clean_flagged() { + + /* Mysql 3.23 doesn't support our cool query so we have to do it a different way */ + if (preg_match("/^3\./",mysql_get_server_info())) { + $sql = "SELECT flagged.id FROM flagged LEFT JOIN song ON song.id=flagged.song WHERE song.id IS NULL"; + $db_results = mysql_query($sql, dbh()); + + $results = array(); + + while ($r = mysql_fetch_row($db_results)) { + $results[] = $r; + } + + foreach ($results as $dead) { + $sql = "DELETE FROM flagged WHERE id='$dead[0]'"; + $db_results = mysql_query($sql, dbh()); + } + return true; + } + + /* Do a complex delete to get flagged items where the songs are now gone */ + $sql = "DELETE FROM flagged USING flagged LEFT JOIN song ON song.id = flagged.song WHERE song.id IS NULL"; + $db_results = mysql_query($sql, dbh()); + + } // clean_flagged + + + /*! + @function clean_artists + @discussion This function cleans out unused artists + @param $this->id Depends on the current object + */ + function clean_artists() { + + /* Mysql 3.23 doesn't support our cool query so we have to do it a different way */ + if (preg_match("/^3\./",mysql_get_server_info())) { + $sql = "SELECT artist.id FROM artist LEFT JOIN song ON song.artist = artist.id WHERE song.id IS NULL"; + $db_results = mysql_query($sql, dbh()); + + $results = array(); + + while ($r = mysql_fetch_row($db_results)) { + $results[] = $r; + } + + foreach ($results as $dead) { + + $sql = "DELETE FROM artist WHERE id='$dead[0]'"; + $db_results = mysql_query($sql,dbh()); + } + return true; + } + + + /* Do a complex delete to get artists where there are no songs */ + $sql = "DELETE FROM artist USING artist LEFT JOIN song ON song.artist = artist.id WHERE song.id IS NULL"; + $db_results = mysql_query($sql, dbh()); + + } //clean_artists + + /* + @function clean_playlists + @discussion cleans out dead files from playlists + @param $this->id depends on the current object + */ + function clean_playlists() { + + /* Mysql 3.23 doesn't support our cool query so we have to do it a different way */ + if (preg_match("/^3\./",mysql_get_server_infO())) { + $sql = "SELECT playlist_data.song FROM playlist_data LEFT JOIN song ON song.id = playlist_data.song WHERE song.file IS NULL"; + $db_results = mysql_query($sql, dbh()); + + $results = array(); + + while ($r = mysql_fetch_row($db_results)) { + $results[] = $r; + } + + foreach ($results as $dead) { + $sql = "DELETE FROM playlist_data WHERE song='$dead[0]'"; + $db_results = mysql_query($sql, dbh()); + } + return true; + } + + /* Do a complex delete to get playlist songs where there are no songs */ + $sql = "DELETE FROM playlist_data USING playlist_data LEFT JOIN song ON song.id = playlist_data.song WHERE song.file IS NULL"; + $db_results = mysql_query($sql, dbh()); + + } // clean_playlists + + /*! + @function clean_stats + @discussion This functions removes stats for songs/albums that no longer exist + @param $catalog_id The ID of the catalog to clean + */ + function clean_stats() { + + $version = mysql_get_server_info(); + + /* Mysql 3.23 doesn't support our cool query so we have to do it a different way */ + if (preg_match("/^3\./",$version)) { + $sql = "SELECT object_count.id FROM object_count LEFT JOIN song ON song.id = object_count.object_id WHERE object_type='song' AND song.id IS NULL"; + $db_results = mysql_query($sql, dbh()); + + $results = array(); + + while ($r = mysql_fetch_row($db_results)) { + $results[] = $r; + } + + foreach ($results as $dead) { + + $sql = "DELETE FROM object_count WHERE id='$dead[0]'"; + $db_results = mysql_query($sql,dbh()); + } + + } + // We assume this will be 4.0+ + else { + /* Crazy SQL Mojo to remove stats where there are no songs */ + $sql = "DELETE FROM object_count USING object_count LEFT JOIN song ON song.id=object_count.object_id WHERE object_type='song' AND song.id IS NULL"; + $db_results = mysql_query($sql, dbh()); + } + + /* Mysql 3.23 doesn't support our cool query so we have to do it a different way */ + if (preg_match("/^3\./",$version)) { + $sql = "SELECT object_count.id FROM object_count LEFT JOIN album ON album.id = object_count.object_id WHERE object_type='album' AND album.id IS NULL"; + $db_results = mysql_query($sql, dbh()); + + $results = array(); + + while ($r = mysql_fetch_row($db_results)) { + $results[] = $r; + } + + foreach ($results as $dead) { + + $sql = "DELETE FROM object_count WHERE id='$dead[0]'"; + $db_results = mysql_query($sql,dbh()); + } + } + // We assume 4.0+ Here + else { + /* Crazy SQL Mojo to remove stats where there are no albums */ + $sql = "DELETE FROM object_count USING object_count LEFT JOIN album ON album.id=object_count.object_id WHERE object_type='album' AND album.id IS NULL"; + $db_results = mysql_query($sql, dbh()); + } + + /* Mysql 3.23 doesn't support our cool query so we have to do it a different way */ + if (preg_match("/^3\./",$version)) { + $sql = "SELECT object_count.id FROM object_count LEFT JOIN artist ON artist.id = object_count.object_id WHERE object_type='artist' AND artist.id IS NULL"; + $db_results = mysql_query($sql, dbh()); + + $results = array(); + + while ($r = mysql_fetch_row($db_results)) { + $results[] = $r; + } + + foreach ($results as $dead) { + + $sql = "DELETE FROM object_count WHERE id='$dead[0]'"; + $db_results = mysql_query($sql,dbh()); + } + } + // We assume 4.0+ here + else { + /* Crazy SQL Mojo to remove stats where ther are no artists */ + $sql = "DELETE FROM object_count USING object_count LEFT JOIN artist ON artist.id=object_count.object_id WHERE object_type='artist' AND artist.id IS NULL"; + $db_results = mysql_query($sql, dbh()); + } + + + } // clean_stats + + + /*! + @function verify_catalog + @discussion This function compares the DB's information with the ID3 tags + @param $catalog_id The ID of the catalog to compare + */ + function verify_catalog($catalog_id=0,$gather_type=0) { + + /* Create and empty song for us to use */ + $total_updated = 0; + + /* Set it to this if they don't pass anything */ + if (!$catalog_id) { + $catalog_id = $this->id; + } + + /* First get the filenames for the catalog */ + $sql = "SELECT id FROM song WHERE catalog='$catalog_id' ORDER BY id"; + $db_results = mysql_query($sql, dbh()); + $number = mysql_num_rows($db_results); + + echo _("Updating the") . " <b>[ $this->name ]</b> " . _("Catalog") . "<br />\n"; + echo $number . " " . _("songs found checking tag information.") . "<br /><br />\n\n"; + flush(); + + /* Magical Fix so we don't run out of time */ + set_time_limit(0); + + /* Recurse through this catalogs files + * and get the id3 tage information, + * if it's not blank, and different in + * in the file then update! + */ + while ($results = mysql_fetch_object($db_results)) { + + $song = new Song($results->id); + + if (is_readable($song->file)) { + unset($skip); + + /* If they have specified fast_update check the file + filemtime to make sure the file has actually + changed + */ + if ($gather_type === "fast_update") { + $file_date = filemtime($song->file); + if ($file_date < $this->last_update) { $skip = true; } + } // if gather_type + + if ($song->update_time >= $this->last_update) { + $skip = true; + $song->update_utime($song->id,time()+86400); + } + + // if the file hasn't been modified since the last_update + if (!$skip) { + + $info = $this->update_song_from_tags($song); + $album_id = $song->album; + if ($info['change']) { + echo "<dl>\n\t<li>"; + echo "<b>$song->file " . _("Updated") . "</b>\n"; + echo $info['text']; + /* If we aren't doing a fast update re-gather album art */ + if ($gather_type !== "fast_update" AND !isset($searched_albums[$album_id])) { + $album = new Album($song->album); + $searched_albums[$album_id] = 1; + $found = $album->get_art(); + unset($album); + if ($found) { $is_found = _(" FOUND"); } + echo "<br /><b>" . _("Searching for new Album Art") . ". . .$is_found</b><br />\n"; + unset($found,$is_found); + } + elseif (isset($searched_albums[$album_id])) { + echo "<br /><b>" . _("Album Art Already Found") . ". . .</b><br />\n"; + } + echo "\t</li>\n</dl>\n<hr align=\"left\" width=\"50%\" />\n"; + flush(); + $total_updated++; + } + + unset($info); + + } // end skip + + /* Stupid little cutesie thing */ + $this->count++; + if ( !($this->count%conf('catalog_echo_count')) ) { + echo "Checked $this->count. . . . <br />\n"; + flush(); + } //echos song count + + } // end if file exists + + else { + echo "<dl>\n <li>"; + echo "<b>$song->file does not exist or is not readable</b>\n"; + echo " </li>\n</dl>\n<hr align=\"left\" width=\"50%\" />\n"; + // Should we remove it from catalog? + } + + + } //end foreach + + + /* After we have updated all the songs with the new information clear any empty albums/artists */ + $this->clean_albums(); + $this->clean_artists(); + $this->clean_stats(); + $this->clean_flagged(); + + // Update the last_update + $this->update_last_update(); + + echo "Update Finished. Checked $this->count. $total_updated songs updated.<br /><br />"; + + } //verify_catalog + + + /*! + @function create_catalog_entry + @discussion Creates a new catalog from path and type + @param $path The root path for this catalog + @param $name The name of the new catalog + */ + function create_catalog_entry($path,$name,$id3cmd=0,$ren=0,$sort=0, $type='local') { + + // Current time + $date = time(); + + $path = sql_escape($path); + $name = sql_escape($name); + + if($id3cmd && $ren && $sort) { + $sql = "INSERT INTO catalog (path,name,last_update,id3_set_command,rename_pattern,sort_pattern,catalog_type) " . + " VALUES ('$path','$name','$date', '$id3cmd', '$ren', '$sort','$type')"; + } + else { + $sql = "INSERT INTO catalog (path,name,last_update) VALUES ('$path','$name','$date')"; + } + + $db_results = mysql_query($sql, dbh()); + $catalog_id = mysql_insert_id(dbh()); + + return $catalog_id; + + } //create_catalog_entry + + + /*! + @function check_catalog + @discussion Checks for the $path already in the catalog table + @param $path The root path for the catalog we are checking + */ + function check_catalog($path) { + + $path = sql_escape($path); + + $sql = "SELECT id FROM catalog WHERE path='$path'"; + $db_results = mysql_query($sql, dbh()); + + $results = mysql_fetch_object($db_results); + + return $results->id; + + } //check_catalog + + + /*! + @function check_artist + @discussion Takes $artist checks if there then return id else insert and return id + @param $artist The name of the artist + */ + function check_artist($artist) { + + // Only get the var ones.. less func calls + $cache_limit = conf('artist_cache_limit'); + + /* Clean up the artist */ + $artist = trim($artist); + $artist = sql_escape($artist); + + + /* Ohh no the artist has lost it's mojo! */ + if (!$artist) { + $artist = "Unknown (Orphaned)"; + } + + // Remove the prefix so we can sort it correctly + preg_match("/^(The\s|An\s|A\s)(.*)/i",$artist,$matches); + + if (count($matches)) { + $artist = $matches[2]; + $prefix = $matches[1]; + } + + // Check to see if we've seen this artist before + if (isset($this->artists[$artist])) { + return $this->artists[$artist]; + } // if we've seen this artist before + + /* Setup the checking sql statement */ + $sql = "SELECT id FROM artist WHERE name LIKE '$artist' "; + $db_results = mysql_query($sql, dbh()); + + /* If it's found */ + if ($r = mysql_fetch_object($db_results)) { + $artist_id = $r->id; + } //if found + + /* If not found create */ + else { + + $sql = "INSERT INTO artist (name, prefix) VALUES ('$artist', '$prefix')"; + $db_results = mysql_query($sql, dbh()); + $artist_id = mysql_insert_id(dbh()); + + + if (!$db_results) { + echo "Error Inserting Artist:$artist <br />"; + flush(); + } + + } //not found + + if ($cache_limit) { + + $artist_count = count($this->artists); + if ($artist_count == $cache_limit) { + $this->artists = array_slice($this->artists,1); + } + if (conf('debug')) { log_event($_SESSION['userdata']['username'],'cache',"Adding $artist with $artist_id to Cache",'ampache-catalog'); } + $array = array($artist => $artist_id); + $this->artists = array_merge($this->artists, $array); + unset($array); + + } // if cache limit is on.. + + return $artist_id; + + } //check_artist + + + /*! + @function check_album + @disucssion Takes $album and checks if there then return id else insert and return id + @param $album The name of the album + */ + function check_album($album,$album_year=0) { + + /* Clean up the album name */ + $album = trim($album); + $album = sql_escape($album); + $album_year = intval($album_year); + + // Set it once to reduce function calls + $cache_limit = conf('album_cache_limit'); + + /* Ohh no the album has lost it's mojo */ + if (!$album) { + $album = "Unknown (Orphaned)"; + } + + // Remove the prefix so we can sort it correctly + preg_match("/^(The\s|An\s|A\s)(.*)/i",$album,$matches); + + if (count($matches)) { + $album = $matches[2]; + $prefix = $matches[1]; + } + + // Check to see if we've seen this album before + if (isset($this->albums[$album])) { + return $this->albums[$album]; + } + + /* Setup the Query */ + $sql = "SELECT id FROM album WHERE name LIKE '$album'"; + if ($album_year) { $sql .= " AND year='$album_year'"; } + $db_results = mysql_query($sql, dbh()); + + /* If it's found */ + if ($r = mysql_fetch_object($db_results)) { + $album_id = $r->id; + + } //if found + + /* If not found create */ + else { + + $sql = "INSERT INTO album (name, prefix,year) VALUES ('$album', '$prefix','$album_year')"; + $db_results = mysql_query($sql, dbh()); + $album_id = mysql_insert_id(dbh()); + + if (!$db_results) { + echo "Error Inserting Album:$album <br />"; + flush(); + } + + } //not found + + if ($cache_limit > 0) { + + $albums_count = count($this->albums); + + if ($albums_count == $cache_limit) { + $this->albums = array_slice($this->albums,1); + } + $array = array($album => $album_id); + $this->albums = array_merge($this->albums,$array); + unset($array); + + } // if cache limit is on.. + + return $album_id; + + } //check_album + + + /*! + @function check_genre + @discussion Finds the Genre_id from the text name + @param $genre The name of the genre + */ + function check_genre($genre) { + + if (!$genre) { + return false; + } + + if ($this->genres[$genre]) { + return $this->genres[$genre]; + } + + /* Look in the genre table */ + $genre = sql_escape($genre); + $sql = "SELECT id FROM genre WHERE name LIKE '$genre'"; + $db_results = mysql_query($sql, dbh()); + + $results = mysql_fetch_object($db_results); + + if (!$results->id) { + $sql = "INSERT INTO genre (name) VALUES ('$genre')"; + $db_results = mysql_query($sql, dbh()); + $results->id = mysql_insert_id(dbh()); + } + + $this->genres[$genre] = $results->id; + + return $results->id; + + } //check_genre + + + /*! + @function check_title + @discussion this checks to make sure something is + set on the title, if it isn't it looks at the + filename and trys to set the title based on that + */ + function check_title($title,$file=0) { + + if (strlen(trim($title)) < 1) { + preg_match("/.+\/(.*)\.....?$/",$file,$matches); + $title = sql_escape($matches[1]); + } + + return $title; + + + } //check_title + + + /*! + @function insert_local_song + @discussion Insert a song that isn't already in the database this + function is in here so we don't have to create a song object + @param $file The file name we are adding (full path) + @param $file_info The information of the file, size etc taken from stat() + */ + function insert_local_song($file,$file_info) { + + /* Create the Audioinfo object and get info */ + $audio_info = new Audioinfo(); + $song_obj = new Song(); + $results = $audio_info->Info($file); + $results['file'] = $file; + + $key = get_tag_type($results); + + /* Fill Empty info from filename/path */ + $results = $song_obj->fill_info($results,$this->sort_pattern . "/" . $this->rename_pattern,$this->id,$key); + + /* Clean Up the tags */ + $results = clean_tag_info($results,$key,$file); + + /* Set the vars here... so we don't have to do the '" . $blah['asd'] . "' */ + $title = sql_escape($results['title']); + $artist = $results['artist']; + $album = $results['album']; + $genre = $results['genre']; + $bitrate = $results['bitrate']; + $rate = $results['rate']; + $mode = $results['mode']; + $size = $results['size']; + $song_time = $results['time']; + $track = $results['track']; + $year = $results['year']; + $comment = $results['comment']; + $current_time = time(); + + /* + * We have the artist/genre/album name need to check it in the tables + * If found then add & return id, else return id + */ + $artist_id = $this->check_artist($artist); + $genre_id = $this->check_genre($genre); + $album_id = $this->check_album($album,$year); + $title = $this->check_title($title,$file); + $add_file = sql_escape($results['file']); + + $sql = "INSERT INTO song (file,catalog,album,artist,title,bitrate,rate,mode,size,time,track,genre,addition_time,year,comment)" . + " VALUES ('$add_file','$this->id','$album_id','$artist_id','$title','$bitrate','$rate','$mode','$size','$song_time','$track','$genre_id','$current_time','$year','$comment')"; + + $db_results = mysql_query($sql, dbh()); + + if (!$db_results) { + if (conf('debug')) { log_event($_SESSION['userdata']['username'],'insert',"Unable to insert $file -- $sql",'ampache-catalog'); } + echo "<span style=\"color: #F00;\">Error Adding $file </span><br />$sql<br />"; + flush(); + } + + /* Clear Variables */ + unset($results,$audio_info,$song_obj); + + } // insert_local_song + + /*! + @function insert_remote_song + @discussion takes the information gotten from XML-RPC and + inserts it into the local database. The filename + ends up being the url. + */ + function insert_remote_song($song) { + + $url = sql_escape($song->file); + $title = $this->check_title($song->title); + $title = sql_escape($title); + $comment = sql_escape($song->comment); + $current_time = time(); + + $sql = "INSERT INTO song (file,catalog,album,artist,title,bitrate,rate,mode,size,time,track,genre,addition_time,year,comment)" . + " VALUES ('$url','$song->catalog','$song->album','$song->artist','$title','$song->bitrate','$song->rate','$song->mode','$song->size','$song->time','$song->track','$song->genre','$current_time','$song->year','$comment')"; + $db_results = mysql_query($sql, dbh()); + + if (!$db_results) { + if (conf('debug')) { log_event($_SESSION['userdata']['username'],'insert',"Unable to Add Remote $url -- $sql",'ampache-catalog'); } + echo "<span style=\"color: #FOO;\">Error Adding Remote $url </span><br />$sql<br />\n"; + flush(); + } + + } // insert_remote_song + + + /*! + @function check_remote_song + @discussion checks to see if a remote song exists in the database or not + if it find a song it returns the UID + */ + function check_remote_song($url) { + + $url = sql_escape($url); + + $sql = "SELECT id FROM song WHERE file='$url'"; + $db_results = mysql_query($sql, dbh()); + + if ($r = mysql_fetch_object($db_results)) { + return $r->id; + } + + return false; + + } // check_remote_song + + + /*! + @function check_local_mp3 + @discussion Checks the song to see if it's there already returns true if found, false if not + @param $full_file The full file name that we are checking + @param $gather_type=0 If we need to check id3 tags or not + */ + function check_local_mp3($full_file, $gather_type=0) { + + if ($gather_type == 'fast_add') { + $file_date = filemtime($full_file); + if ($file_date < $this->last_add) { + return true; + } + } + + $full_file = sql_escape($full_file); + + $sql = "SELECT id FROM song WHERE file = '$full_file'"; + $db_results = mysql_query($sql, dbh()); + + //If it's found then return true + if (@mysql_fetch_row($db_results)) { + return true; + } + + return false; + + } //check_local_mp3 + + /*! + @function import_m3u + @discussion this takes m3u filename and then attempts + to create a Public Playlist based on the filenames + listed in the m3u + */ + function import_m3u($filename) { + + $m3u_handle = @fopen($filename,'r'); + + $data = @fread($m3u_handle,filesize($filename)); + + $results = explode("\n",$data); + + foreach ($results as $value) { + // Remove extra whitespace + $value = trim($value); + if (preg_match("/\.[A-Za-z0-9]{3}$/",$value)) { + $file[0] = str_replace("/","\\",$value); + $file[1] = str_replace("\\","/",$value); + /* Search for this filename, cause it's a audio file */ + $sql = "SELECT id FROM song WHERE file LIKE '%" . sql_escape($file[0]) . "' OR file LIKE '%" . sql_escape($file[1]) . "'"; + $db_results = mysql_query($sql, dbh()); + $song_id = mysql_result($db_results,'id'); + if ($song_id) { $songs[] = $song_id; } + } // if it's a file + + } // end foreach line + + if (conf('debug')) { log_event($GLOBALS['user']->username,' m3u_parse ',"Parsing $filename - Found: " . count($songs) . " Songs"); } + + if (count($songs)) { + $playlist = new Playlist(); + $playlist_name = "M3U - " . basename($filename); + $playlist->create_playlist($playlist_name,$GLOBALS['user']->id,'public'); + $playlist->add_songs($songs); + return true; + } + + return false; + + } // import_m3u + + /*! + @function delete_catalog + @discussion Deletes the catalog and everything assoicated with it + assumes $this + */ + function delete_catalog() { + + // Do some crazyness to delete all the songs in this catalog + // from playlists... + $sql = "SELECT playlist_data.song FROM song,playlist_data,catalog WHERE catalog.id=song.catalog AND playlist_data.song=song.id AND catalog.id='$this->id'"; + $db_results = mysql_query($sql, dbh()); + + $results = array(); + + while ($r = mysql_fetch_object($db_results)) { + $results[] = $r; + } + + foreach ($results as $r) { + // Clear Playlist Data + $sql = "DELETE FROM playlist_data WHERE song='$r->song'"; + $db_results = mysql_query($sql, dbh()); + + } // End Foreach + + // First remove the songs in this catalog + $sql = "DELETE FROM song WHERE catalog = '$this->id'"; + $db_results = mysql_query($sql, dbh()); + + // Next Remove the Catalog Entry it's self + $sql = "DELETE FROM catalog WHERE id = '$this->id'"; + $db_results = mysql_query($sql, dbh()); + + // Run the Aritst/Album Cleaners... + $this->clean_albums(); + $this->clean_artists(); + $this->clean_stats(); + $this->clean_playlists(); + $this->clean_flagged(); + + } // delete_catalog + + + /*! + @function remove_songs + @discussion removes all songs sent in $songs array from the + database, it doesn't actually delete them... + */ + function remove_songs($songs) { + + foreach($songs as $song) { + $sql = "DELETE FROM song WHERE id = '$song'"; + $db_results = mysql_query($sql, dbh()); + } + + } // remove_songs + +} //end of catalog class + +?> |