Madonna") Apple insist on using two key-value pairs // together. (eg: "artistMadonna"). if ($tag == 'KEY') { $key = $contents; if ( in_array($contents, array('Tracks','Playlists')) ) $current_section = $contents; } else { if ( $current_section == 'Tracks' && $level == 5 ) $dict_info[$key] = $contents; elseif ( $current_section == 'Playlists' && $level == 7 ) $dict_info[] = $contents; else $key_info[$key] = $contents; } // If we are exiting level 4 then we have a complete track/playlist object. if ($level-- == 4 && ! empty($dict_info) ) { if ($current_section == 'Tracks') process_itunes_track( $dict_info ); elseif ($current_section == 'Playlists') process_itunes_playlist( $key_info, $dict_info); else send_to_log(6,'Unknown iTunes section encountered',$current_section); } } function tag_contents_itunes($parser, $data) { global $contents; $contents .= $data; } /** * Converts a full URI specification for a local file into an actual PHP file specification (with * forward slashes, regardless of operating system). * * @param string $url * @return string */ function path_from_file_url( $url ) { // Only converts URI's using the "file://" system if ( strpos($url,'file://') !== false) { $url = str_replace('\\','/',rawurldecode($url)); $url = substr($url, strpos($url,'://')+3); $url = substr($url, strpos($url,'/')+1); // If not a local Windows path then make UNC if ( strpos($url,':/') === false ) $url = '/'.$url; } return $url; } /** * Creates an "m3u" playlist identical to the iTunes playlist, and with the same name which * contains all of the songs in the iTunes playlist that are available on the showcenter (ie: are * within a defined media location). * * @param array $attribs * @param array $values */ function process_itunes_playlist( $attribs, $values ) { $file = get_sys_pref("PLAYLISTS", SC_LOCATION.'playlists').'/'.$attribs["Name"].'.m3u'; $sql = 'select m.* from mp3s m, itunes_map i where i.swisscenter_id = m.file_id and i.itunes_id = '; $items = 0; $playlist = array('#EXTM3U'); foreach ($values as $itunes_id) { $mp3 = array_pop(db_toarray($sql.$itunes_id)); if (!empty($mp3)) { $items++; $playlist[] = '#EXTINF:'.$mp3["LENGTH"].','.$mp3["TITLE"]; $playlist[] = os_path($mp3["DIRNAME"].$mp3["FILENAME"]); } } if ($items>0) { array2file($playlist, $file); send_to_log(4,"Writing playlist: ".$file); } } /** * Uses the track details found in the iTunes file and adds/updates the database * * @param array $values */ function process_itunes_track( $values) { $fsp = utf8_decode(path_from_file_url($values["Location"])); $location_id = db_value("select location_id from media_locations where instr('".db_escape_str($fsp)."',name)>0 and media_type=".MEDIA_TYPE_MUSIC); $swiss_id = db_value("select file_id from mp3s where dirname='".db_escape_str(dirname($fsp))."/' and filename='".db_escape_str(basename($fsp))."'"); // Perform some sanity checking on the file if (!is_file($fsp) ) send_to_log(5,'File found in iTunes library cannot be located on disk',$fsp); elseif ( !is_readable($fsp) ) send_to_log(5,'SwissCenter does not have permissions to read the file found in the iTunes library',$fsp); elseif ( !in_array(file_ext($fsp), media_exts_music()) ) send_to_log(5,'SwissCenter does not support files of type "'.$values["Kind"].'"',$fsp); elseif ( empty($location_id) ) send_to_log(5,'File found in iTunes library is not within a SwissCenter media location',$fsp); else { if ( empty($swiss_id) ) { process_mp3( dirname($fsp).'/' , $location_id, basename($fsp)); $swiss_id = db_value("select file_id from mp3s where dirname='".db_escape_str(dirname($fsp))."/' and filename='".db_escape_str(basename($fsp))."'"); } // Record the mapping between the iTunes ID and the swisscenter ID db_insert_row('itunes_map', array( "ITUNES_ID"=>$values["Track ID"], "SWISSCENTER_ID"=>$swiss_id) ); } } /** * Takes an iTunes XML file (either the entire library file, or an exported playlist) and parses * the track and playlist information contained within. Track details are added/updated within the * SwissCenter database and playlists are crreated in the user's specified playlist directory for * each iTunes playlist. * * NOTE: Tracks are only processed if they are located within a defined media location. If they * are stored elsewhere on the filesystem then they will be ignored. * * @param string $filename */ function parse_itunes_file( $filename ) { // Initialize global variables $current_section = ''; $key_info = array(); $dict_info = array(); $level = 0; $tag = ''; $key = ''; send_to_log(4,'Parsing the iTunes Music Library for Playlists'); // Clear the iTunes mapping table before generating any playlists db_sqlcommand("delete from itunes_map"); // Create XML parser $xmlparser = xml_parser_create("UTF-8"); if ($xmlparser !== false) { xml_set_element_handler($xmlparser, "start_tag_itunes", "end_tag_itunes"); xml_set_character_data_handler($xmlparser, "tag_contents_itunes"); // Read and process XML file $fp = fopen($filename, "r"); if ($fp !== false) { while ($data = fread($fp, 8192)) { $data = preg_replace("/>\s+/u", ">", $data); $data = preg_replace("/\s+