1 /*
2 * Copyright (C) 2007 OpenedHand Ltd.
3 *
4 * Author: Jorn Baayen <jorn@openedhand.com>
5 *
6 * SPDX-License-Identifier: LGPL-2.1-or-later
7 */
8
9 #include <libgupnp/gupnp-root-device.h>
10 #include <libgupnp/gupnp-service.h>
11 #include <stdlib.h>
12 #include <locale.h>
13 #include <string.h>
14 #include <signal.h>
15
16
17 #ifndef G_OS_WIN32
18 #include <glib-unix.h>
19 #endif
20
21 GMainLoop *main_loop;
22
23 static gboolean
unix_signal_handler(gpointer user_data)24 unix_signal_handler (gpointer user_data)
25 {
26 g_main_loop_quit (main_loop);
27
28 return G_SOURCE_REMOVE;
29 }
30
31
32 #ifdef G_OS_WIN32
33 /*
34 * Since in Windows this is basically called from
35 * the ConsoleCtrlHandler which does not share the restrictions of Unix signals
36 */
37 static void
interrupt_signal_handler(G_GNUC_UNUSED int signum)38 interrupt_signal_handler (G_GNUC_UNUSED int signum)
39 {
40 unix_signal_handler (NULL);
41 }
42
43 #endif
44
45 static void
notify_failed_cb(G_GNUC_UNUSED GUPnPService * service,G_GNUC_UNUSED const GList * callback_urls,const GError * reason,G_GNUC_UNUSED gpointer user_data)46 notify_failed_cb (G_GNUC_UNUSED GUPnPService *service,
47 G_GNUC_UNUSED const GList *callback_urls,
48 const GError *reason,
49 G_GNUC_UNUSED gpointer user_data)
50 {
51 g_print ("NOTIFY failed: %s\n", reason->message);
52 }
53
54 static gboolean
timeout(gpointer user_data)55 timeout (gpointer user_data)
56 {
57 gupnp_service_notify (GUPNP_SERVICE (user_data),
58 "SystemUpdateID",
59 G_TYPE_UINT,
60 27182818,
61 NULL);
62
63 return FALSE;
64 }
65
66 int
main(int argc,char ** argv)67 main (int argc, char **argv)
68 {
69 GError *error;
70 GUPnPContext *context;
71 GUPnPRootDevice *dev;
72 GUPnPServiceInfo *content_dir;
73
74 if (argc < 2) {
75 g_printerr ("Usage: %s DESCRIPTION_FILE\n", argv[0]);
76
77 return EXIT_FAILURE;
78 }
79
80 setlocale (LC_ALL, "");
81
82 error = NULL;
83 context = g_initable_new (GUPNP_TYPE_CONTEXT, NULL, &error, NULL);
84 if (error) {
85 g_printerr ("Error creating the GUPnP context: %s\n",
86 error->message);
87 g_error_free (error);
88
89 return EXIT_FAILURE;
90 }
91
92 g_print ("Running on port %d\n", gupnp_context_get_port (context));
93
94 /* Create root device */
95 dev = gupnp_root_device_new (context, "description.xml", ".", &error);
96 if (error != NULL) {
97 g_printerr ("Error creating the GUPnP root device: %s\n",
98 error->message);
99 g_error_free (error);
100
101 return EXIT_FAILURE;
102 }
103
104 /* Implement Browse action on ContentDirectory if available */
105 content_dir = gupnp_device_info_get_service
106 (GUPNP_DEVICE_INFO (dev),
107 "urn:schemas-upnp-org:service:ContentDirectory:1");
108
109 if (content_dir) {
110 gupnp_service_signals_autoconnect (GUPNP_SERVICE (content_dir),
111 NULL,
112 &error);
113 if (error) {
114 g_warning ("Failed to autoconnect signals: %s",
115 error->message);
116
117 g_error_free (error);
118 error = NULL;
119 }
120
121 g_signal_connect (content_dir,
122 "notify-failed",
123 G_CALLBACK (notify_failed_cb),
124 NULL);
125
126 g_timeout_add (5000, timeout, content_dir);
127 }
128
129 /* Run */
130 gupnp_root_device_set_available (dev, TRUE);
131
132 main_loop = g_main_loop_new (NULL, FALSE);
133
134 /* Hook the handler for SIGINT */
135 #ifndef G_OS_WIN32
136 g_unix_signal_add (SIGINT, unix_signal_handler, NULL);
137 #else
138 signal(SIGINT, interrupt_signal_handler);
139 #endif /* G_OS_WIN32 */
140
141 g_main_loop_run (main_loop);
142 g_main_loop_unref (main_loop);
143
144 if (content_dir)
145 g_object_unref (content_dir);
146
147 g_object_unref (dev);
148 g_object_unref (context);
149
150 return EXIT_SUCCESS;
151 }
152