diff options
38 files changed, 3157 insertions, 63 deletions
diff --git a/config/ampache.cfg.php.dist b/config/ampache.cfg.php.dist index 75ecc3bb..36368213 100644 --- a/config/ampache.cfg.php.dist +++ b/config/ampache.cfg.php.dist @@ -275,9 +275,9 @@ ratings = "true" ; Album Art Gather Order ; Simply arrange the following in the order you would like -; ampache to search if you want to disable one of the search -; method simply comment it out valid values are -; POSSIBLE VALUES: db id3 folder amazon lastfm +; ampache to search. If you want to disable one of the search +; methods simply leave it out. +; POSSIBLE VALUES: db id3 folder amazon lastfm musicbrainz ; DEFAULT: db,id3,folder,lastfm album_art_order = "db,id3,folder,lastfm" diff --git a/docs/CHANGELOG b/docs/CHANGELOG index 643f0213..783b5675 100755 --- a/docs/CHANGELOG +++ b/docs/CHANGELOG @@ -4,6 +4,8 @@ -------------------------------------------------------------------------- v.3.6-Alpha1 + - Add MusicBrainz MBID support to uniqly identify albums and + also get more album art (Thx flowerysong) - Fix the url to song function - Add full path to the files needed by the installation just to make it a little clearer diff --git a/lib/class/album.class.php b/lib/class/album.class.php index 533a4bfa..5c32ef41 100644 --- a/lib/class/album.class.php +++ b/lib/class/album.class.php @@ -577,6 +577,151 @@ class Album extends database_object { } // get_db_art /** + * get_musicbrainz_art + * This retrieves art based on MusicBrainz' Advanced Relationships + */ + public function get_musicbrainz_art($limit='') { + $images = array(); + $num_found = 0; + $mbquery = new MusicBrainzQuery(); + + if ($this->mbid) { + debug_event('mbz-gatherart', "Album MBID: " . $this->mbid, '5'); + } + else { + return $images; + } + + $includes = new mbReleaseIncludes(); + try { + $release = $mbquery->getReleaseByID($this->mbid, $includes->urlRelations()); + } catch (Exception $e) { + return $images; + } + + $asin = $release->getAsin(); + + if ($asin) { + debug_event('mbz-gatherart', "Found ASIN: " . $asin, '5'); + $base_urls = array( + "01" => "ec1.images-amazon.com", + "02" => "ec1.images-amazon.com", + "03" => "ec2.images-amazon.com", + "08" => "ec1.images-amazon.com", + "09" => "ec1.images-amazon.com", + ); + foreach ($base_urls as $server_num => $base_url) { + // to avoid complicating things even further, we only look for large cover art + $url = 'http://' . $base_url . '/images/P/' . $asin . '.' . $server_num . '.LZZZZZZZ.jpg'; + debug_event('mbz-gatherart', "Evaluating Amazon URL: " . $url, '5'); + $snoopy = new Snoopy(); + if(Config::get('proxy_host') AND Config::get('proxy_port')) { + $snoopy->proxy_user = Config::get('proxy_host'); + $snoopy->proxy_port = Config::get('proxy_port'); + $snoopy->proxy_user = Config::get('proxy_user'); + $snoopy->proxy_pass = Config::get('proxy_pass'); + } + if ($snoopy->fetch($url)) { + $num_found++; + debug_event('mbz-gatherart', "Amazon URL added: " . $url, '5'); + $images[] = array( + 'url' => $url, + 'mime' => 'image/jpeg', + ); + if ($num_found >= $limit) { + return $images; + } + } + } + } + + // The next bit is based directly on the MusicBrainz server code that displays cover art. + // I'm leaving in the releaseuri info for the moment, though it's not going to be used. + $coverartsites[] = array( + name => "CD Baby", + domain => "cdbaby.com", + regexp => '@http://cdbaby\.com/cd/(\w)(\w)(\w*)@', + imguri => 'http://cdbaby.name/$matches[1]/$matches[2]/$matches[1]$matches[2]$matches[3].jpg', + releaseuri => 'http://cdbaby.com/cd/$matches[1]$matches[2]$matches[3]/from/musicbrainz', + ); + $coverartsites[] = array( + name => "CD Baby", + domain => "cdbaby.name", + regexp => "@http://cdbaby\.name/([a-z0-9])/([a-z0-9])/([A-Za-z0-9]*).jpg@", + imguri => 'http://cdbaby.name/$matches[1]/$matches[2]/$matches[3].jpg', + releaseuri => 'http://cdbaby.com/cd/$matches[3]/from/musicbrainz', + ); + $coverartsites[] = array( + name => 'archive.org', + domain => 'archive.org', + regexp => '/^(.*\.(jpg|jpeg|png|gif))$/', + imguri => '$matches[1]', + releaseuri => '', + ); + $coverartsites[] = array( + name => "Jamendo", + domain => "www.jamendo.com", + regexp => '/http://www\.jamendo\.com/(\w\w/)?album/(\d+)/', + imguri => 'http://img.jamendo.com/albums/$matches[2]/covers/1.200.jpg', + releaseuri => 'http://www.jamendo.com/album/$matches[2]', + ); + $coverartsites[] = array( + name => '8bitpeoples.com', + domain => '8bitpeoples.com', + regexp => '/^(.*)$/', + imguri => '$matches[1]', + releaseuri => '', + ); + $coverartsites[] = array( + name => 'Encyclopédisque', + domain => 'encyclopedisque.fr', + regexp => '/http://www.encyclopedisque.fr/images/imgdb/(thumb250|main)/(\d+).jpg/', + imguri => 'http://www.encyclopedisque.fr/images/imgdb/thumb250/$matches[2].jpg', + releaseuri => 'http://www.encyclopedisque.fr/', + ); + $coverartsites[] = array( + name => 'Thastrom', + domain => 'www.thastrom.se', + regexp => '/^(.*)$/', + imguri => '$matches[1]', + releaseuri => '', + ); + $coverartsites[] = array( + name => 'Universal Poplab', + domain => 'www.universalpoplab.com', + regexp => '/^(.*)$/', + imguri => '$matches[1]', + releaseuri => '', + ); + + foreach ($release->getRelations($mbRelation->TO_URL) as $ar) { + $arurl = $ar->getTargetId(); + debug_event('mbz-gatherart', "Found URL AR: " . $arurl , '5'); + foreach ($coverartsites as $casite) { + if (strstr($arurl, $casite['domain'])) { + debug_event('mbz-gatherart', "Matched coverart site: " . $casite['name'], '5'); + if (preg_match($casite['regexp'], $arurl, $matches) == 1) { + $num_found++; + eval("\$url = \"$casite[imguri]\";"); + debug_event('mbz-gatherart', "Generated URL added: " . $url, '5'); + $images[] = array( + 'url' => $url, + 'mime' => 'image/jpeg', + ); + if ($num_found >= $limit) { + return $images; + } + } + } + } + } + + + + return $images; + } // get_musicbrainz_art + + /** * get_amazon_art * This takes keywords and performs a search of the Amazon website * for album art. It returns an array of found objects with mime/url keys diff --git a/lib/class/artist.class.php b/lib/class/artist.class.php index 0db622b3..c2c80a61 100644 --- a/lib/class/artist.class.php +++ b/lib/class/artist.class.php @@ -258,7 +258,7 @@ class Artist extends database_object { // Save our current ID $current_id = $this->id; - $artist_id = Catalog::check_artist($data['name']); + $artist_id = Catalog::check_artist($data['name'], $this->mbid); // If it's changed we need to update if ($artist_id != $this->id) { diff --git a/lib/class/catalog.class.php b/lib/class/catalog.class.php index 57400a58..0a145b01 100644 --- a/lib/class/catalog.class.php +++ b/lib/class/catalog.class.php @@ -2004,29 +2004,63 @@ class Catalog extends database_object { } // Check to see if we've seen this artist before - if (isset(self::$artists[$artist])) { - return self::$artists[$artist]; + if (isset(self::$artists[$artist][$mbid])) { + return self::$artists[$artist][$mbid]; } // if we've seen this artist before - /* Setup the checking sql statement */ - $sql = "SELECT `id` FROM `artist` WHERE `name` LIKE '$artist' "; + $exists = false; + + $sql = "SELECT `id` FROM `artist` WHERE `mbid` LIKE '$mbid'"; $db_results = Dba::query($sql); - /* If it's found */ + // Check for results if ($r = Dba::fetch_assoc($db_results)) { $artist_id = $r['id']; - } //if found + $exists = true; + } - /* If not found create */ - elseif (!$readonly) { + else { // No exact match based on MBID + $sql = "SELECT `id`, `mbid` FROM `artist` WHERE `name` LIKE '$artist'"; + $db_results = Dba::query($sql); - $prefix_txt = 'NULL'; - if ($prefix) { - $prefix_txt = "'$prefix'"; + /* If we have results */ + while ($r = Dba::fetch_assoc($db_results)) { + $key = is_null($r['mbid']) ? 'null' : $r['mbid']; + $id_array[$key] = $r['id']; + } // while + + /* Choose one */ + if (isset($id_array)) { + if ($mbid == '') { // Prefer null entry, otherwise pick the first + $key = isset($id_array['null']) ? 'null' : array_shift(array_keys($id_array)); + $artist_id = $id_array[$key]; + $exists = true; + } + elseif (isset($id_array['null'])) { + $artist_id = $id_array['null']; + $exists = true; + if (!$readonly) { + $sql = "UPDATE `artist` SET `mbid`='$mbid' WHERE `id`='$artist_id'"; + $db_results = Dba::query($sql); + if (!$db_results) { + Error::add('general',"Updating Artist: $artist"); + } + } + } + unset($id_array); } + } // fuzzy matching + + /* If not found create */ + if (!$readonly && !$exists) { - $sql = "INSERT INTO `artist` (`name`, `prefix`) VALUES ('$artist',$prefix_txt)"; + $prefix_txt = $prefix ? "'$prefix'" : 'NULL'; + + $mbid = $mbid == '' ? 'NULL' : "'$mbid'"; + + $sql = "INSERT INTO `artist` (`name`, `prefix`, `mbid`) " . + "VALUES ('$artist',$prefix_txt,$mbid)"; $db_results = Dba::query($sql); $artist_id = Dba::insert_id(); @@ -2036,13 +2070,11 @@ class Catalog extends database_object { } // not found // If readonly, and not found return false - else { + elseif (!$exists) { return false; } - $array = array($artist => $artist_id); - self::$artists = array_merge(self::$artists, $array); - unset($array); + self::$artists[$artist][$mbid] = $artist_id; return $artist_id; @@ -2076,14 +2108,15 @@ class Catalog extends database_object { } // Check to see if we've seen this album before - if (isset(self::$albums[$album][$album_year][$disk])) { - return self::$albums[$album][$album_year][$disk]; + if (isset(self::$albums[$album][$album_year][$disk][$mbid])) { + return self::$albums[$album][$album_year][$disk][$mbid]; } /* Setup the Query */ $sql = "SELECT `id` FROM `album` WHERE trim(`name`) = '$album'"; if ($album_year) { $sql .= " AND `year`='$album_year'"; } if ($album_disk) { $sql .= " AND `disk`='$album_disk'"; } + if ($mbid) { $sql .= " AND `mbid`='$mbid'"; } if ($prefix) { $sql .= " AND `prefix`='" . Dba::escape($prefix) . "'"; } $db_results = Dba::query($sql); @@ -2104,7 +2137,10 @@ class Catalog extends database_object { $prefix_txt = $prefix ? "'$prefix'" : 'NULL'; - $sql = "INSERT INTO `album` (`name`, `prefix`,`year`,`disk`) VALUES ('$album',$prefix_txt,'$album_year','$album_disk')"; + $mbid = $mbid ? "'$mbid'" : 'NULL'; + + $sql = "INSERT INTO `album` (`name`, `prefix`,`year`,`disk`,`mbid`) " . + "VALUES ('$album',$prefix_txt,'$album_year','$album_disk',$mbid)"; $db_results = Dba::query($sql); $album_id = Dba::insert_id(); @@ -2122,7 +2158,7 @@ class Catalog extends database_object { } // Save the cache - self::$albums[$album][$album_year][$disk] = $album_id; + self::$albums[$album][$album_year][$disk][$mbid] = $album_id; return $album_id; @@ -2184,6 +2220,9 @@ class Catalog extends database_object { $size = $results['size']; $song_time = $results['time']; $track = $results['track']; + $track_mbid = $results['mb_trackid']; + $album_mbid = $results['mb_albumid']; + $artist_mbid= $results['mb_artistid']; $disk = $results['disk']; $year = $results['year']; $comment = $results['comment']; @@ -2200,8 +2239,8 @@ class Catalog extends database_object { $title = self::check_title($title,$file); $add_file = Dba::escape($file); - $sql = "INSERT INTO `song` (file,catalog,album,artist,title,bitrate,rate,mode,size,time,track,addition_time,year)" . - " VALUES ('$add_file','$this->id','$album_id','$artist_id','$title','$bitrate','$rate','$mode','$size','$song_time','$track','$current_time','$year')"; + $sql = "INSERT INTO `song` (file,catalog,album,artist,title,bitrate,rate,mode,size,time,track,addition_time,year,mbid)" . + " VALUES ('$add_file','$this->id','$album_id','$artist_id','$title','$bitrate','$rate','$mode','$size','$song_time','$track','$current_time','$year','$track_mbid')"; $db_results = Dba::query($sql); if (!$db_results) { diff --git a/lib/class/song.class.php b/lib/class/song.class.php index 9f5259ef..9a1b1bdd 100644 --- a/lib/class/song.class.php +++ b/lib/class/song.class.php @@ -34,6 +34,8 @@ class Song extends database_object implements media { public $size; public $time; public $track; + public $album_mbid; + public $artist_mbid; public $type; public $mime; public $played; @@ -86,6 +88,7 @@ class Song extends database_object implements media { // Song data cache $sql = "SELECT song.id,file,catalog,album,year,artist,". "title,bitrate,rate,mode,size,time,track,played,song.enabled,update_time,tag_map.tag_id,". + "mbid,". "addition_time FROM `song` " . "LEFT JOIN `tag_map` ON `tag_map`.`object_id`=`song`.`id` AND `tag_map`.`object_type`='song' " . "WHERE `song`.`id` IN $idlist"; @@ -138,6 +141,7 @@ class Song extends database_object implements media { /* Grab the basic information from the catalog and return it */ $sql = "SELECT song.id,file,catalog,album,year,artist,". "title,bitrate,rate,mode,size,time,track,played,song.enabled,update_time,". + "mbid,". "addition_time FROM `song` WHERE `song`.`id` = '$id'"; $db_results = Dba::query($sql); @@ -323,7 +327,7 @@ class Song extends database_object implements media { unset($song->catalog,$song->played,$song->enabled,$song->addition_time,$song->update_time,$song->type); $string_array = array('title','comment','lyrics'); - $skip_array = array('id','tag_id','mime'); + $skip_array = array('id','tag_id','mime','mb_artistid','mbid'); // Pull out all the currently set vars $fields = get_object_vars($song); @@ -369,11 +373,11 @@ class Song extends database_object implements media { case 'artist': // Don't do anything if we've negative one'd this baby if ($value == '-1') { - $value = Catalog::check_artist($data['artist_name']); + $value = Catalog::check_artist($data['artist_name'], $data['mb_artistid']); } case 'album': if ($value == '-1') { - $value = Catalog::check_album($data['album_name']); + $value = Catalog::check_album($data['album_name'], $data['year'], $data['disk'], $data['mb_albumid']); } case 'title': case 'track': @@ -416,6 +420,7 @@ class Song extends database_object implements media { $size = Dba::escape($new_song->size); $time = Dba::escape($new_song->time); $track = Dba::escape($new_song->track); + $mbid = Dba::escape($new_song->mbid); $artist = Dba::escape($new_song->artist); $album = Dba::escape($new_song->album); $year = Dba::escape($new_song->year); @@ -426,6 +431,7 @@ class Song extends database_object implements media { $sql = "UPDATE `song` SET `album`='$album', `year`='$year', `artist`='$artist', " . "`title`='$title', `bitrate`='$bitrate', `rate`='$rate', `mode`='$mode', " . "`size`='$size', `time`='$time', `track`='$track', " . + "`mbid`='$mbid', " . "`update_time`='$update_time' WHERE `id`='$song_id'"; $db_results = Dba::query($sql); @@ -550,6 +556,12 @@ class Song extends database_object implements media { } // update_track + public static function update_mbid($new_mbid,$song_id) { + + self::_update_item('mbid',$new_mbid,$song_id,'50'); + + } // update_mbid + /** * update_artist * updates the artist field diff --git a/lib/class/update.class.php b/lib/class/update.class.php index 5a36b253..0b63e354 100644 --- a/lib/class/update.class.php +++ b/lib/class/update.class.php @@ -323,6 +323,11 @@ class Update { $version[] = array('version'=>'350008','description'=>$update_string); + $update_string = '- Add MBID (MusicBrainz ID) fields<br />' . + '- Remove useless preferences<br />'; + + $version[] = array('version'=>'360001','description'=>$update_string); + return $version; @@ -1758,10 +1763,20 @@ class Update { /** * update_360001 - * This adds the mbid id's to the different tables as well as some additional cleanup + * This adds the MB UUIDs to the different tables as well as some additional cleanup */ public static function update_360001() { + + $sql = "ALTER TABLE `album` ADD `mbid` CHAR ( 36 ) AFTER `prefix`"; + $db_results = Dba::write($sql); + + $sql = "ALTER TABLE `artist` ADD `mbid` CHAR ( 36 ) AFTER `prefix`"; + $db_results = Dba::write($sql); + + $sql = "ALTER TABLE `song` ADD `mbid` CHAR ( 36 ) AFTER `track`"; + $db_results = Dba::write($sql); + // Remove any RIO related information from the database as the plugin has been removed $sql = "DELETE FROM `update_info` WHERE `key` LIKE 'Plugin_Ri%'"; $db_results = Dba::write($sql); @@ -1778,7 +1793,7 @@ class Update { User::fix_preferences($r['id']); } // while we're fixing the useres stuff - // self::set_version('db_version','360001'); + self::set_version('db_version','360001'); } // update_360001 diff --git a/lib/class/vainfo.class.php b/lib/class/vainfo.class.php index 97888430..8bf5862f 100644 --- a/lib/class/vainfo.class.php +++ b/lib/class/vainfo.class.php @@ -192,9 +192,9 @@ class vainfo { /** * get_tag_type - * This takes the result set, and the the tag_order + * This takes the result set, and the tag_order * As defined by your config file and trys to figure out - * which tag type it should use, if your tag_order + * which tag type(s) it should use, if your tag_order * doesn't match anything then it just takes the first one * it finds in the results. */ @@ -208,24 +208,26 @@ class vainfo { } /* Foreach through the defined key order - * the first one we find is the first one we use + * adding them to an ordered array as we go */ + + $i = 0; foreach($order as $key) { if ($results[$key]) { - $returned_key = $key; - break; + $returned_keys[$i++] = $key; } } /* If we didn't find anything then default it to the * first in the results set + * We could also just use the whole array. */ - if (!isset($returned_key)) { + if (!isset($returned_keys)) { $keys = array_keys($results); - $returned_key = $keys['0']; + $returned_keys[0] = $keys['0']; } - return $returned_key; + return $returned_keys; } // get_tag_type @@ -235,7 +237,7 @@ class vainfo { * key we've decided on and the filename and returns it in a * sanatized format that ampache can actually use */ - public static function clean_tag_info($results,$key,$filename) { + public static function clean_tag_info($results,$keys,$filename) { $info = array(); @@ -243,8 +245,6 @@ class vainfo { $wipe_array = array("","","",""); $info['file'] = $filename; - $info['title'] = stripslashes(trim($results[$key]['title'])); - $info['comment'] = Dba::escape(str_replace($clean_array,$wipe_array,$results[$key]['comment'])); /* This are pulled from the info array */ $info['bitrate'] = intval($results['info']['bitrate']); @@ -263,33 +263,80 @@ class vainfo { $info['channels'] = intval($results['info']['channels']); // Specific Audio Flags + foreach ($keys as $key) { if (!$results[$key]['video_codec']) { $slash_point = strpos($results[$key]['disk'],'/'); if ($slash_point !== FALSE) { $results[$key]['disk'] = substr($results[$key]['disk'],0,$slash_point); } /* These are used to generate the correct ID's later */ - $info['year'] = intval($results[$key]['year']); - $info['disk'] = intval($results[$key]['disk']); - $info['artist'] = trim($results[$key]['artist']); - $info['album'] = trim($results[$key]['album']); - $info['genre'] = trim($results[$key]['genre']); + $info['year'] = $info['year'] + ? $info['year'] + : intval($results[$key]['year']); + + $info['disk'] = $info['disk'] + ? $info['disk'] + : intval($results[$key]['disk']); + + $info['artist'] = $info['artist'] + ? $info['artist'] + : trim($results[$key]['artist']); + + $info['album'] = $info['album'] + ? $info['album'] + : trim($results[$key]['album']); + + $info['genre'] = $info['genre'] + ? $info['genre'] + : trim($results[$key] ['genre']); + + $info['mb_trackid'] = $info['mb_trackid'] + ? $info['mb_trackid'] + : trim($results[$key]['mb_trackid']); + + $info['mb_albumid'] = $info['mb_albumid'] + ? $info['mb_albumid'] + : trim($results[$key]['mb_albumid']); + + $info['mb_artistid'] = $info['mb_artistid'] + ? $info['mb_artistid'] + : trim($results[$key]['mb_artistid']); + /* @TODO language doesn't import from id3tag. @momo-i */ - $info['language'] = Dba::escape($results[$key]['language']); - if (!empty($results[$key]['unsynchronised lyric'])) { // ID3v2 USLT - $info['lyrics'] = str_replace(array("\r\n","\r","\n"), '<br />',strip_tags($results[$key]['unsynchronised lyric'])); - } - else { // Lyrics3 v2.0 - $info['lyrics'] = str_replace(array("\r\n","\r","\n"), '<br />',strip_tags($results['info']['lyrics']['unsynchedlyrics'])); - } - $info['track'] = intval($results[$key]['track']); + $info['language'] = $info['language'] + ? $info['language'] + : Dba::escape($results[$key]['language']); + + $info['lyrics'] = $info['lyrics'] + ? $info['lyrics'] + : str_replace(array("\r\n","\r","\n"), '<br />',strip_tags($results[$key]['unsynchronised lyric'])); + + $info['track'] = $info['track'] + ? $info['track'] + : intval($results[$key]['track']); } else { - $info['resolution_x'] = intval($results[$key]['resolution_x']); - $info['resolution_y'] = intval($results[$key]['resolution_y']); - $info['audio_codec'] = Dba::escape($results[$key]['audio_codec']); - $info['video_codec'] = Dba::escape($results[$key]['video_codec']); + $info['resolution_x'] = $info['resolution_x'] + ? $info['resolution_x'] + : intval($results[$key]['resolution_x']); + + $info['resolution_y'] = $info['resolution_y'] + ? $info['resolution_y'] + : intval($results[$key]['resolution_y']); + + $info['audio_codec'] = $info['audio_codec'] + ? $info['audio_codec'] + : Dba::escape($results[$key]['audio_codec']); + + $info['video_codec'] = $info['video_codec'] + ? $info['video_codec'] + : Dba::escape($results[$key]['video_codec']); + } } + // Lyrics3 v2.0 + $info['lyrics'] = $info['lyrics'] + ? $info['lyrics'] + : str_replace(array("\r\n","\r","\n"), '<br />',strip_tags($results['info']['lyrics']['unsynchedlyrics'])); return $info; @@ -631,6 +678,23 @@ class vainfo { } // end foreach + $id3v2 = $this->_raw['id3v2']; + + foreach ($id3v2['UFID'] as $ufid) { + if ($ufid['ownerid'] == 'http://musicbrainz.org') { + $array['mb_trackid'] = $this->_clean_tag($ufid['data'],''); + } + } + + for ($i = 0, $size = sizeof($id3v2['comments']['text']) ; $i < $size ; $i++) { + if ($id3v2['TXXX'][$i]['description'] == 'MusicBrainz Album Id') { + $array['mb_albumid'] = $this->_clean_tag($id3v2['comments']['text'][$i],''); + } + elseif ($id3v2['TXXX'][$i]['description'] == 'MusicBrainz Artist Id') { + $array['mb_artistid'] = $this->_clean_tag($id3v2['comments']['text'][$i],''); + } + } + return $array; } // _parse_id3v2 diff --git a/lib/init.php b/lib/init.php index 585d5ce5..1d319e3e 100644 --- a/lib/init.php +++ b/lib/init.php @@ -146,6 +146,7 @@ require_once $prefix . '/modules/infotools/Snoopy.class.php'; require_once $prefix . '/modules/infotools/AmazonSearchEngine.class.php'; require_once $prefix . '/modules/infotools/lastfm.class.php'; //require_once $prefix . '/modules/infotools/jamendoSearch.class.php'; +require_once $prefix . '/modules/php_musicbrainz/mbQuery.php'; /* Temp Fixes */ $results = Preference::fix_preferences($results); diff --git a/modules/getid3/module.tag.id3v2.php b/modules/getid3/module.tag.id3v2.php index 6777bf5c..76875071 100644 --- a/modules/getid3/module.tag.id3v2.php +++ b/modules/getid3/module.tag.id3v2.php @@ -11,8 +11,8 @@ // +----------------------------------------------------------------------+ // | getID3() - http://getid3.sourceforge.net or http://www.getid3.org | // +----------------------------------------------------------------------+ -// | Authors: James Heinrich <infoØgetid3*org> | -// | Allan Hansen <ahØartemis*dk> | +// | Authors: James Heinrich <info�getid3*org> | +// | Allan Hansen <ah�artemis*dk> | // +----------------------------------------------------------------------+ // | module.tag.id3v2.php | // | module for analyzing ID3v2 tags | @@ -562,7 +562,7 @@ class getid3_id3v2 extends getid3_handler $frame_id_string = substr($parsed_frame['data'], 0, $frame_terminator_pos); $parsed_frame['ownerid'] = $frame_id_string; $parsed_frame['data'] = substr($parsed_frame['data'], $frame_terminator_pos + strlen("\x00")); - unset($parsed_frame['data']); + // unset($parsed_frame['data']); return true; } diff --git a/modules/php_musicbrainz/mbArtist.php b/modules/php_musicbrainz/mbArtist.php new file mode 100644 index 00000000..377ebc3d --- /dev/null +++ b/modules/php_musicbrainz/mbArtist.php @@ -0,0 +1,121 @@ +<?php + class mbArtist extends MusicBrainzEntity { + const TYPE_GROUP = "http://musicbrainz.org/ns/mmd-1.0#Group"; + const TYPE_PERSON = "http://musicbrainz.org/ns/mmd-1.0#Person"; + + private $type; + private $name; + private $sortName; + private $disambiguation; + private $beginDate; + private $endDate; + private $releases; + private $releasesCount = 0; + private $releasesOffset = 0; + private $aliases = array(); + + function mbArtist( $id = '', $type = '', $name = '', $sortName = '' ) { + parent::MusicBrainzEntity($id); + $this->type = $type; + $this->name = $name; + $this->sortName = $sortName; + $this->releases = array(); + } + + function getType() { return $this->type; } + function setType( $type ) { $this->type = $type; } + function getName() { return $this->name; } + function setName( $name ) { $this->name = $name; } + function getSortName() { return $this->sortName; } + function setSortName( $sortName ) { $this->sortName = $sortName; } + function getDisambiguation() { return $this->disambiguation; } + function setDisambiguation( $disambiguation ) { $this->disambiguation = $disambiguation; } + function getBeginDate() { return $this->beginDate; } + function setBeginDate( $beginDate ) { $this->beginDate = $beginDate; } + function getEndDate() { return $this->endDate; } + function setEndDate( $endDate ) { $this->endDate = $endDate; } + + function getUniqueName() { + return empty($this->disambiguation) ? $this->name : + $this->name . ' (' . $this->disambiguation . ')'; + } + + function &getReleases() { + return $this->releases; + } + + function addRelease( Release $release ) { + $this->releases[] = $release; + } + + function &getAliases() { + return $this->aliases; + } + + function addAlias( AristAlias $alias ) { + $this->aliases[] = $alias; + } + + function getNumReleases() { + return count($this->releases); + } + + function getRelease( $i ) { + return $this->releases[$i]; + } + + function getReleasesOffset() { + return $this->releasesOffset; + } + + function setReleasesOffset( $relOffset ) { + $this->releasesOffset = $relOffset; + } + + function getReleasesCount() { + return $this->releasesCount; + } + + function setReleasesCount( $relCount ) { + $this->releasesCount = $relCount; + } + + function getNumAliases() { + return count($this->aliases); + } + + function getAlias( $i ) { + return $this->aliases[$i]; + } + + function imageURL( MusicBrainzQuery $q ) { + $rf = new ReleaseFilter(); + $rf->artistId( $this->getId() )->limit(5)->asin('')->releaseType(Release::TYPE_ALBUM); + + try { + $rresults = $q->getReleases( $rf ); + } catch ( ResponseError $e ) { + echo $e->getMessage() . " "; + return ""; + } + + if ( empty( $rresults ) ) + return ""; + + $keys = array(); + foreach ( $rresults as $key => $rr ) { + $rr = $rr->getRelease(); + if ( $rr->getAsin() && $rr->getAsin() != "" ) + $keys[] = $key; + } + + if ( sizeof($keys) > 0 ) { + $rand = rand(0,sizeof($keys)-1); + return "http://images.amazon.com/images/P/" . $rresults[$keys[$rand]]->getRelease()->getAsin() . + ".01._SCLZZZZZZZ_PU_PU-5_.jpg!,.-''-,.!" . $rresults[$keys[$rand]]->getRelease()->getTitle(); + } + + return ""; + } + } +?> diff --git a/modules/php_musicbrainz/mbArtistAlias.php b/modules/php_musicbrainz/mbArtistAlias.php new file mode 100644 index 00000000..7ada99a5 --- /dev/null +++ b/modules/php_musicbrainz/mbArtistAlias.php @@ -0,0 +1,20 @@ +<?php + class mbArtistAlias { + private $value; + private $type; + private $script; + + function mbAristAlias( $value='', $type='', $script='' ) { + $this->value = $value; + $this->type = $type; + $this->script = $script; + } + + function getType() { return $this->type; } + function setType( $type ) { $this->type = $type; } + function getValue() { return $this->value; } + function setValue( $value ) { $this->value = $value; } + function getScript() { return $this->script; } + function setScript( $script ) { $this->script = $script; } + } +?> diff --git a/modules/php_musicbrainz/mbDisc.php b/modules/php_musicbrainz/mbDisc.php new file mode 100644 index 00000000..4b423ccf --- /dev/null +++ b/modules/php_musicbrainz/mbDisc.php @@ -0,0 +1,52 @@ +<?php + class mbDiscError extends Exception { } + + class mbDisc { + private $id; + private $sectors = 0; + private $firstTrackNum = 0; + private $lastTrackNum = 0; + private $tracks; + + function mbDisc( $id = '' ) { + $this->id = $id; + $this->tracks = array(); + } + + function setId ( $id ) { $this->id = $id; } + function getId ( ) { return $this->id; } + function setSectors ( $sectr ) { $this->sectors = $sectr; } + function getSectors ( ) { return $this->sectors; } + function setLastTrackNum ( $track ) { $this->lastTrackNum = $track; } + function getLastTrackNum ( ) { return $this->lastTrackNum; } + function setFirstTrackNum( $track ) { $this->firstTrackNum = $track; } + function getFirstTrackNum( ) { return $this->firstTrackNum; } + + function &getTracks() { + return $this->tracks; + } + + function addTrack( array $track ) { + $this->tracks[] = $track; + } + + function readDisc( $deviceName = '' ) { + throw new mbDiscError( "Cannot readDisc()", 1 ); + } + + function getSubmissionUrl( Disc $disc, $host='mm.musicbrainz.org', $port=80 ) { + if ( $port == 80 ) + $netloc = $host; + else + $netloc = $host . ':' . $port; + + $toc = $disc->getFirstTrackNum() . '+' . $disc->getLastTrackNum() . '+' . $disc->getSectors(); + + foreach ( $disc->getTracks() as $track ) + $toc .= '+' . $track[0]; + + return "http://" . $netloc . "/bare/cdlookup.html?id=" . $disc->getId() . "&toc=" . $toc . + "&tracks=" . $disc->getLastTrackNum(); + } + } +?> diff --git a/modules/php_musicbrainz/mbEntity.php b/modules/php_musicbrainz/mbEntity.php new file mode 100644 index 00000000..cf749569 --- /dev/null +++ b/modules/php_musicbrainz/mbEntity.php @@ -0,0 +1,76 @@ +<?php + class MusicBrainzEntity { + private $id; + private $relations; + private $tags; + + protected function MusicBrainzEntity( $id ) { + $this->id = $id; + $this->relations = array(); + } + + function getId() { + return $this->id; + } + + function setId( $id ) { + $this->id = $id; + } + + function &getRelations( $target_type='', $relation_type='' ) { + if ( $target_type == '' && $relation_type == '' ) + return $this->relations; + + $result = array(); + + if ( empty($target_type) ) { + foreach ( $this->relations as $relation ) { + if ( $relation->getType() == $relation_type ) { + $result[] = $relation; + } + } + } + else if ( empty($relation_type) ) { + foreach ( $this->relation_tracks as $relation ) { + if ( $relation->getTargetType() == $target_type ) { + $result[] = $relation; + } + } + } + else { + foreach ( $this->relations as $relation ) { + if ( $relation->getTargetType() == $target_type + && $relation->getType() == $relation_type ) { + $result[] = $relation; + } + } + } + + return $result; + } + + function addRelation( mbRelation $relation ) { + $this->relations[] = $relation; + } + + function getNumRelations() { + return count($this->relations); + } + + function &getRelation( $i ) { + return $this->relations[$i]; + } + + function &getTags() { + return $this->tags; + } + + function getNumTags() { + return count($this->tags); + } + + function &getTag( $i ) { + return $this->tags[$i]; + } + } +?> diff --git a/modules/php_musicbrainz/mbFactory.php b/modules/php_musicbrainz/mbFactory.php new file mode 100644 index 00000000..2fac424e --- /dev/null +++ b/modules/php_musicbrainz/mbFactory.php @@ -0,0 +1,29 @@ +<?php + interface mbIFactory { + function newArtist(); + function newArtistAlias(); + function newDisc(); + function newTrack(); + function newRelation(); + function newRelease(); + function newReleaseEvent(); + function newTag(); + function newLabel(); + function newLabelAlias(); + function newUser(); + } + + class mbDefaultFactory implements mbIFactory { + function newArtist() { return new mbArtist(); } + function newArtistAlias() { return new mbArtistAlias(); } + function newDisc() { return new mbDisc(); } + function newTrack() { return new mbTrack(); } + function newRelation() { return new mbRelation(); } + function newRelease() { return new mbRelease(); } + function newReleaseEvent() { return new mbReleaseEvent(); } + function newTag() { return new mbTag(); } + function newLabel() { return new mbLabel(); } + function newLabelAlias() { return new mbLabelAlias(); } + function newUser() { return new mbUser(); } + } +?> diff --git a/modules/php_musicbrainz/mbFilter.php b/modules/php_musicbrainz/mbFilter.php new file mode 100644 index 00000000..f96f9799 --- /dev/null +++ b/modules/php_musicbrainz/mbFilter.php @@ -0,0 +1,149 @@ +<?php + interface MusicBrainzFilter { + function createParameters(); + } + + class mbArtistFilter implements MusicBrainzFilter { + private $parameterList = array(); + + function createParameters() { + return $this->parameterList; + } + + function name( $name ) { + $this->parameterList['name'] = $name; + return $this; + } + + function limit( $limit ) { + $this->parameterList['limit'] = $limit; + return $this; + } + + function offset( $offset ) { + $this->parameterList['offset'] = $offset; + return $this; + } + } + + class mbReleaseFilter implements MusicBrainzFilter { + private $parameters = array(); + + function createParameters() { + return $this->parameters; + } + + function title( $title ) { + $this->parameters['title'] = $title; + return $this; + } + + function discId( $discid ) { + $this->parameters['discid'] = $discid; + return $this; + } + + function releaseType( $rtype ) { + $type = extractFragment($rtype); + + if ( isset( $this->parameters['releasetypes'] ) ) { + $this->parameters['releasetypes'] .= ' ' . $type; + } + else { + $this->parameters['releasetypes'] = $type; + } + + return $this; + } + + function artistName( $name ) { + $this->parameters['artist'] = $name; + return $this; + } + + function artistId( $id ) { + $this->parameters['artistid'] = $id; + return $this; + } + + function asin( $asin ) { + $this->parameters['asin'] = $asin; + return $this; + } + + function limit( $limit ) { + $this->parameters['limit'] = $limit; + return $this; + } + + function offset( $offset ) { + $this->parameterList['offset'] = $offset; + return $this; + } + } + + class mbTrackFilter implements MusicBrainzFilter { + private $parameters = array(); + + function createParameters() { + return $this->parameters; + } + + function title( $title ) { + $this->parameters['title'] = $title; + return $this; + } + + function artistName( $name ) { + $this->parameters['artist'] = $name; + return $this; + } + + function artistId( $id ) { + $this->parameters['artistid'] = $id; + return $this; + } + + function releaseTitle( $title ) { + $this->parameters['release'] = $title; + return $this; + } + + function releaseId( $id ) { + $this->parameters['releaseid'] = $id; + return $this; + } + + function duration( $duration ) { + $this->parameters['duration'] = $duration; + return $this; + } + + function puid( $puid ) { + $this->parameters['puid'] = $puid; + return $this; + } + + function limit( $limit ) { + $this->parameters['limit'] = $limit; + return $this; + } + + function offset( $offset ) { + $this->parameterList['offset'] = $offset; + return $this; + } + } + + class mbUserFilter implements MusicBrainzFilter { + private $parameters = array(); + + function createParameters() { + return $this->parameters; + } + + function name( $value ) { + $this->parameters['name'] = $value; + } + } +?> diff --git a/modules/php_musicbrainz/mbInclude.php b/modules/php_musicbrainz/mbInclude.php new file mode 100644 index 00000000..3156f0fc --- /dev/null +++ b/modules/php_musicbrainz/mbInclude.php @@ -0,0 +1,149 @@ +<?php + interface MusicBrainzInclude { + function createIncludeTags(); + } + + class mbArtistIncludes implements MusicBrainzInclude { + private $includes = array(); + + function createIncludeTags() { + return $this->includes; + } + + function releases( $type ) { + $this->includes[] = "sa-" . extractFragment( $type ); + return $this; + } + + function vaReleases( $type ) { + $this->includes[] = "va-" . extractFragment( $type ); + return $this; + } + + function aliases() { + $this->includes[] = 'aliases'; + return $this; + } + + function artistRelations() { + $this->includes[] = 'artist-rels'; + return $this; + } + + function releaseRelations() { + $this->includes[] = 'release-rels'; + return $this; + } + + function trackRelations() { + $this->includes[] = 'track-rels'; + return $this; + } + + function urlRelations() { + $this->includes[] = 'url-rels'; + return $this; + } + + function releaseEvents() { + $this->includes[] = 'release-events'; + return $this; + } + } + + class mbReleaseIncludes implements MusicBrainzInclude { + private $includes; + + function createIncludeTags() { + return $this->includes; + } + + function artist() { + $this->includes[] = 'artist'; + return $this; + } + + function counts() { + $this->includes[] = 'counts'; + return $this; + } + + function releaseEvents() { + $this->includes[] = 'release-events'; + return $this; + } + + function discs() { + $this->includes[] = 'discs'; + return $this; + } + + function tracks() { + $this->includes[] = 'tracks'; + return $this; + } + + function artistRelations() { + $this->includes[] = 'artist-rels'; + return $this; + } + + function releaseRelations() { + $this->includes[] = 'release-rels'; + return $this; + } + + function trackRelations() { + $this->includes[] = 'track-rels'; + return $this; + } + + function urlRelations() { + $this->includes[] = 'url-rels'; + return $this; + } + } + + class mbTrackIncludes implements MusicBrainzInclude { + private $includes; + + function createIncludeTags() { + return $this->includes; + } + + function artist() { + $this->includes[] = 'artist'; + return $this; + } + + function releases() { + $this->includes[] = 'releases'; + return $this; + } + + function puids() { + $this->includes[] = 'puids'; + return $this; + } + + function artistRelations() { + $this->includes[] = 'artist-rels'; + return $this; + } + + function releaseRelations() { + $this->includes[] = 'release-rels'; + return $this; + } + + function trackRelations() { + $this->includes[] = 'track-rels'; + return $this; + } + + function urlRelations() { + $this->includes[] = 'url-rels'; + return $this; + } + } +?> diff --git a/modules/php_musicbrainz/mbLabel.php b/modules/php_musicbrainz/mbLabel.php new file mode 100644 index 00000000..91ca3a22 --- /dev/null +++ b/modules/php_musicbrainz/mbLabel.php @@ -0,0 +1,90 @@ +<?php + class mbLabel extends MusicBrainzEntity { + const TYPE_GROUP = "http://musicbrainz.org/ns/mmd-1.0#Group"; + const TYPE_PERSON = "http://musicbrainz.org/ns/mmd-1.0#Person"; + + private $type; + private $name; + private $sortName; + private $disambiguation; + private $beginDate; + private $endDate; + private $releases; + private $releasesCount; + private $releasesOffset; + private $aliases; + + function mbLabel( $id='', $type='', $name='', $sortName='' ) { + parent::MusicBrainzEntity($id); + $this->type = $type; + $this->name = $name; + $this->sortName = $sortName; + } + + function setType( $type ) { $this->type = $type; } + function getType() { return $this->type; } + function setName( $name ) { $this->name = $name; } + function getName() { return $this->name; } + function setSortName( $sortName ) { $this->sortName = $sortName; } + function getSortName() { return $this->sortName; } + function setDisambiguation( $disambiguation ) { $this->disambiguation = $disambiguation; } + function getDisambiguation() { return $this->disambiguation; } + function setBeginDate( $beginDate ) { $this->beginDate = $beginDate; } + function getBeginDate() { return $this->beginDate; } + function setEndDate( $endDate ) { $this->endDate = $endDate; } + function getEndDate() { return $this->endDate; } + + function getUniqueName() { + return empty($this->disambiguation) ? $this->name : + $this->name . ' (' . $this->disambiguation . ')'; + } + + function &getReleases() { + return $this->releases; + } + + function addRelease( mbRelease $release ) { + $this->releases[] = $release; + } + + function &getAliases() { + return $this->aliases; + } + + function addAlias( mbLabelAlias $alias ) { + $this->aliases[] = $alias; + } + + function getNumReleases() { + return count($this->releases); + } + + function &getRelease( $i ) { + return $this->releases[$i]; + } + + function getReleasesOffset() { + return $this->releasesOffset; + } + + function setReleasesOffset( $relOffset ) { + $this->releasesOffset = $relOffset; + } + + function getReleasesCount() { + return $this->releasesCount; + } + + function setReleasesCount( $relCount ) { + $this->releasesCount = $relCount; + } + + function getNumAliases() { + return count($this->aliases); + } + + function &getAlias( $i ) { + return $this->aliases[$i]; + } + } +?> diff --git a/modules/php_musicbrainz/mbLabelAlias.php b/modules/php_musicbrainz/mbLabelAlias.php new file mode 100644 index 00000000..b426e3a0 --- /dev/null +++ b/modules/php_musicbrainz/mbLabelAlias.php @@ -0,0 +1,3 @@ +<?php + class mbLabelArtist extends mbArtistAlias { } +?> diff --git a/modules/php_musicbrainz/mbMetadata.php b/modules/php_musicbrainz/mbMetadata.php new file mode 100644 index 00000000..5f1a10aa --- /dev/null +++ b/modules/php_musicbrainz/mbMetadata.php @@ -0,0 +1,81 @@ +<?php + class mbMetadata { + private $artist = null; + private $track = null; + private $release = null; + private $label = null; + private $artistList; + private $trackList; + private $releaseList; + private $userList; + + function mbMetadata() { + $this->artistList = array(); + $this->trackList = array(); + $this->releaseList = array(); + $this->userList = array(); + } + + function setArtist ( mbArtist $artist ) { $this->artist = $artist; } + function setTrack ( mbTrack $track ) { $this->track = $track; } + function setRelease( mbRelease $release ) { $this->release = $release; } + function setLabel ( mbLabel $label ) { $this->label = $label; } + + function getArtist( $remove=false ) { + $a = $this->artist; + if ( $remove ) + $this->artist = null; + return $a; + } + + function getTrack( $remove=false ) { + $t = $this->track; + if ( $remove ) + $this->track = null; + return $t; + } + + function getRelease( $remove=false ) { + $r = $this->release; + if ( $remove ) + $this->release = null; + return $r; + } + + function getLabel( $remove=false ) { + $l = $this->label; + if ( $remove ) + $this->label = null; + return $l; + } + + function &getUserList () { return $this->userList; } + function &getArtistResults () { return $this->artistList; } + function &getTrackResults () { return $this->trackList; } + function &getReleaseResults() { return $this->releaseList; } + + function getUserList2( $remove ) { + $ul = $this->userList; + $this->userList = array(); + return $ul; + } + + function getArtistResults2( $remove ) { + $al = $this->artistList; + $this->artistList = array(); + return $al; + } + + function getTrackResults2( $remove ) { + $tl = $this->trackList; + $this->trackList = array(); + return $tl; + } + + function getReleaseResults2( $remove ) { + $rl = $this->releaseList; + $this->releaseList = array(); + return $rl; + } + } +?> diff --git a/modules/php_musicbrainz/mbQuery.php b/modules/php_musicbrainz/mbQuery.php new file mode 100644 index 00000000..186d38bd --- /dev/null +++ b/modules/php_musicbrainz/mbQuery.php @@ -0,0 +1,131 @@ +<?php + define ( 'NS_MMD_1', "http://musicbrainz.org/ns/mmd-1.0#" ); + + require_once( 'xml/xmlParser.php' ); + + require_once( 'mbUtil.php' ); + require_once( 'mbRelation.php' ); + require_once( 'mbEntity.php' ); + require_once( 'mbArtistAlias.php' ); + require_once( 'mbArtist.php' ); + require_once( 'mbReleaseEvent.php' ); + require_once( 'mbRelease.php' ); + require_once( 'mbTrack.php' ); + require_once( 'mbDisc.php' ); + require_once( 'mbLabel.php' ); + require_once( 'mbLabelAlias.php' ); + require_once( 'mbTag.php' ); + require_once( 'mbResults.php' ); + require_once( 'mbMetadata.php' ); + require_once( 'mbFilter.php' ); + require_once( 'mbInclude.php' ); + require_once( 'mbWebService.php' ); + require_once( 'mbXmlParser.php' ); + require_once( 'mbFactory.php' ); + + class mbRequestError extends Exception { } + class mbResponseError extends Exception { } + + class MusicBrainzQuery { + private $ws; + private $ownWs = false; + private $clientId; + + function MusicBrainzQuery( IWebService $ws=null, $clientId = '' ) { + if ( $ws != null ) + $this->ws = $ws; + else { + $this->ws = new mbWebService(); + $this->ownWs = true; + } + + $this->clientId = $clientId; + } + + function getUserByName( $name ) { + $metadata = $this->getFromWebService( "user", "", null, mbUserFilter().name($name) ); + $list = $metadata->getUserList(true); + + if ( count($list) > 0 ) { + return $list[0]; + } + + throw mbResponseError("response didn't contain user data"); + } + + function getArtists( mbArtistFilter $artist_filters ) { + $metadata = $this->getFromWebService( "artist", "", null, $artist_filters ); + return $metadata->getArtistResults2(true); + } + + function getReleases( mbReleaseFilter $release_filters ) { + $metadata = $this->getFromWebService( "release", "", null, $release_filters ); + return $metadata->getReleaseResults2(true); + } + + function getTracks( mbTrackFilter $track_filters ) { + $metadata = $this->getFromWebService( "track", "", null, $track_filters ); + return $metadata->getTrackResults2(true); + } + + function getArtistById( $aID, mbArtistIncludes $artist_includes ) { + try { + $id = extractUuid($aID); + } catch ( mbValueError $e ) { + throw new mbRequestError($e->getMessage(),$e->getCode()); + } + $metadata = $this->getFromWebService( "artist", $id, $artist_includes ); + $artist = $metadata->getArtist(true); + return $artist; + } + + function getReleaseById( $rID, mbReleaseIncludes $release_includes ) { + try { + $id = extractUuid($rID); + } catch ( mbValueError $e ) { + throw new mbRequestError($e->getMessage(),$e->getCode()); + } + $metadata = $this->getFromWebService( "release", $id, $release_includes ); + $release = $metadata->getRelease(true); + return $release; + } + + function getTrackById( $tID, mbTrackIncludes $track_includes ) { + try { + $id = extractUuid($tID); + } catch ( mbValueError $e ) { + throw new mbRequestError($e->getMessage(),$e->getCode()); + } + $metadata = $this->getFromWebService( "track", $id, $track_includes ); + $track = $metadata->getTrack(true); + return $track; + } + + protected function getFromWebService( $entity, $id, $includes=null, $filters=null ) { + $includeList = $includes ? $includes->createIncludeTags() : null; + $filterList = $filters ? $filters->createParameters() : null; + $content = $this->ws->get( $entity, $id, $includeList, $filterList ); + + try { + $parser = new mbXmlParser(); + $parsed_content = $parser->parse($content); + return $parsed_content; + } catch ( mbParseError $e ) { + throw new mbResponseError( $e->getMessage(), $e->getCode() ); + } + } + + function submitPuids( array $tracks2puids ) { + if ( empty($this->clientId) ) { + throw WebServiceError("Please supply a client ID"); + } + $params = array( + array( 'client', $this->clientId ) + ); + foreach ( $tracks2puids as $puid => $track ) { + $params[] = array( 'puid', extractUuid($puid).' '.$track ); + } + $this->ws->post("track", "", urlencode($params) ); + } + } +?> diff --git a/modules/php_musicbrainz/mbRelation.php b/modules/php_musicbrainz/mbRelation.php new file mode 100644 index 00000000..a64274ec --- /dev/null +++ b/modules/php_musicbrainz/mbRelation.php @@ -0,0 +1,111 @@ +<?php + class mbRelation { + const DIR_BOTH = 0; + const DIR_FORWARD = 1; + const DIR_BACKWARD = 2; + + const TO_ARTIST = "http://musicbrainz.org/ns/mmd-1.0#Artist"; + const TO_TRACK = "http://musicbrainz.org/ns/mmd-1.0#Track"; + const TO_RELEASE = "http://musicbrainz.org/ns/mmd-1.0#Release"; + const TO_URL = "http://musicbrainz.org/ns/mmd-1.0#Url"; + + private $type; + private $targetType; + private $targetId; + private $direction; + private $attributes; + private $beginDate; + private $endDate; + private $target; + + function mbRelation( $relationType = '', + $targetType = '', + $targetId = '', + $direction = DIR_BOTH, + array $attributes = array(), + $beginDate = '', + $endDate = '', + MusicBrainzEntity $target = null ) { + $this->type = $relationType; + $this->targetType = $targetType; + $this->targetId = $targetId; + $this->direction = $direction; + $this->attributes = $attributes; + $this->beginDate = $beginDate; + $this->endDate = $endDate; + $this->target = $target; + } + + function setType( $type ) { + $this->type = $type; + } + + function getType() { + return $this->type; + } + + function setTargetType( $ttype ) { + $this->targetType = $ttype; + } + + function getTargetType() { + return $this->targetType; + } + + function setTargetId( $tid ) { + $this->targetId = $tid; + } + + function getTargetId() { + return $this->targetId; + } + + function setBeginDate( $bdate ) { + $this->beginDate = $bdate; + } + + function getBeginDate() { + return $this->beginDate; + } + + function setEndDate( $edate ) { + $this->endDate = $edate; + } + + function getEndDate() { + return $this->endDate; + } + + function getDirection() { + return $this->direction; + } + + function setDirection( $dir ) { + $this->direction = $dir; + } + + function getTarget() { + return $this->target; + } + + function setTarget( MusicBrainzEntity $entity=null ) { + $this->target = $entity; + } + + function &getAttributes() { + return $this->attributes; + } + + function addAttribute( $value ) { + $this->attributes[] = $value; + } + + function getNumAttributes() { + return count($this->attributes); + } + + function getAttribute( $i ) { + return $this->attributes( $i ); + } + } +?> diff --git a/modules/php_musicbrainz/mbRelease.php b/modules/php_musicbrainz/mbRelease.php new file mode 100644 index 00000000..32ee7f6e --- /dev/null +++ b/modules/php_musicbrainz/mbRelease.php @@ -0,0 +1,126 @@ +<?php + class mbRelease extends MusicBrainzEntity { + // Types + const TYPE_NONE = "http://musicbrainz.org/ns/mmd-1.0#None"; + + const TYPE_ALBUM = "http://musicbrainz.org/ns/mmd-1.0#Album"; + const TYPE_SINGLE = "http://musicbrainz.org/ns/mmd-1.0#Single"; + const TYPE_EP = "http://musicbrainz.org/ns/mmd-1.0#EP"; + const TYPE_COMPILATION = "http://musicbrainz.org/ns/mmd-1.0#Compilation"; + const TYPE_SOUNDTRACK = "http://musicbrainz.org/ns/mmd-1.0#Soundtrack"; + const TYPE_SPOKENWORD = "http://musicbrainz.org/ns/mmd-1.0#Spokenword"; + const TYPE_INTERVIEW = "http://musicbrainz.org/ns/mmd-1.0#Interview"; + const TYPE_AUDIOBOOK = "http://musicbrainz.org/ns/mmd-1.0#Audiobook"; + const TYPE_LIVE = "http://musicbrainz.org/ns/mmd-1.0#Live"; + const TYPE_REMIX = "http://musicbrainz.org/ns/mmd-1.0#Remix"; + const TYPE_OTHER = "http://musicbrainz.org/ns/mmd-1.0#Other"; + + // Statuses + const TYPE_OFFICIAL = "http://musicbrainz.org/ns/mmd-1.0#Official"; + const TYPE_PROMOTION = "http://musicbrainz.org/ns/mmd-1.0#Promotion"; + const TYPE_BOOTLEG = "http://musicbrainz.org/ns/mmd-1.0#Bootleg"; + const TYPE_PSEUDO_RELEASE = "http://musicbrainz.org/ns/mmd-1.0#Pseudo-Release"; + + private $title; + private $textLanguage; + private $textScript; + private $asin; + private $types = array(); + private $artist = null; + private $tracks = array(); + private $tracksOffset = 0; + private $tracksCount = 0; + private $discs = array(); + private $releaseEvents = array(); + + function mbRelease( $id = '', $title = '' ) { + parent::MusicBrainzEntity($id); + $this->title = $title; + } + + function getTitle() { return $this->title; } + function setTitle( $title ) { $this->title = $title; } + function getTextLanguage() { return $this->textLanguage; } + function setTextLanguage( $tlang ) { $this->textLanguage = $tlang; } + function getTextScript() { return $this->textScript; } + function setTextScript( $tscript ) { $this->textScript = $tscript; } + function getAsin() { return $this->asin; } + function setAsin( $asin ) { $this->asin = $asin; } + + function getArtist() { + return $this->artist; + } + + function setArtist( Artist $artist ) { + $this->artist = $artist; + } + + function &getTracks() { + return $this->tracks; + } + + function getTracksOffset() { + return $this->tracksOffset; + } + + function setTracksOffset( $value ) { + $this->tracksOffset = $value; + } + + function getTracksCount() { + return $this->tracksCount; + } + + function setTracksCount( $tracksCount ) { + $this->tracksCount = $tracksCount; + } + + function &getDiscs() { + return $this->discs; + } + + function &getReleaseEvents() { + return $this->releaseEvents; + } + + function getNumReleaseEvents() { + return count($this->releaseEvents); + } + + function getReleaseEvent( $i ) { + return $this->releaseEvents[$i]; + } + + function getNumDiscs() { + return count($this->discs); + } + + function getDisc( $i ) { + return $this->discs[$i]; + } + + function getNumTracks() { + return count($this->tracks); + } + + function getTrack( $i ) { + return $this->tracks[$i]; + } + + function setTypes( array $types ) { + $this->types = $types; + } + + function &getTypes() { + return $this->types; + } + + function getNumTypes() { + return count($this->types); + } + + function getType( $i ) { + return $this->types[$i]; + } + } +?> diff --git a/modules/php_musicbrainz/mbReleaseEvent.php b/modules/php_musicbrainz/mbReleaseEvent.php new file mode 100644 index 00000000..1c47ba11 --- /dev/null +++ b/modules/php_musicbrainz/mbReleaseEvent.php @@ -0,0 +1,31 @@ +<?php + class mbReleaseEvent { + private $country; + private $dateStr; + private $catalogNumber; + private $barcode; + private $label = null; + + function mbReleaseEvent( $country = '', $dateStr = '' ) { + $this->country = $country; + $this->dateStr = $dateStr; + } + + function setCountry ( $country ) { $this->country = $country; } + function getCountry ( ) { return $this->country; } + function setCatalogNumber( $c_number ) { $this->catalogNumber = $c_number; } + function getCatalogNumber( ) { return $this->catalogNumber; } + function setBarcode ( $barcode ) { $this->barcode = $barcode; } + function getBarcode ( ) { return $this->barcode; } + function setDate ( $date ) { $this->date = $date; } + function getDate ( ) { return $this->date; } + + function setLabel( Label $label ) { + $this->label = $label; + } + + function getLabel() { + return $this->label; + } + } +?> diff --git a/modules/php_musicbrainz/mbResults.php b/modules/php_musicbrainz/mbResults.php new file mode 100644 index 00000000..b6f5e65e --- /dev/null +++ b/modules/php_musicbrainz/mbResults.php @@ -0,0 +1,69 @@ +<?php + class mbResult { + private $score; + private $count; + private $offset; + + function mbResult( $score ) { + $this->score = $score; + } + + function getScore( ) { return $this->score; } + function setScore( $score ) { $this->score = $score; } + function getCount( ) { return $this->count; } + function setCount( $count ) { $this->count = $count; } + function getOffset( ) { return $this->offset; } + function setOffset( $offset ) { $this->offset = $offset; } + } + + class mbArtistResult extends mbResult { + private $artist; + + function mbArtistResult( Artist $artist, $score ) { + parent::mbResult($score); + $this->artist = $artist; + } + + function setArtist( mbArtist $artist ) { + $this->artist = $artist; + } + + function getArtist() { + return $this->artist; + } + } + + class mbReleaseResult extends mbResult { + private $release; + + function mbReleaseResult( mbRelease $release, $score ) { + parent::mbResult($score); + $this->release = $release; + } + + function setRelease( Release $release ) { + $this->release = $release; + } + + function getRelease() { + return $this->release; + } + } + + class mbTrackResult extends mbResult { + private $track; + + function mbTrackResult( mbTrack $track, $score ) { + parent::mbResult($score); + $this->track = $track; + } + + function setTrack( mbTrack $track ) { + $this->track = $track; + } + + function getTrack() { + return $this->track; + } + } +?> diff --git a/modules/php_musicbrainz/mbTag.php b/modules/php_musicbrainz/mbTag.php new file mode 100644 index 00000000..f823642e --- /dev/null +++ b/modules/php_musicbrainz/mbTag.php @@ -0,0 +1,16 @@ +<?php + class mbTag { + private $name; + private $count; + + function mbTag( $name='', $count=0 ) { + $this->name = $name; + $this->count = $count; + } + + function setName ( $name ) { $this->name = $name; } + function getName ( ) { return $this->name; } + function setCount( $count ) { $this->count = $count; } + function getCount( ) { return $this->count; } + } +?> diff --git a/modules/php_musicbrainz/mbTrack.php b/modules/php_musicbrainz/mbTrack.php new file mode 100644 index 00000000..27dccc7f --- /dev/null +++ b/modules/php_musicbrainz/mbTrack.php @@ -0,0 +1,60 @@ +<?php + class mbTrack extends MusicBrainzEntity { + private $title; + private $artist = null; + private $duration = 0; + private $releases; + private $releasesCount = 0; + private $releasesOffset = 0; + + function mbTrack( $id = '', $title = '' ) { + parent::MusicBrainzEntity($id); + $this->title = $title; + } + + function getTitle ( ) { return $this->title; } + function setTitle ( $title ) { $this->title = $title; } + function getDuration( ) { return $this->duration; } + function setDuration( $duration ) { $this->duration = $duration; } + + function getArtist() { + return $this->artist; + } + + function setArtist( mbArtist $artist ) { + $this->artist = $artist; + } + + function &getReleases() { + return $this->releases; + } + + function addRelease( mbRelease $release ) { + $this->releases[] = $release; + } + + function getNumReleases() { + return count($this->releases); + } + + function getRelease( $i ) { + return $this->releases[$i]; + } + + function getReleasesOffset() { + return $this->releasesOffset; + } + + function setReleasesOffset( $relOffset ) { + $this->releasesOffset = $relOffset; + } + + function getReleasesCount() { + return $this->releasesCount; + } + + function setReleasesCount( $relCount ) { + $this->releasesCount = $relCount; + } + } +?> diff --git a/modules/php_musicbrainz/mbUser.php b/modules/php_musicbrainz/mbUser.php new file mode 100644 index 00000000..6ca2bd5e --- /dev/null +++ b/modules/php_musicbrainz/mbUser.php @@ -0,0 +1,33 @@ +<?php + class mbUser { + private $name; + private $showNag = false; + private $types = array(); + + function mbUser() { + } + + function setName( $name ) { $this->name = $name; } + function getName() { return $this->name; } + + function getShowNag() { + return $this->showNag; + } + + function setShowNag( $value ) { + $this->setShowNag = $value; + } + + function addType( $type ) { + $this->types[] = $type; + } + + function getNumTypes() { + return count($this->types); + } + + function getType( $i ) { + return $this->types[$i]; + } + } +?> diff --git a/modules/php_musicbrainz/mbUtil.php b/modules/php_musicbrainz/mbUtil.php new file mode 100644 index 00000000..87517556 --- /dev/null +++ b/modules/php_musicbrainz/mbUtil.php @@ -0,0 +1,62 @@ +<?php + class mbValueError extends Exception {} + + function extractFragment( $type ) { + if ( ( $p = parse_url( $type ) ) == false ) { + return $type; + } + return $p['fragment']; + } + + function extractUuid( $uid ) { + if ( empty($uid) ) + return $uid; + + $types = array( "artist/", "release/", "track/" ); + for ( $i = 0; $i < 3; $i++ ) { + if ( ($pos = strpos( $uid, $types[$i] )) !== false ) { + $pos += strlen($types[$i]); + if ( $pos + 36 == strlen($uid) ) { + return substr( $uid, $pos, 36 ); + } + } + } + + if ( strlen($uid) == 36 ) + return $uid; + + throw new mbValueError( "$uid is not a valid MusicBrainz ID.", 1 ); + } + + require_once( 'mbUtil_countrynames.php' ); + function getCountryName( $id ) { + if ( isset( $mbCountryNames[$id] ) ) + return $mbCountryNames[$id]; + + return ""; + } + + require_once( 'mbUtil_languagenames.php' ); + function getLanguageName( $id ) { + if ( isset( $mbLanguageNames[$id] ) ) + return $mbLanguageNames[$id]; + + return ""; + } + + require_once( 'mbUtil_scriptnames.php' ); + function getScriptName( $id ) { + if ( isset( $mbScriptNames[$id] ) ) + return $mbScriptNames[$id]; + + return ""; + } + + require_once( 'mbUtil_releasetypenames.php' ); + function getReleaseTypeName( $id ) { + if ( isset( $mbReleaseTypeNames[$id] ) ) + return $mbReleaseTypeNames[$id]; + + return ""; + } +?> diff --git a/modules/php_musicbrainz/mbUtil_countrynames.php b/modules/php_musicbrainz/mbUtil_countrynames.php new file mode 100644 index 00000000..3de82ccb --- /dev/null +++ b/modules/php_musicbrainz/mbUtil_countrynames.php @@ -0,0 +1,249 @@ +<?php + $mbCountryNames = array( + "BD" => "Bangladesh", + "BE" => "Belgium", + "BF" => "Burkina Faso", + "BG" => "Bulgaria", + "BB" => "Barbados", + "WF" => "Wallis and Futuna Islands", + "BM" => "Bermuda", + "BN" => "Brunei Darussalam", + "BO" => "Bolivia", + "BH" => "Bahrain", + "BI" => "Burundi", + "BJ" => "Benin", + "BT" => "Bhutan", + "JM" => "Jamaica", + "BV" => "Bouvet Island", + "BW" => "Botswana", + "WS" => "Samoa", + "BR" => "Brazil", + "BS" => "Bahamas", + "BY" => "Belarus", + "BZ" => "Belize", + "RU" => "Russian Federation", + "RW" => "Rwanda", + "RE" => "Reunion", + "TM" => "Turkmenistan", + "TJ" => "Tajikistan", + "RO" => "Romania", + "TK" => "Tokelau", + "GW" => "Guinea-Bissau", + "GU" => "Guam", + "GT" => "Guatemala", + "GR" => "Greece", + "GQ" => "Equatorial Guinea", + "GP" => "Guadeloupe", + "JP" => "Japan", + "GY" => "Guyana", + "GF" => "French Guiana", + "GE" => "Georgia", + "GD" => "Grenada", + "GB" => "United Kingdom", + "GA" => "Gabon", + "SV" => "El Salvador", + "GN" => "Guinea", + "GM" => "Gambia", + "GL" => "Greenland", + "GI" => "Gibraltar", + "GH" => "Ghana", + "OM" => "Oman", + "TN" => "Tunisia", + "JO" => "Jordan", + "HT" => "Haiti", + "HU" => "Hungary", + "HK" => "Hong Kong", + "HN" => "Honduras", + "HM" => "Heard and Mc Donald Islands", + "VE" => "Venezuela", + "PR" => "Puerto Rico", + "PW" => "Palau", + "PT" => "Portugal", + "SJ" => "Svalbard and Jan Mayen Islands", + "PY" => "Paraguay", + "IQ" => "Iraq", + "PA" => "Panama", + "PF" => "French Polynesia", + "PG" => "Papua New Guinea", + "PE" => "Peru", + "PK" => "Pakistan", + "PH" => "Philippines", + "PN" => "Pitcairn", + "PL" => "Poland", + "PM" => "St. Pierre and Miquelon", + "ZM" => "Zambia", + "EH" => "Western Sahara", + "EE" => "Estonia", + "EG" => "Egypt", + "ZA" => "South Africa", + "EC" => "Ecuador", + "IT" => "Italy", + "VN" => "Viet Nam", + "SB" => "Solomon Islands", + "ET" => "Ethiopia", + "SO" => "Somalia", + "ZW" => "Zimbabwe", + "SA" => "Saudi Arabia", + "ES" => "Spain", + "ER" => "Eritrea", + "MD" => "Moldova, Republic of", + "MG" => "Madagascar", + "MA" => "Morocco", + "MC" => "Monaco", + "UZ" => "Uzbekistan", + "MM" => "Myanmar", + "ML" => "Mali", + "MO" => "Macau", + "MN" => "Mongolia", + "MH" => "Marshall Islands", + "MK" => "Macedonia, The Former Yugoslav Republic of", + "MU" => "Mauritius", + "MT" => "Malta", + "MW" => "Malawi", + "MV" => "Maldives", + "MQ" => "Martinique", + "MP" => "Northern Mariana Islands", + "MS" => "Montserrat", + "MR" => "Mauritania", + "UG" => "Uganda", + "MY" => "Malaysia", + "MX" => "Mexico", + "IL" => "Israel", + "FR" => "France", + "IO" => "British Indian Ocean Territory", + "SH" => "St. Helena", + "FI" => "Finland", + "FJ" => "Fiji", + "FK" => "Falkland Islands (Malvinas)", + "FM" => "Micronesia, Federated States of", + "FO" => "Faroe Islands", + "NI" => "Nicaragua", + "NL" => "Netherlands", + "NO" => "Norway", + "NA" => "Namibia", + "VU" => "Vanuatu", + "NC" => "New Caledonia", + "NE" => "Niger", + "NF" => "Norfolk Island", + "NG" => "Nigeria", + "NZ" => "New Zealand", + "ZR" => "Zaire", + "NP" => "Nepal", + "NR" => "Nauru", + "NU" => "Niue", + "CK" => "Cook Islands", + "CI" => "Cote d'Ivoire", + "CH" => "Switzerland", + "CO" => "Colombia", + "CN" => "China", + "CM" => "Cameroon", + "CL" => "Chile", + "CC" => "Cocos (Keeling) Islands", + "CA" => "Canada", + "CG" => "Congo", + "CF" => "Central African Republic", + "CZ" => "Czech Republic", + "CY" => "Cyprus", + "CX" => "Christmas Island", + "CR" => "Costa Rica", + "CV" => "Cape Verde", + "CU" => "Cuba", + "SZ" => "Swaziland", + "SY" => "Syrian Arab Republic", + "KG" => "Kyrgyzstan", + "KE" => "Kenya", + "SR" => "Suriname", + "KI" => "Kiribati", + "KH" => "Cambodia", + "KN" => "Saint Kitts and Nevis", + "KM" => "Comoros", + "ST" => "Sao Tome and Principe", + "SI" => "Slovenia", + "KW" => "Kuwait", + "SN" => "Senegal", + "SM" => "San Marino", + "SL" => "Sierra Leone", + "SC" => "Seychelles", + "KZ" => "Kazakhstan", + "KY" => "Cayman Islands", + "SG" => "Singapore", + "SE" => "Sweden", + "SD" => "Sudan", + "DO" => "Dominican Republic", + "DM" => "Dominica", + "DJ" => "Djibouti", + "DK" => "Denmark", + "VG" => "Virgin Islands (British)", + "DE" => "Germany", + "YE" => "Yemen", + "DZ" => "Algeria", + "US" => "United States", + "UY" => "Uruguay", + "YT" => "Mayotte", + "UM" => "United States Minor Outlying Islands", + "LB" => "Lebanon", + "LC" => "Saint Lucia", + "LA" => "Lao People's Democratic Republic", + "TV" => "Tuvalu", + "TW" => "Taiwan", + "TT" => "Trinidad and Tobago", + "TR" => "Turkey", + "LK" => "Sri Lanka", + "LI" => "Liechtenstein", + "LV" => "Latvia", + "TO" => "Tonga", + "LT" => "Lithuania", + "LU" => "Luxembourg", + "LR" => "Liberia", + "LS" => "Lesotho", + "TH" => "Thailand", + "TF" => "French Southern Territories", + "TG" => "Togo", + "TD" => "Chad", + "TC" => "Turks and Caicos Islands", + "LY" => "Libyan Arab Jamahiriya", + "VA" => "Vatican City State (Holy See)", + "VC" => "Saint Vincent and The Grenadines", + "AE" => "United Arab Emirates", + "AD" => "Andorra", + "AG" => "Antigua and Barbuda", + "AF" => "Afghanistan", + "AI" => "Anguilla", + "VI" => "Virgin Islands (U.S.)", + "IS" => "Iceland", + "IR" => "Iran (Islamic Republic of)", + "AM" => "Armenia", + "AL" => "Albania", + "AO" => "Angola", + "AN" => "Netherlands Antilles", + "AQ" => "Antarctica", + "AS" => "American Samoa", + "AR" => "Argentina", + "AU" => "Australia", + "AT" => "Austria", + "AW" => "Aruba", + "IN" => "India", + "TZ" => "Tanzania, United Republic of", + "AZ" => "Azerbaijan", + "IE" => "Ireland", + "ID" => "Indonesia", + "UA" => "Ukraine", + "QA" => "Qatar", + "MZ" => "Mozambique", + "BA" => "Bosnia and Herzegovina", + "CD" => "Congo, The Democratic Republic of the", + "CS" => "Serbia and Montenegro", + "HR" => "Croatia", + "KP" => "Korea (North), Democratic People's Republic of", + "KR" => "Korea (South), Republic of", + "SK" => "Slovakia", + "SU" => "Soviet Union (historical, 1922-1991)", + "TL" => "East Timor", + "XC" => "Czechoslovakia (historical, 1918-1992)", + "XE" => "Europe", + "XG" => "East Germany (historical, 1949-1990)", + "XU" => "[Unknown Country]", + "XW" => "[Worldwide]", + "YU" => "Yugoslavia (historical, 1918-1992)" + ); +?> diff --git a/modules/php_musicbrainz/mbUtil_languagenames.php b/modules/php_musicbrainz/mbUtil_languagenames.php new file mode 100644 index 00000000..9847e735 --- /dev/null +++ b/modules/php_musicbrainz/mbUtil_languagenames.php @@ -0,0 +1,396 @@ +<?php + $mbLanguageNames = array( + "ART" => "Artificial (Other)", + "ROH" => "Raeto-Romance", + "SCO" => "Scots", + "SCN" => "Sicilian", + "ROM" => "Romany", + "RON" => "Romanian", + "OSS" => "Ossetian; Ossetic", + "ALE" => "Aleut", + "MNI" => "Manipuri", + "NWC" => "Classical Newari; Old Newari; Classical Nepal Bhasa", + "OSA" => "Osage", + "MNC" => "Manchu", + "MWR" => "Marwari", + "VEN" => "Venda", + "MWL" => "Mirandese", + "FAS" => "Persian", + "FAT" => "Fanti", + "FAN" => "Fang", + "FAO" => "Faroese", + "DIN" => "Dinka", + "HYE" => "Armenian", + "DSB" => "Lower Sorbian", + "CAR" => "Carib", + "DIV" => "Divehi", + "TEL" => "Telugu", + "TEM" => "Timne", + "NBL" => "Ndebele, South; South Ndebele", + "TER" => "Tereno", + "TET" => "Tetum", + "SUN" => "Sundanese", + "KUT" => "Kutenai", + "SUK" => "Sukuma", + "KUR" => "Kurdish", + "KUM" => "Kumyk", + "SUS" => "Susu", + "NEW" => "Newari; Nepal Bhasa", + "KUA" => "Kuanyama; Kwanyama", + "MEN" => "Mende", + "LEZ" => "Lezghian", + "GLA" => "Gaelic; Scottish Gaelic", + "BOS" => "Bosnian", + "GLE" => "Irish", + "EKA" => "Ekajuk", + "GLG" => "Gallegan", + "AKA" => "Akan", + "BOD" => "Tibetan", + "GLV" => "Manx", + "JRB" => "Judeo-Arabic", + "VIE" => "Vietnamese", + "IPK" => "Inupiaq", + "UZB" => "Uzbek", + "BRE" => "Breton", + "BRA" => "Braj", + "AYM" => "Aymara", + "CHA" => "Chamorro", + "CHB" => "Chibcha", + "CHE" => "Chechen", + "CHG" => "Chagatai", + "CHK" => "Chuukese", + "CHM" => "Mari", + "CHN" => "Chinook jargon", + "CHO" => "Choctaw", + "CHP" => "Chipewyan", + "CHR" => "Cherokee", + "CHU" => "Church Slavic; Old Slavonic; Church Slavonic; Old Bulgarian; Old Church Slavonic", + "CHV" => "Chuvash", + "CHY" => "Cheyenne", + "MSA" => "Malay", + "III" => "Sichuan Yi", + "ACE" => "Achinese", + "IBO" => "Igbo", + "IBA" => "Iban", + "XHO" => "Xhosa", + "DEU" => "German", + "CAT" => "Catalan; Valencian", + "DEL" => "Delaware", + "DEN" => "Slave (Athapascan)", + "CAD" => "Caddo", + "TAT" => "Tatar", + "RAJ" => "Rajasthani", + "SPA" => "Spanish; Castilian", + "TAM" => "Tamil", + "TAH" => "Tahitian", + "AFH" => "Afrihili", + "ENG" => "English", + "CSB" => "Kashubian", + "NYN" => "Nyankole", + "NYO" => "Nyoro", + "SID" => "Sidamo", + "NYA" => "Chichewa; Chewa; Nyanja", + "SIN" => "Sinhala; Sinhalese", + "AFR" => "Afrikaans", + "LAM" => "Lamba", + "SND" => "Sindhi", + "MAR" => "Marathi", + "LAH" => "Lahnda", + "NYM" => "Nyamwezi", + "SNA" => "Shona", + "LAD" => "Ladino", + "SNK" => "Soninke", + "MAD" => "Madurese", + "MAG" => "Magahi", + "MAI" => "Maithili", + "MAH" => "Marshallese", + "LAV" => "Latvian", + "MAL" => "Malayalam", + "MAN" => "Mandingo", + "ZND" => "Zande", + "ZEN" => "Zenaga", + "KBD" => "Kabardian", + "ITA" => "Italian", + "VAI" => "Vai", + "TSN" => "Tswana", + "TSO" => "Tsonga", + "TSI" => "Tsimshian", + "BYN" => "Blin; Bilin", + "FIJ" => "Fijian", + "FIN" => "Finnish", + "EUS" => "Basque", + "CEB" => "Cebuano", + "DAN" => "Danish", + "NOG" => "Nogai", + "NOB" => "Norwegian Bokmål; Bokmål, Norwegian", + "DAK" => "Dakota", + "CES" => "Czech", + "DAR" => "Dargwa", + "DAY" => "Dayak", + "NOR" => "Norwegian", + "KPE" => "Kpelle", + "GUJ" => "Gujarati", + "MDF" => "Moksha", + "MAS" => "Masai", + "LAO" => "Lao", + "MDR" => "Mandar", + "GON" => "Gondi", + "SMS" => "Skolt Sami", + "SMO" => "Samoan", + "SMN" => "Inari Sami", + "SMJ" => "Lule Sami", + "GOT" => "Gothic", + "SME" => "Northern Sami", + "BLA" => "Siksika", + "SMA" => "Southern Sami", + "GOR" => "Gorontalo", + "AST" => "Asturian; Bable", + "ORM" => "Oromo", + "QUE" => "Quechua", + "ORI" => "Oriya", + "CRH" => "Crimean Tatar; Crimean Turkish", + "ASM" => "Assamese", + "PUS" => "Pushto", + "DGR" => "Dogrib", + "LTZ" => "Luxembourgish; Letzeburgesch", + "NDO" => "Ndonga", + "GEZ" => "Geez", + "ISL" => "Icelandic", + "LAT" => "Latin", + "MAK" => "Makasar", + "ZAP" => "Zapotec", + "YID" => "Yiddish", + "KOK" => "Konkani", + "KOM" => "Komi", + "KON" => "Kongo", + "UKR" => "Ukrainian", + "TON" => "Tonga (Tonga Islands)", + "KOS" => "Kosraean", + "KOR" => "Korean", + "TOG" => "Tonga (Nyasa)", + "HUN" => "Hungarian", + "HUP" => "Hupa", + "CYM" => "Welsh", + "UDM" => "Udmurt", + "BEJ" => "Beja", + "BEN" => "Bengali", + "BEL" => "Belarusian", + "BEM" => "Bemba", + "AAR" => "Afar", + "NZI" => "Nzima", + "SAH" => "Yakut", + "SAN" => "Sanskrit", + "SAM" => "Samaritan Aramaic", + "SAG" => "Sango", + "SAD" => "Sandawe", + "RAR" => "Rarotongan", + "RAP" => "Rapanui", + "SAS" => "Sasak", + "SAT" => "Santali", + "MIN" => "Minangkabau", + "LIM" => "Limburgan; Limburger; Limburgish", + "LIN" => "Lingala", + "LIT" => "Lithuanian", + "EFI" => "Efik", + "BTK" => "Batak (Indonesia)", + "KAC" => "Kachin", + "KAB" => "Kabyle", + "KAA" => "Kara-Kalpak", + "KAN" => "Kannada", + "KAM" => "Kamba", + "KAL" => "Kalaallisut; Greenlandic", + "KAS" => "Kashmiri", + "KAR" => "Karen", + "KAU" => "Kanuri", + "KAT" => "Georgian", + "KAZ" => "Kazakh", + "TYV" => "Tuvinian", + "AWA" => "Awadhi", + "URD" => "Urdu", + "DOI" => "Dogri", + "TPI" => "Tok Pisin", + "MRI" => "Maori", + "ABK" => "Abkhazian", + "TKL" => "Tokelau", + "NLD" => "Dutch; Flemish", + "OJI" => "Ojibwa", + "OCI" => "Occitan (post 1500); Provençal", + "WOL" => "Wolof", + "JAV" => "Javanese", + "HRV" => "Croatian", + "DYU" => "Dyula", + "SSW" => "Swati", + "MUL" => "Multiple languages", + "HIL" => "Hiligaynon", + "HIM" => "Himachali", + "HIN" => "Hindi", + "BAS" => "Basa", + "GBA" => "Gbaya", + "WLN" => "Walloon", + "BAD" => "Banda", + "NEP" => "Nepali", + "CRE" => "Cree", + "BAN" => "Balinese", + "BAL" => "Baluchi", + "BAM" => "Bambara", + "BAK" => "Bashkir", + "SHN" => "Shan", + "ARP" => "Arapaho", + "ARW" => "Arawak", + "ARA" => "Arabic", + "ARC" => "Aramaic", + "ARG" => "Aragonese", + "SEL" => "Selkup", + "ARN" => "Araucanian", + "LUS" => "Lushai", + "MUS" => "Creek", + "LUA" => "Luba-Lulua", + "LUB" => "Luba-Katanga", + "LUG" => "Ganda", + "LUI" => "Luiseno", + "LUN" => "Lunda", + "LUO" => "Luo (Kenya and Tanzania)", + "IKU" => "Inuktitut", + "TUR" => "Turkish", + "TUK" => "Turkmen", + "TUM" => "Tumbuka", + "COP" => "Coptic", + "COS" => "Corsican", + "COR" => "Cornish", + "ILO" => "Iloko", + "GWI" => "Gwich´in", + "TLI" => "Tlingit", + "TLH" => "Klingon; tlhIngan-Hol", + "POR" => "Portuguese", + "PON" => "Pohnpeian", + "POL" => "Polish", + "TGK" => "Tajik", + "TGL" => "Tagalog", + "FRA" => "French", + "BHO" => "Bhojpuri", + "SWA" => "Swahili", + "DUA" => "Duala", + "SWE" => "Swedish", + "YAP" => "Yapese", + "TIV" => "Tiv", + "YAO" => "Yao", + "XAL" => "Kalmyk", + "FRY" => "Frisian", + "GAY" => "Gayo", + "OTA" => "Turkish, Ottoman (1500-1928)", + "HMN" => "Hmong", + "HMO" => "Hiri Motu", + "GAA" => "Ga", + "FUR" => "Friulian", + "MLG" => "Malagasy", + "SLV" => "Slovenian", + "FIL" => "Filipino; Pilipino", + "MLT" => "Maltese", + "SLK" => "Slovak", + "FUL" => "Fulah", + "JPN" => "Japanese", + "VOL" => "Volapük", + "VOT" => "Votic", + "IND" => "Indonesian", + "AVE" => "Avestan", + "JPR" => "Judeo-Persian", + "AVA" => "Avaric", + "PAP" => "Papiamento", + "EWO" => "Ewondo", + "PAU" => "Palauan", + "EWE" => "Ewe", + "PAG" => "Pangasinan", + "PAM" => "Pampanga", + "PAN" => "Panjabi; Punjabi", + "KIR" => "Kirghiz", + "NIA" => "Nias", + "KIK" => "Kikuyu; Gikuyu", + "SYR" => "Syriac", + "KIN" => "Kinyarwanda", + "NIU" => "Niuean", + "EPO" => "Esperanto", + "JBO" => "Lojban", + "MIC" => "Mi'kmaq; Micmac", + "THA" => "Thai", + "HAI" => "Haida", + "ELL" => "Greek, Modern (1453-)", + "ADY" => "Adyghe; Adygei", + "ELX" => "Elamite", + "ADA" => "Adangme", + "GRB" => "Grebo", + "HAT" => "Haitian; Haitian Creole", + "HAU" => "Hausa", + "HAW" => "Hawaiian", + "BIN" => "Bini", + "AMH" => "Amharic", + "BIK" => "Bikol", + "BIH" => "Bihari", + "MOS" => "Mossi", + "MOH" => "Mohawk", + "MON" => "Mongolian", + "MOL" => "Moldavian", + "BIS" => "Bislama", + "TVL" => "Tuvalu", + "IJO" => "Ijo", + "EST" => "Estonian", + "KMB" => "Kimbundu", + "UMB" => "Umbundu", + "TMH" => "Tamashek", + "FON" => "Fon", + "HSB" => "Upper Sorbian", + "RUN" => "Rundi", + "RUS" => "Russian", + "PLI" => "Pali", + "SRD" => "Sardinian", + "ACH" => "Acoli", + "NDE" => "Ndebele, North; North Ndebele", + "DZO" => "Dzongkha", + "KRU" => "Kurukh", + "SRR" => "Serer", + "IDO" => "Ido", + "SRP" => "Serbian", + "KRO" => "Kru", + "KRC" => "Karachay-Balkar", + "NDS" => "Low German; Low Saxon; German, Low; Saxon, Low", + "ZUN" => "Zuni", + "ZUL" => "Zulu", + "TWI" => "Twi", + "NSO" => "Northern Sotho, Pedi; Sepedi", + "SOM" => "Somali", + "SON" => "Songhai", + "SOT" => "Sotho, Southern", + "MKD" => "Macedonian", + "HER" => "Herero", + "LOL" => "Mongo", + "HEB" => "Hebrew", + "LOZ" => "Lozi", + "GIL" => "Gilbertese", + "WAS" => "Washo", + "WAR" => "Waray", + "BUL" => "Bulgarian", + "WAL" => "Walamo", + "BUA" => "Buriat", + "BUG" => "Buginese", + "AZE" => "Azerbaijani", + "ZHA" => "Zhuang; Chuang", + "ZHO" => "Chinese", + "NNO" => "Norwegian Nynorsk; Nynorsk, Norwegian", + "UIG" => "Uighur; Uyghur", + "MYV" => "Erzya", + "INH" => "Ingush", + "KHM" => "Khmer", + "MYA" => "Burmese", + "KHA" => "Khasi", + "INA" => "Interlingua (International Auxiliary Language Association)", + "NAH" => "Nahuatl", + "TIR" => "Tigrinya", + "NAP" => "Neapolitan", + "NAV" => "Navajo; Navaho", + "NAU" => "Nauru", + "GRN" => "Guarani", + "TIG" => "Tigre", + "YOR" => "Yoruba", + "ILE" => "Interlingue", + "SQI" => "Albanian" + ); +?> diff --git a/modules/php_musicbrainz/mbUtil_releasetypenames.php b/modules/php_musicbrainz/mbUtil_releasetypenames.php new file mode 100644 index 00000000..f22a3581 --- /dev/null +++ b/modules/php_musicbrainz/mbUtil_releasetypenames.php @@ -0,0 +1,19 @@ +<?php + $mbReleaseTypeNames = array( + "http://musicbrainz.org/ns/mmd-1.0#None" => "None", + "http://musicbrainz.org/ns/mmd-1.0#Album" => "Album", + "http://musicbrainz.org/ns/mmd-1.0#Single" => "Single", + "http://musicbrainz.org/ns/mmd-1.0#EP" => "EP", + "http://musicbrainz.org/ns/mmd-1.0#Compilation" => "Compilation", + "http://musicbrainz.org/ns/mmd-1.0#Soundtrack" => "Soundtrack", + "http://musicbrainz.org/ns/mmd-1.0#Spokenword" => "Spokenword", + "http://musicbrainz.org/ns/mmd-1.0#Interview" => "Interview", + "http://musicbrainz.org/ns/mmd-1.0#Audiobook" => "Audiobook", + "http://musicbrainz.org/ns/mmd-1.0#Live" => "Live", + "http://musicbrainz.org/ns/mmd-1.0#Remix" => "Remix", + "http://musicbrainz.org/ns/mmd-1.0#Other" => "Other", + "http://musicbrainz.org/ns/mmd-1.0#Official" => "Official", + "http://musicbrainz.org/ns/mmd-1.0#Promotion" => "Promotion", + "http://musicbrainz.org/ns/mmd-1.0#Bootleg" => "Bootleg" + ); +?> diff --git a/modules/php_musicbrainz/mbUtil_scriptnames.php b/modules/php_musicbrainz/mbUtil_scriptnames.php new file mode 100644 index 00000000..75477f71 --- /dev/null +++ b/modules/php_musicbrainz/mbUtil_scriptnames.php @@ -0,0 +1,55 @@ +<?php + $mbScriptNames = array( + "Yiii" => "Yi", + "Telu" => "Telugu", + "Taml" => "Tamil", + "Guru" => "Gurmukhi", + "Hebr" => "Hebrew", + "Geor" => "Georgian (Mkhedruli)", + "Ugar" => "Ugaritic", + "Cyrl" => "Cyrillic", + "Hrkt" => "Kanji & Kana", + "Armn" => "Armenian", + "Runr" => "Runic", + "Khmr" => "Khmer", + "Latn" => "Latin", + "Hani" => "Han (Hanzi, Kanji, Hanja)", + "Ital" => "Old Italic (Etruscan, Oscan, etc.)", + "Hano" => "Hanunoo (Hanunóo)", + "Ethi" => "Ethiopic (Ge'ez)", + "Gujr" => "Gujarati", + "Hang" => "Hangul", + "Arab" => "Arabic", + "Thaa" => "Thaana", + "Buhd" => "Buhid", + "Sinh" => "Sinhala", + "Orya" => "Oriya", + "Hans" => "Han (Simplified variant)", + "Thai" => "Thai", + "Cprt" => "Cypriot", + "Linb" => "Linear B", + "Hant" => "Han (Traditional variant)", + "Osma" => "Osmanya", + "Mong" => "Mongolian", + "Deva" => "Devanagari (Nagari)", + "Laoo" => "Lao", + "Tagb" => "Tagbanwa", + "Hira" => "Hiragana", + "Bopo" => "Bopomofo", + "Goth" => "Gothic", + "Tale" => "Tai Le", + "Mymr" => "Myanmar (Burmese)", + "Tglg" => "Tagalog", + "Grek" => "Greek", + "Mlym" => "Malayalam", + "Cher" => "Cherokee", + "Tibt" => "Tibetan", + "Kana" => "Katakana", + "Syrc" => "Syriac", + "Cans" => "Unified Canadian Aboriginal Syllabics", + "Beng" => "Bengali", + "Limb" => "Limbu", + "Ogam" => "Ogham", + "Knda" => "Kannada" + ); +?> diff --git a/modules/php_musicbrainz/mbWebService.php b/modules/php_musicbrainz/mbWebService.php new file mode 100644 index 00000000..8d5a3b09 --- /dev/null +++ b/modules/php_musicbrainz/mbWebService.php @@ -0,0 +1,189 @@ +<?php + interface IWebService { + function get ( $entity, $id, $include, $filter, $version = '1' ); + function post( $entity, $id, $data, $version = '1' ); + } + + class mbWebService implements IWebService { + private $host; + private $port; + private $pathPrefix; + private $lastError; + private $fSock; + private $lastResponse = ""; + private $lastHeaders = array(); + + function mbWebService( $host="musicbrainz.org", $port=80, $pathPrefix="/ws" ) { + $this->host = $host; + $this->port = $port; + $this->pathPrefix = $pathPrefix; + $this->fSock = -1; + } + + function connect() { + $this->fSock = fsockopen( $this->host, $this->port, $errno, $this->lastError, 30 ); + + if ( $this->fSock == false ) { + $this->fSock = -1; + return false; + } + + return true; + } + + function close() { + if ( $this->fSock != -1 ) { + fclose($this->fSock); + $this->fSock = -1; + return true; + } + else { + $this->lastError = "Trying to close closed socket."; + return false; + } + } + + function parseHeaders( $string ) { + $lines = explode( "\n", $string ); + $this->lastHeaders = array(); + + foreach ( $lines as $key => $line ) { + // Status line + if ( $key == 0 ) { + if ( !preg_match( "/^HTTP\/(\d+)\.(\d+) (\d+) .+$/", $line, $matches ) ) { + $this->lastHeader = array(); + return false; + } + else { + $this->lastHeaders['HTTP_major_version'] = $matches[1]; + $this->lastHeaders['HTTP_minor_version'] = $matches[2]; + $this->lastHeaders['HTTP_status'] = $matches[3]; + } + } + // Empty line + else if ( $line == "\r" ) { + $new_string = ""; + for ( $i = $key+1; $i < sizeof($lines); $i++ ) + $new_string .= $lines[$i] . "\n"; + return $new_string; + } + // Not a header + else if ( !preg_match( "/^([^:]+): (.+)\r$/", $line, $matches ) ) { + $this->lastHeaders = array(); + return false; + } + // A header + else + $this->lastHeaders[$matches[1]] = $matches[2]; + } + + $this->lastHeaders = array(); + return false; + } + + function getHeaders() { + return $this->lastHeaders; + } + + function sendRequest( $string, $post_data='' ) { + if ( $this->fSock == -1 ) { + $this->lastError = "Trying to write to closed socket."; + return false; + } + + fwrite( $this->fSock, $string . "\r\n" ); + fwrite( $this->fSock, "Host: " . $this->host . "\r\n" ); + fwrite( $this->fSock, "Accept: */*\r\n" ); + fwrite( $this->fSock, "User-Agent: phpMbQuery\r\n" ); + //fwrite( $this->fSock, "Keep-Alive: 60\r\n" ); + //fwrite( $this->fSock, "Connection: keep-alive\r\n" ); + fwrite( $this->fSock, "Connection: close\r\n\r\n" ); + fwrite( $this->fSock, $post_data . "\r\n\r\n" ); + + return true; + } + + function getResponse() { + if ( $this->fSock == -1 ) { + $this->lastError = "Trying to read from closed socket."; + return false; + } + + $buffer = ""; + + while ( !feof($this->fSock) ) + $buffer .= fread( $this->fSock, 4096 ); + + if ( !$this->parseHeaders($buffer) ) + return $buffer; + + return $this->parseHeaders($buffer); + } + + function get( $entity, $uid, $includes, $filters, $version="1" ) { + $params = array(); + $params['type'] = "xml"; + + if ( is_array($includes) ) { + $inc_string = ""; + foreach ( $includes as $inc ) { + if ( $inc_string != "" ) + $inc_string .= " "; + $inc_string .= $inc; + } + if ( $inc_string != "" ) + $params['inc'] = $inc_string; + } + + if ( is_array($filters) ) { + foreach ( $filters as $filter => $value ) + $params[$filter] = $value; + } + + $URI = $this->pathPrefix . "/" . $version . "/" . $entity . "/" . $uid . "?" . $this->build_query( $params ); + + if ( $this->fSock == -1 && !$this->connect() ) + return false; + + $this->sendRequest( "GET $URI HTTP/1.1" ); + $this->lastResponse = $this->getResponse(); + $this->close(); + + if ( isset($this->lastHeaders['HTTP_status']) && $this->lastHeaders['HTTP_status'] != 200 ) + return false; + + return $this->lastResponse; + } + + function post( $entity, $id, $data, $version = '1' ) { + $URI = $this->pathPrefix . '/' . $version . '/' . $entity . '/' . $id; + if ( $this->fSock == -1 && !$this->connect() ) + return false; + + $this->sendRequest( "POST $URI HTTP/1.1", $data ); + $this->lastResponse = $this->getResponse(); + $this->close(); + + if ( isset($this->lastHeaders['HTTP_status']) && $this->lastHeaders['HTTP_status'] != 200 ) + return false; + + return $this->lastResponse; + } + + function build_query( $array ) { + $first = true; + $query_string = ""; + + if ( !is_array($array) || sizeof($array) == 0 ) + return ""; + + foreach ( $array as $key => $value ) { + $query_string .= ($first?"":"&") . "$key=" . urlencode($value); + if ( $first ) + $first = false; + } + + return $query_string; + } + } +?> diff --git a/modules/php_musicbrainz/mbXmlParser.php b/modules/php_musicbrainz/mbXmlParser.php new file mode 100644 index 00000000..4ce50ad6 --- /dev/null +++ b/modules/php_musicbrainz/mbXmlParser.php @@ -0,0 +1,390 @@ +<?php + class mbParseError extends Exception { } + + class mbXmlParser { + private $xml_parser; + private $factory; + + function mbXmlParser() { + $this->xml_parser = new xmlParser(); + $this->factory = new mbDefaultFactory(); + } + + private function parseList( XMLNode $node, array &$list, $func ) { + for ( $i = 0; $i < $node->nChildNodes(); $i++ ) { + $cnode = $node->getChildNode($i); + $list[] = call_user_func( array( &$this, $func ), $cnode ); + } + } + + private function parseResults( XMLNode $node, array &$list, $func, $type ) { + for ( $i = 0; $i < $node->nChildNodes(); $i++ ) { + $cnode = $node->getChildNode($i); + $object = call_user_func( array( &$this, $func ), $cnode ); + $score = $cnode->getAttribute("ext:score"); + eval( '$to_add = new ' . $type . 'Result($object,$score);' ); + $to_add->setCount( $node->getAttribute("count") ); + $to_add->setOffset( $node->getAttribute("offset") ); + $list[] = $to_add; + } + } + + private function parseRelations( XMLNode $node, MusicBrainzEntity $entity ) { + $targetType = $node->getAttribute("target-type"); + if ( $targetType == '' ) + return; + + for ( $i = 0; $i < $node->nChildNodes(); $i++ ) { + $cnode = $node->getChildNode($i); + if ( strtolower($cnode->getName()) == "relation" ) { + $relation = $this->createRelation( $cnode, $targetType ); + if ( $relation ) + $entity->addRelation( $relation ); + } + } + } + + private function parseUserResults( XMLNode $node, array &$userList ) { + for ( $i = 0; $i < $node->nChildNodes(); $i++ ) { + $cnode = $node->getChildNode($i); + $userList[] = $this->createUser( $cnode ); + } + } + + private function createUser( XMLNode $node ) { + $user = $this->factory->newUser(); + for ( $i = 0; $i < $node->nChildNodes(); $i++ ) { + $cNode = $node->getChildNode($i); + $name = $cNode->getName(); + switch ( $name ) { + case "name": + $user->setName($cNode->getText()); + break; + case "ext:nag": + $user->setShowNag($node->getAttribute("show") == 'true' ? true : false); + break; + } + } + return $user; + } + + private function createArtistAlias( XMLNode $node ) { + $aa = $this->factory->newArtistAlias(); + $aa->setType($node->getAttribute("type")); + $aa->setScript($node->getAttribute("script")); + $aa->setValue($node->getText()); + return $aa; + + } + + private function createTag( XMLNode $node ) { + $tag = $this->factory->newTag(); + $tag->setCount($node->getAttribute("count")); + $tag->setName($node->getText()); + return $tag; + } + + private function createLabelAlias( XML $node ) { + $la = $this->factory->newLabelAlias(); + $la->setType($node->getAttribute("type")); + $la->setScript($node->getAttribute("script")); + $la->setValue($node->getText()); + return $la; + } + + private function createDisc( XMLNode $node ) { + $disc = $this->factory->newDisc(); + $disc->setId($node->getAttribute("id")); + return $disc; + } + + private function createReleaseEvent( XMLNode $node ) { + $relEvent = $this->factory->newReleaseEvent(); + $relEvent->setCountry($node->getAttribute("country")); + $relEvent->setDate($node->getAttribute("date")); + $relEvent->setCatalogNumber($node->getAttribute("catalog-number")); + $relEvent->setBarcode($node->getAttribute("barcode")); + for ( $i = 0; $i < $node->nChildNodes(); $i++ ) { + $cnode = $node->getChildNode($i); + switch ( strtolower($cnode->getName()) ) { + case "label": + $relEvent->setLabel($this->createLabel($cnode)); + break; + } + } + return $relEvent; + } + + private function createLabel( XMLNode $node ) { + $label = $this->factory->newLabel(); + $label->setId($node->getAttribute("id")); + $label->setType($node->getAttribute("type")); + for ( $i = 0; $i < $node->nChildNodes(); $i++ ) { + $cnode = $node->getChildNode($i); + switch ( strtolower($cnode->getName()) ) { + case "name": + case "sort-name": + $label->setSortName($cnode->getText()); + break; + case "disambiguation": + $label->setDisambiguation($cnode->getText()); + break; + case "life-span": + $begin = $cnode->getAttribute("begin"); + $end = $cnode->getAttribute("end"); + if ( $begin != "" ) + $label->setBeginDate($begin); + if ( $end != "" ) + $label->setEndDate($end); + break; + case "alias-list": + $pAlias = &$label->getAliases(); + $this->parseList( $cnode, $pAlias, 'createAlias' ); + break; + case "release-list": + $pRel = &$label->getReleases(); + $label->setReleasesCount($cnode->getAttribute("count")); + $label->setReleasesOffset($cnode->getAttribute("offset")); + $this->parseList( $cnode, $pRel, 'createRelease' ); + break; + case "relation-list": + $this->parseRelations( $cnode, $label ); + break; + case "tag-list": + $pTag = &$label->getTags(); + $this->parseList( $cnode, $pTag, 'createTag' ); + break; + } + } + + return $label; + } + + private function createArtist( XMLNode $node ) { + $artist = $this->factory->newArtist(); + $artist->setId($node->getAttribute("id")); + $artist->setType($node->getAttribute("type")); + for ( $i = 0; $i < $node->nChildNodes(); $i++ ) { + $cnode = $node->getChildNode($i); + switch ( strtolower($cnode->getName()) ) { + case "name": + $artist->setName($cnode->getText()); + break; + case "sort-name": + $artist->setSortName($cnode->getText()); + break; + case "disambiguation": + $artist->setDisambiguation($cnode->getText()); + break; + case "life-span": + $begin = $cnode->getAttribute("begin"); + $end = $cnode->getAttribute("end"); + if ( $begin != "" ) + $artist->setBeginDate( $begin ); + if ( $end != "" ) + $artist->setEndDate( $end ); + break; + case "alias-list": + $pAli = &$artist->getAliases(); + $this->parseList( $cnode, $pAli, 'createArtistAlias' ); + break; + case "release-list": + $pRel = &$artist->getReleases(); + $artist->setReleasesCount($cnode->getAttribute("count")); + $artist->setReleasesOffset($cnode->getAttribute("offset")); + $this->parseList( $cnode, $pRel, 'createRelease' ); + break; + case "relation-list": + $this->parseRelations( $cnode, $artist ); + break; + case "tag-list": + $pTag = &$artist->getTags(); + $this->parseList( $cnode, $pTag, 'createTag' ); + break; + } + } + + return $artist; + } + + private function createTrack( XMLNode $node ) { + $track = $this->factory->newTrack(); + $track->setId($node->getAttribute("id")); + for ( $i = 0; $i < $node->nChildNodes(); $i++ ) { + $cnode = $node->getChildNode($i); + switch( strtolower($cnode->getName()) ) { + case "title": + $track->setTitle($cnode->getText()); + break; + case "artist": + $track->setArtist($this->createArtist($cnode)); + break; + case "duration": + $track->setDuration($cnode->getText()); + break; + case "release-list": + $pRel = &$track->getReleases(); + $track->setReleasesOffset($cnode->getAttribute("offset")); + $track->setReleasesCount($cnode->getAttribute("count")); + $this->parseList( $cnode, $pRel, 'createRelease' ); + break; + case "relation-list": + $this->parseRelations( $cnode, $track ); + break; + case "tag-list": + $pTag = &$track->getTags(); + $this->parseList( $cnode, $pTag, 'createTag' ); + break; + } + } + + return $track; + } + + private function createRelease( XMLNode $node ) { + $release = $this->factory->newRelease(); + $release->setId($node->getAttribute("id")); + $array = array(); + $types = $node->getAttribute( "type" ); + $types = explode( ' ', $types ); + foreach ( $types as $one_type ) + $array[] = $one_type; + $release->setTypes( $array ); + + for ( $i = 0; $i < $node->nChildNodes(); $i++ ) { + $cnode = $node->getChildNode($i); + switch ( strtolower($cnode->getName()) ) { + case "title": + $release->setTitle($cnode->getText()); + break; + case "text-representation": + $release->setTextLanguage($cnode->getAttribute("language")); + $release->setTextScript($cnode->getAttribute("script")); + break; + case "asin": + $release->setAsin($cnode->getText()); + break; + case "artist": + $release->setArtist($this->createArtist($cnode)); + break; + case "release-event-list": + $pRelEv = &$release->getReleaseEvents(); + $this->parseList( $cnode, $pRelEv, 'createReleaseEvent' ); + break; + case "disc-list": + $pDisc = &$release->getDiscs(); + $this->parseList( $cnode, $pDisc, 'createDisc' ); + break; + case "track-list": + $pTrack = &$release->getTracks(); + $release->setTracksOffset($cnode->getAttribute("offset")); + $release->setTracksCount($cnode->getAttribute("count")); + $this->parseList( $cnode, $pTrack, 'createTrack' ); + break; + case "relation-list": + $this->parseRelations( $cnode, $release ); + break; + case "tag-list": + $pTag = &$release->getTags(); + $this->parseList( $cnode, $pTag, 'createTag' ); + break; + } + } + + return $release; + } + + private function createRelation( XMLNode $node, $type ) { + $relation = $this->factory->newRelation(); + $relation->setType(extractFragment($node->getAttribute("type"))); // TODO: fixme + $relation->setTargetType($type); + $relation->setTargetId($node->getAttribute("target")); + + $dir = mbRelation::DIR_BOTH; + switch( strtolower($node->getAttribute("direction")) ) { + case "forward": + $dir = mbRelation::DIR_FORWARD; + break; + case "backward": + $dir = mbRelation::DIR_BACKWARD; + break; + } + $relation->setDirection($dir); + + $relation->setBeginDate($node->getAttribute("begin")); + $relation->setEndDate($node->getAttribute("end")); + + // TODO: ns + $attrs = $node->getAttribute("attributes"); + $attributes = explode( ' ', $attrs ); + foreach ( $attributes as $attr ) + $relation->addAttribute( $attr ); + + $target = null; + if ( $node->nChildNodes() > 0 ) { + $cnode = $node->getChildNode(0); + switch ( strtolower($cnode->getName()) ) { + case "artist": + $target = $this->createArtist($cnode); + break; + case "release": + $target = $this->createRelease($cnode); + break; + case "track": + $target = $this->createTrack($cnode); + break; + } + } + $relation->setTarget($target); + + return $relation; + } + + function parse( $data ) { + $nodes = $this->xml_parser->parse( $data ); + + if ( $nodes == false ) + throw new mbParseError( $this->xml_parser->lastError(), 1 ); + + $md = new mbMetadata(); + + + for ( $i = 0; $i < $nodes->nChildNodes(); $i++ ) { + $node = $nodes->getChildNode($i); + $name = strtolower($node->getName()); + + switch ( $name ) { + case "artist": + $md->setArtist($this->createArtist($node)); + break; + case "track": + $md->setTrack($this->createTrack($node)); + break; + case "release": + $md->setRelease($this->createRelease($node)); + break; + case "label": + $md->setLabel($this->createLabel($node)); + break; + case "artist-list": + $pArt = &$md->getArtistResults(); + $this->parseResults($node, $pArt, 'createArtist', 'Artist' ); + break; + case "track-list": + $pTrack = &$md->getTrackResults(); + $this->parseResults($node, $pTrack, 'createTrack', 'Track' ); + break; + case "release-list": + $pRel = &$md->getReleaseResults(); + $this->parseResults($node, $pRel, 'createRelease', 'Release' ); + break; + case "ext:user-list": + $list = &$md->getUserList(); + $this->parseUserResults( $node, $list ); + break; + } + } + return $md; + } + } +?> diff --git a/modules/php_musicbrainz/xml/xmlParser.php b/modules/php_musicbrainz/xml/xmlParser.php new file mode 100644 index 00000000..3cc8c8d3 --- /dev/null +++ b/modules/php_musicbrainz/xml/xmlParser.php @@ -0,0 +1,106 @@ +<?php + class XMLNode { + private $name; + private $attributes; + private $childNodes = array(); + private $parentNode; + + function XMLNode( $name, array $attributes, $parent=null ) { + $this->name = $name; + $this->attributes = $attributes; + $this->parentNode = $parent; + } + + function getParentNode() { + return $this->parentNode; + } + + function nChildNodes() { + return sizeof($this->childNodes); + } + + function getChildNode( $i ) { + return $this->childNodes[$i]; + } + + function setChildNode( XMLNode $node ) { + $this->childNodes[] = $node; + } + + function getName() { + return $this->name; + } + + function getAttribute( $name ) { + $name = strtoupper($name); + return isset($this->attributes[$name]) ? $this->attributes[$name] : + ""; + } + + function setText( $text ) { + $this->attributes['TEXT'] = $text; + } + + function getText() { + return $this->attributes['TEXT']; + } + } + + class xmlParser { + private $_parser; + private $_root_node = null; + private $_curr_node = null; + + public function xmlParser() { + $this->_parser = xml_parser_create(); + + xml_set_object($this->_parser, $this); + xml_set_default_handler( $this->_parser, 'text_handler' ); + xml_set_element_handler( $this->_parser, + 'start_element_handler', + 'end_element_handler' ); + } + + public function destroy() { + xml_parser_free($this->_parser); + } + + public function lastError() { + return $this->_last_error; + } + + public function parse( $data ) { + if ( !xml_parse( $this->_parser, $data ) ) { + $this->_last_error = xml_get_current_line_number($this->_parser) . ": ". xml_error_string($this->_parser); + return false; + } + return $this->_root_node; + } + + private function start_element_handler( $parser, $name, $attribs ) { + if ( !$this->_root_node ) { + $new_node = new XMLNode( $name, $attribs ); + $this->_root_node = $new_node; + $this->_curr_node = $new_node; + } + else { + $old_node = $this->_curr_node; + $new_node = new XMLNode( $name, $attribs, $old_node ); + $old_node->setChildNode( $new_node ); + $this->_curr_node = $new_node; + } + + } + + private function text_handler( $parser, $text ) { + if ( $this->_curr_node ) + $this->_curr_node->setText( $text ); + } + + private function end_element_handler( $parser, $name ) { + if ( $this->_root_node ) { + $this->_curr_node = $this->_curr_node->getParentNode(); + } + } + } +?> diff --git a/sql/ampache.sql b/sql/ampache.sql index 56ea00c7..602de62d 100644 --- a/sql/ampache.sql +++ b/sql/ampache.sql @@ -76,6 +76,7 @@ CREATE TABLE `album` ( `id` int(11) unsigned NOT NULL auto_increment, `name` varchar(255) character set utf8 default NULL, `prefix` varchar(32) character set utf8 default NULL, + `mbid` varchar(36) default NULL, `year` int(4) unsigned NOT NULL default '1984', `disk` smallint(5) unsigned default NULL, PRIMARY KEY (`id`), @@ -132,6 +133,7 @@ CREATE TABLE `artist` ( `id` int(11) unsigned NOT NULL auto_increment, `name` varchar(255) character set utf8 default NULL, `prefix` varchar(32) character set utf8 default NULL, + `mbid` varchar(36) default NULL, PRIMARY KEY (`id`), KEY `name` (`name`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; @@ -716,6 +718,7 @@ CREATE TABLE `song` ( `size` int(11) unsigned NOT NULL default '0', `time` smallint(5) unsigned NOT NULL default '0', `track` smallint(5) unsigned default NULL, + `mbid` varchar(36) default NULL, `played` tinyint(1) unsigned NOT NULL default '0', `enabled` tinyint(1) unsigned NOT NULL default '1', `update_time` int(11) unsigned default '0', diff --git a/templates/show_album.inc.php b/templates/show_album.inc.php index e336ff52..e3465f55 100644 --- a/templates/show_album.inc.php +++ b/templates/show_album.inc.php @@ -88,6 +88,6 @@ $title = scrub_out($album->name) . ' (' . $album->year . ')' . $disk .'&nb Browse::set_simple_browse(1); Browse::set_filter('album', $album->id); Browse::set_sort('track','ASC'); - Browse::get_objects(); + Browse::get_objects(); Browse::show_objects(); ?> |