Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //============================================================================
- // Name : UPnPClient7.cpp
- // Author : Majik
- // Purpose : Play URL stream on specified Renderer
- //============================================================================
- #include <string.h>
- #include <glib-2.0/glib.h>
- #include <libgupnp/gupnp-control-point.h>
- #include <libgupnp-av/gupnp-av.h>
- #define MEDIA_RENDERER "urn:schemas-upnp-org:device:MediaRenderer:1"
- #define AV_TRANSPORT "urn:schemas-upnp-org:service:AVTransport"
- static GMainLoop *main_loop;
- static GHashTable *renderers;
- static GUPnPLastChangeParser *lc_parser;
- char *rendererName;
- bool rendererFound = false;
- char *uri;
- /* This is our callback method to terminate the main loop
- * after the timeout has expired
- */
- static gboolean main_loop_timeout(void *data)
- {
- g_main_loop_quit (main_loop);
- if (!rendererFound) {
- g_print("Renderer %s not found\n", rendererName);
- }
- return 0;
- }
- /*
- * Utility function to play URL on Media Renderer
- */
- static void play_stream(const GUPnPDeviceProxy *renderer, const char *uri) {
- GUPnPServiceProxy *av_transport;
- char *friendly_name;
- GError *error;
- error = NULL;
- char metadata[1000];
- /* Build metadata, this is very hacky but is good to show raw data */
- char *metadata1 =
- "<DIDL-Lite xmlns:dc="http://purl.org/dc/elements/1.1/""
- " xmlns:upnp="urn:schemas-upnp-org:metadata-1-0/upnp/""
- " xmlns:r="urn:schemas-rinconnetworks-com:metadata-1-0/""
- " xmlns="urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/">"
- "<item id="-1" parentID="-1" restricted="true">"
- "<res protocolInfo="http-get:*:audio/mpeg:*" >";
- char *metadata2 = "</res>"
- "<dc:title>UPnPClient7 Test</dc:title>"
- "<upnp:class>object.item.audioItem.musicTrack</upnp:class>"
- "</item>"
- "</DIDL-Lite>";
- /* metadata is metadata1 + uri + metadata2 */
- strcat(metadata, metadata1);
- strcat(metadata, uri);
- strcat(metadata, metadata2);
- g_print("Trying to play stream...\n");
- /* Get AVTransport service for device */
- av_transport = GUPNP_SERVICE_PROXY (gupnp_device_info_get_service(GUPNP_DEVICE_INFO(renderer), AV_TRANSPORT));
- friendly_name = gupnp_device_info_get_friendly_name(GUPNP_DEVICE_INFO(renderer));
- if ( gupnp_service_proxy_send_action (av_transport, "SetAVTransportURI", &error,
- "InstanceID", G_TYPE_UINT, 0,
- "CurrentURI", G_TYPE_STRING, uri,
- "CurrentURIMetaData", G_TYPE_STRING, metadata,
- NULL,NULL) )
- {
- if ( !gupnp_service_proxy_send_action (av_transport, "Play", &error,
- "InstanceID", G_TYPE_UINT, 0,
- "Speed", G_TYPE_UINT, 1,
- NULL,NULL) )
- {
- g_warning("Could not start Renderer playing due to error: '%s'",error->message);
- }
- } else {
- g_warning("Could not set Transport URI due to error: '%s'",error->message);
- }
- }
- /* This is our callback method to handle new devices
- * which have been discovered.
- */
- static void device_proxy_available_cb(GUPnPControlPoint *cp,
- GUPnPDeviceProxy *renderer)
- {
- /* Add device to list of current devices */
- g_hash_table_insert(renderers,
- const_cast<char*>(gupnp_device_info_get_udn(GUPNP_DEVICE_INFO(renderer))),
- renderer);
- if ( strncmp( rendererName, gupnp_device_info_get_friendly_name(GUPNP_DEVICE_INFO(renderer)), strlen(rendererName) ) == 0 ) {
- rendererFound = true;
- // Do something here
- g_print("Renderer %s found\n", rendererName);
- play_stream( renderer, uri);
- }
- }
- /* This is our callback method to handle devices
- * which are removed from the network
- */
- static void device_proxy_unavailable_cb(GUPnPControlPoint *cp,
- GUPnPDeviceProxy *renderer)
- {
- /* Remove device from list of current devices */
- g_hash_table_remove(renderers,
- const_cast<char*>(gupnp_device_info_get_udn(GUPNP_DEVICE_INFO(renderer))));
- }
- /*
- * This is the main program
- */
- int main (int argc, char **argv)
- {
- int run_time = 2;
- GUPnPContext *context;
- GUPnPControlPoint *cp;
- /* Check parameters - very basic check */
- if ( argc != 3 )
- {
- g_warning("Wrong number of parameters\nUsage: UPnPClient7 <renderer Name> <uri>");
- return 0;
- }
- rendererName = argv[1];
- uri= argv[2];
- /* Required initialisation */
- g_thread_init (NULL);
- g_type_init ();
- /* Create a new GHashTable to store the discovered devices in */
- renderers = g_hash_table_new(g_str_hash, g_str_equal);
- /* Create a new parser to help with decoding the AV XML data */
- lc_parser = gupnp_last_change_parser_new();
- /* Create a new GUPnP Context. By here we are using the default GLib main
- context, and connecting to the current machine's default IP on an
- automatically generated port. */
- context = gupnp_context_new (NULL, NULL, 0, NULL);
- /* Create a Control Point targeting UPnP AV MediaRenderer devices */
- cp = gupnp_control_point_new(context, MEDIA_RENDERER);
- /* The device-proxy-available signal is emitted when any devices which match
- our target are found, so connect to it */
- g_signal_connect (cp,
- "device-proxy-available",
- G_CALLBACK (device_proxy_available_cb),
- NULL);
- /* The device-proxy-unavailable signal is emitted when any devices which match
- our target are removed, so connect to it */
- g_signal_connect (cp,
- "device-proxy-unavailable",
- G_CALLBACK (device_proxy_unavailable_cb),
- NULL);
- /* Tell the Control Point to start searching */
- gssdp_resource_browser_set_active (GSSDP_RESOURCE_BROWSER (cp), TRUE);
- /* Set a timeout to finish processing */
- if (run_time >0) {
- g_timeout_add_seconds (run_time,main_loop_timeout, NULL);
- }
- /* Enter the main loop. This will start the search and result in callbacks to
- device_proxy_available_cb. */
- main_loop = g_main_loop_new (NULL, FALSE);
- g_main_loop_run (main_loop);
- /* Clean up */
- g_main_loop_unref (main_loop);
- g_object_unref (cp);
- g_object_unref (context);
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement