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