document.write('
Data hosted with ♥ by Pastebin.com - Download Raw - See Original
  1. //============================================================================
  2. // Name        : UPnPClient6.cpp
  3. // Author      : Majik
  4. // Purpose     : Monitor transport state of zoneplayers
  5. //============================================================================
  6.  
  7. #include <string.h>
  8. #include <glib-2.0/glib.h>
  9. #include <libgupnp/gupnp-control-point.h>
  10. #include <libgupnp-av/gupnp-av.h>
  11.  
  12. #define MEDIA_RENDERER "urn:schemas-upnp-org:device:MediaRenderer:1"
  13. #define AV_TRANSPORT "urn:schemas-upnp-org:service:AVTransport"
  14.  
  15. static GMainLoop *main_loop;
  16. static GHashTable *renderers;
  17. static GUPnPLastChangeParser *lc_parser;
  18.  
  19. /* Callback method to terminate the main loop
  20.  * after the timeout has expired
  21.  */
  22. static gboolean main_loop_timeout(void *data)
  23. {
  24.         g_main_loop_quit (main_loop);
  25.         return 0;
  26. }
  27.  
  28. /* Callback method to print out key details about
  29.  * the current track. This comes as a "DIDL" object
  30.  */
  31. static void on_didl_object_available (GUPnPDIDLLiteParser *parser,
  32.                 GUPnPDIDLLiteObject *object,
  33.                 gpointer             renderer)
  34. {
  35.         SoupURI *aa_uri;
  36.         SoupURI        *url_base;
  37.  
  38.         /* Get the URL base of the renderer */
  39.         url_base = (SoupURI *) gupnp_device_info_get_url_base(GUPNP_DEVICE_INFO((GUPnPDeviceProxy *)renderer));
  40.         aa_uri = soup_uri_new_with_base(url_base, gupnp_didl_lite_object_get_album_art(object));
  41.         g_print("  Artist: %s\\n", gupnp_didl_lite_object_get_creator(object));
  42.         g_print("  Title: %s\\n", gupnp_didl_lite_object_get_title(object));
  43.         g_print("  Album: %s\\n", gupnp_didl_lite_object_get_album(object));
  44.         g_print("  Album Art: %s\\n", soup_uri_to_string (aa_uri, FALSE));
  45. }
  46.  
  47. /* Callback method to process av transport "last change" events */
  48. static void on_last_change (GUPnPServiceProxy *av_transport,
  49.                                     const char        *variable_name,
  50.                                     GValue            *value,
  51.                                     gpointer           user_data)
  52. {
  53.         const char *last_change_xml;
  54.         char       *state_name;
  55.         char       *metadata;
  56.         GError     *lc_error;
  57.         GError     *error;
  58.         const char *udn;
  59.         SoupURI        *url_base;
  60.         static GUPnPDeviceProxy* renderer;
  61.         GUPnPDIDLLiteParser *parser;
  62.  
  63.         last_change_xml = g_value_get_string (value);
  64.         parser = gupnp_didl_lite_parser_new ();
  65.         lc_error = NULL;
  66.         error = NULL;
  67.         state_name = NULL;
  68.         metadata = NULL;
  69.  
  70.         if (gupnp_last_change_parser_parse_last_change(lc_parser, 0, last_change_xml, &lc_error,
  71.                                                            "TransportState", G_TYPE_STRING, &state_name,
  72.                                                        "CurrentTrackMetaData", G_TYPE_STRING, &metadata,
  73.                                                        NULL))
  74.         {
  75.                 /* Look up the UDN in our hashtable to get the renderer */
  76.                 udn = gupnp_service_info_get_udn(GUPNP_SERVICE_INFO (av_transport));
  77.                 renderer = (GUPnPDeviceProxy*)g_hash_table_lookup(renderers, udn);
  78.  
  79.                 /* Now print the state using the Renderer Friendly Name */
  80.                 if (state_name != NULL) {
  81.                         g_print("Device %s is now in state %s\\n",
  82.                                         gupnp_device_info_get_friendly_name(GUPNP_DEVICE_INFO(renderer)),
  83.                                         state_name);
  84.                         g_free (state_name);
  85.                 }
  86.  
  87.                 /* Get metadata */
  88.                 if (strlen(metadata) > 5) {
  89.                         //g_print(" Metadata:%s\\n",metadata);
  90.                         g_signal_connect (parser, "object-available", G_CALLBACK (on_didl_object_available), (gpointer) renderer);
  91.                         gupnp_didl_lite_parser_parse_didl (parser, metadata, &error);
  92.                         if (error) {
  93.                                 g_warning ("%s\\n", error->message);
  94.                                 g_error_free (error);
  95.                         }
  96.                         g_object_unref (parser);
  97.                         g_free (metadata);
  98.                 }
  99.  
  100.  
  101.         } else if (lc_error) {
  102.                 g_warning ("%s\\n", lc_error->message);
  103.                 g_error_free (lc_error);
  104.         }
  105. }
  106.  
  107.  
  108. /* Callback method to handle newly discovered devices */
  109. static void device_proxy_available_cb(GUPnPControlPoint *cp,
  110.                 GUPnPDeviceProxy *renderer)
  111. {
  112.         GUPnPServiceProxy *av_transport;
  113.  
  114.         /*
  115.          * Add to list of current devices
  116.          */
  117.         g_hash_table_insert(renderers,
  118.                         const_cast<char*>(gupnp_device_info_get_udn(GUPNP_DEVICE_INFO(renderer))),
  119.                         renderer);
  120.         /* Get AVTransport service for device */
  121.         av_transport = GUPNP_SERVICE_PROXY (gupnp_device_info_get_service(GUPNP_DEVICE_INFO(renderer), AV_TRANSPORT));
  122.  
  123.  
  124.         /* Add "LastChange" to the list of states we want to be notified about
  125.          * and turn on event subscription
  126.          */
  127.         gupnp_service_proxy_add_notify (av_transport,
  128.                         "LastChange",
  129.                         G_TYPE_STRING,
  130.                         on_last_change,
  131.                         NULL);
  132.         gupnp_service_proxy_set_subscribed (av_transport, TRUE);
  133. }
  134.  
  135. /* callback method to handle devices removed from the network */
  136. static void device_proxy_unavailable_cb(GUPnPControlPoint *cp,
  137.                 GUPnPDeviceProxy *renderer)
  138. {
  139.         /*
  140.          * Remove from list of current devices
  141.          */
  142.         g_hash_table_remove(renderers,
  143.                         const_cast<char*>(gupnp_device_info_get_udn(GUPNP_DEVICE_INFO(renderer))));
  144. }
  145.  
  146.  
  147. /*
  148.  * Main program
  149.  */
  150. int main (int argc, char **argv)
  151. {
  152.         int run_time = 0;
  153.         GUPnPContext *context;
  154.         GUPnPControlPoint *cp;
  155.  
  156.         if ( argc == 2 ) /* Argument is run time in seconds */
  157.         {
  158.                 run_time = atoi(argv[1]);
  159.         }
  160.  
  161.         /* Required initialisation */
  162.         g_thread_init (NULL);
  163.         g_type_init ();
  164.  
  165.         /* Create a new GHashTable to store the discovered devices */
  166.         renderers = g_hash_table_new(g_str_hash, g_str_equal);
  167.  
  168.         /* Create a new parser to decode the AV XML data */
  169.         lc_parser = gupnp_last_change_parser_new();
  170.  
  171.         /* Create a new GUPnP Context. */
  172.         context = gupnp_context_new (NULL, NULL, 0, NULL);
  173.  
  174.         /* Create a Control Point targeting UPnP AV MediaRenderer devices */
  175.         cp = gupnp_control_point_new(context, MEDIA_RENDERER);
  176.  
  177.         /* The device-proxy-available signal is emitted when any devices which match
  178.          our target are found, so connect to it */
  179.         g_signal_connect (cp,
  180.                         "device-proxy-available",
  181.                         G_CALLBACK (device_proxy_available_cb),
  182.                         NULL);
  183.         /* The device-proxy-unavailable signal is emitted when any devices which match
  184.           our target are removed, so connect to it */
  185.         g_signal_connect (cp,
  186.                         "device-proxy-unavailable",
  187.                         G_CALLBACK (device_proxy_unavailable_cb),
  188.                         NULL);
  189.  
  190.         /* Tell the Control Point to start searching */
  191.         gssdp_resource_browser_set_active (GSSDP_RESOURCE_BROWSER (cp), TRUE);
  192.  
  193.         /* Set a timeout to finish processing */
  194.         if (run_time >0) {
  195.                 g_timeout_add_seconds (run_time,main_loop_timeout, NULL);
  196.         }
  197.  
  198.         /* Enter the main loop. This will start the search and result in callbacks to
  199.          device_proxy_available_cb. */
  200.         main_loop = g_main_loop_new (NULL, FALSE);
  201.         g_main_loop_run (main_loop);
  202.  
  203.         /* Clean up */
  204.         g_main_loop_unref (main_loop);
  205.         g_object_unref (cp);
  206.         g_object_unref (context);
  207.  
  208.         return 0;
  209. }
');