1
0
Fork 0
mirror of https://github.com/Yetangitu/ampache synced 2025-10-06 03:49:56 +02:00

UPNP fixes and optimization

1) optimization: _xxxChilds: slice whole items array BEFORE converting to output objects
2) fix with special chars in items title.
Some players stops after receiving some special chars.
Don't know which exactly char is wrong, replace all special chars to '-'
This commit is contained in:
SeregaPru 2014-09-14 21:46:42 +04:00
parent e75a38a007
commit 1569f8019d
3 changed files with 62 additions and 25 deletions

View file

@ -442,9 +442,17 @@ class Upnp_Api
return $meta; return $meta;
} }
public static function _musicChilds($prmPath, $prmQuery) private static function _slice($items, $start, $count)
{
$maxCount = count($items);
debug_event('upnp-api', 'slice: ' . $maxCount . " " . $start . " " . $count, '5');
return array($maxCount, array_slice($items, $start, ($count == 0 ? $maxCount - $start : $count)));
}
public static function _musicChilds($prmPath, $prmQuery, $start, $count)
{ {
$mediaItems = array(); $mediaItems = array();
$maxCount = 0;
$queryData = array(); $queryData = array();
parse_str($prmQuery, $queryData); parse_str($prmQuery, $queryData);
@ -459,6 +467,7 @@ class Upnp_Api
switch (count($pathreq)) { switch (count($pathreq)) {
case 1: // Get artists list case 1: // Get artists list
$artists = Catalog::get_artists(); $artists = Catalog::get_artists();
list($maxCount, $artists) = self::_slice($artists, $start, $count);
foreach ($artists as $artist) { foreach ($artists as $artist) {
$artist->format(); $artist->format();
$mediaItems[] = self::_itemArtist($artist, $parent); $mediaItems[] = self::_itemArtist($artist, $parent);
@ -468,6 +477,7 @@ class Upnp_Api
$artist = new Artist($pathreq[1]); $artist = new Artist($pathreq[1]);
if ($artist->id) { if ($artist->id) {
$album_ids = $artist->get_albums(); $album_ids = $artist->get_albums();
list($maxCount, $album_ids) = self::_slice($album_ids, $start, $count);
foreach ($album_ids as $album_id) { foreach ($album_ids as $album_id) {
$album = new Album($album_id); $album = new Album($album_id);
$album->format(); $album->format();
@ -482,6 +492,7 @@ class Upnp_Api
switch (count($pathreq)) { switch (count($pathreq)) {
case 1: // Get albums list case 1: // Get albums list
$album_ids = Catalog::get_albums(); $album_ids = Catalog::get_albums();
list($maxCount, $album_ids) = self::_slice($album_ids, $start, $count);
foreach ($album_ids as $album_id) { foreach ($album_ids as $album_id) {
$album = new Album($album_id); $album = new Album($album_id);
$album->format(); $album->format();
@ -492,6 +503,7 @@ class Upnp_Api
$album = new Album($pathreq[1]); $album = new Album($pathreq[1]);
if ($album->id) { if ($album->id) {
$song_ids = $album->get_songs(); $song_ids = $album->get_songs();
list($maxCount, $song_ids) = self::_slice($song_ids, $start, $count);
foreach ($song_ids as $song_id) { foreach ($song_ids as $song_id) {
$song = new Song($song_id); $song = new Song($song_id);
$song->format(); $song->format();
@ -509,6 +521,7 @@ class Upnp_Api
foreach ($catalogs as $catalog_id) { foreach ($catalogs as $catalog_id) {
$catalog = Catalog::create_from_id($catalog_id); $catalog = Catalog::create_from_id($catalog_id);
$songs = $catalog->get_songs(); $songs = $catalog->get_songs();
list($maxCount, $songs) = self::_slice($songs, $start, $count);
foreach ($songs as $song) { foreach ($songs as $song) {
$song->format(); $song->format();
$mediaItems[] = self::_itemSong($song, $parent); $mediaItems[] = self::_itemSong($song, $parent);
@ -522,6 +535,7 @@ class Upnp_Api
switch (count($pathreq)) { switch (count($pathreq)) {
case 1: // Get playlists list case 1: // Get playlists list
$pl_ids = Playlist::get_playlists(); $pl_ids = Playlist::get_playlists();
list($maxCount, $pl_ids) = self::_slice($pl_ids, $start, $count);
foreach ($pl_ids as $pl_id) { foreach ($pl_ids as $pl_id) {
$playlist = new Playlist($pl_id); $playlist = new Playlist($pl_id);
$playlist->format(); $playlist->format();
@ -532,6 +546,7 @@ class Upnp_Api
$playlist = new Playlist($pathreq[1]); $playlist = new Playlist($pathreq[1]);
if ($playlist->id) { if ($playlist->id) {
$items = $playlist->get_items(); $items = $playlist->get_items();
list($maxCount, $items) = self::_slice($items, $start, $count);
foreach ($items as $item) { foreach ($items as $item) {
if ($item['object_type'] == 'song') { if ($item['object_type'] == 'song') {
$song = new Song($item['object_id']); $song = new Song($item['object_id']);
@ -548,6 +563,7 @@ class Upnp_Api
switch (count($pathreq)) { switch (count($pathreq)) {
case 1: // Get playlists list case 1: // Get playlists list
$pl_ids = Search::get_searches(); $pl_ids = Search::get_searches();
list($maxCount, $pl_ids) = self::_slice($pl_ids, $start, $count);
foreach ($pl_ids as $pl_id) { foreach ($pl_ids as $pl_id) {
$playlist = new Search($pl_id, 'song'); $playlist = new Search($pl_id, 'song');
$playlist->format(); $playlist->format();
@ -558,6 +574,7 @@ class Upnp_Api
$playlist = new Search($pathreq[1], 'song'); $playlist = new Search($pathreq[1], 'song');
if ($playlist->id) { if ($playlist->id) {
$items = $playlist->get_items(); $items = $playlist->get_items();
list($maxCount, $items) = self::_slice($items, $start, $count);
foreach ($items as $item) { foreach ($items as $item) {
if ($item['object_type'] == 'song') { if ($item['object_type'] == 'song') {
$song = new Song($item['object_id']); $song = new Song($item['object_id']);
@ -579,7 +596,9 @@ class Upnp_Api
break; break;
} }
return $mediaItems; if ($maxCount == 0)
$maxCount = count($mediaItems);
return array($maxCount, $mediaItems);
} }
public static function _videoMetadata($prmPath, $prmQuery = '') public static function _videoMetadata($prmPath, $prmQuery = '')
@ -719,9 +738,10 @@ class Upnp_Api
return $meta; return $meta;
} }
public static function _videoChilds($prmPath, $prmQuery) public static function _videoChilds($prmPath, $prmQuery, $start, $count)
{ {
$mediaItems = array(); $mediaItems = array();
$maxCount = 0;
$queryData = array(); $queryData = array();
parse_str($prmQuery, $queryData); parse_str($prmQuery, $queryData);
@ -736,6 +756,7 @@ class Upnp_Api
switch (count($pathreq)) { switch (count($pathreq)) {
case 1: // Get tvshow list case 1: // Get tvshow list
$tvshows = Catalog::get_tvshows(); $tvshows = Catalog::get_tvshows();
list($maxCount, $tvshows) = self::_slice($tvshows, $start, $count);
foreach ($tvshows as $tvshow) { foreach ($tvshows as $tvshow) {
$tvshow->format(); $tvshow->format();
$mediaItems[] = self::_itemTVShow($tvshow, $parent); $mediaItems[] = self::_itemTVShow($tvshow, $parent);
@ -745,6 +766,7 @@ class Upnp_Api
$tvshow = new TVShow($pathreq[1]); $tvshow = new TVShow($pathreq[1]);
if ($tvshow->id) { if ($tvshow->id) {
$season_ids = $tvshow->get_seasons(); $season_ids = $tvshow->get_seasons();
list($maxCount, $season_ids) = self::_slice($season_ids, $start, $count);
foreach ($season_ids as $season_id) { foreach ($season_ids as $season_id) {
$season = new TVShow_Season($season_id); $season = new TVShow_Season($season_id);
$season->format(); $season->format();
@ -756,6 +778,7 @@ class Upnp_Api
$season = new TVShow_Season($pathreq[2]); $season = new TVShow_Season($pathreq[2]);
if ($season->id) { if ($season->id) {
$episode_ids = $season->get_episodes(); $episode_ids = $season->get_episodes();
list($maxCount, $episode_ids) = self::_slice($episode_ids, $start, $count);
foreach ($episode_ids as $episode_id) { foreach ($episode_ids as $episode_id) {
$video = new Video($episode_id); $video = new Video($episode_id);
$video->format(); $video->format();
@ -770,6 +793,7 @@ class Upnp_Api
switch (count($pathreq)) { switch (count($pathreq)) {
case 1: // Get clips list case 1: // Get clips list
$videos = Catalog::get_videos(null, 'clip'); $videos = Catalog::get_videos(null, 'clip');
list($maxCount, $videos) = self::_slice($videos, $start, $count);
foreach ($videos as $video) { foreach ($videos as $video) {
$video->format(); $video->format();
$mediaItems[] = self::_itemVideo($video, $parent); $mediaItems[] = self::_itemVideo($video, $parent);
@ -782,6 +806,7 @@ class Upnp_Api
switch (count($pathreq)) { switch (count($pathreq)) {
case 1: // Get clips list case 1: // Get clips list
$videos = Catalog::get_videos(null, 'movie'); $videos = Catalog::get_videos(null, 'movie');
list($maxCount, $videos) = self::_slice($videos, $start, $count);
foreach ($videos as $video) { foreach ($videos as $video) {
$video->format(); $video->format();
$mediaItems[] = self::_itemVideo($video, $parent); $mediaItems[] = self::_itemVideo($video, $parent);
@ -794,6 +819,7 @@ class Upnp_Api
switch (count($pathreq)) { switch (count($pathreq)) {
case 1: // Get clips list case 1: // Get clips list
$videos = Catalog::get_videos(null, 'personal_video'); $videos = Catalog::get_videos(null, 'personal_video');
list($maxCount, $videos) = self::_slice($videos, $start, $count);
foreach ($videos as $video) { foreach ($videos as $video) {
$video->format(); $video->format();
$mediaItems[] = self::_itemVideo($video, $parent); $mediaItems[] = self::_itemVideo($video, $parent);
@ -810,7 +836,9 @@ class Upnp_Api
break; break;
} }
return $mediaItems; if ($maxCount == 0)
$maxCount = count($mediaItems);
return array($maxCount, $mediaItems);
} }
public static function _callSearch($criteria) public static function _callSearch($criteria)
@ -819,6 +847,19 @@ class Upnp_Api
return array(); return array();
} }
private static function _replaceSpecialSymbols($title)
{
debug_event('upnp_class', 'replace <<< ' . $title, 5);
// replace non letter or digits
$title = preg_replace('~[^\\pL\d\.\s\(\)]+~u', '-', $title);
debug_event('upnp_class', 'replace >>> ' . $title, 5);
if ($title == "")
$title = '(no title)';
return $title;
}
private static function _itemArtist($artist, $parent) private static function _itemArtist($artist, $parent)
{ {
return array( return array(
@ -826,7 +867,7 @@ class Upnp_Api
'parentID' => $parent, 'parentID' => $parent,
'restricted' => '1', 'restricted' => '1',
'childCount' => $artist->albums, 'childCount' => $artist->albums,
'dc:title' => $artist->f_name, 'dc:title' => self::_replaceSpecialSymbols($artist->f_name),
'upnp:class' => 'object.container', // object.container.person.musicArtist 'upnp:class' => 'object.container', // object.container.person.musicArtist
); );
} }
@ -841,7 +882,7 @@ class Upnp_Api
'parentID' => $parent, 'parentID' => $parent,
'restricted' => '1', 'restricted' => '1',
'childCount' => $album->song_count, 'childCount' => $album->song_count,
'dc:title' => $album->f_title, 'dc:title' => self::_replaceSpecialSymbols($album->f_title),
'upnp:class' => 'object.container', // object.container.album.musicAlbum 'upnp:class' => 'object.container', // object.container.album.musicAlbum
'upnp:albumArtURI' => $art_url, 'upnp:albumArtURI' => $art_url,
); );
@ -854,7 +895,7 @@ class Upnp_Api
'parentID' => $parent, 'parentID' => $parent,
'restricted' => '1', 'restricted' => '1',
'childCount' => count($playlist->get_items()), 'childCount' => count($playlist->get_items()),
'dc:title' => $playlist->f_name, 'dc:title' => self::_replaceSpecialSymbols($playlist->f_name),
'upnp:class' => 'object.container', // object.container.playlistContainer 'upnp:class' => 'object.container', // object.container.playlistContainer
); );
} }
@ -866,7 +907,7 @@ class Upnp_Api
'parentID' => $parent, 'parentID' => $parent,
'restricted' => '1', 'restricted' => '1',
'childCount' => count($playlist->get_items()), 'childCount' => count($playlist->get_items()),
'dc:title' => $playlist->f_name, 'dc:title' => self::_replaceSpecialSymbols($playlist->f_name),
'upnp:class' => 'object.container', 'upnp:class' => 'object.container',
); );
} }
@ -883,7 +924,7 @@ class Upnp_Api
'id' => 'amp://music/songs/' . $song->id, 'id' => 'amp://music/songs/' . $song->id,
'parentID' => $parent, 'parentID' => $parent,
'restricted' => '1', 'restricted' => '1',
'dc:title' => $song->f_title, 'dc:title' => self::_replaceSpecialSymbols($song->f_title),
'upnp:class' => (isset($arrFileType['class'])) ? $arrFileType['class'] : 'object.item.unknownItem', 'upnp:class' => (isset($arrFileType['class'])) ? $arrFileType['class'] : 'object.item.unknownItem',
'upnp:albumArtURI' => $art_url, 'upnp:albumArtURI' => $art_url,
'upnp:artist' => $song->f_artist, 'upnp:artist' => $song->f_artist,
@ -910,7 +951,7 @@ class Upnp_Api
'parentID' => $parent, 'parentID' => $parent,
'restricted' => '1', 'restricted' => '1',
'childCount' => count($tvshow->get_seasons()), 'childCount' => count($tvshow->get_seasons()),
'dc:title' => $tvshow->f_name, 'dc:title' => self::_replaceSpecialSymbols($tvshow->f_name),
'upnp:class' => 'object.container', 'upnp:class' => 'object.container',
); );
} }
@ -922,7 +963,7 @@ class Upnp_Api
'parentID' => $parent, 'parentID' => $parent,
'restricted' => '1', 'restricted' => '1',
'childCount' => count($season->get_episodes()), 'childCount' => count($season->get_episodes()),
'dc:title' => $season->f_name, 'dc:title' => self::_replaceSpecialSymbols($season->f_name),
'upnp:class' => 'object.container', 'upnp:class' => 'object.container',
); );
} }
@ -939,7 +980,7 @@ class Upnp_Api
'id' => $parent . '/' . $video->id, 'id' => $parent . '/' . $video->id,
'parentID' => $parent, 'parentID' => $parent,
'restricted' => '1', 'restricted' => '1',
'dc:title' => $video->f_title, 'dc:title' => self::_replaceSpecialSymbols($video->f_title),
'upnp:class' => (isset($arrFileType['class'])) ? $arrFileType['class'] : 'object.item.unknownItem', 'upnp:class' => (isset($arrFileType['class'])) ? $arrFileType['class'] : 'object.item.unknownItem',
'upnp:albumArtURI' => $art_url, 'upnp:albumArtURI' => $art_url,
'upnp:genre' => Tag::get_display($video->tags, false, 'video'), 'upnp:genre' => Tag::get_display($video->tags, false, 'video'),

View file

@ -26,6 +26,7 @@ $rootMediaItems[] = Upnp_Api::_videoMetadata('');
} }
$items = array(); $items = array();
$totMatches = 0;
$responseType = "u:Error"; $responseType = "u:Error";
switch ($upnpRequest['action']) { switch ($upnpRequest['action']) {
case 'search': case 'search':
@ -34,7 +35,7 @@ $rootMediaItems[] = Upnp_Api::_videoMetadata('');
break; break;
case 'browse': case 'browse':
$responseType = 'u:BrowseResponse'; $responseType = 'u:BrowseResponse';
$items = array();
if ($upnpRequest['objectid'] == '0') { if ($upnpRequest['objectid'] == '0') {
// Root items // Root items
if ($upnpRequest['browseflag'] == 'BrowseMetadata') { if ($upnpRequest['browseflag'] == 'BrowseMetadata') {
@ -68,14 +69,14 @@ $rootMediaItems[] = Upnp_Api::_videoMetadata('');
if ($upnpRequest['browseflag'] == 'BrowseMetadata') { if ($upnpRequest['browseflag'] == 'BrowseMetadata') {
$items = Upnp_Api::_musicMetadata($reqObjectURL['path'], $reqObjectURL['query']); $items = Upnp_Api::_musicMetadata($reqObjectURL['path'], $reqObjectURL['query']);
} else { } else {
$items = Upnp_Api::_musicChilds($reqObjectURL['path'], $reqObjectURL['query']); list($totMatches, $items) = Upnp_Api::_musicChilds($reqObjectURL['path'], $reqObjectURL['query'], $upnpRequest['startingindex'], $upnpRequest['requestedcount']);
} }
break; break;
case 'video': case 'video':
if ($upnpRequest['browseflag'] == 'BrowseMetadata') { if ($upnpRequest['browseflag'] == 'BrowseMetadata') {
$items = Upnp_Api::_videoMetadata($reqObjectURL['path'], $reqObjectURL['query']); $items = Upnp_Api::_videoMetadata($reqObjectURL['path'], $reqObjectURL['query']);
} else { } else {
$items = Upnp_Api::_videoChilds($reqObjectURL['path'], $reqObjectURL['query']); list($totMatches, $items) = Upnp_Api::_videoChilds($reqObjectURL['path'], $reqObjectURL['query'], $upnpRequest['startingindex'], $upnpRequest['requestedcount']);
} }
break; break;
} }
@ -85,18 +86,13 @@ $rootMediaItems[] = Upnp_Api::_videoMetadata('');
break; break;
} }
$totMatches = count($items); $totMatches = ($totMatches == 0) ? count($items) : $totMatches;
if ($items == null || $totMatches == 0) { if ($items == null || $totMatches == 0) {
$domDIDL = Upnp_Api::createDIDL(''); $domDIDL = Upnp_Api::createDIDL('');
$numRet = 0; $numRet = 0;
} else { } else {
if ($upnpRequest['requestedcount'] == 0) { $domDIDL = Upnp_Api::createDIDL($items);
$upnpRequest['requestedcount'] = $totMatches - $upnpRequest['startingindex']; $numRet = count($items);
}
$slicedItems = array_slice($items, $upnpRequest['startingindex'], $upnpRequest['requestedcount']);
$domDIDL = Upnp_Api::createDIDL($slicedItems);
$numRet = count($slicedItems);
} }
$xmlDIDL = $domDIDL->saveXML(); $xmlDIDL = $domDIDL->saveXML();

View file

@ -17,7 +17,7 @@ if (($_GET['btnSend']) || ($_GET['btnSendAuto'])) {
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<?php <?php
if ($_GET['btnSendAuto']) { if ($_GET['btnSendAuto']) {
echo '<meta http-equiv="refresh" content="10">'; echo '<meta http-equiv="refresh" content="1">';
} }
?> ?>
<title>Ampache UPnP</title> <title>Ampache UPnP</title>
@ -41,7 +41,7 @@ body {
<br /> <br />
<br /> <br />
<input type="submit" name="btnSend" id="id-btnSend" value="Send SSDP broadcast" /> <input type="submit" name="btnSend" id="id-btnSend" value="Send SSDP broadcast" />
<input type="submit" name="btnSendAuto" id="id-btnSendAuto" value="Send SSDP broadcast every 10 sec" /> <input type="submit" name="btnSendAuto" id="id-btnSendAuto" value="Send SSDP broadcast every second" />
</form> </form>
<br /> <br />
<?php <?php