private static function addVideo(SimpleXMLElement $xml, Video $video, $details = false) { $id = self::getVideoId($video->id); $xvid = $xml->addChild('Video'); $xvid->addAttribute('ratingKey', $id); $xvid->addAttribute('key', self::getMetadataUri($id)); $xvid->addAttribute('title', $video->f_title); if ($video->release_date) { $year = date('Y', $video->release_date); if ($year) { $xvid->addAttribute('year', $year); } $xvid->addAttribute('originallyAvailableAt', $video->f_release_date); } $rating = new Rating($video->id, "video"); $rating_value = $rating->get_average_rating(); if ($rating_value > 0) { $xvid->addAttribute('rating', intval($rating_value * 2)); } $time = $video->time * 1000; $xvid->addAttribute('duration', $time); $xvid->addAttribute('addedAt', ''); $xvid->addAttribute('updatedAt', ''); $xvid->addAttribute('thumb', self::getMetadataUri($id) . '/thumb/' . $id); $xmedia = $xvid->addChild('Media'); $xmedia->addAttribute('id', $id); // Same ID that video => OK? $xmedia->addAttribute('duration', $time); $xmedia->addAttribute('bitrate', intval($video->bitrate / 1000)); $xmedia->addAttribute('audioChannels', $video->channels); // Type != Codec != Container, but that's how Ampache works today... $xmedia->addAttribute('audioCodec', $video->audio_codec); $xmedia->addAttribute('videoCodec', $video->video_codec); $xmedia->addAttribute('container', $video->type); $xmedia->addAttribute('width', $video->resolution_x); $xmedia->addAttribute('height', $video->resolution_y); //$xmedia->addAttribute('videoResolution', 'sd'); // TODO //$xmedia->addAttribute('aspectRatio', '1.78'); // TODO $xmedia->addAttribute('videoFrameRate', intval(ceil($video->frame_rate)) . 'p'); $xpart = $xmedia->addChild('Part'); $partid = self::getPartId($id); $xpart->addAttribute('id', $partid); $xpart->addAttribute('key', self::getPartUri($partid, $video->type)); $xpart->addAttribute('duration', $time); $xpart->addAttribute('file', $video->file); $xpart->addAttribute('size', $video->size); $xpart->addAttribute('container', $video->type); // TODO: support Writer/Director tags here as part of Video/ /* <Writer tag="Grant Scharbo" /> <Writer tag="Richard Hatem" /> <Director tag="Terry McDonough" /> */ $tags = Tag::get_top_tags('video', $video->id); if (is_array($tags)) { foreach ($tags as $tag_id => $tag) { $xgenre = $xvid->addChild('Genre'); $xgenre->addAttribute('id', $tag['id']); $xgenre->addAttribute('tag', $tag['name']); } } if ($details) { // Subtitles $subtitles = $video->get_subtitles(); foreach ($subtitles as $subtitle) { $streamid = hexdec(bin2hex($subtitle['lang_code'])) . $partid; $xstream = $xpart->addChild('Stream'); $xstream->addAttribute('id', $streamid); $xstream->addAttribute('key', '/library/streams/' . $streamid); $xstream->addAttribute('streamType', '3'); $xstream->addAttribute('codec', 'srt'); $xstream->addAttribute('language', $subtitle['lang_name']); $xstream->addAttribute('languageCode', $subtitle['lang_code']); $xstream->addAttribute('format', 'srt'); } // TODO: support real audio/video streams! /* <Stream id="93" streamType="1" codec="mpeg4" index="0" bitrate="833" bitDepth="8" chromaSubsampling="4:2:0" colorSpace="yuv" duration="2989528" frameRate="23,976" gmc="0" height="352" level="5" profile="asp" qpel="0" scanType="progressive" width="624" /> <Stream id="94" streamType="2" selected="1" codec="mp3" index="1" channels="2" bitrate="135" bitrateMode="vbr" duration="2989488" samplingRate="48000" /> */ } return $xvid; }
public static function createSong($xml, $song, $elementName = 'song') { $xsong = $xml->addChild(htmlspecialchars($elementName)); $xsong->addAttribute('id', self::getSongId($song->id)); $xsong->addAttribute('parent', self::getAlbumId($song->album)); //$xsong->addAttribute('created', ); $xsong->addAttribute('title', $song->title); $xsong->addAttribute('isDir', 'false'); $xsong->addAttribute('isVideo', 'false'); $xsong->addAttribute('type', 'music'); $album = new Album($song->album); $xsong->addAttribute('albumId', self::getAlbumId($album->id)); $xsong->addAttribute('album', $album->name); $artist = new Artist($song->artist); $xsong->addAttribute('artistId', self::getArtistId($song->artist)); $xsong->addAttribute('artist', $artist->name); $xsong->addAttribute('coverArt', self::getAlbumId($album->id)); $xsong->addAttribute('duration', $song->time); $xsong->addAttribute('bitRate', intval($song->bitrate / 1000)); $rating = new Rating($song->id, "song"); $user_rating = $rating->get_user_rating(); if ($user_rating > 0) { $xsong->addAttribute('userRating', ceil($user_rating)); } $avg_rating = $rating->get_average_rating(); if ($avg_rating > 0) { $xsong->addAttribute('averageRating', ceil($avg_rating)); } if ($song->track > 0) { $xsong->addAttribute('track', $song->track); } if ($song->year > 0) { $xsong->addAttribute('year', $song->year); } $tags = Tag::get_object_tags('song', $song->id); if (count($tags) > 0) { $xsong->addAttribute('genre', $tags[0]['name']); } $xsong->addAttribute('size', $song->size); if ($album->disk > 0) { $xsong->addAttribute('discNumber', $album->disk); } $xsong->addAttribute('suffix', $song->type); $xsong->addAttribute('contentType', $song->mime); // Create a clean fake path instead of song real file path to have better offline mode storage on Subsonic clients $path = $artist->name . '/' . $album->name . '/' . basename($song->file); $xsong->addAttribute('path', $path); // Set transcoding information if required $transcode_cfg = AmpConfig::get('transcode'); $valid_types = Song::get_stream_types_for_type($song->type, 'api'); if ($transcode_cfg == 'always' || $transcode_cfg != 'never' && !in_array('native', $valid_types)) { $transcode_settings = $song->get_transcode_settings(null, 'api'); if ($transcode_settings) { $transcode_type = $transcode_settings['format']; $xsong->addAttribute('transcodedSuffix', $transcode_type); $xsong->addAttribute('transcodedContentType', Song::type_to_mime($transcode_type)); } } return $xsong; }
private static function tlv_songs($songs, $meta) { if (array_search('all', $meta) > -1) { $meta = self::$metas; } $lo = ''; foreach ($songs as $song) { $song->format(); $o = self::tlv('dmap.itemkind', 2); $o .= self::tlv('dmap.itemid', $song->id); foreach ($meta as $m) { switch ($m) { case 'dmap.itemname': $o .= self::tlv($m, $song->f_title); break; case 'dmap.containeritemid': /* case 'dmap.persistentid': */ $o .= self::tlv($m, $song->id); break; case 'daap.songalbum': $o .= self::tlv($m, $song->f_album); break; case 'daap.songartist': $o .= self::tlv($m, $song->f_artist); break; case 'daap.songbitrate': $o .= self::tlv($m, intval($song->bitrate / 1000)); break; case 'daap.songcomment': $o .= self::tlv($m, $song->comment); break; case 'daap.songdateadded': $o .= self::tlv($m, $song->addition_time); break; case 'daap.songdatemodified': if ($song->update_time) { $o .= self::tlv($m, $song->update_time); } break; case 'daap.songdiscnumber': $album = new Album($song->album); $o .= self::tlv($m, $album->disk); break; case 'daap.songformat': $o .= self::tlv($m, $song->type); break; case 'daap.songgenre': $o .= self::tlv($m, Tag::get_display($song->tags, false, 'song')); break; case 'daap.songsamplerate': $o .= self::tlv($m, $song->rate); break; case 'daap.songsize': $o .= self::tlv($m, $song->size); break; case 'daap.songtime': $o .= self::tlv($m, $song->time * 1000); break; case 'daap.songtracknumber': $o .= self::tlv($m, $song->track); break; case 'daap.songuserrating': $rating = new Rating($song->id, "song"); $rating_value = $rating->get_average_rating(); $o .= self::tlv($m, $rating_value); break; case 'daap.songyear': $o .= self::tlv($m, $song->year); break; } } $lo .= self::tlv('dmap.listingitem', $o); } return $lo; }
/** * democratic * * This handles creating an xml document for democratic items, this can be a little complicated * due to the votes and all of that * * @param array $object_ids Object IDs * @return string return xml */ public static function democratic($object_ids = array()) { if (!is_array($object_ids)) { $object_ids = array(); } $democratic = Democratic::get_current_playlist(); $string = ''; foreach ($object_ids as $row_id => $data) { $song = new $data['object_type']($data['object_id']); $song->format(); //FIXME: This is duplicate code and so wrong, functions need to be improved $tag = new Tag($song->tags['0']); $song->genre = $tag->id; $song->f_genre = $tag->name; $tag_string = self::tags_string($song->tags); $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->f_artist_full . "]]></artist>\n" . "\t<album id=\"" . $song->album . "\"><![CDATA[" . $song->f_album_full . "]]></album>\n" . "\t<genre id=\"" . $song->genre . "\"><![CDATA[" . $song->f_genre . "]]></genre>\n" . $tag_string . "\t<track>" . $song->track . "</track>\n" . "\t<time>" . $song->time . "</time>\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<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" . "\t<vote>" . $democratic->get_vote($row_id) . "</vote>\n" . "</song>\n"; } // end foreach $final = self::_header() . $string . self::_footer(); return $final; }
public static function addAlbum($xml, $album, $songs = false, $elementName = "album") { $xalbum = $xml->addChild($elementName); $xalbum->addAttribute('id', self::getAlbumId($album->id)); $xalbum->addAttribute('album', $album->name); $xalbum->addAttribute('title', self::formatAlbum($album)); $xalbum->addAttribute('name', $album->name); $xalbum->addAttribute('isDir', 'true'); $album->format(); if ($album->has_art) { $xalbum->addAttribute('coverArt', self::getAlbumId($album->id)); } $xalbum->addAttribute('songCount', $album->song_count); $xalbum->addAttribute('duration', $album->total_duration); $xalbum->addAttribute('artistId', self::getArtistId($album->artist_id)); $xalbum->addAttribute('parent', self::getArtistId($album->artist_id)); $xalbum->addAttribute('artist', $album->artist_name); $rating = new Rating($album->id, "album"); $rating_value = $rating->get_average_rating(); $xalbum->addAttribute('averageRating', $rating_value ? $rating_value : 0); if ($songs) { $allsongs = $album->get_songs(); foreach ($allsongs as $id) { $song = new Song($id); self::addSong($xalbum, $song); } } }
public static function addSong($xml, $song) { $xdir = $xml->addChild('Track'); self::addSongMeta($xdir, $song); $time = $song->time * 1000; $xdir->addAttribute('title', $song->title); $albumid = self::getAlbumId($song->album); $album = new Album($song->album); $xdir->addAttribute('parentRatingKey', $albumid); $xdir->addAttribute('parentKey', self::getMetadataUri($albumid)); $xdir->addAttribute('originalTitle', $album->f_name); $xdir->addAttribute('summary', ''); $xdir->addAttribute('index', $song->track); $xdir->addAttribute('duration', $time); $xdir->addAttribute('type', 'track'); $xdir->addAttribute('addedAt', ''); $xdir->addAttribute('updatedAt', ''); $rating = new Rating($song->id, "song"); $rating_value = $rating->get_average_rating(); if ($rating_value > 0) { $xdir->addAttribute('rating', intval($rating_value * 2)); } $xmedia = $xdir->addChild('Media'); $mediaid = self::getMediaId($song->id); $xmedia->addAttribute('id', $mediaid); $xmedia->addAttribute('duration', $time); $xmedia->addAttribute('bitrate', intval($song->bitrate / 1000)); $xmedia->addAttribute('audioChannels', ''); // Type != Codec != Container, but that's how Ampache works today... $xmedia->addAttribute('audioCodec', $song->type); $xmedia->addAttribute('container', $song->type); $xpart = $xmedia->addChild('Part'); $partid = self::getPartId($song->id); $xpart->addAttribute('id', $partid); $xpart->addAttribute('key', self::getPartUri($partid, $song->type)); $xpart->addAttribute('duration', $time); $xpart->addAttribute('file', $song->file); $xpart->addAttribute('size', $song->size); $xpart->addAttribute('container', $song->type); }