1 /* Aravis - Digital camera library
2 *
3 * Copyright © 2009-2010 Emmanuel Pacaud
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General
16 * Public License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 *
20 * Author: Emmanuel Pacaud <emmanuel@gnome.org>
21 */
22
23 /**
24 * SECTION: arvgvinterface
25 * @short_description: GigEVision interface
26 */
27
28 #include <arpa/inet.h>
29 #include <arvgvinterfaceprivate.h>
30 #include <arvinterfaceprivate.h>
31 #include <arvgvdeviceprivate.h>
32 #include <arvgvcp.h>
33 #include <arvdebug.h>
34 #include <arvmisc.h>
35 #include <arvstr.h>
36 #include <glib/gprintf.h>
37 #include <gio/gio.h>
38 #include <sys/types.h>
39 #include <sys/socket.h>
40 #include <net/if.h>
41 #include <netinet/in.h>
42 #include <netdb.h>
43 #include <ifaddrs.h>
44 #include <stdlib.h>
45 #include <string.h>
46
47 /* ArvGvDiscoverSocket implementation */
48
49 typedef struct {
50 GSocketAddress *interface_address;
51 GSocket *socket;
52 } ArvGvDiscoverSocket;
53
54 static gboolean
arv_gv_discover_socket_set_broadcast(ArvGvDiscoverSocket * discover_socket,gboolean enable)55 arv_gv_discover_socket_set_broadcast (ArvGvDiscoverSocket *discover_socket, gboolean enable)
56 {
57 int socket_fd;
58 int result;
59
60 socket_fd = g_socket_get_fd (discover_socket->socket);
61
62 result = setsockopt (socket_fd, SOL_SOCKET, SO_BROADCAST, (char*)&enable, sizeof (enable));
63
64 return result == 0;
65 }
66
67 typedef struct {
68 unsigned int n_sockets;
69 GSList *sockets;
70 GPollFD *poll_fds;
71 } ArvGvDiscoverSocketList;
72
73 static ArvGvDiscoverSocketList *
arv_gv_discover_socket_list_new(void)74 arv_gv_discover_socket_list_new (void)
75 {
76 ArvGvDiscoverSocketList *socket_list;
77 GSList *iter;
78 struct ifaddrs *ifap = NULL;
79 struct ifaddrs *ifap_iter;
80 int i;
81
82 socket_list = g_new0 (ArvGvDiscoverSocketList, 1);
83
84 if (getifaddrs (&ifap) < 0)
85 return socket_list;
86
87 for (ifap_iter = ifap; ifap_iter != NULL; ifap_iter = ifap_iter->ifa_next) {
88 if ((ifap_iter->ifa_flags & IFF_UP) != 0 &&
89 (ifap_iter->ifa_flags & IFF_POINTOPOINT) == 0 &&
90 (ifap_iter->ifa_addr != NULL) &&
91 (ifap_iter->ifa_addr->sa_family == AF_INET)) {
92 ArvGvDiscoverSocket *discover_socket = g_new0 (ArvGvDiscoverSocket, 1);
93 GSocketAddress *socket_address;
94 GInetAddress *inet_address;
95 char *inet_address_string;
96 GError *error = NULL;
97
98 socket_address = g_socket_address_new_from_native (ifap_iter->ifa_addr,
99 sizeof (struct sockaddr));
100 inet_address = g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (socket_address));
101 inet_address_string = g_inet_address_to_string (inet_address);
102 arv_debug_interface ("[GvDiscoverSocket::new] Add interface %s", inet_address_string);
103 g_free (inet_address_string);
104 discover_socket->interface_address = g_inet_socket_address_new (inet_address, 0);
105 g_object_unref (socket_address);
106
107 discover_socket->socket = g_socket_new (G_SOCKET_FAMILY_IPV4,
108 G_SOCKET_TYPE_DATAGRAM,
109 G_SOCKET_PROTOCOL_UDP, NULL);
110 g_socket_bind (discover_socket->socket, discover_socket->interface_address, FALSE, &error);
111
112 socket_list->sockets = g_slist_prepend (socket_list->sockets, discover_socket);
113 socket_list->n_sockets++;
114 }
115 }
116
117 freeifaddrs (ifap);
118
119 socket_list->poll_fds = g_new (GPollFD, socket_list->n_sockets);
120 for (i = 0, iter = socket_list->sockets; iter != NULL; i++, iter = iter->next) {
121 ArvGvDiscoverSocket *discover_socket = iter->data;
122
123 socket_list->poll_fds[i].fd = g_socket_get_fd (discover_socket->socket);
124 socket_list->poll_fds[i].events = G_IO_IN;
125 socket_list->poll_fds[i].revents = 0;
126 }
127
128 return socket_list;
129 }
130
131 static void
arv_gv_discover_socket_list_free(ArvGvDiscoverSocketList * socket_list)132 arv_gv_discover_socket_list_free (ArvGvDiscoverSocketList *socket_list)
133 {
134 GSList *iter;
135
136 g_return_if_fail (socket_list != NULL);
137
138 for (iter = socket_list->sockets; iter != NULL; iter = iter->next) {
139 ArvGvDiscoverSocket *discover_socket = iter->data;
140
141 g_object_unref (discover_socket->interface_address);
142 g_object_unref (discover_socket->socket);
143 g_free (discover_socket);
144 }
145 g_slist_free (socket_list->sockets);
146 g_free (socket_list->poll_fds);
147
148 socket_list->sockets = NULL;
149 socket_list->n_sockets = 0;
150 socket_list->poll_fds = NULL;
151
152 g_free (socket_list);
153 }
154
155 static void
arv_gv_discover_socket_list_send_discover_packet(ArvGvDiscoverSocketList * socket_list)156 arv_gv_discover_socket_list_send_discover_packet (ArvGvDiscoverSocketList *socket_list)
157 {
158 GInetAddress *broadcast_address;
159 GSocketAddress *broadcast_socket_address;
160 ArvGvcpPacket *packet;
161 GSList *iter;
162 size_t size;
163
164 packet = arv_gvcp_packet_new_discovery_cmd (&size);
165
166 broadcast_address = g_inet_address_new_from_string ("255.255.255.255");
167 broadcast_socket_address = g_inet_socket_address_new (broadcast_address, ARV_GVCP_PORT);
168 g_object_unref (broadcast_address);
169
170 for (iter = socket_list->sockets; iter != NULL; iter = iter->next) {
171 ArvGvDiscoverSocket *discover_socket = iter->data;
172 GError *error = NULL;
173
174 arv_gv_discover_socket_set_broadcast (discover_socket, TRUE);
175 g_socket_send_to (discover_socket->socket,
176 broadcast_socket_address,
177 (const char *) packet, size,
178 NULL, &error);
179 if (error != NULL) {
180 arv_warning_interface ("[ArvGVInterface::send_discover_packet] Error: %s", error->message);
181 g_error_free (error);
182 }
183 arv_gv_discover_socket_set_broadcast (discover_socket, FALSE);
184 }
185
186 g_object_unref (broadcast_socket_address);
187
188 arv_gvcp_packet_free (packet);
189 }
190
191 /* ArvGvInterfaceDeviceInfos implementation */
192
193 typedef struct {
194 char *name;
195 char *full_name;
196 char *user_name;
197 char *manufacturer;
198 char *model;
199 char *serial_number;
200 char *mac_string;
201
202 GInetAddress *interface_address;
203
204 guchar discovery_data[ARV_GVBS_DISCOVERY_DATA_SIZE];
205
206 volatile gint ref_count;
207 } ArvGvInterfaceDeviceInfos;
208
209 static ArvGvInterfaceDeviceInfos *
arv_gv_interface_device_infos_new(GInetAddress * interface_address,void * discovery_data)210 arv_gv_interface_device_infos_new (GInetAddress *interface_address,
211 void *discovery_data)
212 {
213 ArvGvInterfaceDeviceInfos *infos;
214
215 g_return_val_if_fail (G_IS_INET_ADDRESS (interface_address), NULL);
216 g_return_val_if_fail (discovery_data != NULL, NULL);
217
218 g_object_ref (interface_address);
219
220 infos = g_new0 (ArvGvInterfaceDeviceInfos, 1);
221
222 memcpy (infos->discovery_data, discovery_data, ARV_GVBS_DISCOVERY_DATA_SIZE);
223
224 infos->manufacturer = g_strndup ((char *) &infos->discovery_data[ARV_GVBS_MANUFACTURER_NAME_OFFSET],
225 ARV_GVBS_MANUFACTURER_NAME_SIZE);
226 infos->model = g_strndup ((char *) &infos->discovery_data[ARV_GVBS_MODEL_NAME_OFFSET],
227 ARV_GVBS_MODEL_NAME_SIZE);
228 infos->serial_number = g_strndup ((char *) &infos->discovery_data[ARV_GVBS_SERIAL_NUMBER_OFFSET],
229 ARV_GVBS_SERIAL_NUMBER_SIZE);
230 infos->user_name = g_strndup ((char *) &infos->discovery_data[ARV_GVBS_USER_DEFINED_NAME_OFFSET],
231 ARV_GVBS_USER_DEFINED_NAME_SIZE);
232
233 infos->name = g_strdup_printf ("%s-%s", arv_vendor_alias_lookup (infos->manufacturer), infos->serial_number);
234 arv_str_strip (infos->name, ARV_DEVICE_NAME_ILLEGAL_CHARACTERS, ARV_DEVICE_NAME_REPLACEMENT_CHARACTER);
235 infos->full_name = g_strdup_printf ("%s-%s", infos->manufacturer, infos->serial_number);
236 arv_str_strip (infos->full_name, ARV_DEVICE_NAME_ILLEGAL_CHARACTERS, ARV_DEVICE_NAME_REPLACEMENT_CHARACTER);
237
238 infos->interface_address = interface_address;
239
240 infos->mac_string = g_strdup_printf ("%02x:%02x:%02x:%02x:%02x:%02x",
241 infos->discovery_data[ARV_GVBS_DEVICE_MAC_ADDRESS_HIGH_OFFSET + 2],
242 infos->discovery_data[ARV_GVBS_DEVICE_MAC_ADDRESS_HIGH_OFFSET + 3],
243 infos->discovery_data[ARV_GVBS_DEVICE_MAC_ADDRESS_HIGH_OFFSET + 4],
244 infos->discovery_data[ARV_GVBS_DEVICE_MAC_ADDRESS_HIGH_OFFSET + 5],
245 infos->discovery_data[ARV_GVBS_DEVICE_MAC_ADDRESS_HIGH_OFFSET + 6],
246 infos->discovery_data[ARV_GVBS_DEVICE_MAC_ADDRESS_HIGH_OFFSET + 7]);
247 infos->ref_count = 1;
248
249 return infos;
250 }
251
252 static ArvGvInterfaceDeviceInfos *
arv_gv_interface_device_infos_ref(ArvGvInterfaceDeviceInfos * infos)253 arv_gv_interface_device_infos_ref (ArvGvInterfaceDeviceInfos *infos)
254 {
255 g_return_val_if_fail (infos != NULL, NULL);
256 g_return_val_if_fail (g_atomic_int_get (&infos->ref_count) > 0, NULL);
257
258 g_atomic_int_inc (&infos->ref_count);
259
260 return infos;
261 }
262
263 static void
arv_gv_interface_device_infos_unref(ArvGvInterfaceDeviceInfos * infos)264 arv_gv_interface_device_infos_unref (ArvGvInterfaceDeviceInfos *infos)
265 {
266 g_return_if_fail (infos != NULL);
267 g_return_if_fail (g_atomic_int_get (&infos->ref_count) > 0);
268
269 if (g_atomic_int_dec_and_test (&infos->ref_count)) {
270 g_object_unref (infos->interface_address);
271 g_free (infos->name);
272 g_free (infos->user_name);
273 g_free (infos->full_name);
274 g_free (infos->manufacturer);
275 g_free (infos->serial_number);
276 g_free (infos->model);
277 g_free (infos->mac_string);
278 g_free (infos);
279 }
280 }
281
282 /* ArvGvInterface implementation */
283
284 static GObjectClass *parent_class = NULL;
285
286 struct _ArvGvInterfacePrivate {
287 GHashTable *devices;
288 };
289
290 static ArvGvInterfaceDeviceInfos *
_discover(GHashTable * devices,const char * device_id)291 _discover (GHashTable *devices, const char *device_id)
292 {
293 ArvGvDiscoverSocketList *socket_list;
294 GSList *iter;
295 char buffer[ARV_GV_INTERFACE_SOCKET_BUFFER_SIZE];
296 int count;
297 int i;
298
299 g_assert (devices == NULL || device_id == NULL);
300
301 if (devices != NULL)
302 g_hash_table_remove_all (devices);
303
304 socket_list = arv_gv_discover_socket_list_new ();
305
306 if (socket_list->n_sockets < 1) {
307 arv_gv_discover_socket_list_free (socket_list);
308 return NULL;
309 }
310
311 arv_gv_discover_socket_list_send_discover_packet (socket_list);
312
313 do {
314 if (g_poll (socket_list->poll_fds, socket_list->n_sockets, ARV_GV_INTERFACE_DISCOVERY_TIMEOUT_MS) == 0) {
315 arv_gv_discover_socket_list_free (socket_list);
316 return NULL;
317 }
318
319 for (i = 0, iter = socket_list->sockets; iter != NULL; i++, iter = iter->next) {
320 ArvGvDiscoverSocket *discover_socket = iter->data;
321
322 do {
323 g_socket_set_blocking (discover_socket->socket, FALSE);
324 count = g_socket_receive (discover_socket->socket, buffer, ARV_GV_INTERFACE_SOCKET_BUFFER_SIZE,
325 NULL, NULL);
326 g_socket_set_blocking (discover_socket->socket, TRUE);
327
328 if (count > 0) {
329 ArvGvcpPacket *packet = (ArvGvcpPacket *) buffer;
330
331 if (g_ntohs (packet->header.command) == ARV_GVCP_COMMAND_DISCOVERY_ACK &&
332 g_ntohs (packet->header.id) == 0xffff) {
333 ArvGvInterfaceDeviceInfos *device_infos;
334 GInetAddress *interface_address;
335 char *address_string;
336 char *data = buffer + sizeof (ArvGvcpHeader);
337
338 arv_gvcp_packet_debug (packet, ARV_DEBUG_LEVEL_LOG);
339
340 interface_address = g_inet_socket_address_get_address
341 (G_INET_SOCKET_ADDRESS (discover_socket->interface_address));
342 device_infos = arv_gv_interface_device_infos_new (interface_address,
343 data);
344 address_string = g_inet_address_to_string (interface_address);
345
346 arv_debug_interface ("[GvInterface::discovery] Device '%s' found "
347 "(interface %s) user_name '%s' - MAC_name '%s'",
348 device_infos->name,
349 address_string,
350 device_infos->user_name,
351 device_infos->full_name,
352 device_infos->mac_string);
353
354 g_free (address_string);
355
356 if (devices != NULL) {
357 if (device_infos->name != NULL && device_infos->name[0] != '\0')
358 g_hash_table_replace (devices, device_infos->name,
359 arv_gv_interface_device_infos_ref (device_infos));
360 if (device_infos->full_name != NULL && device_infos->full_name[0] != '\0')
361 g_hash_table_replace (devices, device_infos->full_name,
362 arv_gv_interface_device_infos_ref (device_infos));
363 if (device_infos->user_name != NULL && device_infos->user_name[0] != '\0')
364 g_hash_table_replace (devices, device_infos->user_name,
365 arv_gv_interface_device_infos_ref (device_infos));
366 g_hash_table_replace (devices, device_infos->mac_string,
367 arv_gv_interface_device_infos_ref (device_infos));
368 } else {
369 if (device_id == NULL ||
370 g_strcmp0 (device_infos->name, device_id) == 0 ||
371 g_strcmp0 (device_infos->full_name, device_id) == 0 ||
372 g_strcmp0 (device_infos->user_name, device_id) == 0 ||
373 g_strcmp0 (device_infos->mac_string, device_id) == 0) {
374 arv_gv_discover_socket_list_free (socket_list);
375
376 return device_infos;
377 }
378 }
379
380 arv_gv_interface_device_infos_unref (device_infos);
381 }
382 }
383 } while (count > 0);
384 }
385 } while (1);
386 }
387
388 static void
arv_gv_interface_discover(ArvGvInterface * gv_interface)389 arv_gv_interface_discover (ArvGvInterface *gv_interface)
390 {
391 _discover (gv_interface->priv->devices, NULL);
392 }
393
394 static GInetAddress *
_device_infos_to_ginetaddress(ArvGvInterfaceDeviceInfos * device_infos)395 _device_infos_to_ginetaddress (ArvGvInterfaceDeviceInfos *device_infos)
396 {
397 GInetAddress *device_address;
398
399 device_address = g_inet_address_new_from_bytes
400 (&device_infos->discovery_data[ARV_GVBS_CURRENT_IP_ADDRESS_OFFSET],
401 G_SOCKET_FAMILY_IPV4);
402
403 return device_address;
404 }
405
406 static void
arv_gv_interface_update_device_list(ArvInterface * interface,GArray * device_ids)407 arv_gv_interface_update_device_list (ArvInterface *interface, GArray *device_ids)
408 {
409 ArvGvInterface *gv_interface;
410 GHashTableIter iter;
411 gpointer key, value;
412
413 g_assert (device_ids->len == 0);
414
415 gv_interface = ARV_GV_INTERFACE (interface);
416
417 arv_gv_interface_discover (gv_interface);
418
419 g_hash_table_iter_init (&iter, gv_interface->priv->devices);
420 while (g_hash_table_iter_next (&iter, &key, &value)) {
421 ArvGvInterfaceDeviceInfos *infos = value;
422
423 if (g_strcmp0 (key, infos->name) == 0) {
424 ArvInterfaceDeviceIds *ids;
425 GInetAddress *device_address;
426
427 ids = g_new0 (ArvInterfaceDeviceIds, 1);
428
429 ids->device = g_strdup (key);
430 ids->physical = g_strdup (infos->mac_string);
431 device_address = _device_infos_to_ginetaddress (infos);
432 ids->address = g_inet_address_to_string (device_address);
433 g_object_unref (device_address);
434 ids->vendor = g_strdup (infos->manufacturer);
435 ids->model = g_strdup (infos->model);
436 ids->serial_nbr = g_strdup (infos->serial_number);
437
438 g_array_append_val (device_ids, ids);
439 }
440 }
441 }
442
443 static GInetAddress *
arv_gv_interface_camera_locate(ArvGvInterface * gv_interface,GInetAddress * device_address)444 arv_gv_interface_camera_locate (ArvGvInterface *gv_interface, GInetAddress *device_address)
445 {
446 ArvGvDiscoverSocketList *socket_list;
447 ArvGvcpPacket *packet;
448 char buffer[ARV_GV_INTERFACE_SOCKET_BUFFER_SIZE];
449 GSList *iter;
450 GSocketAddress *device_socket_address;
451 size_t size;
452 int i, count;
453
454 socket_list = arv_gv_discover_socket_list_new ();
455
456 if (socket_list->n_sockets < 1) {
457 arv_gv_discover_socket_list_free (socket_list);
458 return NULL;
459 }
460
461 /* Just read a random register from the camera socket */
462 packet = arv_gvcp_packet_new_read_register_cmd (ARV_GVBS_N_STREAM_CHANNELS_OFFSET, 0, &size);
463 device_socket_address = g_inet_socket_address_new (device_address, ARV_GVCP_PORT);
464
465 for (iter = socket_list->sockets; iter != NULL; iter = iter->next) {
466 ArvGvDiscoverSocket *socket = iter->data;
467 GError *error = NULL;
468
469 g_socket_send_to (socket->socket,
470 device_socket_address,
471 (const char *) packet, size,
472 NULL, &error);
473 if (error != NULL) {
474 arv_warning_interface ("[ArvGVInterface::arv_gv_interface_camera_locate] Error: %s", error->message);
475 g_error_free (error);
476 }
477 }
478
479 arv_gvcp_packet_free (packet);
480
481 do {
482 /* Now parse the result */
483 if (g_poll (socket_list->poll_fds, socket_list->n_sockets,
484 ARV_GV_INTERFACE_DISCOVERY_TIMEOUT_MS) == 0) {
485 arv_gv_discover_socket_list_free (socket_list);
486 return NULL;
487 }
488
489 for (i = 0, iter = socket_list->sockets; iter != NULL; i++, iter = iter->next) {
490 ArvGvDiscoverSocket *socket = iter->data;
491
492 do {
493 g_socket_set_blocking (socket->socket, FALSE);
494 count = g_socket_receive (socket->socket, buffer,
495 ARV_GV_INTERFACE_SOCKET_BUFFER_SIZE,
496 NULL, NULL);
497 g_socket_set_blocking (socket->socket, TRUE);
498
499 if (count > 0) {
500 ArvGvcpPacket *packet = (ArvGvcpPacket *) buffer;
501
502 if (g_ntohs (packet->header.command) == ARV_GVCP_COMMAND_READ_REGISTER_CMD ||
503 g_ntohs (packet->header.command) == ARV_GVCP_COMMAND_READ_REGISTER_ACK) {
504 GInetAddress *interface_address = g_inet_socket_address_get_address(
505 G_INET_SOCKET_ADDRESS (socket->interface_address));
506
507 g_object_ref(interface_address);
508 arv_gv_discover_socket_list_free (socket_list);
509 return interface_address;
510 }
511 }
512 } while (count > 0);
513 }
514 } while (1);
515 arv_gv_discover_socket_list_free (socket_list);
516 return NULL;
517 }
518
519 static ArvDevice *
_open_device(ArvInterface * interface,GHashTable * devices,const char * device_id)520 _open_device (ArvInterface *interface, GHashTable *devices, const char *device_id)
521 {
522 ArvGvInterface *gv_interface;
523 ArvDevice *device = NULL;
524 ArvGvInterfaceDeviceInfos *device_infos;
525 GInetAddress *device_address;
526
527 gv_interface = ARV_GV_INTERFACE (interface);
528
529 if (device_id == NULL) {
530 GList *device_list;
531
532 device_list = g_hash_table_get_values (devices);
533 device_infos = device_list != NULL ? device_list->data : NULL;
534 g_list_free (device_list);
535 } else
536 device_infos = g_hash_table_lookup (devices, device_id);
537
538 if (device_infos == NULL) {
539 struct addrinfo hints;
540 struct addrinfo *servinfo, *endpoint;
541
542 if (device_id == NULL)
543 return NULL;
544
545 /* Try if device_id is a hostname/IP address */
546
547 memset(&hints, 0, sizeof (hints));
548 hints.ai_family = AF_INET;
549 hints.ai_socktype = SOCK_DGRAM;
550
551 if (getaddrinfo(device_id, "3956", &hints, &servinfo) != 0) {
552 return NULL;
553 }
554
555 for (endpoint=servinfo; endpoint!=NULL; endpoint=endpoint->ai_next) {
556 char ipstr[INET_ADDRSTRLEN];
557 struct sockaddr_in *ip = (struct sockaddr_in *) endpoint->ai_addr;
558
559 inet_ntop (endpoint->ai_family, &ip->sin_addr, ipstr, sizeof (ipstr));
560
561 device_address = g_inet_address_new_from_string (ipstr);
562 if (device_address != NULL) {
563 /* Try and find an interface that the camera will respond on */
564 GInetAddress *interface_address =
565 arv_gv_interface_camera_locate (gv_interface, device_address);
566
567 if (interface_address != NULL) {
568 device = arv_gv_device_new (interface_address, device_address);
569 g_object_unref (interface_address);
570 }
571 }
572 g_object_unref (device_address);
573 if (device != NULL) {
574 break;
575 }
576 }
577 freeaddrinfo (servinfo);
578 return device;
579 }
580
581 device_address = _device_infos_to_ginetaddress (device_infos);
582 device = arv_gv_device_new (device_infos->interface_address, device_address);
583 g_object_unref (device_address);
584
585 return device;
586 }
587
588 static ArvDevice *
arv_gv_interface_open_device(ArvInterface * interface,const char * device_id)589 arv_gv_interface_open_device (ArvInterface *interface, const char *device_id)
590 {
591 ArvDevice *device;
592 ArvGvInterfaceDeviceInfos *device_infos;
593
594 device = _open_device (interface, ARV_GV_INTERFACE (interface)->priv->devices, device_id);
595 if (ARV_IS_DEVICE (device))
596 return device;
597
598 device_infos = _discover (NULL, device_id);
599 if (device_infos != NULL) {
600 GInetAddress *device_address;
601
602 device_address = _device_infos_to_ginetaddress (device_infos);
603 device = arv_gv_device_new (device_infos->interface_address, device_address);
604 g_object_unref (device_address);
605
606 arv_gv_interface_device_infos_unref (device_infos);
607
608 return device;
609 }
610
611 return NULL;
612 }
613
614 static ArvInterface *gv_interface = NULL;
615 ARV_DEFINE_STATIC_MUTEX (gv_interface_mutex);
616
617 /**
618 * arv_gv_interface_get_instance:
619 *
620 * Gets the unique instance of the GV interface.
621 *
622 * Returns: (transfer none): a #ArvInterface singleton.
623 */
624
625 ArvInterface *
arv_gv_interface_get_instance(void)626 arv_gv_interface_get_instance (void)
627 {
628 arv_g_mutex_lock (&gv_interface_mutex);
629
630 if (gv_interface == NULL)
631 gv_interface = g_object_new (ARV_TYPE_GV_INTERFACE, NULL);
632
633 arv_g_mutex_unlock (&gv_interface_mutex);
634
635 return ARV_INTERFACE (gv_interface);
636 }
637
638 void
arv_gv_interface_destroy_instance(void)639 arv_gv_interface_destroy_instance (void)
640 {
641 arv_g_mutex_lock (&gv_interface_mutex);
642
643 if (gv_interface != NULL) {
644 g_object_unref (gv_interface);
645 gv_interface = NULL;
646 }
647
648 arv_g_mutex_unlock (&gv_interface_mutex);
649 }
650
651 static void
arv_gv_interface_init(ArvGvInterface * gv_interface)652 arv_gv_interface_init (ArvGvInterface *gv_interface)
653 {
654 gv_interface->priv = G_TYPE_INSTANCE_GET_PRIVATE (gv_interface, ARV_TYPE_GV_INTERFACE, ArvGvInterfacePrivate);
655
656 gv_interface->priv->devices = g_hash_table_new_full (g_str_hash, g_str_equal, NULL,
657 (GDestroyNotify) arv_gv_interface_device_infos_unref);
658 }
659
660 static void
arv_gv_interface_finalize(GObject * object)661 arv_gv_interface_finalize (GObject *object)
662 {
663 ArvGvInterface *gv_interface = ARV_GV_INTERFACE (object);
664
665 g_hash_table_unref (gv_interface->priv->devices);
666 gv_interface->priv->devices = NULL;
667
668 parent_class->finalize (object);
669 }
670
671 static void
arv_gv_interface_class_init(ArvGvInterfaceClass * gv_interface_class)672 arv_gv_interface_class_init (ArvGvInterfaceClass *gv_interface_class)
673 {
674 GObjectClass *object_class = G_OBJECT_CLASS (gv_interface_class);
675 ArvInterfaceClass *interface_class = ARV_INTERFACE_CLASS (gv_interface_class);
676
677 g_type_class_add_private (gv_interface_class, sizeof (ArvGvInterfacePrivate));
678
679 parent_class = g_type_class_peek_parent (gv_interface_class);
680
681 object_class->finalize = arv_gv_interface_finalize;
682
683 interface_class->update_device_list = arv_gv_interface_update_device_list;
684 interface_class->open_device = arv_gv_interface_open_device;
685
686 interface_class->protocol = "GigEVision";
687 }
688
689 G_DEFINE_TYPE (ArvGvInterface, arv_gv_interface, ARV_TYPE_INTERFACE)
690