uca-kiro-camera.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666
  1. /* Copyright (C) 2011, 2012 Matthias Vogelgesang <matthias.vogelgesang@kit.edu>
  2. (Karlsruhe Institute of Technology)
  3. This library is free software; you can redistribute it and/or modify it
  4. under the terms of the GNU Lesser General Public License as published by the
  5. Free Software Foundation; either version 2.1 of the License, or (at your
  6. option) any later version.
  7. This library is distributed in the hope that it will be useful, but WITHOUT
  8. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  9. FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
  10. details.
  11. You should have received a copy of the GNU Lesser General Public License along
  12. with this library; if not, write to the Free Software Foundation, Inc., 51
  13. Franklin St, Fifth Floor, Boston, MA 02110, USA */
  14. #include <gmodule.h>
  15. #include <gio/gio.h>
  16. #include <string.h>
  17. #include <math.h>
  18. #include <kiro/kiro-messenger.h>
  19. #include "uca-kiro-camera.h"
  20. #define UCA_KIRO_CAMERA_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), UCA_TYPE_KIRO_CAMERA, UcaKiroCameraPrivate))
  21. static void uca_kiro_initable_iface_init (GInitableIface *iface);
  22. GError *initable_iface_error = NULL;
  23. G_DEFINE_TYPE_WITH_CODE (UcaKiroCamera, uca_kiro_camera, UCA_TYPE_CAMERA,
  24. G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
  25. uca_kiro_initable_iface_init))
  26. /**
  27. * UcaCameraError:
  28. @UCA_KIRO_CAMERA_ERROR_MISSING_ADDRESS: No KIRO address ('kiro://<IP>:<PORT>') property was supplied during camera creation
  29. @UCA_KIRO_CAMERA_ERROR_ADDRESS_WRONG_FORMAT: KIRO address has the wrong format. Expected: 'kiro://<IP>:<PORT>'
  30. @UCA_KIRO_CAMERA_ERROR_KIRO_CONNECTION_FAILED: Failed to establish a KIRO connection to the given TANGO server
  31. */
  32. GQuark uca_kiro_camera_error_quark()
  33. {
  34. return g_quark_from_static_string ("uca-kiro-camera-error-quark");
  35. }
  36. enum {
  37. PROP_KIRO_ADDRESS = N_BASE_PROPERTIES,
  38. PROP_KIRO_REMOTE_NAME,
  39. N_PROPERTIES
  40. };
  41. static const gint kiro_overrideables[] = {
  42. PROP_NAME,
  43. 0,
  44. };
  45. static GParamSpec *kiro_properties[N_PROPERTIES] = { NULL, };
  46. //+1 to make index and property ID identical
  47. static guint64 kiro_scalar_prop_buffers[N_PROPERTIES] = { 0, };
  48. typedef struct {
  49. GParamSpec *pspec;
  50. guint32 remote_id;
  51. guint32 local_id;
  52. guint64 buffer;
  53. } KiroDynamicScalarProperty;
  54. struct _UcaKiroCameraPrivate {
  55. guint8 *dummy_data;
  56. guint current_frame;
  57. gchar *kiro_address_string;
  58. gchar *kiro_address;
  59. gchar *kiro_port;
  60. gchar *remote_name;
  61. GList *property_install_list;
  62. KiroDynamicScalarProperty *kiro_dynamic_scalar_properties;
  63. gboolean thread_running;
  64. gboolean kiro_connected;
  65. gboolean construction_error;
  66. GThread *grab_thread;
  67. KiroMessenger *messenger;
  68. gulong peer_rank;
  69. KiroRequest *rec_request;
  70. guint roi_height;
  71. guint roi_width;
  72. guint bytes_per_pixel;
  73. };
  74. static gpointer
  75. kiro_grab_func(gpointer data)
  76. {
  77. /* UcaKiroCamera *kiro_camera = UCA_KIRO_CAMERA (data); */
  78. /* g_return_val_if_fail (UCA_IS_KIRO_CAMERA (kiro_camera), NULL); */
  79. /* UcaKiroCameraPrivate *priv = UCA_KIRO_CAMERA_GET_PRIVATE (kiro_camera); */
  80. /* UcaCamera *camera = UCA_CAMERA (kiro_camera); */
  81. /* gdouble fps; */
  82. /* g_object_get (G_OBJECT (data), "frames-per-second", &fps, NULL); */
  83. /* const gulong sleep_time = (gulong) G_USEC_PER_SEC / fps; */
  84. /* while (priv->thread_running) { */
  85. /* camera->grab_func (NULL, camera->user_data); */
  86. /* g_usleep (sleep_time); */
  87. /* } */
  88. return NULL;
  89. }
  90. static void
  91. uca_kiro_camera_start_recording(UcaCamera *camera, GError **error)
  92. {
  93. /* gboolean transfer_async = FALSE; */
  94. /* UcaKiroCameraPrivate *priv; */
  95. /* g_return_if_fail(UCA_IS_KIRO_CAMERA (camera)); */
  96. /* priv = UCA_KIRO_CAMERA_GET_PRIVATE (camera); */
  97. /* g_object_get (G_OBJECT(camera), */
  98. /* "transfer-asynchronously", &transfer_async, */
  99. /* NULL); */
  100. /* //'Cache' ROI settings from TANGO World */
  101. /* g_object_get (G_OBJECT(camera), */
  102. /* "roi-width", &priv->roi_width, */
  103. /* NULL); */
  104. /* g_object_get (G_OBJECT(camera), */
  105. /* "roi-height", &priv->roi_height, */
  106. /* NULL); */
  107. /* size_t bits = 0; */
  108. /* g_object_get (G_OBJECT(camera), */
  109. /* "sensor-bitdepth", &bits, */
  110. /* NULL); */
  111. /* priv->bytes_per_pixel = 1; */
  112. /* if (bits > 8) priv->bytes_per_pixel++; */
  113. /* if (bits > 16) priv->bytes_per_pixel++; */
  114. /* if (bits > 24) priv->bytes_per_pixel++; */
  115. /* Tango::DevState state; */
  116. /* g_object_get (G_OBJECT(camera), */
  117. /* "State", &state, */
  118. /* NULL); */
  119. /* try { */
  120. /* if (Tango::DevState::STANDBY == state) */
  121. /* priv->tango_device->command_inout ("StartRecording"); */
  122. /* } */
  123. /* catch (Tango::DevFailed &e) { */
  124. /* g_warning ("Failed to execute 'StartRecording' on the remote camera due to a TANGO exception.\n"); */
  125. /* g_set_error (error, UCA_KIRO_CAMERA_ERROR, UCA_KIRO_CAMERA_ERROR_TANGO_EXCEPTION_OCCURED, */
  126. /* "A TANGO exception was raised: '%s'", (const char *)e.errors[0].desc); */
  127. /* return; */
  128. /* } */
  129. /* /* */
  130. /* * In case asynchronous transfer is requested, we start a new thread that */
  131. /* * invokes the grab callback, otherwise nothing will be done here. */
  132. /* *1/ */
  133. /* if (transfer_async) { */
  134. /* GError *tmp_error = NULL; */
  135. /* priv->thread_running = TRUE; */
  136. /* priv->grab_thread = g_thread_create (kiro_grab_func, camera, TRUE, &tmp_error); */
  137. /* if (tmp_error != NULL) { */
  138. /* priv->thread_running = FALSE; */
  139. /* g_propagate_error (error, tmp_error); */
  140. /* try { */
  141. /* priv->tango_device->command_inout ("StopRecording"); */
  142. /* } */
  143. /* catch (Tango::DevFailed &e) { */
  144. /* g_warning ("Failed to execute 'StopRecording' on the remote camera due to a TANGO exception: '%s'\n", (const char *)e.errors[0].desc); */
  145. /* } */
  146. /* } */
  147. /* } */
  148. /* kiro_sb_thaw (priv->receive_buffer); */
  149. }
  150. static void
  151. uca_kiro_camera_stop_recording(UcaCamera *camera, GError **error)
  152. {
  153. /* g_return_if_fail(UCA_IS_KIRO_CAMERA (camera)); */
  154. /* UcaKiroCameraPrivate *priv; */
  155. /* priv = UCA_KIRO_CAMERA_GET_PRIVATE (camera); */
  156. /* Tango::DevState state; */
  157. /* g_object_get (G_OBJECT(camera), */
  158. /* "State", &state, */
  159. /* NULL); */
  160. /* try { */
  161. /* if (Tango::DevState::RUNNING == state) */
  162. /* priv->tango_device->command_inout ("StopRecording"); */
  163. /* } */
  164. /* catch (Tango::DevFailed &e) { */
  165. /* g_warning ("Failed to execute 'StopRecording' on the remote camera due to a TANGO exception.\n"); */
  166. /* g_set_error (error, UCA_KIRO_CAMERA_ERROR, UCA_KIRO_CAMERA_ERROR_TANGO_EXCEPTION_OCCURED, */
  167. /* "A TANGO exception was raised: '%s'", (const char *)e.errors[0].desc); */
  168. /* } */
  169. /* gboolean transfer_async = FALSE; */
  170. /* g_object_get(G_OBJECT (camera), */
  171. /* "transfer-asynchronously", &transfer_async, */
  172. /* NULL); */
  173. /* if (transfer_async) { */
  174. /* priv->thread_running = FALSE; */
  175. /* g_thread_join (priv->grab_thread); */
  176. /* } */
  177. /* kiro_sb_freeze (priv->receive_buffer); */
  178. /* g_free (priv->dummy_data); */
  179. }
  180. static void
  181. uca_kiro_camera_trigger (UcaCamera *camera, GError **error)
  182. {
  183. }
  184. static gboolean
  185. uca_kiro_camera_grab (UcaCamera *camera, gpointer data, GError **error)
  186. {
  187. /* g_return_val_if_fail (UCA_IS_KIRO_CAMERA (camera), FALSE); */
  188. /* UcaKiroCameraPrivate *priv = UCA_KIRO_CAMERA_GET_PRIVATE (camera); */
  189. /* //This is a hack to make sure we actually wait for a new frame; */
  190. /* gpointer frame = kiro_sb_get_data_blocking (priv->receive_buffer); */
  191. /* kiro_sb_freeze (priv->receive_buffer); */
  192. /* //Element 0 might still be in the process of being written. */
  193. /* //Therefore, we take Element 1, to be sure this one is finished. */
  194. /* if (data) */
  195. /* g_memmove (data, frame, priv->roi_width * priv->roi_height * priv->bytes_per_pixel); */
  196. /* kiro_sb_thaw (priv->receive_buffer); */
  197. return TRUE;
  198. }
  199. static gboolean
  200. kiro_address_decode (const gchar *addr_in, gchar **addr, gchar **port, GError **error)
  201. {
  202. if (!g_str_has_prefix (addr_in, "kiro://")) {
  203. g_set_error_literal (error, UCA_KIRO_CAMERA_ERROR, UCA_KIRO_CAMERA_ERROR_ADDRESS_WRONG_FORMAT,
  204. "Address does not use 'kiro://' scheme.");
  205. return FALSE;
  206. }
  207. /* Pitfall: kiro will silently accept hostnames like kiro://localhost:5555
  208. * but not bind to it as it treats it like an interface name (like eth0).
  209. * We have to use IP addresses instead of DNS names.
  210. */
  211. gchar *host = g_strdup (&addr_in[7]);
  212. if (!g_ascii_isdigit (host[0]) && host[0] != '*')
  213. g_debug ("Treating address %s as interface device name. Use IP address if supplying a host was intended.", host);
  214. gchar **split = g_strsplit (host, ":", 2);
  215. if (!g_ascii_isdigit (*split[1])) {
  216. g_set_error (error, UCA_KIRO_CAMERA_ERROR, UCA_KIRO_CAMERA_ERROR_ADDRESS_WRONG_FORMAT,
  217. "Address '%s' has wrong format", addr_in);
  218. g_strfreev (split);
  219. g_free (host);
  220. return FALSE;
  221. }
  222. *addr = g_strdup (split[0]);
  223. *port = g_strdup (split[1]);
  224. g_strfreev (split);
  225. g_free (host);
  226. return TRUE;
  227. }
  228. static void
  229. null_callback (gpointer unused)
  230. {
  231. (void)unused;
  232. }
  233. void
  234. receive_handler (KiroRequest *request, gpointer user_data)
  235. {
  236. UcaKiroCamera *cam = (UcaKiroCamera *)user_data;
  237. UcaKiroCameraPrivate *priv = UCA_KIRO_CAMERA_GET_PRIVATE (cam);
  238. KiroMessage *msg = request->message;
  239. if (msg->msg == KIROCS_INSTALL) {
  240. PropertyRequisition *req = (PropertyRequisition *)msg->payload;
  241. g_debug ("Got requisition for a non-base property '%s' of type '%s' with ID %u", req->name, g_type_name (req->value_type),
  242. req->id);
  243. priv->property_install_list = g_list_append (priv->property_install_list, msg->payload);
  244. msg->payload = NULL;
  245. goto done;
  246. }
  247. if (msg->msg == KIROCS_READY) {
  248. g_debug ("Interface Setup Done.");
  249. priv->kiro_connected = TRUE;
  250. goto done;
  251. }
  252. if (msg->msg == KIROCS_UPDATE) {
  253. PropUpdate *update = (PropUpdate *)request->message->payload;
  254. const gchar *name = NULL;
  255. gpointer buffer = NULL;
  256. if (update->scalar == TRUE) {
  257. PropUpdateScalar *scalar_update = (PropUpdateScalar *)request->message->payload;
  258. if (update->id >= N_BASE_PROPERTIES) {
  259. name = priv->kiro_dynamic_scalar_properties[update->id - N_BASE_PROPERTIES].pspec->name;
  260. buffer = &priv->kiro_dynamic_scalar_properties[update->id - N_BASE_PROPERTIES].buffer;
  261. }
  262. else {
  263. name = uca_camera_props[update->id];
  264. buffer = &kiro_scalar_prop_buffers[update->id];
  265. }
  266. memcpy (buffer, &scalar_update->prop_raw, sizeof (guint64));
  267. }
  268. g_debug ("Peer informed us about an update of property '%s' (ID: %u)", name, update->id);
  269. goto done;
  270. }
  271. g_message ("Message Type '%u' is unhandled.", msg->msg);
  272. done:
  273. if (msg->payload)
  274. g_free (msg->payload);
  275. g_free (msg);
  276. kiro_messenger_receive (priv->messenger, request);
  277. }
  278. static void
  279. uca_kiro_camera_clone_interface(UcaKiroCamera *kiro_camera)
  280. {
  281. UcaKiroCameraPrivate *priv = UCA_KIRO_CAMERA_GET_PRIVATE (kiro_camera);
  282. UcaKiroCameraClass *klass = UCA_KIRO_CAMERA_GET_CLASS (kiro_camera);
  283. GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
  284. if (priv->messenger) {
  285. kiro_messenger_free (priv->messenger);
  286. priv->messenger = kiro_messenger_new ();
  287. }
  288. priv->rec_request = g_malloc0 (sizeof (KiroRequest));
  289. priv->rec_request->id = 0;
  290. priv->rec_request->callback = (KiroMessageCallbackFunc) receive_handler;
  291. priv->rec_request->user_data = (gpointer) kiro_camera;
  292. kiro_messenger_receive (priv->messenger, priv->rec_request);
  293. priv->kiro_connected = FALSE;
  294. kiro_messenger_connect (priv->messenger, priv->kiro_address, priv->kiro_port, &priv->peer_rank, &initable_iface_error);
  295. if (initable_iface_error) {
  296. priv->construction_error = TRUE;
  297. g_free (priv->rec_request);
  298. return;
  299. }
  300. //Wait until the remote side has given us the "READY" signal
  301. while (!priv->kiro_connected) {};
  302. guint count = g_list_length (priv->property_install_list);
  303. if (count > 0) {
  304. g_debug ("Registering buffers for %u dyanmic properties", count);
  305. priv->kiro_dynamic_scalar_properties = g_malloc0 (count * sizeof (KiroDynamicScalarProperty));
  306. GList *curr = g_list_first (priv->property_install_list);
  307. guint idx = 0;
  308. while (curr) {
  309. PropertyRequisition *req = (PropertyRequisition *)curr->data;
  310. g_debug ("Registering dynamic property '%s'", req->name);
  311. GParamSpec *pspec = g_param_spec_boolean (req->name, "Remote Property",
  312. "Remote Property", TRUE, G_PARAM_READWRITE);
  313. guint local_id = N_PROPERTIES + idx;
  314. g_object_class_install_property (gobject_class, local_id, pspec);
  315. priv->kiro_dynamic_scalar_properties[idx].local_id = local_id;
  316. priv->kiro_dynamic_scalar_properties[idx].remote_id = req->id;
  317. priv->kiro_dynamic_scalar_properties[idx].pspec = pspec;
  318. KiroMessage message;
  319. message.msg = KIROCS_FETCH;
  320. message.size = strlen (req->name) + 1; //Don't forget the NULL-byte
  321. message.payload = &(req->name);
  322. g_debug ("Sending request to fetch value of property '%s'", req->name);
  323. GError *error = NULL;
  324. kiro_messenger_send_blocking (priv->messenger, &message, priv->peer_rank, &error);
  325. if (error) {
  326. g_error ("Oh shit! (%s)", error->message);
  327. g_error_free (error);
  328. }
  329. idx++;
  330. curr = g_list_next (curr);
  331. }
  332. g_list_free (priv->property_install_list);
  333. }
  334. if (priv->construction_error) {
  335. kiro_messenger_stop (priv->messenger);
  336. //TODO
  337. //Maybe set an error?
  338. }
  339. }
  340. static void
  341. uca_kiro_camera_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
  342. {
  343. g_return_if_fail(UCA_IS_KIRO_CAMERA (object));
  344. UcaKiroCameraPrivate *priv = UCA_KIRO_CAMERA_GET_PRIVATE (object);
  345. switch (property_id) {
  346. case PROP_KIRO_ADDRESS:
  347. if (priv->kiro_address_string)
  348. g_free (priv->kiro_address_string);
  349. priv->kiro_address_string = g_value_dup_string (value);
  350. break;
  351. default:
  352. g_debug ("Updating %s.", pspec->name);
  353. if (!priv->kiro_connected) {
  354. g_warning ("Trying to modify a property before a connection to the remote camera was established.");
  355. G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
  356. return;
  357. }
  358. if (property_id >= N_PROPERTIES) {
  359. g_debug ("Non-Base-Property ID %u (Index: %u)", property_id, property_id - N_PROPERTIES);
  360. g_value_write_to_raw_data (value, &(priv->kiro_dynamic_scalar_properties[property_id - N_PROPERTIES].buffer));
  361. }
  362. else
  363. g_value_write_to_raw_data (value, &kiro_scalar_prop_buffers[property_id]);
  364. KiroMessage message;
  365. message.msg = KIROCS_UPDATE;
  366. message.size = sizeof (PropUpdate) + sizeof (guint64);
  367. message.payload = g_malloc0 (message.size);
  368. gpointer data_pointer = message.payload + sizeof (PropUpdate);
  369. PropUpdate *update = (PropUpdate *)message.payload;
  370. update->size = 1;
  371. update->scalar = TRUE;
  372. if (property_id > N_BASE_PROPERTIES) {
  373. update->id = priv->kiro_dynamic_scalar_properties[property_id - N_PROPERTIES].remote_id;
  374. memcpy (data_pointer, &(priv->kiro_dynamic_scalar_properties[property_id - N_PROPERTIES].buffer), sizeof (guint64));
  375. }
  376. else {
  377. update->id = property_id;
  378. memcpy (data_pointer, &kiro_scalar_prop_buffers[property_id], sizeof (guint64));
  379. }
  380. GError *error = NULL;
  381. kiro_messenger_send_blocking (priv->messenger, &message, priv->peer_rank, &error);
  382. if (error) {
  383. g_error ("Oh shit! (%s)", error->message);
  384. g_error_free (error);
  385. }
  386. g_free (message.payload);
  387. }
  388. }
  389. static void
  390. uca_kiro_camera_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
  391. {
  392. UcaKiroCameraPrivate *priv = UCA_KIRO_CAMERA_GET_PRIVATE (object);
  393. switch (property_id) {
  394. case PROP_NAME:
  395. g_value_set_string (value, "KIRO camera");
  396. break;
  397. case PROP_KIRO_ADDRESS:
  398. g_value_set_string (value, priv->kiro_address_string);
  399. break;
  400. case PROP_KIRO_REMOTE_NAME:
  401. g_value_set_string (value, priv->remote_name);
  402. break;
  403. default:
  404. //TODO:
  405. //Handle non-scalar types specifically
  406. if (property_id <= N_BASE_PROPERTIES) {
  407. g_value_set_from_raw_data (value, &kiro_scalar_prop_buffers[property_id]);
  408. }
  409. else {
  410. g_value_set_from_raw_data (value, &(priv->kiro_dynamic_scalar_properties[property_id - N_PROPERTIES].buffer));
  411. }
  412. break;
  413. }
  414. }
  415. static void
  416. uca_kiro_camera_finalize(GObject *object)
  417. {
  418. UcaKiroCameraPrivate *priv = UCA_KIRO_CAMERA_GET_PRIVATE(object);
  419. if (priv->thread_running) {
  420. priv->thread_running = FALSE;
  421. g_thread_join (priv->grab_thread);
  422. }
  423. if (priv->messenger) {
  424. kiro_messenger_free (priv->messenger);
  425. priv->messenger = NULL;
  426. }
  427. priv->kiro_connected = FALSE;
  428. if (priv->dummy_data) {
  429. g_free (priv->dummy_data);
  430. priv->dummy_data = NULL;
  431. }
  432. g_free (priv->kiro_address_string);
  433. g_free (priv->kiro_address);
  434. g_free (priv->kiro_port);
  435. G_OBJECT_CLASS (uca_kiro_camera_parent_class)->finalize(object);
  436. }
  437. static gboolean
  438. ufo_kiro_camera_initable_init (GInitable *initable,
  439. GCancellable *cancellable,
  440. GError **error)
  441. {
  442. g_return_val_if_fail (UCA_IS_KIRO_CAMERA (initable), FALSE);
  443. UcaKiroCameraPrivate *priv = UCA_KIRO_CAMERA_GET_PRIVATE (UCA_KIRO_CAMERA (initable));
  444. if(priv->construction_error) {
  445. g_propagate_error (error, initable_iface_error);
  446. return FALSE;
  447. }
  448. return TRUE;
  449. }
  450. static void
  451. uca_kiro_initable_iface_init (GInitableIface *iface)
  452. {
  453. iface->init = ufo_kiro_camera_initable_init;
  454. }
  455. static void
  456. uca_kiro_camera_constructed (GObject *object)
  457. {
  458. //Initialization for the KIRO Messenger and interface cloning is moved
  459. //here and done early!
  460. //We want to add dynamic properties and it is too late to do so in the
  461. //real initable part. Therefore, we do it here and 'remember' any errors
  462. //that occur and check them later in the initable part.
  463. UcaKiroCamera *self = UCA_KIRO_CAMERA (object);
  464. UcaKiroCameraPrivate *priv = UCA_KIRO_CAMERA_GET_PRIVATE (self);
  465. priv->construction_error = FALSE;
  466. GValue address = G_VALUE_INIT;
  467. g_value_init(&address, G_TYPE_STRING);
  468. uca_kiro_camera_get_property (object, PROP_KIRO_ADDRESS, &address, NULL);
  469. const gchar *addrstring = g_value_get_string (&address);
  470. gint address_not_none = g_strcmp0(addrstring, "NONE");
  471. if (0 == address_not_none) {
  472. g_warning ("kiro-address was not set! Can not connect to server...\n");
  473. priv->construction_error = TRUE;
  474. g_set_error (&initable_iface_error, UCA_KIRO_CAMERA_ERROR, UCA_KIRO_CAMERA_ERROR_MISSING_ADDRESS,
  475. "'kiro-address' property was not set during construction.");
  476. }
  477. else {
  478. if (kiro_address_decode (addrstring, &priv->kiro_address, &priv->kiro_port, &initable_iface_error)) {
  479. uca_kiro_camera_clone_interface (self);
  480. }
  481. else {
  482. priv->construction_error = TRUE;
  483. }
  484. }
  485. G_OBJECT_CLASS (uca_kiro_camera_parent_class)->constructed(object);
  486. }
  487. static void
  488. uca_kiro_camera_class_init(UcaKiroCameraClass *klass)
  489. {
  490. GObjectClass *gobject_class = G_OBJECT_CLASS( klass);
  491. gobject_class->set_property = uca_kiro_camera_set_property;
  492. gobject_class->get_property = uca_kiro_camera_get_property;
  493. gobject_class->finalize = uca_kiro_camera_finalize;
  494. gobject_class->constructed = uca_kiro_camera_constructed;
  495. UcaCameraClass *camera_class = UCA_CAMERA_CLASS (klass);
  496. camera_class->start_recording = uca_kiro_camera_start_recording;
  497. camera_class->stop_recording = uca_kiro_camera_stop_recording;
  498. camera_class->grab = uca_kiro_camera_grab;
  499. camera_class->trigger = uca_kiro_camera_trigger;
  500. for (guint i = 0; i < N_BASE_PROPERTIES; i++)
  501. g_object_class_override_property (gobject_class, i, uca_camera_props[i]);
  502. kiro_properties[PROP_KIRO_ADDRESS] =
  503. g_param_spec_string("kiro-address",
  504. "KIRO Server Address",
  505. "Address of the KIRO Server to grab images from",
  506. "NONE",
  507. G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
  508. kiro_properties[PROP_KIRO_REMOTE_NAME] =
  509. g_param_spec_string("remote-name",
  510. "Name of the remote camera",
  511. "Name of the camera plugin that is loaded on the KIRO remote side",
  512. "NONE",
  513. G_PARAM_READABLE);
  514. for (guint id = N_BASE_PROPERTIES; id < N_PROPERTIES; id++)
  515. g_object_class_install_property (gobject_class, id, kiro_properties[id]);
  516. g_type_class_add_private (klass, sizeof(UcaKiroCameraPrivate));
  517. }
  518. static void
  519. uca_kiro_camera_init(UcaKiroCamera *self)
  520. {
  521. self->priv = UCA_KIRO_CAMERA_GET_PRIVATE(self);
  522. self->priv->grab_thread = NULL;
  523. self->priv->current_frame = 0;
  524. self->priv->kiro_address_string = g_strdup ("NONE");
  525. self->priv->remote_name = g_strdup ("NONE");
  526. self->priv->construction_error = FALSE;
  527. self->priv->kiro_dynamic_scalar_properties = NULL;
  528. self->priv->messenger = kiro_messenger_new ();
  529. self->priv->peer_rank = 0;
  530. }
  531. G_MODULE_EXPORT GType
  532. uca_camera_get_type (void)
  533. {
  534. return UCA_TYPE_KIRO_CAMERA;
  535. }