</dd> </dl><br /> <?php UI::show_box_bottom(); UI::show_box_top(T_('Active Playlist')); ?> <table cellspacing="0"> <tr> <td valign="top"> <?php $tmp_playlist = new Tmp_Playlist(Tmp_Playlist::get_from_userid($client->id)); $object_ids = $tmp_playlist->get_items(); foreach ($object_ids as $object_data) { $type = array_shift($object_data); $object = new $type(array_shift($object_data)); $object->format(); echo $object->f_link; ?> <br /> <?php } ?> </td> </tr> </table><br /> <?php UI::show_box_bottom(); $data = Song::get_recently_played($client->id); Song::build_cache(array_keys($data)); $user_id = $client->id; require AmpConfig::get('prefix') . '/templates/show_recently_played.inc.php';
/** * show_objects * This takes an array of objects * and requires the correct template based on the * type that we are currently browsing * * @param int[] $object_ids */ public function show_objects($object_ids = null, $argument = null) { if ($this->is_simple() || !is_array($object_ids)) { $object_ids = $this->get_saved(); } else { $this->save_objects($object_ids); } // Limit is based on the user's preferences if this is not a // simple browse because we've got too much here if ($this->get_start() >= 0 && count($object_ids) > $this->get_start() && !$this->is_simple()) { $object_ids = array_slice($object_ids, $this->get_start(), $this->get_offset(), true); } else { if (!count($object_ids)) { $this->set_total(0); } } // Load any additional object we need for this $extra_objects = $this->get_supplemental_objects(); $browse = $this; foreach ($extra_objects as $class_name => $id) { ${$class_name} = new $class_name($id); } $match = ''; // Format any matches we have so we can show them to the masses if ($filter_value = $this->get_filter('alpha_match')) { $match = ' (' . $filter_value . ')'; } elseif ($filter_value = $this->get_filter('starts_with')) { $match = ' (' . $filter_value . ')'; /*} elseif ($filter_value = $this->get_filter('regex_match')) { $match = ' (' . $filter_value . ')'; } elseif ($filter_value = $this->get_filter('regex_not_match')) { $match = ' (' . $filter_value . ')';*/ } elseif ($filter_value = $this->get_filter('catalog')) { // Get the catalog title $catalog = Catalog::create_from_id(intval($filter_value)); $match = ' (' . $catalog->name . ')'; } $type = $this->get_type(); // Update the session value only if it's allowed on the current browser if ($this->get_update_session()) { $_SESSION['browse_current_' . $type]['start'] = $browse->get_start(); } // Set the correct classes based on type $class = "box browse_" . $type; $argument_param = $argument ? '&argument=' . scrub_in($argument) : ''; debug_event('browse', 'Show objects called for type {' . $type . '}', '5'); $limit_threshold = $this->get_threshold(); // Switch on the type of browsing we're doing switch ($type) { case 'song': $box_title = T_('Songs') . $match; Song::build_cache($object_ids, $limit_threshold); $box_req = AmpConfig::get('prefix') . '/templates/show_songs.inc.php'; break; case 'album': Album::build_cache($object_ids); $box_title = T_('Albums') . $match; if (is_array($argument)) { $allow_group_disks = $argument['group_disks']; if ($argument['title']) { $box_title = $argument['title']; } } else { $allow_group_disks = false; } $box_req = AmpConfig::get('prefix') . '/templates/show_albums.inc.php'; break; case 'user': $box_title = T_('Users') . $match; $box_req = AmpConfig::get('prefix') . '/templates/show_users.inc.php'; break; case 'artist': $box_title = T_('Artists') . $match; Artist::build_cache($object_ids, true, $limit_threshold); $box_req = AmpConfig::get('prefix') . '/templates/show_artists.inc.php'; break; case 'live_stream': require_once AmpConfig::get('prefix') . '/templates/show_live_stream.inc.php'; $box_title = T_('Radio Stations') . $match; $box_req = AmpConfig::get('prefix') . '/templates/show_live_streams.inc.php'; break; case 'playlist': Playlist::build_cache($object_ids); $box_title = T_('Playlists') . $match; $box_req = AmpConfig::get('prefix') . '/templates/show_playlists.inc.php'; break; case 'playlist_song': $box_title = T_('Playlist Songs') . $match; $box_req = AmpConfig::get('prefix') . '/templates/show_playlist_songs.inc.php'; break; case 'playlist_localplay': $box_title = T_('Current Playlist'); $box_req = AmpConfig::get('prefix') . '/templates/show_localplay_playlist.inc.php'; UI::show_box_bottom(); break; case 'smartplaylist': $box_title = T_('Smart Playlists') . $match; $box_req = AmpConfig::get('prefix') . '/templates/show_searches.inc.php'; break; case 'catalog': $box_title = T_('Catalogs'); $box_req = AmpConfig::get('prefix') . '/templates/show_catalogs.inc.php'; break; case 'shoutbox': $box_title = T_('Shoutbox Records'); $box_req = AmpConfig::get('prefix') . '/templates/show_manage_shoutbox.inc.php'; break; case 'tag': Tag::build_cache($object_ids); $box_title = T_('Tag Cloud'); $box_req = AmpConfig::get('prefix') . '/templates/show_tagcloud.inc.php'; break; case 'video': Video::build_cache($object_ids); $video_type = 'video'; $box_title = T_('Videos'); $box_req = AmpConfig::get('prefix') . '/templates/show_videos.inc.php'; break; case 'democratic': $box_title = T_('Democratic Playlist'); $box_req = AmpConfig::get('prefix') . '/templates/show_democratic_playlist.inc.php'; break; case 'wanted': $box_title = T_('Wanted Albums'); $box_req = AmpConfig::get('prefix') . '/templates/show_wanted_albums.inc.php'; break; case 'share': $box_title = T_('Shared Objects'); $box_req = AmpConfig::get('prefix') . '/templates/show_shared_objects.inc.php'; break; case 'song_preview': $box_title = T_('Songs'); $box_req = AmpConfig::get('prefix') . '/templates/show_song_previews.inc.php'; break; case 'channel': $box_title = T_('Channels'); $box_req = AmpConfig::get('prefix') . '/templates/show_channels.inc.php'; break; case 'broadcast': $box_title = T_('Broadcasts'); $box_req = AmpConfig::get('prefix') . '/templates/show_broadcasts.inc.php'; break; case 'license': $box_title = T_('Media Licenses'); $box_req = AmpConfig::get('prefix') . '/templates/show_manage_license.inc.php'; break; case 'tvshow': $box_title = T_('TV Shows'); $box_req = AmpConfig::get('prefix') . '/templates/show_tvshows.inc.php'; break; case 'tvshow_season': $box_title = T_('Seasons'); $box_req = AmpConfig::get('prefix') . '/templates/show_tvshow_seasons.inc.php'; break; case 'tvshow_episode': $box_title = T_('Episodes'); $video_type = $type; $box_req = AmpConfig::get('prefix') . '/templates/show_videos.inc.php'; break; case 'movie': $box_title = T_('Movies'); $video_type = $type; $box_req = AmpConfig::get('prefix') . '/templates/show_videos.inc.php'; break; case 'clip': $box_title = T_('Clips'); $video_type = $type; $box_req = AmpConfig::get('prefix') . '/templates/show_videos.inc.php'; break; case 'personal_video': $box_title = T_('Personal Videos'); $video_type = $type; $box_req = AmpConfig::get('prefix') . '/templates/show_videos.inc.php'; break; case 'label': $box_title = T_('Labels'); $box_req = AmpConfig::get('prefix') . '/templates/show_labels.inc.php'; break; case 'pvmsg': $box_title = T_('Private Messages'); $box_req = AmpConfig::get('prefix') . '/templates/show_pvmsgs.inc.php'; break; default: // Rien a faire break; } // end switch on type Ajax::start_container($this->get_content_div(), 'browse_content'); if ($this->get_show_header()) { if (isset($box_req) && isset($box_title)) { UI::show_box_top($box_title, $class); } } if (isset($box_req)) { require $box_req; } if ($this->get_show_header()) { if (isset($box_req)) { UI::show_box_bottom(); } echo '<script type="text/javascript">'; echo Ajax::action('?page=browse&action=get_filters&browse_id=' . $this->id . $argument_param, ''); echo ';</script>'; } else { if (!$this->get_use_pages()) { $this->show_next_link($argument); } } Ajax::end_container(); }
/** * get_songs * * Returns an array of song objects. * @return \Song[] */ public function get_songs() { $songs = array(); $results = array(); $sql = "SELECT `id` FROM `song` WHERE `catalog` = ? AND `enabled`='1'"; $db_results = Dba::read($sql, array($this->id)); while ($row = Dba::fetch_assoc($db_results)) { $songs[] = $row['id']; } if (AmpConfig::get('memory_cache')) { Song::build_cache($songs); } foreach ($songs as $song_id) { $results[] = new Song($song_id); } return $results; }
/** * democratic * This is for controlling democratic play */ public static function democratic($input) { // Load up democratic information $democratic = Democratic::get_current_playlist(); $democratic->set_parent(); switch ($input['method']) { case 'vote': $type = 'song'; $media = new $type($input['oid']); if (!$media->id) { echo XML_Data::error('400', T_('Media Object Invalid or Not Specified')); break; } $democratic->add_vote(array(array('object_type' => 'song', 'object_id' => $media->id))); // If everything was ok $xml_array = array('action' => $input['action'], 'method' => $input['method'], 'result' => true); echo XML_Data::keyed_array($xml_array); break; case 'devote': $type = 'song'; $media = new $type($input['oid']); if (!$media->id) { echo XML_Data::error('400', T_('Media Object Invalid or Not Specified')); } $uid = $democratic->get_uid_from_object_id($media->id, $type); $democratic->remove_vote($uid); // Everything was ok $xml_array = array('action' => $input['action'], 'method' => $input['method'], 'result' => true); echo XML_Data::keyed_array($xml_array); break; case 'playlist': $objects = $democratic->get_items(); Song::build_cache($democratic->object_ids); Democratic::build_vote_cache($democratic->vote_ids); XML_Data::democratic($objects); break; case 'play': $url = $democratic->play_url(); $xml_array = array('url' => $url); echo XML_Data::keyed_array($xml_array); break; default: echo XML_Data::error('405', T_('Invalid Request')); break; } // switch on method }
/** * show_objects * This takes an array of objects * and requires the correct template based on the * type that we are currently browsing */ public function show_objects($object_ids = null, $argument = null) { if ($this->is_simple() || !is_array($object_ids)) { $object_ids = $this->get_saved(); } else { $this->save_objects($object_ids); } // Limit is based on the user's preferences if this is not a // simple browse because we've got too much here if (count($object_ids) > $this->get_start() && !$this->is_simple() && !$this->is_static_content()) { $object_ids = array_slice($object_ids, $this->get_start(), $this->get_offset(), true); } else { if (!count($object_ids)) { $this->set_total(0); } } // Load any additional object we need for this $extra_objects = $this->get_supplemental_objects(); $browse = $this; foreach ($extra_objects as $class_name => $id) { ${$class_name} = new $class_name($id); } $match = ''; // Format any matches we have so we can show them to the masses if ($filter_value = $this->get_filter('alpha_match')) { $match = ' (' . $filter_value . ')'; } elseif ($filter_value = $this->get_filter('starts_with')) { $match = ' (' . $filter_value . ')'; /*} elseif ($filter_value = $this->get_filter('regex_match')) { $match = ' (' . $filter_value . ')'; } elseif ($filter_value = $this->get_filter('regex_not_match')) { $match = ' (' . $filter_value . ')';*/ } elseif ($filter_value = $this->get_filter('catalog')) { // Get the catalog title $catalog = Catalog::create_from_id($filter_value); $match = ' (' . $catalog->name . ')'; } $type = $this->get_type(); // Set the correct classes based on type $class = "box browse_" . $type; debug_event('browse', 'Called for type {' . $type . '}', '5'); // Switch on the type of browsing we're doing switch ($type) { case 'song': $box_title = T_('Songs') . $match; Song::build_cache($object_ids); $box_req = AmpConfig::get('prefix') . '/templates/show_songs.inc.php'; break; case 'album': $box_title = T_('Albums') . $match; Album::build_cache($object_ids); $allow_group_disks = $argument; $box_req = AmpConfig::get('prefix') . '/templates/show_albums.inc.php'; break; case 'user': $box_title = T_('Manage Users') . $match; $box_req = AmpConfig::get('prefix') . '/templates/show_users.inc.php'; break; case 'artist': $box_title = T_('Artists') . $match; Artist::build_cache($object_ids, 'extra'); $box_req = AmpConfig::get('prefix') . '/templates/show_artists.inc.php'; break; case 'live_stream': require_once AmpConfig::get('prefix') . '/templates/show_live_stream.inc.php'; $box_title = T_('Radio Stations') . $match; $box_req = AmpConfig::get('prefix') . '/templates/show_live_streams.inc.php'; break; case 'playlist': Playlist::build_cache($object_ids); $box_title = T_('Playlists') . $match; $box_req = AmpConfig::get('prefix') . '/templates/show_playlists.inc.php'; break; case 'playlist_song': $box_title = T_('Playlist Songs') . $match; $box_req = AmpConfig::get('prefix') . '/templates/show_playlist_songs.inc.php'; break; case 'playlist_localplay': $box_title = T_('Current Playlist'); $box_req = AmpConfig::get('prefix') . '/templates/show_localplay_playlist.inc.php'; UI::show_box_bottom(); break; case 'smartplaylist': $box_title = T_('Smart Playlists') . $match; $box_req = AmpConfig::get('prefix') . '/templates/show_smartplaylists.inc.php'; break; case 'catalog': $box_title = T_('Catalogs'); $box_req = AmpConfig::get('prefix') . '/templates/show_catalogs.inc.php'; break; case 'shoutbox': $box_title = T_('Shoutbox Records'); $box_req = AmpConfig::get('prefix') . '/templates/show_manage_shoutbox.inc.php'; break; case 'tag': Tag::build_cache($object_ids); $box_title = T_('Tag Cloud'); $box_req = AmpConfig::get('prefix') . '/templates/show_tagcloud.inc.php'; break; case 'video': Video::build_cache($object_ids); $box_title = T_('Videos'); $box_req = AmpConfig::get('prefix') . '/templates/show_videos.inc.php'; break; case 'democratic': $box_title = T_('Democratic Playlist'); $box_req = AmpConfig::get('prefix') . '/templates/show_democratic_playlist.inc.php'; break; case 'wanted': $box_title = T_('Wanted Albums'); $box_req = AmpConfig::get('prefix') . '/templates/show_wanted_albums.inc.php'; break; case 'share': $box_title = T_('Shared Objects'); $box_req = AmpConfig::get('prefix') . '/templates/show_shared_objects.inc.php'; break; case 'song_preview': $box_title = T_('Songs'); $box_req = AmpConfig::get('prefix') . '/templates/show_song_previews.inc.php'; break; case 'channel': $box_title = T_('Channels'); $box_req = AmpConfig::get('prefix') . '/templates/show_channels.inc.php'; break; case 'broadcast': $box_title = T_('Broadcasts'); $box_req = AmpConfig::get('prefix') . '/templates/show_broadcasts.inc.php'; break; default: // Rien a faire break; } // end switch on type Ajax::start_container('browse_content_' . $type, 'browse_content'); if ($this->get_show_header()) { if (isset($box_req) && isset($box_title)) { UI::show_box_top($box_title, $class); } } if (isset($box_req)) { require $box_req; } if ($this->get_show_header()) { if (isset($box_req)) { UI::show_box_bottom(); } echo '<script type="text/javascript">'; echo Ajax::action('?page=browse&action=get_filters&browse_id=' . $this->id, ''); echo ';</script>'; } else { if (!$this->get_use_pages()) { $this->show_next_link(); } } Ajax::end_container(); }
if (!Access::check('interface', '75')) { UI::access_denied(); break; } // Get all of the non-user playlists $playlists = Democratic::get_playlists(); require_once AmpConfig::get('prefix') . UI::find_template('show_manage_democratic.inc.php'); break; case 'show_playlist': default: $democratic = Democratic::get_current_playlist(); if (!$democratic->id) { require_once AmpConfig::get('prefix') . UI::find_template('show_democratic.inc.php'); break; } $democratic->set_parent(); $democratic->format(); require_once AmpConfig::get('prefix') . UI::find_template('show_democratic.inc.php'); $objects = $democratic->get_items(); Song::build_cache($democratic->object_ids); Democratic::build_vote_cache($democratic->vote_ids); $browse = new Browse(); $browse->set_type('democratic'); $browse->set_static_content(false); $browse->save_objects($objects); $browse->show_objects(); $browse->store(); break; } // end switch on action UI::show_footer();
/** * databases */ public static function databases($input) { // $revision = $_GET['revision-number']; $o = ''; // Database list if (count($input) == 0) { self::check_session('daap.serverdatabases'); $o = self::tlv('dmap.status', 200); $o .= self::tlv('dmap.updatetype', 0); $o .= self::tlv('dmap.specifiedtotalcount', 1); $o .= self::tlv('dmap.returnedcount', 1); $r = self::tlv('dmap.itemid', 1); $r .= self::tlv('dmap.persistentid', 1); $r .= self::tlv('dmap.itemname', 'Ampache'); $counts = Catalog::count_medias(); $r .= self::tlv('dmap.itemcount', $counts['songs']); $r .= self::tlv('dmap.containercount', count(Playlist::get_playlists())); $r = self::tlv('dmap.listingitem', $r); $o .= self::tlv('dmap.listing', $r); $o = self::tlv('daap.serverdatabases', $o); } elseif (count($input) == 2) { if ($input[1] == 'items') { // Songs list self::check_session('daap.databasesongs'); $o = self::catalog_songs(); $o = self::tlv('daap.databasesongs', $o); } elseif ($input[1] == 'containers') { // Playlist list self::check_session('daap.databaseplaylists'); $o = self::tlv('dmap.status', 200); $o .= self::tlv('dmap.updatetype', 0); $playlists = Playlist::get_playlists(); $searches = Search::get_searches(); $o .= self::tlv('dmap.specifiedtotalcount', count($playlists) + count($searches) + 1); $o .= self::tlv('dmap.returnedcount', count($playlists) + count($searches) + 1); $l = self::base_library(); foreach ($playlists as $playlist_id) { $playlist = new Playlist($playlist_id); $playlist->format(); $l .= self::tlv_playlist($playlist); } foreach ($searches as $search_id) { $playlist = new Search($search_id, 'song'); $playlist->format(); $l .= self::tlv_playlist($playlist); } $o .= self::tlv('dmap.listing', $l); $o = self::tlv('daap.databaseplaylists', $o); } } elseif (count($input) == 3) { // Stream if ($input[1] == 'items') { $finfo = explode('.', $input[2]); if (count($finfo) == 2) { $id = intval($finfo[0]); $type = $finfo[1]; $params = ''; $headers = apache_request_headers(); $client = $headers['User-Agent']; if (!empty($client)) { $params .= '&client=' . $client; } $params .= '&transcode_to=' . $type; $url = Song::play_url($id, $params, 'api', true); self::follow_stream($url); exit; } } } elseif (count($input) == 4) { // Playlist if ($input[1] == 'containers' && $input[3] == 'items') { $id = intval($input[2]); self::check_session('daap.playlistsongs'); if ($id == Daap_Api::BASE_LIBRARY) { $o = self::catalog_songs(); $o = self::tlv('daap.playlistsongs', $o); } else { if ($id > Daap_Api::AMPACHEID_SMARTPL) { $id -= Daap_Api::AMPACHEID_SMARTPL; $playlist = new Search($id, 'song'); } else { $playlist = new Playlist($id); } if ($playlist->id) { $meta = explode(',', strtolower($_GET['meta'])); $o = self::tlv('dmap.status', 200); $o .= self::tlv('dmap.updatetype', 0); $items = $playlist->get_items(); $song_ids = array(); foreach ($items as $item) { if ($item['object_type'] == 'song') { $song_ids[] = $item['object_id']; } } if (AmpConfig::get('memory_cache')) { Song::build_cache($song_ids); } $songs = array(); foreach ($song_ids as $song_id) { $songs[] = new Song($song_id); } $o .= self::tlv('dmap.specifiedtotalcount', count($songs)); $o .= self::tlv('dmap.returnedcount', count($songs)); $o .= self::tlv('dmap.listing', self::tlv_songs($songs, $meta)); $o = self::tlv('daap.playlistsongs', $o); } else { self::createApiError('daap.playlistsongs', 500, 'Invalid playlist id: ' . $id); } } } } self::apiOutput($o); }
/** * songs * * This returns an xml document from an array of song ids. * (Spiffy isn't it!) */ public static function songs($songs, $playlist_data = '') { if (count($songs) > self::$limit or self::$offset > 0) { $songs = array_slice($songs, self::$offset, self::$limit); } Song::build_cache($songs); Stream::set_session($_REQUEST['auth']); $string = ""; // Foreach the ids! foreach ($songs as $song_id) { $song = new Song($song_id); // If the song id is invalid/null or disabled if (!$song->id || !$song->enabled) { continue; } $song->format(); $playlist_track_string = self::playlist_song_tracks_string($song, $playlist_data); $tag_string = self::tags_string(Tag::get_top_tags('song', $song_id)); $rating = new Rating($song_id, 'song'); $art_url = Art::url($song->album, 'album', $_REQUEST['auth']); $string .= "<song id=\"" . $song->id . "\">\n" . "\t<title><![CDATA[" . $song->title . "]]></title>\n" . "\t<artist id=\"" . $song->artist . '"><![CDATA[' . $song->get_artist_name() . "]]></artist>\n" . "\t<album id=\"" . $song->album . '"><![CDATA[' . $song->get_album_name() . "]]></album>\n"; if ($song->albumartist) { $string .= "\t<albumartist id=\"" . $song->albumartist . "\"><![CDATA[" . $song->get_album_artist_name() . "]]></albumartist>\n"; } $string .= $tag_string . "\t<filename><![CDATA[" . $song->file . "]]></filename>\n" . "\t<track>" . $song->track . "</track>\n" . $playlist_track_string . "\t<time>" . $song->time . "</time>\n" . "\t<year>" . $song->year . "</year>\n" . "\t<bitrate>" . $song->bitrate . "</bitrate>\n" . "\t<rate>" . $song->rate . "</rate>\n" . "\t<mode>" . $song->mode . "</mode>\n" . "\t<mime>" . $song->mime . "</mime>\n" . "\t<url><![CDATA[" . Song::play_url($song->id, '', 'api') . "]]></url>\n" . "\t<size>" . $song->size . "</size>\n" . "\t<mbid>" . $song->mbid . "</mbid>\n" . "\t<album_mbid>" . $song->album_mbid . "</album_mbid>\n" . "\t<artist_mbid>" . $song->artist_mbid . "</artist_mbid>\n" . "\t<albumartist_mbid>" . $song->albumartist_mbid . "</albumartist_mbid>\n" . "\t<art><![CDATA[" . $art_url . "]]></art>\n" . "\t<preciserating>" . ($rating->get_user_rating() ?: 0) . "</preciserating>\n" . "\t<rating>" . ($rating->get_user_rating() ?: 0) . "</rating>\n" . "\t<averagerating>" . ($rating->get_average_rating() ?: 0) . "</averagerating>\n" . "\t<composer>" . $song->composer . "</composer>\n" . "\t<channels>" . $song->channels . "</channels>\n" . "\t<comment><![CDATA[" . $song->comment . "]]></comment>\n"; $string .= "\t<publisher><![CDATA[" . $song->label . "]]></publisher>\n" . "\t<language>" . $song->language . "</language>\n" . "\t<replaygain_album_gain>" . $song->replaygain_album_gain . "</replaygain_album_gain>\n" . "\t<replaygain_album_peak>" . $song->replaygain_album_peak . "</replaygain_album_peak>\n" . "\t<replaygain_track_gain>" . $song->replaygain_track_gain . "</replaygain_track_gain>\n" . "\t<replaygain_track_peak>" . $song->replaygain_track_peak . "</replaygain_track_peak>\n"; foreach ($song->tags as $tag) { $string .= "\t<genre><![CDATA[" . $tag['name'] . "]]></genre>\n"; } $string .= "</song>\n"; } // end foreach return self::_header() . $string . self::_footer(); }
/** * songs * * This returns an xml document from an array of song ids. * (Spiffy isn't it!) */ public static function songs($songs) { if (count($songs) > self::$limit or self::$offset > 0) { $songs = array_slice($songs, self::$offset, self::$limit); } Song::build_cache($songs); Stream::set_session($_REQUEST['auth']); $string = ""; // Foreach the ids! foreach ($songs as $song_id) { $song = new Song($song_id); // If the song id is invalid/null if (!$song->id) { continue; } $tag_string = self::tags_string(Tag::get_top_tags('song', $song_id)); $rating = new Rating($song_id, 'song'); $art_url = Art::url($song->album, 'album', $_REQUEST['auth']); $string .= "<song id=\"" . $song->id . "\">\n" . "\t<title><![CDATA[" . $song->title . "]]></title>\n" . "\t<artist id=\"" . $song->artist . '"><![CDATA[' . $song->get_artist_name() . "]]></artist>\n" . "\t<album id=\"" . $song->album . '"><![CDATA[' . $song->get_album_name() . "]]></album>\n" . $tag_string . "\t<filename><![CDATA[" . $song->file . "]]></filename>\n" . "\t<track>" . $song->track . "</track>\n" . "\t<time>" . $song->time . "</time>\n" . "\t<year>" . $song->year . "</year>\n" . "\t<bitrate>" . $song->bitrate . "</bitrate>\n" . "\t<mode>" . $song->mode . "</mode>\n" . "\t<mime>" . $song->mime . "</mime>\n" . "\t<url><![CDATA[" . Song::play_url($song->id) . "]]></url>\n" . "\t<size>" . $song->size . "</size>\n" . "\t<mbid>" . $song->mbid . "</mbid>\n" . "\t<album_mbid>" . $song->album_mbid . "</album_mbid>\n" . "\t<artist_mbid>" . $song->artist_mbid . "</artist_mbid>\n" . "\t<art><![CDATA[" . $art_url . "]]></art>\n" . "\t<preciserating>" . $rating->get_user_rating() . "</preciserating>\n" . "\t<rating>" . $rating->get_user_rating() . "</rating>\n" . "\t<averagerating>" . $rating->get_average_rating() . "</averagerating>\n" . "</song>\n"; } // end foreach return self::_header() . $string . self::_footer(); }