diff -r 9bab67afb6c2 -r 7afeec40ed62 gmyth-upnp/src/gmyth_upnp.c --- a/gmyth-upnp/src/gmyth_upnp.c Wed Jan 10 23:23:54 2007 +0000 +++ b/gmyth-upnp/src/gmyth_upnp.c Tue May 22 19:14:37 2007 +0100 @@ -32,6 +32,7 @@ #endif #include "gmyth_upnp.h" +#include "gmyth_upnp_marshal.h" #include #include @@ -45,48 +46,83 @@ #include #include +/* Maximum number of searches in the synchronized search */ #define GMYTH_UPNP_MAX_SEARCHS 10 +#define GMYTH_UPNP_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GMYTH_UPNP_TYPE, GMythUPnPPrivate)) + +struct _GMythUPnPPrivate { + GHashTable *mythtv_servers; + GMythUPnPDeviceStatus last_status; + gboolean upnp_dev_found; + gchar *udn; + GMutex *mutex; +}; + static void gmyth_upnp_class_init (GMythUPnPClass *klass); static void gmyth_upnp_init (GMythUPnP *object); static void gmyth_upnp_dispose (GObject *object); static void gmyth_upnp_finalize (GObject *object); -static gboolean gmyth_upnp_initialize ( GMythUPnP *gmyth_upnp, GMythBackendInfo *gmyth_backend_info ); +static void _mythtv_device_found ( GMythUPnPDeviceStatus status, gchar *dev ); +static void _clinkc_mythtv_device_found ( gchar *udn, GMythUPnPDeviceStatus status ); -static gboolean gmyth_upnp_print_cp_device_list( CgUpnpControlPoint* controlPt, gchar **udn, - GList **mythtv_servers_lst ); +static gboolean gmyth_upnp_initialize ( GMythUPnP *gmyth_upnp, GMythBackendInfo *gmyth_backend_info, + GMythUPnPDeviceListener listener); + +static gboolean gmyth_upnp_got_mythtv_service( CgUpnpControlPoint* controlPt, gchar **udn, + GHashTable **mythtv_servers_lst ); G_DEFINE_TYPE(GMythUPnP, gmyth_upnp, G_TYPE_OBJECT) -static GStaticMutex mutex = G_STATIC_MUTEX_INIT; +static GMythUPnP *gmyth_upnp_static = NULL; static void gmyth_upnp_class_init (GMythUPnPClass *klass) { GObjectClass *gobject_class; + GMythUPnPClass *gupnp_class; gobject_class = (GObjectClass *) klass; + gupnp_class = (GMythUPnPClass*) gobject_class; gobject_class->dispose = gmyth_upnp_dispose; - gobject_class->finalize = gmyth_upnp_finalize; + gobject_class->finalize = gmyth_upnp_finalize; + + g_type_class_add_private( gobject_class, sizeof( GMythUPnPPrivate ) ); + + gupnp_class->device_found_handler = _mythtv_device_found; + + gupnp_class->device_found_handler_signal_id = + g_signal_new ("device-found", + G_TYPE_FROM_CLASS (gupnp_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | + G_SIGNAL_NO_HOOKS, 0, NULL, NULL, + gmyth_upnp_marshal_VOID__INT_STRING, G_TYPE_NONE, 2, + G_TYPE_INT, G_TYPE_STRING); + } static void gmyth_upnp_init ( GMythUPnP *gmyth_upnp ) { - gmyth_upnp->upnp_dev_found = FALSE; - - gmyth_upnp->uri = NULL; - gmyth_upnp->host = NULL; - gmyth_upnp->port = 0; - gmyth_upnp->protocol = NULL; - - gmyth_upnp->gmyth_backend_info = NULL; - + + gmyth_upnp->backend_info = NULL; + gmyth_upnp->control_point = NULL; - + + gmyth_upnp->priv = GMYTH_UPNP_GET_PRIVATE(gmyth_upnp); + gmyth_upnp->priv->mutex = g_mutex_new (); + gmyth_upnp->priv->upnp_dev_found = FALSE; + + g_signal_connect (G_OBJECT (gmyth_upnp), "device-found", + (GCallback) (GMYTH_UPNP_GET_CLASS (gmyth_upnp)-> + device_found_handler), NULL); + + gmyth_upnp_static = gmyth_upnp; + } /** Creates a new instance of GMythUPnP. @@ -94,14 +130,18 @@ * @return a new instance of GMythUPnP. */ GMythUPnP * -gmyth_upnp_new ( GMythBackendInfo *gmyth_backend_info ) +gmyth_upnp_new ( GMythBackendInfo *gmyth_backend_info, GMythUPnPDeviceListener handler ) { GMythUPnP *gmyth_upnp = GMYTH_UPNP (g_object_new (GMYTH_UPNP_TYPE, NULL)); - gmyth_upnp->gmyth_backend_info = gmyth_backend_info; - - if ( !gmyth_upnp_initialize ( gmyth_upnp, gmyth_backend_info ) ) - return NULL; + g_object_ref( gmyth_backend_info ); + + gmyth_upnp->backend_info = gmyth_backend_info; + + if ( !gmyth_upnp_initialize ( gmyth_upnp, gmyth_backend_info, handler ) ) + { + gmyth_debug( "Error initializing the GMythUPnP!!!" ); + } return gmyth_upnp; } @@ -116,27 +156,17 @@ cg_upnp_controlpoint_delete( gmyth_upnp->control_point ); gmyth_upnp->control_point = NULL; } + + if ( gmyth_upnp->priv->mythtv_servers != NULL ) { + g_hash_table_destroy( gmyth_upnp->priv->mythtv_servers ); + gmyth_upnp->priv->mythtv_servers = NULL; + } - if ( gmyth_upnp->uri != NULL ) { - g_free ( gmyth_upnp->uri ); - gmyth_upnp->uri = NULL; + if ( gmyth_upnp->backend_info != NULL ) { + g_object_unref( gmyth_upnp->backend_info ); + gmyth_upnp->backend_info = NULL; } - - if ( gmyth_upnp->host != NULL ) { - g_free ( gmyth_upnp->host ); - gmyth_upnp->host = NULL; - } - - if ( gmyth_upnp->protocol != NULL ) { - g_free ( gmyth_upnp->protocol ); - gmyth_upnp->protocol = NULL; - } - - if ( gmyth_upnp->mythtv_servers != NULL ) { - g_list_free( gmyth_upnp->mythtv_servers ); - gmyth_upnp->mythtv_servers = NULL; - } - + G_OBJECT_CLASS (gmyth_upnp_parent_class)->dispose (object); } @@ -149,103 +179,139 @@ } /** + * GObject's signal handler + */ +static void +_mythtv_device_found( GMythUPnPDeviceStatus status, gchar* udn ) +{ + g_debug( "status = %d, UDN = %s\n", status, udn ); +} + +/** + * GObject's signal handler + */ +static void +_clinkc_mythtv_device_found ( gchar *udn, GMythUPnPDeviceStatus status ) +{ + if ( gmyth_upnp_static != NULL ) + g_signal_emit ( gmyth_upnp_static, + GMYTH_UPNP_GET_CLASS (gmyth_upnp_static)->device_found_handler_signal_id, 0, /* details */ + status, udn ); +} + +/** * Create a control point and start it. */ static gboolean -gmyth_upnp_initialize ( GMythUPnP *gmyth_upnp, GMythBackendInfo *gmyth_backend_info ) +gmyth_upnp_initialize ( GMythUPnP *gmyth_upnp, GMythBackendInfo *gmyth_backend_info, + GMythUPnPDeviceListener device_found_handler ) { - - gboolean ret = FALSE; - - GMythURI* uri = NULL; - - guint iter_count = GMYTH_UPNP_MAX_SEARCHS; - + gboolean ret = TRUE; + g_return_val_if_fail( gmyth_backend_info != NULL, FALSE ); - + /* Create the cybergarage control point */ gmyth_upnp->control_point = cg_upnp_controlpoint_new(); - /* cg_upnp_controlpoint_setdevicelistener( gmyth_upnp->control_point, device_listener ); */ - + + if ( device_found_handler != NULL ) + { + GMYTH_UPNP_GET_CLASS(gmyth_upnp)->device_found_handler = device_found_handler; + + cg_upnp_controlpoint_setdevicelistener( gmyth_upnp->control_point, _clinkc_mythtv_device_found ); + } + /* Start the control point */ - if ( cg_upnp_controlpoint_start( gmyth_upnp->control_point ) == FALSE) + if ( cg_upnp_controlpoint_start( gmyth_upnp->control_point ) == FALSE) { - gmyth_debug( "Unable to start UPnP control point!!!" ); - goto done; - } + gmyth_debug( "Unable to start UPnP control point!!!" ); + ret = FALSE; + goto done; + } else { - gmyth_debug( "Control point started." ); + gmyth_debug( "Control point started." ); } - - while ( gmyth_upnp->upnp_dev_found == FALSE && ( --iter_count > 0 ) ) { - + +done: + + return ret; +} + +static void +_gmyth_foreach_key_value( gchar *udn, gchar *dev, GList *upnp_servers_list ) +{ + GMythUPnPDevice *gmyth_upnp = g_malloc0( sizeof( GMythUPnPDevice ) ); + + GMythURI* uri = NULL; + gmyth_upnp->uri = (gchar*) (dev); + uri = gmyth_uri_new_with_value( gmyth_upnp->uri ); + + gmyth_upnp->host = gmyth_uri_get_host( uri ); + gmyth_upnp->port = gmyth_uri_get_port( uri ); + gmyth_upnp->protocol = gmyth_uri_get_protocol( uri ); + + upnp_servers_list = g_list_append( upnp_servers_list, gmyth_upnp ); + + if ( uri != NULL ) + { + g_object_unref( uri ); + uri = NULL; + } + +} + +GList * +gmyth_upnp_do_search_sync( GMythUPnP* gmyth_upnp ) +{ + GList *upnp_servers_list = NULL; + guint iter_count = GMYTH_UPNP_MAX_SEARCHS; + /* gmyth_upnp->priv = GMYTH_UPNP_GET_PRIVATE( gmyth_upnp ); */ + + while ( gmyth_upnp->priv->upnp_dev_found == FALSE && ( --iter_count > 0 ) ) { + gmyth_debug( "UPnP MythTV Client control point is searching MythTV AV Device server...\n" ); - + if ( gmyth_upnp->control_point != NULL ) cg_upnp_controlpoint_search ( gmyth_upnp->control_point, - "urn:schemas-upnp-org:service:ContentDirectory:1" ); + "urn:schemas-upnp-org:service:ContentDirectory:1" ); /* just to avoid clinkc pthread concurrency faults */ cg_wait( 1000 ); - + /* discover if it was found */ - gmyth_upnp->upnp_dev_found = gmyth_upnp_print_cp_device_list( gmyth_upnp->control_point, &gmyth_upnp->udn, - &gmyth_upnp->mythtv_servers ); - - } - - if ( gmyth_upnp->upnp_dev_found ) { - + gmyth_upnp->priv->upnp_dev_found = gmyth_upnp_got_mythtv_service( gmyth_upnp->control_point, &gmyth_upnp->priv->udn, + &gmyth_upnp->priv->mythtv_servers ); + + } /* while */ + + if ( gmyth_upnp->priv->upnp_dev_found ) { + gmyth_debug( "Found UPnP MythTV AV Device...\n" ); - - if ( g_list_first( gmyth_upnp->mythtv_servers ) != NULL && (g_list_first( gmyth_upnp->mythtv_servers ))->data != NULL ) - { - gmyth_upnp->uri = (gchar*) (g_list_first( gmyth_upnp->mythtv_servers ))->data; - uri = gmyth_uri_new_with_value( gmyth_upnp->uri ); - - gmyth_upnp->host = gmyth_uri_get_host( uri ); - gmyth_upnp->port = gmyth_uri_get_port( uri ); - gmyth_upnp->protocol = gmyth_uri_get_protocol( uri ); - - /* sets all the discovered data from the UPnP remote device, like host name, IP address, port,... */ - if ( NULL != gmyth_upnp->host ) - gmyth_backend_info_set_hostname ( gmyth_upnp->gmyth_backend_info, gmyth_upnp->host ); - - if ( gmyth_upnp->port > 0 ) - gmyth_backend_info_set_port ( gmyth_upnp->gmyth_backend_info, gmyth_upnp->port ); - - ret = TRUE; - } - } -done: + g_hash_table_foreach( gmyth_upnp->priv->mythtv_servers, (GHFunc)_gmyth_foreach_key_value, upnp_servers_list ); - if ( uri != NULL ) - { - g_object_unref( uri ); - uri = NULL; - } + } /* if - found UPnP device */ - return ret; - + return upnp_servers_list; } /** - * Prints the Control Point's device list + * Checks if got the MythTV service in the Control Point's device list. */ static gboolean -gmyth_upnp_print_cp_device_list( CgUpnpControlPoint* controlPt, gchar **udn, GList **mythtv_servers_lst ) +gmyth_upnp_got_mythtv_service( CgUpnpControlPoint* controlPt, gchar **udn, + GHashTable **mythtv_servers_lst ) { g_return_val_if_fail( mythtv_servers_lst != NULL, FALSE ); g_return_val_if_fail( controlPt != NULL, FALSE ); + + *mythtv_servers_lst = g_hash_table_new( g_str_hash, g_str_equal ); gchar* mythtvFriendlyName = "Myth"; /* begin assertion about the size of discovered devices */ gint numDevices = cg_upnp_controlpoint_getndevices(controlPt); gint cntDevs = 0; - //CgUpnpDeviceList *devList = NULL; CgUpnpDevice *childDev; gchar *devName = NULL, *dev_url = NULL; gboolean upnp_dev_found = FALSE; @@ -259,8 +325,10 @@ gmyth_debug( "Device's friendly name = %s, and device's URL = %s\n", devName, dev_url ); if ( ( upnp_dev_found = ( g_strstr_len( devName, strlen( devName ), mythtvFriendlyName ) != NULL ) ) == TRUE ) { + /* stores the last UDN number ID */ *udn = cg_upnp_device_getudn( childDev ); - *mythtv_servers_lst = g_list_append( *mythtv_servers_lst, dev_url ); + /* *mythtv_servers_lst = g_list_append( *mythtv_servers_lst, dev_url ); */ + g_hash_table_insert( *mythtv_servers_lst, (gpointer)*udn, (gpointer)dev_url ); } ++cntDevs; } @@ -277,57 +345,22 @@ } -/** Gets the GMythBackendInfo host object associated to this upnp. - * - * @return The string host object currently valid or NULL if the settings - * were not opened. - */ -gchar* -gmyth_upnp_get_host ( GMythUPnP *gmyth_upnp ) -{ - - if ( NULL == gmyth_upnp || NULL == gmyth_upnp->host ) - { - gmyth_debug ("[%s] GMythUPnP host field not initialized\n", __FUNCTION__); - return NULL; - } - - return gmyth_upnp->host; -} - -/** Gets the GMythBackendInfo port object associated to this upnp. - * - * @return The string object currently valid or NULL if the port number. - */ -gint -gmyth_upnp_get_port( GMythUPnP *gmyth_upnp ) -{ - - if ( NULL == gmyth_upnp || gmyth_upnp->port <= 0 ) - { - gmyth_debug ("[%s] GMythUPnP host field not initialized\n", __FUNCTION__); - return 0; - } - - return gmyth_upnp->port; -} - /** Gets the UPnP AV devices server's list associated to this upnp. * - * @return The GList* containing all the URI values for each recognized UPnP device, + * @return The GHashTable* containing all the URI values for each recognized UPnP device, * or NULL if it couldn't recognize any MythTV AV device. */ -GList* +GHashTable* gmyth_upnp_get_servers ( GMythUPnP *gmyth_upnp ) { - if ( NULL == gmyth_upnp || NULL == gmyth_upnp->mythtv_servers ) + if ( NULL == gmyth_upnp || NULL == gmyth_upnp->priv->mythtv_servers ) { gmyth_debug ("[%s] GMythUPnP has no MythTV servers recognized.\n", __FUNCTION__); return NULL; } - return gmyth_upnp->mythtv_servers; + return gmyth_upnp->priv->mythtv_servers; } /** Gets the GMythBackendInfo object associated to this upnp. @@ -339,12 +372,12 @@ gmyth_upnp_get_backend_info ( GMythUPnP *gmyth_upnp ) { - if ( NULL == gmyth_upnp || NULL == gmyth_upnp->gmyth_backend_info ) + if ( NULL == gmyth_upnp || NULL == gmyth_upnp->backend_info ) { gmyth_debug ("[%s] GMythUPnP not initialized\n", __FUNCTION__); return NULL; } - return gmyth_upnp->gmyth_backend_info; + return gmyth_upnp->backend_info; }