|
MythTV
0.26-pre
|
00001 00002 // Program Name: upnpcdsmusic.cpp 00003 // 00004 // Purpose - uPnp Content Directory Extension for Music 00005 // 00006 // Created By : David Blain Created On : Jan. 24, 2005 00007 // Modified By : Modified On: 00008 // 00010 00011 #include <climits> 00012 00013 #include <QFileInfo> 00014 00015 #include "upnpcdsmusic.h" 00016 #include "httprequest.h" 00017 #include "mythcorecontext.h" 00018 00019 /* 00020 Music Music 00021 - All Music Music/All 00022 + <Track 1> Music/All/item?Id=1 00023 + <Track 2> 00024 + <Track 3> 00025 - PlayLists 00026 - By Artist Music/artist 00027 - <Artist 1> Music/artist/artistKey=Pink Floyd 00028 - <Album 1> Music/artist/artistKey=Pink Floyd/album/albumKey=The Wall 00029 + <Track 1> Music/artist/artistKey=Pink Floyd/album/albumKey=The Wall/item?Id=1 00030 + <Track 2> 00031 - By Album 00032 - <Album 1> 00033 + <Track 1> 00034 + <Track 2> 00035 - By Recently Added 00036 + <Track 1> 00037 + <Track 2> 00038 - By Genre 00039 - By Artist Music/artist 00040 - <Artist 1> Music/artist/artistKey=Pink Floyd 00041 - <Album 1> Music/artist/artistKey=Pink Floyd/album/albumKey=The Wall 00042 + <Track 1> Music/artist/artistKey=Pink Floyd/album/albumKey=The Wall/item?Id=1 00043 + <Track 2> 00044 */ 00045 00046 UPnpCDSRootInfo UPnpCDSMusic::g_RootNodes[] = 00047 { 00048 { "All Music", 00049 "*", 00050 "SELECT song_id as id, " 00051 "name, " 00052 "1 as children " 00053 "FROM music_songs song " 00054 "%1 " 00055 "ORDER BY name", 00056 "", "name" }, 00057 00058 #if 0 00059 // This is currently broken... need to handle list of items with single parent 00060 // (like 'All Music') 00061 00062 { "Recently Added", 00063 "*", 00064 "SELECT song_id id, " 00065 "name, " 00066 "1 as children " 00067 "FROM music_songs song " 00068 "%1 " 00069 "ORDER BY name", 00070 "WHERE (DATEDIFF( CURDATE(), date_modified ) <= 30 ) ", "" }, 00071 #endif 00072 00073 { "By Album", 00074 "song.album_id", 00075 "SELECT a.album_id as id, " 00076 "a.album_name as name, " 00077 "count( song.album_id ) as children " 00078 "FROM music_songs song join music_albums a on a.album_id = song.album_id " 00079 "%1 " 00080 "GROUP BY a.album_id " 00081 "ORDER BY a.album_name", 00082 "WHERE song.album_id=:KEY", "album.album_name" }, 00083 00084 #if 0 00085 { "By Artist", 00086 "artist_id", 00087 "SELECT a.artist_id as id, " 00088 "a.artist_name as name, " 00089 "count( distinct song.artist_id ) as children " 00090 "FROM music_songs song join music_artists a on a.artist_id = song.artist_id " 00091 "%1 " 00092 "GROUP BY a.artist_id " 00093 "ORDER BY a.artist_name", 00094 "WHERE song.artist_id=:KEY", "" }, 00095 00096 { "By Genre", 00097 "genre_id", 00098 "SELECT g.genre_id as id, " 00099 "genre as name, " 00100 "count( distinct song.genre_id ) as children " 00101 "FROM music_songs song join music_genres g on g.genre_id = song.genre_id " 00102 "%1 " 00103 "GROUP BY g.genre_id " 00104 "ORDER BY g.genre", 00105 "WHERE song.genre_id=:KEY", "" }, 00106 #endif 00107 00108 }; 00109 00110 int UPnpCDSMusic::g_nRootCount = sizeof( g_RootNodes ) / sizeof( UPnpCDSRootInfo ); 00111 00113 // 00115 00116 UPnpCDSRootInfo *UPnpCDSMusic::GetRootInfo( int nIdx ) 00117 { 00118 if ((nIdx >=0 ) && ( nIdx < g_nRootCount )) 00119 return &(g_RootNodes[ nIdx ]); 00120 00121 return NULL; 00122 } 00123 00125 // 00127 00128 int UPnpCDSMusic::GetRootCount() 00129 { 00130 return g_nRootCount; 00131 } 00132 00134 // 00136 00137 QString UPnpCDSMusic::GetTableName( QString sColumn ) 00138 { 00139 return "music_songs song"; 00140 } 00141 00143 // 00145 00146 QString UPnpCDSMusic::GetItemListSQL( QString /* sColumn */ ) 00147 { 00148 return "SELECT song.song_id as intid, artist.artist_name as artist, " \ 00149 "album.album_name as album, song.name as title, " \ 00150 "genre.genre, song.year, song.track as tracknum, " \ 00151 "song.description, song.filename, song.length " \ 00152 "FROM music_songs song " \ 00153 " join music_artists artist on artist.artist_id = song.artist_id " \ 00154 " join music_albums album on album.album_id = song.album_id " \ 00155 " join music_genres genre on genre.genre_id = song.genre_id "; 00156 } 00157 00159 // 00161 00162 void UPnpCDSMusic::BuildItemQuery( MSqlQuery &query, const QStringMap &mapParams ) 00163 { 00164 int nId = mapParams[ "Id" ].toInt(); 00165 00166 QString sSQL = QString( "%1 WHERE song.song_id=:ID " ) 00167 .arg( GetItemListSQL() ); 00168 00169 query.prepare( sSQL ); 00170 00171 query.bindValue( ":ID", (int)nId ); 00172 } 00173 00175 // 00177 00178 bool UPnpCDSMusic::IsBrowseRequestForUs( UPnpCDSRequest *pRequest ) 00179 { 00180 // ---------------------------------------------------------------------- 00181 // See if we need to modify the request for compatibility 00182 // ---------------------------------------------------------------------- 00183 00184 // Xbox360 compatibility code. 00185 00186 if (pRequest->m_eClient == CDS_ClientXBox && 00187 pRequest->m_sContainerID == "7") 00188 { 00189 pRequest->m_sObjectId = "Music"; 00190 00191 LOG(VB_UPNP, LOG_INFO, 00192 "UPnpCDSMusic::IsBrowseRequestForUs - Yes, ContainerId == 7"); 00193 00194 return true; 00195 } 00196 00197 if ((pRequest->m_sObjectId.isEmpty()) && 00198 (!pRequest->m_sContainerID.isEmpty())) 00199 pRequest->m_sObjectId = pRequest->m_sContainerID; 00200 00201 LOG(VB_UPNP, LOG_INFO, 00202 "UPnpCDSMusic::IsBrowseRequestForUs - Not sure... Calling base class."); 00203 00204 return UPnpCDSExtension::IsBrowseRequestForUs( pRequest ); 00205 } 00206 00208 // 00210 00211 bool UPnpCDSMusic::IsSearchRequestForUs( UPnpCDSRequest *pRequest ) 00212 { 00213 // ---------------------------------------------------------------------- 00214 // See if we need to modify the request for compatibility 00215 // ---------------------------------------------------------------------- 00216 00217 // XBox 360 compatibility code 00218 00219 if (pRequest->m_eClient == CDS_ClientXBox && 00220 pRequest->m_sContainerID == "7") 00221 { 00222 pRequest->m_sObjectId = "Music/1"; 00223 pRequest->m_sSearchCriteria = "object.container.album.musicAlbum"; 00224 pRequest->m_sSearchList.append( pRequest->m_sSearchCriteria ); 00225 00226 LOG(VB_UPNP, LOG_INFO, "UPnpCDSMusic::IsSearchRequestForUs... Yes."); 00227 00228 return true; 00229 } 00230 00231 if (pRequest->m_sContainerID == "4") 00232 { 00233 pRequest->m_sObjectId = "Music"; 00234 pRequest->m_sSearchCriteria = "object.item.audioItem.musicTrack"; 00235 pRequest->m_sSearchList.append( pRequest->m_sSearchCriteria ); 00236 00237 LOG(VB_UPNP, LOG_INFO, "UPnpCDSMusic::IsSearchRequestForUs... Yes."); 00238 00239 return true; 00240 } 00241 00242 if ((pRequest->m_sObjectId.isEmpty()) && 00243 (!pRequest->m_sContainerID.isEmpty())) 00244 pRequest->m_sObjectId = pRequest->m_sContainerID; 00245 00246 LOG(VB_UPNP, LOG_INFO, 00247 "UPnpCDSMusic::IsSearchRequestForUs.. Don't know, calling base class."); 00248 00249 return UPnpCDSExtension::IsSearchRequestForUs( pRequest ); 00250 } 00251 00253 // 00255 00256 void UPnpCDSMusic::AddItem( const UPnpCDSRequest *pRequest, 00257 const QString &sObjectId, 00258 UPnpCDSExtensionResults *pResults, 00259 bool bAddRef, 00260 MSqlQuery &query ) 00261 { 00262 QString sName; 00263 00264 int nId = query.value( 0).toInt(); 00265 QString sArtist = query.value( 1).toString(); 00266 QString sAlbum = query.value( 2).toString(); 00267 QString sTitle = query.value( 3).toString(); 00268 QString sGenre = query.value( 4).toString(); 00269 // int nYear = query.value( 5).toInt(); 00270 int nTrackNum = query.value( 6).toInt(); 00271 QString sDescription = query.value( 7).toString(); 00272 QString sFileName = query.value( 8).toString(); 00273 uint nLength = query.value( 9).toInt(); 00274 00275 #if 0 00276 if ((nNodeIdx == 0) || (nNodeIdx == 1)) 00277 { 00278 sName = QString( "%1-%2:%3" ) 00279 .arg( sArtist) 00280 .arg( sAlbum ) 00281 .arg( sTitle ); 00282 } 00283 else 00284 #endif 00285 sName = sTitle; 00286 00287 00288 // ---------------------------------------------------------------------- 00289 // Cache Host ip Address & Port 00290 // ---------------------------------------------------------------------- 00291 00292 #if 0 00293 if (!m_mapBackendIp.contains( sHostName )) 00294 m_mapBackendIp[ sHostName ] = gCoreContext->GetSettingOnHost( "BackendServerIp", sHostName); 00295 00296 if (!m_mapBackendPort.contains( sHostName )) 00297 m_mapBackendPort[ sHostName ] = gCoreContext->GetSettingOnHost("BackendStatusPort", sHostName); 00298 #endif 00299 00300 QString sServerIp = gCoreContext->GetSetting( "BackendServerIp" ); 00301 QString sPort = gCoreContext->GetSetting( "BackendStatusPort" ); 00302 00303 // ---------------------------------------------------------------------- 00304 // Build Support Strings 00305 // ---------------------------------------------------------------------- 00306 00307 QString sURIBase = QString( "http://%1:%2/Content/" ) 00308 .arg( sServerIp ) 00309 .arg( sPort ); 00310 00311 QString sURIParams = QString( "?Id=%1" ) 00312 .arg( nId ); 00313 00314 00315 QString sId = QString( "Music/1/item%1") 00316 .arg( sURIParams ); 00317 00318 CDSObject *pItem = CDSObject::CreateMusicTrack( sId, 00319 sName, 00320 sObjectId ); 00321 pItem->m_bRestricted = true; 00322 pItem->m_bSearchable = true; 00323 pItem->m_sWriteStatus = "NOT_WRITABLE"; 00324 00325 if ( bAddRef ) 00326 { 00327 QString sRefId = QString( "%1/0/item%2") 00328 .arg( m_sExtensionId ) 00329 .arg( sURIParams ); 00330 00331 pItem->SetPropValue( "refID", sRefId ); 00332 } 00333 00334 pItem->SetPropValue( "genre" , sGenre ); 00335 pItem->SetPropValue( "description" , sTitle ); 00336 pItem->SetPropValue( "longDescription" , sDescription); 00337 00338 pItem->SetPropValue( "artist" , sArtist ); 00339 pItem->SetPropValue( "album" , sAlbum ); 00340 pItem->SetPropValue( "originalTrackNumber" , QString::number(nTrackNum)); 00341 00342 #if 0 00343 pObject->AddProperty( new Property( "publisher" , "dc" )); 00344 pObject->AddProperty( new Property( "language" , "dc" )); 00345 pObject->AddProperty( new Property( "relation" , "dc" )); 00346 pObject->AddProperty( new Property( "rights" , "dc" )); 00347 00348 00349 pObject->AddProperty( new Property( "playlist" , "upnp" )); 00350 pObject->AddProperty( new Property( "storageMedium" , "upnp" )); 00351 pObject->AddProperty( new Property( "contributor" , "dc" )); 00352 pObject->AddProperty( new Property( "date" , "dc" )); 00353 #endif 00354 00355 pResults->Add( pItem ); 00356 00357 // ---------------------------------------------------------------------- 00358 // Add Music Resource Element based on File extension (HTTP) 00359 // ---------------------------------------------------------------------- 00360 00361 QFileInfo fInfo( sFileName ); 00362 00363 QString sMimeType = HTTPRequest::GetMimeType( fInfo.suffix() ); 00364 QString sProtocol = QString( "http-get:*:%1:DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01500000000000000000000000000000" ).arg( sMimeType ); 00365 QString sURI = QString( "%1GetMusic%2").arg( sURIBase ) 00366 .arg( sURIParams ); 00367 00368 Resource *pRes = pItem->AddResource( sProtocol, sURI ); 00369 00370 nLength /= 1000; 00371 00372 QString sDur; 00373 00374 sDur.sprintf("%02d:%02d:%02d", 00375 (nLength / 3600) % 24, 00376 (nLength / 60) % 60, 00377 nLength % 60); 00378 00379 pRes->AddAttribute( "duration" , sDur ); 00380 } 00381 00382 // vim:ts=4:sw=4:ai:et:si:sts=4
1.7.6.1