summaryrefslogtreecommitdiff
path: root/examples/light-server.c
blob: 88b3e27bffdf0f3b17350336b186ab164d81d781 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
/*
 * Example UPnP device/service, implementing the BinaryLight device and
 * SwitchPower services to emulate a light switch.
 *
 * The user interface is as minimal as possible so that the GUPnP concepts and
 * best practises are more apparent.  For a better implementation of
 * BinaryLight, see gupnp-tools.
 *
 * This example code is in the public domain.
 */

#include <libgupnp/gupnp.h>
#include <stdlib.h>
#include <gmodule.h>

static gboolean status;
static gboolean quiet;

static GOptionEntry entries[] =
{
  { "quiet", 'q', 0, G_OPTION_ARG_NONE, &quiet, "Turn off output", NULL },
  { NULL }
};

G_BEGIN_DECLS
G_MODULE_EXPORT void set_target_cb (GUPnPService *service,
                                    GUPnPServiceAction *action,
                                    gpointer user_data);
G_MODULE_EXPORT void get_target_cb (GUPnPService *service,
                                    GUPnPServiceAction *action,
                                    gpointer user_data);
G_MODULE_EXPORT void get_status_cb (GUPnPService *service,
                                    GUPnPServiceAction *action,
                                    gpointer user_data);
G_MODULE_EXPORT void query_target_cb (GUPnPService *service, char *variable,
                                      GValue *value, gpointer user_data);
G_MODULE_EXPORT void query_status_cb (GUPnPService *service, char *variable,
                                      GValue *value, gpointer user_data);
G_END_DECLS
/*
 * Action handlers
 */

/* SetTarget */
G_MODULE_EXPORT void
set_target_cb (GUPnPService          *service,
               GUPnPServiceAction    *action,
               G_GNUC_UNUSED gpointer user_data)
{
  gboolean target;

  /* Get the new target value */
  gupnp_service_action_get (action,
                            "newTargetValue", G_TYPE_BOOLEAN, &target,
                            NULL);

  /* If the new target doesn't match the current status, change the status and
     emit a notification that the status has changed. */
  if (target != status) {
    status = target;
    gupnp_service_notify (service,
                          "Status", G_TYPE_BOOLEAN, status,
                          NULL);

    if (!quiet)
    {
      g_print ("The light is now %s.\n", status ? "on" : "off");
    }
  }

  /* Return success to the client */
  gupnp_service_action_return_success (action);
}

/* GetTarget */
G_MODULE_EXPORT void
get_target_cb (G_GNUC_UNUSED GUPnPService *service,
               GUPnPServiceAction         *action,
               G_GNUC_UNUSED gpointer      user_data)
{
  gupnp_service_action_set (action,
                            "RetTargetValue", G_TYPE_BOOLEAN, status,
                            NULL);
  gupnp_service_action_return_success (action);
}

/* GetStatus */
G_MODULE_EXPORT void
get_status_cb (G_GNUC_UNUSED GUPnPService *service,
               GUPnPServiceAction         *action,
               G_GNUC_UNUSED gpointer      user_data)
{
  gupnp_service_action_set (action,
                            "ResultStatus", G_TYPE_BOOLEAN, status,
                            NULL);
  gupnp_service_action_return_success (action);
}

/*
 * State Variable query handlers
 */

/* Target */
G_MODULE_EXPORT void
query_target_cb (G_GNUC_UNUSED GUPnPService *service,
                 G_GNUC_UNUSED char         *variable,
                 GValue                     *value,
                 G_GNUC_UNUSED gpointer      user_data)
{
  g_value_init (value, G_TYPE_BOOLEAN);
  g_value_set_boolean (value, status);
}

/* Status */
G_MODULE_EXPORT void
query_status_cb (G_GNUC_UNUSED GUPnPService *service,
                 G_GNUC_UNUSED char         *variable,
                 GValue                     *value,
                 G_GNUC_UNUSED gpointer      user_data)
{
  g_value_init (value, G_TYPE_BOOLEAN);
  g_value_set_boolean (value, status);
}


int
main (G_GNUC_UNUSED int argc, G_GNUC_UNUSED char **argv)
{
  GOptionContext *optionContext;
  GMainLoop *main_loop;
  GError *error = NULL;
  GUPnPContext *context;
  GUPnPRootDevice *dev;
  GUPnPServiceInfo *service;
  
  optionContext = g_option_context_new (NULL);
  g_option_context_add_main_entries (optionContext, entries, NULL);
  if (!g_option_context_parse (optionContext, &argc, &argv, &error))
  {
    g_print ("option parsing failed: %s\n", error->message);
    exit (1);
  }

  /* By default the light is off */
  status = FALSE;
  if (!quiet)
  {
    g_print ("The light is now %s.\n", status ? "on" : "off");
  }

  /* Create the UPnP context */
  context = gupnp_context_new_for_address (NULL, 0, GSSDP_UDA_VERSION_1_0, &error);
  if (error) {
    g_printerr ("Error creating the GUPnP context: %s\n",
		error->message);
    g_error_free (error);

    return EXIT_FAILURE;
  }

  /* Create root device */
  dev = gupnp_root_device_new (context, "BinaryLight1.xml", ".", &error);
  if (error != NULL) {
    g_printerr ("Error creating the GUPnP root device: %s\n",
                error->message);

    g_error_free (error);

    return EXIT_FAILURE;
  }
  gupnp_root_device_set_available (dev, TRUE);

  /* Get the switch service from the root device */
  service = gupnp_device_info_get_service
    (GUPNP_DEVICE_INFO (dev), "urn:schemas-upnp-org:service:SwitchPower:1");
  if (!service) {
    g_printerr ("Cannot get SwitchPower1 service\n");

    return EXIT_FAILURE;
  }
  

  /* Autoconnect the action and state variable handlers.  This connects
     query_target_cb and query_status_cb to the Target and Status state
     variables query callbacks, and set_target_cb, get_target_cb and
     get_status_cb to SetTarget, GetTarget and GetStatus actions
     respectively. */
  gupnp_service_signals_autoconnect (GUPNP_SERVICE (service), NULL, &error);
  if (error) {
    g_printerr ("Failed to autoconnect signals: %s\n", error->message);
    g_error_free (error);

    return EXIT_FAILURE;
  }
  
  /* Run the main loop */
  main_loop = g_main_loop_new (NULL, FALSE);
  g_main_loop_run (main_loop);

  /* Cleanup */
  g_main_loop_unref (main_loop);
  g_object_unref (service);
  g_object_unref (dev);
  g_object_unref (context);
  
  return EXIT_SUCCESS;
}