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

UPnP localplay implementation

This commit is contained in:
SeregaPru 2015-03-21 01:43:30 +04:00
parent 5d09e7dcad
commit 7463e75204
11 changed files with 1578 additions and 65 deletions

View file

@ -55,10 +55,10 @@ class Upnp_Api
socket_set_option($socket, SOL_SOCKET, SO_BROADCAST, 1);
socket_sendto($socket, $buf, strlen($buf), 0, $host, $port);
socket_close($socket);
usleep($delay*1000);
usleep($delay * 1000);
}
public static function sddpSend($delay=15, $host="239.255.255.250", $port=1900)
public static function sddpSend($delay=15, $host="239.255.255.250", $port=1900, $prefix="NT")
{
$strHeader = 'NOTIFY * HTTP/1.1' . "\r\n";
$strHeader .= 'HOST: ' . $host . ':' . $port . "\r\n";
@ -66,28 +66,28 @@ class Upnp_Api
$strHeader .= 'SERVER: DLNADOC/1.50 UPnP/1.0 Ampache/3.7' . "\r\n";
$strHeader .= 'CACHE-CONTROL: max-age=1800' . "\r\n";
$strHeader .= 'NTS: ssdp:alive' . "\r\n";
$rootDevice = 'NT: upnp:rootdevice' . "\r\n";
$rootDevice .= 'USN: uuid:' . self::UUIDSTR . '::upnp:rootdevice' . "\r\n". "\r\n";
$rootDevice = $prefix . ': upnp:rootdevice' . "\r\n";
$rootDevice .= 'USN: uuid:' . self::UUIDSTR . '::upnp:rootdevice' . "\r\n". "\r\n";
$buf = $strHeader . $rootDevice;
self::udpSend($buf, $delay, $host, $port);
$uuid = 'NT: uuid:' . self::UUIDSTR . "\r\n";
$uuid = $prefix . ': uuid:' . self::UUIDSTR . "\r\n";
$uuid .= 'USN: uuid:' . self::UUIDSTR . "\r\n". "\r\n";
$buf = $strHeader . $uuid;
self::udpSend($buf, $delay, $host, $port);
$deviceType = 'NT: urn:schemas-upnp-org:device:MediaServer:1' . "\r\n";
$deviceType = $prefix . ': urn:schemas-upnp-org:device:MediaServer:1' . "\r\n";
$deviceType .= 'USN: uuid:' . self::UUIDSTR . '::urn:schemas-upnp-org:device:MediaServer:1' . "\r\n". "\r\n";
$buf = $strHeader . $deviceType;
self::udpSend($buf, $delay, $host, $port);
$serviceCM = 'NT: urn:schemas-upnp-org:service:ConnectionManager:1' . "\r\n";
$serviceCM = $prefix . ': urn:schemas-upnp-org:service:ConnectionManager:1' . "\r\n";
$serviceCM .= 'USN: uuid:' . self::UUIDSTR . '::urn:schemas-upnp-org:service:ConnectionManager:1' . "\r\n". "\r\n";
$buf = $strHeader . $serviceCM;
self::udpSend($buf, $delay, $host, $port);
$serviceCD = 'NT: urn:schemas-upnp-org:service:ContentDirectory:1' . "\r\n";
$serviceCD = $prefix . ': urn:schemas-upnp-org:service:ContentDirectory:1' . "\r\n";
$serviceCD .= 'USN: uuid:' . self::UUIDSTR . '::urn:schemas-upnp-org:service:ContentDirectory:1' . "\r\n". "\r\n";
$buf = $strHeader . $serviceCD;
self::udpSend($buf, $delay, $host, $port);
@ -185,7 +185,7 @@ class Upnp_Api
continue;
}
if ($item['upnp:class'] == 'object.container') {
if ($item['upnp:class'] == 'object.container') {
$ndItem = $xmlDoc->createElement('container');
} else {
$ndItem = $xmlDoc->createElement('item');
@ -313,10 +313,10 @@ class Upnp_Api
$counts = Catalog::count_medias();
$meta = array(
'id' => $root . '/artists',
'parentID' => $root,
'parentID' => $root,
'restricted' => '1',
'childCount' => $counts['artists'],
'dc:title' => T_('Artists'),
'dc:title' => T_('Artists'),
'upnp:class' => 'object.container',
);
break;
@ -337,10 +337,10 @@ class Upnp_Api
$counts = Catalog::count_medias();
$meta = array(
'id' => $root . '/albums',
'parentID' => $root,
'parentID' => $root,
'restricted' => '1',
'childCount' => $counts['albums'],
'dc:title' => T_('Albums'),
'dc:title' => T_('Albums'),
'upnp:class' => 'object.container',
);
break;
@ -361,10 +361,10 @@ class Upnp_Api
$counts = Catalog::count_medias();
$meta = array(
'id' => $root . '/songs',
'parentID' => $root,
'parentID' => $root,
'restricted' => '1',
'childCount' => $counts['songs'],
'dc:title' => T_('Songs'),
'dc:title' => T_('Songs'),
'upnp:class' => 'object.container',
);
break;
@ -385,10 +385,10 @@ class Upnp_Api
$counts = Catalog::count_medias();
$meta = array(
'id' => $root . '/playlists',
'parentID' => $root,
'parentID' => $root,
'restricted' => '1',
'childCount' => $counts['playlists'],
'dc:title' => T_('Playlists'),
'dc:title' => T_('Playlists'),
'upnp:class' => 'object.container',
);
break;
@ -409,10 +409,10 @@ class Upnp_Api
$counts = Catalog::count_medias();
$meta = array(
'id' => $root . '/smartplaylists',
'parentID' => $root,
'parentID' => $root,
'restricted' => '1',
'childCount' => $counts['smartplaylists'],
'dc:title' => T_('Smart Playlists'),
'dc:title' => T_('Smart Playlists'),
'upnp:class' => 'object.container',
);
break;
@ -430,10 +430,10 @@ class Upnp_Api
default:
$meta = array(
'id' => $root,
'parentID' => '0',
'parentID' => '0',
'restricted' => '1',
'childCount' => '5',
'dc:title' => T_('Music'),
'dc:title' => T_('Music'),
'upnp:class' => 'object.container',
);
break;
@ -466,8 +466,10 @@ class Upnp_Api
case 'artists':
switch (count($pathreq)) {
case 1: // Get artists list
$artists = Catalog::get_artists();
list($maxCount, $artists) = self::_slice($artists, $start, $count);
//$artists = Catalog::get_artists();
//list($maxCount, $artists) = self::_slice($artists, $start, $count);
$artists = Catalog::get_artists($count, $start);
list($maxCount, $artists) = array(999999, $artists);
foreach ($artists as $artist) {
$artist->format();
$mediaItems[] = self::_itemArtist($artist, $parent);
@ -491,8 +493,10 @@ class Upnp_Api
case 'albums':
switch (count($pathreq)) {
case 1: // Get albums list
$album_ids = Catalog::get_albums();
list($maxCount, $album_ids) = self::_slice($album_ids, $start, $count);
//!!$album_ids = Catalog::get_albums();
//!!list($maxCount, $album_ids) = self::_slice($album_ids, $start, $count);
$album_ids = Catalog::get_albums($count, $start);
list($maxCount, $album_ids) = array(999999, $album_ids);
foreach ($album_ids as $album_id) {
$album = new Album($album_id);
$album->format();
@ -617,10 +621,10 @@ class Upnp_Api
$counts = count(Catalog::get_tvshows());
$meta = array(
'id' => $root . '/tvshows',
'parentID' => $root,
'parentID' => $root,
'restricted' => '1',
'childCount' => $counts,
'dc:title' => T_('TV Shows'),
'dc:title' => T_('TV Shows'),
'upnp:class' => 'object.container',
);
break;
@ -657,10 +661,10 @@ class Upnp_Api
$counts = Catalog::get_videos_count(null, 'clip');
$meta = array(
'id' => $root . '/clips',
'parentID' => $root,
'parentID' => $root,
'restricted' => '1',
'childCount' => $counts,
'dc:title' => T_('Clips'),
'dc:title' => T_('Clips'),
'upnp:class' => 'object.container',
);
break;
@ -681,10 +685,10 @@ class Upnp_Api
$counts = Catalog::get_videos_count(null, 'movie');
$meta = array(
'id' => $root . '/movies',
'parentID' => $root,
'parentID' => $root,
'restricted' => '1',
'childCount' => $counts,
'dc:title' => T_('Movies'),
'dc:title' => T_('Movies'),
'upnp:class' => 'object.container',
);
break;
@ -705,10 +709,10 @@ class Upnp_Api
$counts = Catalog::get_videos_count(null, 'personal_video');
$meta = array(
'id' => $root . '/personal_videos',
'parentID' => $root,
'parentID' => $root,
'restricted' => '1',
'childCount' => $counts,
'dc:title' => T_('Personal Videos'),
'dc:title' => T_('Personal Videos'),
'upnp:class' => 'object.container',
);
break;
@ -726,10 +730,10 @@ class Upnp_Api
default:
$meta = array(
'id' => $root,
'parentID' => '0',
'parentID' => '0',
'restricted' => '1',
'childCount' => '4',
'dc:title' => T_('Video'),
'dc:title' => T_('Video'),
'upnp:class' => 'object.container',
);
break;
@ -849,10 +853,10 @@ class Upnp_Api
private static function _replaceSpecialSymbols($title)
{
debug_event('upnp_class', 'replace <<< ' . $title, 5);
///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);
$title = preg_replace('~[^\\pL\d\.\s\(\)\.\,\'\"]+~u', '-', $title);
///debug_event('upnp_class', 'replace >>> ' . $title, 5);
if ($title == "")
$title = '(no title)';
@ -864,10 +868,10 @@ class Upnp_Api
{
return array(
'id' => 'amp://music/artists/' . $artist->id,
'parentID' => $parent,
'parentID' => $parent,
'restricted' => '1',
'childCount' => $artist->albums,
'dc:title' => self::_replaceSpecialSymbols($artist->f_name),
'dc:title' => self::_replaceSpecialSymbols($artist->f_name),
'upnp:class' => 'object.container', // object.container.person.musicArtist
);
}
@ -879,10 +883,10 @@ class Upnp_Api
return array(
'id' => 'amp://music/albums/' . $album->id,
'parentID' => $parent,
'restricted' => '1',
'parentID' => $parent,
'restricted' => '1',
'childCount' => $album->song_count,
'dc:title' => self::_replaceSpecialSymbols($album->f_title),
'dc:title' => self::_replaceSpecialSymbols($album->f_title),
'upnp:class' => 'object.container', // object.container.album.musicAlbum
'upnp:albumArtURI' => $art_url,
);
@ -892,10 +896,10 @@ class Upnp_Api
{
return array(
'id' => 'amp://music/playlists/' . $playlist->id,
'parentID' => $parent,
'parentID' => $parent,
'restricted' => '1',
'childCount' => count($playlist->get_items()),
'dc:title' => self::_replaceSpecialSymbols($playlist->f_name),
'dc:title' => self::_replaceSpecialSymbols($playlist->f_name),
'upnp:class' => 'object.container', // object.container.playlistContainer
);
}
@ -904,15 +908,15 @@ class Upnp_Api
{
return array(
'id' => 'amp://music/smartplaylists/' . $playlist->id,
'parentID' => $parent,
'parentID' => $parent,
'restricted' => '1',
'childCount' => count($playlist->get_items()),
'dc:title' => self::_replaceSpecialSymbols($playlist->f_name),
'dc:title' => self::_replaceSpecialSymbols($playlist->f_name),
'upnp:class' => 'object.container',
);
}
private static function _itemSong($song, $parent)
public static function _itemSong($song, $parent)
{
$api_session = (AmpConfig::get('require_session')) ? Stream::get_session() : false;
$art_url = Art::url($song->album, 'album', $api_session);
@ -922,13 +926,13 @@ class Upnp_Api
return array(
'id' => 'amp://music/songs/' . $song->id,
'parentID' => $parent,
'parentID' => $parent,
'restricted' => '1',
'dc:title' => self::_replaceSpecialSymbols($song->f_title),
'dc:title' => self::_replaceSpecialSymbols($song->f_title),
'upnp:class' => (isset($arrFileType['class'])) ? $arrFileType['class'] : 'object.item.unknownItem',
'upnp:albumArtURI' => $art_url,
'upnp:artist' => $song->f_artist,
'upnp:album' => $song->f_album,
'upnp:artist' => self::_replaceSpecialSymbols($song->f_artist),
'upnp:album' => self::_replaceSpecialSymbols($song->f_album),
'upnp:genre' => Tag::get_display($song->tags, false, 'song'),
//'dc:date' => date("c", $song->addition_time),
'upnp:originalTrackNumber' => $song->track,
@ -940,7 +944,7 @@ class Upnp_Api
'bitrate' => $song->bitrate,
'sampleFrequency' => $song->rate,
//'nrAudioChannels' => '1',
'description' => $song->comment,
'description' => self::_replaceSpecialSymbols($song->comment),
);
}
@ -948,10 +952,10 @@ class Upnp_Api
{
return array(
'id' => 'amp://video/tvshows/' . $tvshow->id,
'parentID' => $parent,
'parentID' => $parent,
'restricted' => '1',
'childCount' => count($tvshow->get_seasons()),
'dc:title' => self::_replaceSpecialSymbols($tvshow->f_name),
'dc:title' => self::_replaceSpecialSymbols($tvshow->f_name),
'upnp:class' => 'object.container',
);
}
@ -960,10 +964,10 @@ class Upnp_Api
{
return array(
'id' => 'amp://video/tvshows/' . $season->tvshow . '/' . $season->id,
'parentID' => $parent,
'parentID' => $parent,
'restricted' => '1',
'childCount' => count($season->get_episodes()),
'dc:title' => self::_replaceSpecialSymbols($season->f_name),
'dc:title' => self::_replaceSpecialSymbols($season->f_name),
'upnp:class' => 'object.container',
);
}
@ -978,9 +982,9 @@ class Upnp_Api
return array(
'id' => $parent . '/' . $video->id,
'parentID' => $parent,
'parentID' => $parent,
'restricted' => '1',
'dc:title' => self::_replaceSpecialSymbols($video->f_title),
'dc:title' => self::_replaceSpecialSymbols($video->f_title),
'upnp:class' => (isset($arrFileType['class'])) ? $arrFileType['class'] : 'object.item.unknownItem',
'upnp:albumArtURI' => $art_url,
'upnp:genre' => Tag::get_display($video->tags, false, 'video'),