00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include <stdlib.h>
00032
00033 #include <cybergarage/upnp/media/player/MediaPlayer.h>
00034
00035 #undef PACKAGE_NAME
00036 #include <vlc/vlc.h>
00037 #include <vlc/intf.h>
00038
00039
00040
00041
00042
00043
00044
00045 using namespace std;
00046 using namespace CyberLink;
00047
00048
00049
00050
00051
00052
00053 static int Open ( vlc_object_t * );
00054 static void Close( vlc_object_t * );
00055
00056 vlc_module_begin();
00057 set_shortname( _("UPnP"));
00058 set_description( _("Universal Plug'n'Play discovery") );
00059 set_category( CAT_PLAYLIST );
00060 set_subcategory( SUBCAT_PLAYLIST_SD );
00061
00062 set_capability( "services_discovery", 0 );
00063 set_callbacks( Open, Close );
00064
00065 vlc_module_end();
00066
00067
00068
00069
00070
00071
00072 struct services_discovery_sys_t
00073 {
00074
00075 playlist_item_t *p_node;
00076 playlist_t *p_playlist;
00077 };
00078
00079
00080
00081
00082
00083
00084 static void Run ( services_discovery_t *p_sd );
00085
00086
00087
00088
00089 static int Open( vlc_object_t *p_this )
00090 {
00091 services_discovery_t *p_sd = ( services_discovery_t* )p_this;
00092 services_discovery_sys_t *p_sys = (services_discovery_sys_t *)
00093 malloc( sizeof( services_discovery_sys_t ) );
00094
00095 playlist_view_t *p_view;
00096 vlc_value_t val;
00097
00098 p_sd->pf_run = Run;
00099 p_sd->p_sys = p_sys;
00100
00101
00102 p_sys->p_playlist = (playlist_t *)vlc_object_find( p_sd,
00103 VLC_OBJECT_PLAYLIST,
00104 FIND_ANYWHERE );
00105 if( !p_sys->p_playlist )
00106 {
00107 msg_Warn( p_sd, "unable to find playlist, cancelling UPnP listening");
00108 return VLC_EGENERIC;
00109 }
00110
00111 p_view = playlist_ViewFind( p_sys->p_playlist, VIEW_CATEGORY );
00112 p_sys->p_node = playlist_NodeCreate( p_sys->p_playlist, VIEW_CATEGORY,
00113 _("UPnP"), p_view->p_root );
00114 p_sys->p_node->i_flags |= PLAYLIST_RO_FLAG;
00115 p_sys->p_node->i_flags &= ~PLAYLIST_SKIP_FLAG;
00116 val.b_bool = VLC_TRUE;
00117 var_Set( p_sys->p_playlist, "intf-change", val );
00118
00119 return VLC_SUCCESS;
00120 }
00121
00122
00123
00124
00125
00126 static void Close( vlc_object_t *p_this )
00127 {
00128 services_discovery_t *p_sd = ( services_discovery_t* )p_this;
00129 services_discovery_sys_t *p_sys = p_sd->p_sys;
00130
00131 if( p_sys->p_playlist )
00132 {
00133 playlist_NodeDelete( p_sys->p_playlist, p_sys->p_node, VLC_TRUE,
00134 VLC_TRUE );
00135 vlc_object_release( p_sys->p_playlist );
00136 }
00137
00138 free( p_sys );
00139 }
00140
00141
00142
00143
00144
00145
00146 class UPnPHandler : public MediaPlayer, public DeviceChangeListener,
00147 public SearchResponseListener
00148 {
00149 private:
00150 services_discovery_t *p_sd;
00151 services_discovery_sys_t *p_sys;
00152
00153 Device *GetDeviceFromUSN( const string& usn )
00154 {
00155 return getDevice( usn.substr( 0, usn.find( "::" ) ).c_str() );
00156 }
00157
00158 playlist_item_t *FindDeviceNode( Device *dev )
00159 {
00160 return playlist_ChildSearchName( p_sys->p_node, dev->getFriendlyName() );
00161 }
00162
00163 playlist_item_t *FindDeviceNode( const string &usn )
00164 {
00165 return FindDeviceNode( GetDeviceFromUSN( usn ) );
00166 }
00167
00168 playlist_item_t *AddDevice( Device *dev );
00169 void AddDeviceContent( Device *dev );
00170 void AddContent( playlist_item_t *p_parent, ContentNode *node );
00171 void RemoveDevice( Device *dev );
00172
00173
00174 virtual void deviceAdded( Device *dev );
00175 virtual void deviceRemoved( Device *dev );
00176
00177 virtual void deviceSearchResponseReceived( SSDPPacket *packet );
00178
00179
00180
00181
00182 public:
00183 UPnPHandler( services_discovery_t *p_this )
00184 : p_sd( p_this ), p_sys( p_this->p_sys )
00185 {
00186 addDeviceChangeListener( this );
00187 addSearchResponseListener( this );
00188
00189 }
00190
00191 };
00192
00193 static void Run( services_discovery_t *p_sd )
00194 {
00195 UPnPHandler u( p_sd );
00196
00197 u.start();
00198
00199 msg_Dbg( p_sd, "UPnP discovery started" );
00200
00201 while( !p_sd->b_die )
00202 {
00203 msleep( 500 );
00204 }
00205
00206 u.stop();
00207 msg_Dbg( p_sd, "UPnP discovery stopped" );
00208 }
00209
00210
00211 playlist_item_t *UPnPHandler::AddDevice( Device *dev )
00212 {
00213 if( dev == NULL )
00214 return NULL;
00215
00216
00217 if ( !dev->isDeviceType( MediaServer::DEVICE_TYPE ) )
00218 return NULL;
00219
00220 playlist_item_t *p_item = FindDeviceNode( dev );
00221 if ( p_item != NULL )
00222 return p_item;
00223
00224
00225
00226
00227
00228 char *str = strdup( dev->getFriendlyName( ) );
00229
00230 p_item = playlist_NodeCreate( p_sys->p_playlist, VIEW_CATEGORY,
00231 str, p_sys->p_node );
00232 p_item->i_flags &= ~PLAYLIST_SKIP_FLAG;
00233 msg_Dbg( p_sd, "device %s added", str );
00234 free( str );
00235
00236 return p_item;
00237 }
00238
00239 void UPnPHandler::AddDeviceContent( Device *dev )
00240 {
00241 playlist_item_t *p_devnode = AddDevice( dev );
00242
00243 if( p_devnode == NULL )
00244 return;
00245
00246 AddContent( p_devnode, getContentDirectory( dev ) );
00247 }
00248
00249 void UPnPHandler::AddContent( playlist_item_t *p_parent, ContentNode *node )
00250 {
00251 if( node == NULL )
00252 return;
00253
00254 const char *title = node->getTitle();
00255 if( title == NULL )
00256 return;
00257
00258 msg_Dbg( p_sd, "title = %s", title );
00259
00260 if ( node->isItemNode() )
00261 {
00262 ItemNode *iNode = (ItemNode *)node;
00263
00264 playlist_item_t *p_item;
00265 p_item = playlist_ItemNew( p_sd, iNode->getResource(), title );
00266
00267 playlist_NodeAddItem( p_sys->p_playlist, p_item, VIEW_CATEGORY,
00268 p_parent, PLAYLIST_APPEND, PLAYLIST_END );
00269
00270 } else if ( node->isContainerNode() )
00271 {
00272 ContainerNode *conNode = (ContainerNode *)node;
00273
00274 char* p_name = strdup(title);
00275 playlist_item_t* p_node = playlist_NodeCreate( p_sys->p_playlist, VIEW_CATEGORY,
00276 p_name, p_parent );
00277 free(p_name);
00278
00279 unsigned nContentNodes = conNode->getNContentNodes();
00280
00281 for( unsigned n = 0; n < nContentNodes; n++ )
00282 AddContent( p_node, conNode->getContentNode( n ) );
00283 }
00284 }
00285
00286
00287 void UPnPHandler::RemoveDevice( Device *dev )
00288 {
00289 playlist_item_t *p_item = FindDeviceNode( dev );
00290
00291 if( p_item != NULL )
00292 playlist_NodeDelete( p_sys->p_playlist, p_item, VLC_TRUE, VLC_TRUE );
00293 }
00294
00295
00296 void UPnPHandler::deviceAdded( Device *dev )
00297 {
00298 msg_Dbg( p_sd, "adding device" );
00299 AddDeviceContent( dev );
00300 }
00301
00302
00303 void UPnPHandler::deviceRemoved( Device *dev )
00304 {
00305 msg_Dbg( p_sd, "removing device" );
00306 RemoveDevice( dev );
00307 }
00308
00309
00310 void UPnPHandler::deviceSearchResponseReceived( SSDPPacket *packet )
00311 {
00312 if( !packet->isRootDevice() )
00313 return;
00314
00315 string usn, nts, nt, udn;
00316
00317 packet->getUSN( usn );
00318 packet->getNT( nt );
00319 packet->getNTS( nts );
00320 udn = usn.substr( 0, usn.find( "::" ) );
00321
00322
00323
00324 Device *dev = GetDeviceFromUSN( usn );
00325 RemoveDevice( dev );
00326
00327 if( !packet->isByeBye() )
00328 AddDeviceContent( dev );
00329 }
00330
00331
00332
00333
00334
00335
00336