uca-kiro-camera.cpp 40 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115
  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 <tango.h>
  15. extern "C" {
  16. #include <gmodule.h>
  17. #include <gio/gio.h>
  18. #include <string.h>
  19. #include <math.h>
  20. #include <kiro/kiro-sb.h>
  21. #include "uca-kiro-camera.h"
  22. } // EXTERN C
  23. #define UCA_KIRO_CAMERA_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), UCA_TYPE_KIRO_CAMERA, UcaKiroCameraPrivate))
  24. static void uca_kiro_initable_iface_init (GInitableIface *iface);
  25. GError *initable_iface_error = NULL;
  26. G_DEFINE_TYPE_WITH_CODE (UcaKiroCamera, uca_kiro_camera, UCA_TYPE_CAMERA,
  27. G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
  28. uca_kiro_initable_iface_init))
  29. /**
  30. * UcaCameraError:
  31. @UCA_KIRO_CAMERA_ERROR_MISSING_TANGO_ADDRESS: No TANGO address ('kiro-tango-address') property was supplied during camera creation
  32. @UCA_KIRO_CAMERA_ERROR_TANGO_CONNECTION_FAILED: Could not connect to the given TANGO address
  33. @UCA_KIRO_CAMERA_ERROR_KIRO_CONNECTION_FAILED: Failed to establish a KIRO connection to the given TANGO server
  34. @UCA_KIRO_CAMERA_ERROR_TANGO_EXCEPTION_OCCURED: A TANGO exception was raised during communication with the server
  35. @UCA_KIRO_CAMERA_ERROR_BAD_CAMERA_INTERFACE: The given TANGO server does not expose the expected UcaCamera base interface
  36. */
  37. GQuark uca_kiro_camera_error_quark()
  38. {
  39. return g_quark_from_static_string ("uca-kiro-camera-error-quark");
  40. }
  41. enum {
  42. PROP_KIRO_ADDRESS = N_BASE_PROPERTIES,
  43. PROP_KIRO_PORT,
  44. PROP_KIRO_TANGO_ADDRESS,
  45. PROP_KIRO_REMOTE_NAME,
  46. N_PROPERTIES
  47. };
  48. static const gint kiro_overrideables[] = {
  49. PROP_NAME,
  50. 0,
  51. };
  52. static GParamSpec *kiro_properties[N_PROPERTIES] = { NULL, };
  53. struct _UcaKiroCameraPrivate {
  54. guint8 *dummy_data;
  55. guint current_frame;
  56. gchar *kiro_address;
  57. gchar *kiro_port;
  58. guint kiro_port_uint;
  59. gchar *kiro_tango_address;
  60. gchar *remote_name;
  61. Tango::DeviceProxy *tango_device;
  62. GParamSpec **kiro_dynamic_attributes;
  63. gboolean thread_running;
  64. gboolean kiro_connected;
  65. gboolean construction_error;
  66. GThread *grab_thread;
  67. KiroSb *receive_buffer;
  68. guint roi_height;
  69. guint roi_width;
  70. guint bytes_per_pixel;
  71. };
  72. static gpointer
  73. kiro_grab_func(gpointer data)
  74. {
  75. UcaKiroCamera *kiro_camera = UCA_KIRO_CAMERA (data);
  76. g_return_val_if_fail (UCA_IS_KIRO_CAMERA (kiro_camera), NULL);
  77. UcaKiroCameraPrivate *priv = UCA_KIRO_CAMERA_GET_PRIVATE (kiro_camera);
  78. UcaCamera *camera = UCA_CAMERA (kiro_camera);
  79. gdouble fps;
  80. g_object_get (G_OBJECT (data), "frames-per-second", &fps, NULL);
  81. const gulong sleep_time = (gulong) G_USEC_PER_SEC / fps;
  82. while (priv->thread_running) {
  83. camera->grab_func (NULL, camera->user_data);
  84. g_usleep (sleep_time);
  85. }
  86. return NULL;
  87. }
  88. static void
  89. uca_kiro_camera_start_recording(UcaCamera *camera, GError **error)
  90. {
  91. gboolean transfer_async = FALSE;
  92. UcaKiroCameraPrivate *priv;
  93. g_return_if_fail(UCA_IS_KIRO_CAMERA (camera));
  94. priv = UCA_KIRO_CAMERA_GET_PRIVATE (camera);
  95. g_object_get (G_OBJECT(camera),
  96. "transfer-asynchronously", &transfer_async,
  97. NULL);
  98. //'Cache' ROI settings from TANGO World
  99. g_object_get (G_OBJECT(camera),
  100. "roi-width", &priv->roi_width,
  101. NULL);
  102. g_object_get (G_OBJECT(camera),
  103. "roi-height", &priv->roi_height,
  104. NULL);
  105. size_t bits = 0;
  106. g_object_get (G_OBJECT(camera),
  107. "sensor-bitdepth", &bits,
  108. NULL);
  109. priv->bytes_per_pixel = 1;
  110. if (bits > 8) priv->bytes_per_pixel++;
  111. if (bits > 16) priv->bytes_per_pixel++;
  112. if (bits > 24) priv->bytes_per_pixel++;
  113. Tango::DevState state;
  114. g_object_get (G_OBJECT(camera),
  115. "State", &state,
  116. NULL);
  117. try {
  118. if (Tango::DevState::STANDBY == state)
  119. priv->tango_device->command_inout ("StartRecording");
  120. }
  121. catch (Tango::DevFailed &e) {
  122. g_warning ("Failed to execute 'StartRecording' on the remote camera due to a TANGO exception.\n");
  123. g_set_error (error, UCA_KIRO_CAMERA_ERROR, UCA_KIRO_CAMERA_ERROR_TANGO_EXCEPTION_OCCURED,
  124. "A TANGO exception was raised: '%s'", (const char *)e.errors[0].desc);
  125. return;
  126. }
  127. /*
  128. * In case asynchronous transfer is requested, we start a new thread that
  129. * invokes the grab callback, otherwise nothing will be done here.
  130. */
  131. if (transfer_async) {
  132. GError *tmp_error = NULL;
  133. priv->thread_running = TRUE;
  134. priv->grab_thread = g_thread_create (kiro_grab_func, camera, TRUE, &tmp_error);
  135. if (tmp_error != NULL) {
  136. priv->thread_running = FALSE;
  137. g_propagate_error (error, tmp_error);
  138. try {
  139. priv->tango_device->command_inout ("StopRecording");
  140. }
  141. catch (Tango::DevFailed &e) {
  142. g_warning ("Failed to execute 'StopRecording' on the remote camera due to a TANGO exception: '%s'\n", (const char *)e.errors[0].desc);
  143. }
  144. }
  145. }
  146. kiro_sb_thaw (priv->receive_buffer);
  147. }
  148. static void
  149. uca_kiro_camera_stop_recording(UcaCamera *camera, GError **error)
  150. {
  151. g_return_if_fail(UCA_IS_KIRO_CAMERA (camera));
  152. UcaKiroCameraPrivate *priv;
  153. priv = UCA_KIRO_CAMERA_GET_PRIVATE (camera);
  154. Tango::DevState state;
  155. g_object_get (G_OBJECT(camera),
  156. "State", &state,
  157. NULL);
  158. try {
  159. if (Tango::DevState::RUNNING == state)
  160. priv->tango_device->command_inout ("StopRecording");
  161. }
  162. catch (Tango::DevFailed &e) {
  163. g_warning ("Failed to execute 'StopRecording' on the remote camera due to a TANGO exception.\n");
  164. g_set_error (error, UCA_KIRO_CAMERA_ERROR, UCA_KIRO_CAMERA_ERROR_TANGO_EXCEPTION_OCCURED,
  165. "A TANGO exception was raised: '%s'", (const char *)e.errors[0].desc);
  166. }
  167. gboolean transfer_async = FALSE;
  168. g_object_get(G_OBJECT (camera),
  169. "transfer-asynchronously", &transfer_async,
  170. NULL);
  171. if (transfer_async) {
  172. priv->thread_running = FALSE;
  173. g_thread_join (priv->grab_thread);
  174. }
  175. kiro_sb_freeze (priv->receive_buffer);
  176. g_free (priv->dummy_data);
  177. }
  178. static void
  179. uca_kiro_camera_trigger (UcaCamera *camera, GError **error)
  180. {
  181. }
  182. static gboolean
  183. uca_kiro_camera_grab (UcaCamera *camera, gpointer data, GError **error)
  184. {
  185. g_return_val_if_fail (UCA_IS_KIRO_CAMERA (camera), FALSE);
  186. UcaKiroCameraPrivate *priv = UCA_KIRO_CAMERA_GET_PRIVATE (camera);
  187. //This is a hack to make sure we actually wait for a new frame;
  188. gpointer frame = kiro_sb_get_data_blocking (priv->receive_buffer);
  189. kiro_sb_freeze (priv->receive_buffer);
  190. //Element 0 might still be in the process of being written.
  191. //Therefore, we take Element 1, to be sure this one is finished.
  192. if (data)
  193. g_memmove (data, frame, priv->roi_width * priv->roi_height * priv->bytes_per_pixel);
  194. kiro_sb_thaw (priv->receive_buffer);
  195. return TRUE;
  196. }
  197. // ---------------------------------------------------------- //
  198. // TANGO <-> GLib //
  199. // ---------------------------------------------------------- //
  200. gboolean
  201. unpack_gvaluearray_from_tango (GValue *value, Tango::DeviceAttribute &t_attr, GParamSpec *pspec)
  202. {
  203. GType value_type = ((GParamSpecValueArray*)pspec)->element_spec->value_type;
  204. if (G_TYPE_UINT != value_type) {
  205. g_print ("Array type attribue '%s' holds elements of type '%s' which can't be handled.\n", pspec->name, g_type_name (value_type) );
  206. return FALSE;
  207. }
  208. guint array_length = t_attr.get_dim_x ();
  209. GValueArray *gvalarray = g_value_array_new (array_length);
  210. //Convenience Macro to prevent either having to rewrite this block
  211. //of code over and over again, or creating two almost identical
  212. // switch-cases...
  213. //UNPACK TANGO GVALUEARRAY
  214. #define __U_T_GVA(__GTYPE, __GFUNC) { \
  215. vector<__GTYPE> t_vect; \
  216. t_attr >> t_vect; \
  217. for (guint idx = 0; idx < array_length; idx++) { \
  218. g_value_array_append (gvalarray, NULL); \
  219. GValue *val = g_value_array_get_nth (gvalarray, idx); \
  220. g_value_init (val, value_type); \
  221. __GFUNC (val, t_vect[idx]); \
  222. } \
  223. }
  224. switch (value_type) {
  225. case G_TYPE_BOOLEAN:
  226. //We need to to this manualy since there is no implicit conversion from c++ bool to gboolean
  227. {
  228. vector<bool> t_vect;
  229. t_attr >> t_vect;
  230. for (guint idx = 0; idx < array_length; idx++) {
  231. g_value_array_append (gvalarray, NULL);
  232. GValue *val = g_value_array_get_nth (gvalarray, idx);
  233. g_value_init (val, value_type);
  234. g_value_set_boolean (val, (t_vect[idx] ? TRUE : FALSE));
  235. }
  236. }
  237. break;
  238. case G_TYPE_STRING:
  239. //We need to to this manualy since there is no implicit conversion from c++ string to gchar*
  240. {
  241. vector<string> t_vect;
  242. t_attr >> t_vect;
  243. for (guint idx = 0; idx < array_length; idx++) {
  244. g_value_array_append (gvalarray, NULL);
  245. GValue *val = g_value_array_get_nth (gvalarray, idx);
  246. g_value_init (val, value_type);
  247. g_value_set_string (val, t_vect[idx].c_str ());
  248. }
  249. }
  250. break;
  251. case G_TYPE_UCHAR:
  252. __U_T_GVA (guchar, g_value_set_uchar);
  253. break;
  254. case G_TYPE_INT:
  255. __U_T_GVA (gint, g_value_set_int);
  256. break;
  257. case G_TYPE_UINT:
  258. __U_T_GVA (guint, g_value_set_uint);
  259. break;
  260. case G_TYPE_INT64:
  261. __U_T_GVA (gint64, g_value_set_int64);
  262. break;
  263. case G_TYPE_UINT64:
  264. __U_T_GVA (guint64, g_value_set_uint64);
  265. break;
  266. case G_TYPE_LONG:
  267. __U_T_GVA (glong, g_value_set_long);
  268. break;
  269. case G_TYPE_ULONG:
  270. __U_T_GVA (gulong, g_value_set_ulong);
  271. break;
  272. case G_TYPE_FLOAT:
  273. __U_T_GVA (gfloat, g_value_set_float);
  274. break;
  275. case G_TYPE_DOUBLE:
  276. __U_T_GVA (gdouble, g_value_set_double);
  277. break;
  278. default:
  279. g_print ("Array type attribue '%s' holds elements of type '%s' which can't be handled.\n", pspec->name, g_type_name (value_type) );
  280. return FALSE;
  281. }
  282. g_value_set_boxed_take_ownership (value, gvalarray);
  283. return TRUE;
  284. }
  285. void
  286. try_handle_read_tango_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
  287. {
  288. Tango::DeviceAttribute t_attr;
  289. UcaKiroCamera *camera = UCA_KIRO_CAMERA (object);
  290. UcaKiroCameraPrivate *priv = UCA_KIRO_CAMERA_GET_PRIVATE (camera);
  291. bool property_is_handled = (property_id >= N_PROPERTIES) ? (bool)priv->kiro_dynamic_attributes[property_id] : (bool)kiro_properties[property_id];
  292. if (property_is_handled) {
  293. try {
  294. priv->tango_device->read_attribute (pspec->name, t_attr);
  295. }
  296. catch (Tango::DevFailed &e) {
  297. g_warning ("Property '%s' could not be read due to an unexpected TANGO error...\n", pspec->name);
  298. Tango::Except::print_exception (e);
  299. return;
  300. }
  301. //Stupid workaround for TANGO::State attribute...
  302. //Because they just HAD to make a special case
  303. //for that one specific Enum...
  304. if (0 == g_strcmp0 (pspec->name, "State")) {
  305. Tango::DevState state;
  306. t_attr >> state;
  307. g_value_set_uint (value, (unsigned int)state);
  308. return;
  309. }
  310. //Convenience Macro to prevent having to write this block
  311. //of code over and over again
  312. #define T_TO_G_CONVERT(GTYPE, T_ATTR, FUNCTION, TARGET) { \
  313. GTYPE t_val; \
  314. T_ATTR >> t_val; \
  315. FUNCTION (TARGET, t_val); \
  316. }
  317. // 17.06.2015
  318. // Somehow the implicit conversions from the glib types to any datatype
  319. // known by TANGO got broken. We need to use the explicit C++ types here
  320. // to make TANGO happy and then rely on the implicit conversion back to
  321. // glib types when the call to g_value_set_XXX occurs...
  322. switch (value->g_type) {
  323. case G_TYPE_FLOAT:
  324. T_TO_G_CONVERT (float, t_attr, g_value_set_float, value);
  325. break;
  326. case G_TYPE_DOUBLE:
  327. T_TO_G_CONVERT (double, t_attr, g_value_set_double, value);
  328. break;
  329. case G_TYPE_UCHAR:
  330. T_TO_G_CONVERT (unsigned char, t_attr, g_value_set_uchar, value);
  331. break;
  332. case G_TYPE_INT:
  333. T_TO_G_CONVERT (short int, t_attr, g_value_set_int, value);
  334. break;
  335. case G_TYPE_UINT:
  336. T_TO_G_CONVERT (unsigned short int, t_attr, g_value_set_uint, value);
  337. break;
  338. case G_TYPE_LONG:
  339. T_TO_G_CONVERT (long int, t_attr, g_value_set_long, value);
  340. break;
  341. case G_TYPE_ULONG:
  342. T_TO_G_CONVERT (unsigned long int, t_attr, g_value_set_ulong, value);
  343. break;
  344. case G_TYPE_INT64:
  345. T_TO_G_CONVERT (int64_t, t_attr, g_value_set_int64, value);
  346. break;
  347. case G_TYPE_UINT64:
  348. T_TO_G_CONVERT (uint64_t, t_attr, g_value_set_uint64, value);
  349. break;
  350. case G_TYPE_BOOLEAN:
  351. {
  352. bool t_val;
  353. t_attr >> t_val;
  354. g_value_set_boolean (value, (t_val ? TRUE : FALSE));
  355. }
  356. break;
  357. case G_TYPE_STRING:
  358. {
  359. string t_val;
  360. t_attr >> t_val;
  361. g_value_set_string (value, t_val.c_str ());
  362. }
  363. break;
  364. default:
  365. {
  366. if (g_type_parent (value->g_type) == G_TYPE_ENUM) {
  367. T_TO_G_CONVERT (gint, t_attr, g_value_set_enum, value);
  368. break;
  369. }
  370. if (G_TYPE_VALUE_ARRAY == value->g_type) {
  371. if (Tango::AttrDataFormat::SPECTRUM != t_attr.get_data_format ()) {
  372. g_warning ("TANGO attribute '%s' is not of type SPECTRUM! (Not a 1-dimensional array, yet libuca was expecting one.)\n", pspec->name);
  373. return;
  374. }
  375. if (0 == unpack_gvaluearray_from_tango (value, t_attr, pspec))
  376. g_warning ("Failed to read property '%s'\n", pspec->name);
  377. return;
  378. }
  379. GType unhandled = pspec->value_type;
  380. if (G_TYPE_GTYPE == unhandled) {
  381. unhandled = ((GParamSpecGType*)pspec)->is_a_type;
  382. }
  383. g_print ("GType '%s' can't be handled...\n", g_type_name (unhandled));
  384. G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
  385. }
  386. }
  387. }
  388. else {
  389. g_print ("Unhandled property...\n");
  390. G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
  391. }
  392. #undef T_TO_G_CONVERT
  393. }
  394. gboolean
  395. pack_gvaluearray_to_tango (const GValue *value, Tango::DeviceAttribute &t_attr, GParamSpec *pspec)
  396. {
  397. GType value_type = ((GParamSpecValueArray*)pspec)->element_spec->value_type;
  398. GValueArray *gvalarray = (GValueArray *) g_value_get_boxed (value);
  399. guint array_length = gvalarray->n_values;
  400. //Convenience Macro to prevent either having to rewrite this block
  401. //of code over and over again, or creating two almost identical
  402. // switch-cases...
  403. #define __P_GVA_T(__GTYPE, __GFUNC) { \
  404. vector<__GTYPE> t_vect (array_length); \
  405. for (guint idx = 0; idx < array_length; idx++) { \
  406. GValue *val = g_value_array_get_nth (gvalarray, idx); \
  407. t_vect[idx] = __GFUNC (val); \
  408. } \
  409. t_attr << t_vect; \
  410. }
  411. switch (value_type) {
  412. case G_TYPE_BOOLEAN:
  413. __P_GVA_T (bool, g_value_get_boolean); //This relys on the implicit conversion from int to c++ bool
  414. break;
  415. case G_TYPE_UCHAR:
  416. __P_GVA_T (guchar, g_value_get_uchar);
  417. break;
  418. case G_TYPE_STRING:
  419. __P_GVA_T (string, g_value_get_string); //This relys on the implicit conversion from char* to c++ string
  420. break;
  421. case G_TYPE_INT:
  422. __P_GVA_T (gint, g_value_get_int);
  423. break;
  424. case G_TYPE_UINT:
  425. __P_GVA_T (guint, g_value_get_uint);
  426. break;
  427. case G_TYPE_INT64:
  428. __P_GVA_T (gint64, g_value_get_int64);
  429. break;
  430. case G_TYPE_UINT64:
  431. __P_GVA_T (guint64, g_value_get_uint64);
  432. break;
  433. case G_TYPE_LONG:
  434. __P_GVA_T (glong, g_value_get_long);
  435. break;
  436. case G_TYPE_ULONG:
  437. __P_GVA_T (gulong, g_value_get_ulong);
  438. break;
  439. case G_TYPE_FLOAT:
  440. __P_GVA_T (gfloat, g_value_get_float);
  441. break;
  442. case G_TYPE_DOUBLE:
  443. __P_GVA_T (gdouble, g_value_get_double);
  444. break;
  445. default:
  446. g_print ("Array type attribue '%s' holds elements of type '%s' which can't be handled.\n", pspec->name, g_type_name (value_type) );
  447. return FALSE;
  448. }
  449. t_attr.data_format = Tango::AttrDataFormat::SPECTRUM;
  450. t_attr.dim_x = array_length;
  451. return TRUE;
  452. #undef __P_GVA_T
  453. }
  454. void
  455. try_handle_write_tango_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
  456. {
  457. Tango::DeviceAttribute t_attr;
  458. UcaKiroCamera *camera = UCA_KIRO_CAMERA (object);
  459. UcaKiroCameraPrivate *priv = UCA_KIRO_CAMERA_GET_PRIVATE (camera);
  460. bool property_is_handled = (property_id > N_PROPERTIES) ? (bool)priv->kiro_dynamic_attributes[property_id] : (bool)kiro_properties[property_id];
  461. if (property_is_handled) {
  462. // 17.06.2015
  463. // Implicit conversions from glib types to TANGO C++ types are broken.
  464. // We need to to a manual cast for each one to make TANGO happy again...
  465. switch (value->g_type) {
  466. case G_TYPE_BOOLEAN:
  467. {
  468. bool t_val = (g_value_get_boolean (value) == TRUE);
  469. t_attr << t_val;
  470. }
  471. break;
  472. case G_TYPE_INT:
  473. t_attr << (int)g_value_get_int (value);
  474. break;
  475. case G_TYPE_FLOAT:
  476. t_attr << (float)g_value_get_float (value);
  477. break;
  478. case G_TYPE_DOUBLE:
  479. t_attr << (double)g_value_get_double (value);
  480. break;
  481. case G_TYPE_UINT:
  482. t_attr << (unsigned short int)g_value_get_uint (value);
  483. break;
  484. case G_TYPE_ULONG:
  485. t_attr << (unsigned long int)g_value_get_ulong (value);
  486. break;
  487. case G_TYPE_STRING:
  488. t_attr << g_value_get_string (value);
  489. break;
  490. case G_TYPE_UCHAR:
  491. t_attr << (unsigned char)g_value_get_uchar (value);
  492. break;
  493. case G_TYPE_INT64:
  494. t_attr << (int64_t)g_value_get_int64 (value);
  495. break;
  496. case G_TYPE_UINT64:
  497. t_attr << (uint64_t)g_value_get_uint64 (value);
  498. break;
  499. case G_TYPE_LONG:
  500. t_attr << (long int)g_value_get_long (value);
  501. break;
  502. case G_TYPE_ENUM:
  503. t_attr << g_value_get_enum (value);
  504. break;
  505. default:
  506. {
  507. if (g_type_parent (value->g_type) == G_TYPE_ENUM) {
  508. t_attr << g_value_get_enum (value);
  509. break;
  510. }
  511. if (value->g_type == G_TYPE_VALUE_ARRAY) {
  512. if (0 == pack_gvaluearray_to_tango (value, t_attr, pspec)) {
  513. g_warning ("Failed to write property '%s'.\n", pspec->name);
  514. return;
  515. }
  516. break;
  517. }
  518. GType unhandled = value->g_type;
  519. if (G_TYPE_GTYPE == unhandled) {
  520. unhandled = ((GParamSpecGType*)pspec)->is_a_type;
  521. }
  522. g_print ("GType '%s' can't be handled...\n", g_type_name (unhandled));
  523. G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
  524. }
  525. break;
  526. }
  527. t_attr.set_name (pspec->name);
  528. try {
  529. priv->tango_device->write_attribute (t_attr);
  530. }
  531. catch (Tango::DevFailed &e) {
  532. g_warning ("Property '%s' could not be written due to a TANGO exception: '%s'\n", pspec->name, (const char *)e.errors[0].desc);
  533. Tango::Except::print_exception (e);
  534. return;
  535. }
  536. }
  537. else
  538. G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
  539. }
  540. GType
  541. gtype_from_tango_type (Tango::CmdArgType t)
  542. {
  543. using namespace Tango;
  544. switch (t) {
  545. case DEV_VOID:
  546. return G_TYPE_NONE;
  547. case DEV_BOOLEAN:
  548. return G_TYPE_BOOLEAN;
  549. case DEV_SHORT:
  550. //Fall-through intentional
  551. case DEV_INT:
  552. //Fall-through intentional
  553. case DEV_LONG:
  554. return G_TYPE_INT;
  555. case DEV_FLOAT:
  556. return G_TYPE_FLOAT;
  557. case DEV_DOUBLE:
  558. return G_TYPE_DOUBLE;
  559. case DEV_ULONG:
  560. //return G_TYPE_ULONG;
  561. //Fall-through intentional
  562. //NOTE: There seems to be a bug somewhere either in TANGO or in GLib or in Pyhton that
  563. //Breaks the functionality of the G_TYPE_ULONG properties. Using a G_TYPE_UINT instead
  564. //works around this problem but might provoke potential overflows...
  565. case DEV_USHORT:
  566. return G_TYPE_UINT;
  567. case CONST_DEV_STRING:
  568. //Fall-through intentional
  569. case DEV_STRING:
  570. return G_TYPE_STRING;
  571. case DEV_UCHAR:
  572. return G_TYPE_UCHAR;
  573. case DEV_LONG64:
  574. return G_TYPE_INT64;
  575. case DEV_ULONG64:
  576. return G_TYPE_UINT64;
  577. case DEV_STATE:
  578. return G_TYPE_UINT;
  579. /*
  580. DEV_ENCODED
  581. DEVVAR_CHARARRAY
  582. DEVVAR_SHORTARRAY
  583. DEVVAR_LONGARRAY
  584. DEVVAR_FLOATARRAY
  585. DEVVAR_DOUBLEARRAY
  586. DEVVAR_USHORTARRAY
  587. DEVVAR_ULONGARRAY
  588. DEVVAR_STRINGARRAY
  589. DEVVAR_LONGSTRINGARRAY
  590. DEVVAR_DOUBLESTRINGARRAY
  591. DEVVAR_BOOLEANARRAY
  592. DEVVAR_LONG64ARRAY
  593. DEVVAR_ULONG64ARRAY
  594. */
  595. default:
  596. return G_TYPE_INVALID;
  597. };
  598. }
  599. gint
  600. get_property_id_from_name(const gchar* name)
  601. {
  602. guint idx = 0;
  603. gboolean found = FALSE;
  604. for (;idx < N_PROPERTIES; ++idx) {
  605. if (0 == g_strcmp0(name, uca_camera_props[idx])) {
  606. found = TRUE;
  607. break;
  608. }
  609. }
  610. return (TRUE == found) ? idx : -1;
  611. }
  612. void
  613. build_param_spec(GParamSpec **pspec, const Tango::AttributeInfoEx *attrInfo)
  614. {
  615. GType type = gtype_from_tango_type ((Tango::CmdArgType)attrInfo->data_type);
  616. const gchar *name = attrInfo->name.c_str ();
  617. GParamFlags flags = G_PARAM_READABLE;
  618. if (attrInfo->writable == Tango::AttrWriteType::WRITE)
  619. flags = (GParamFlags) G_PARAM_READWRITE;
  620. //Convenience Macro to prevent having to rewrite this block
  621. //of code over and over again..
  622. #define __M_PSCPEC(__SPEC_TYPE, __LIMITS_1, __LIMITS_2, __LIMITS_3) { \
  623. *pspec = \
  624. __SPEC_TYPE (name, \
  625. attrInfo->description.c_str (), \
  626. g_strconcat ("KIRO TANGO <-> GLib interface of ", name, NULL), \
  627. __LIMITS_1, __LIMITS_2, __LIMITS_3,\
  628. flags); \
  629. }
  630. switch (type) {
  631. case G_TYPE_INT:
  632. __M_PSCPEC (g_param_spec_int, G_MININT32, G_MAXINT32, 0);
  633. break;
  634. case G_TYPE_FLOAT:
  635. __M_PSCPEC (g_param_spec_float, G_MINFLOAT, G_MAXFLOAT, 0.);
  636. break;
  637. case G_TYPE_DOUBLE:
  638. __M_PSCPEC (g_param_spec_double, G_MINDOUBLE, G_MAXDOUBLE, 0.)
  639. break;
  640. case G_TYPE_UINT:
  641. __M_PSCPEC (g_param_spec_uint, 0, G_MAXUINT, 0)
  642. break;
  643. case G_TYPE_ULONG:
  644. __M_PSCPEC (g_param_spec_ulong, 0, G_MAXULONG, 0)
  645. break;
  646. case G_TYPE_UCHAR:
  647. __M_PSCPEC (g_param_spec_uchar, 0x00, 0xff, 0x42)
  648. break;
  649. case G_TYPE_INT64:
  650. __M_PSCPEC (g_param_spec_int64, G_MININT64, G_MAXINT64, 0)
  651. break;
  652. case G_TYPE_UINT64:
  653. __M_PSCPEC (g_param_spec_uint64, 0, G_MAXUINT64, 0)
  654. break;
  655. case G_TYPE_LONG:
  656. __M_PSCPEC (g_param_spec_long, G_MININT64, G_MAXINT64, 1)
  657. break;
  658. case G_TYPE_ENUM:
  659. __M_PSCPEC (g_param_spec_int, 0, G_MAXUINT, 0)
  660. break;
  661. case G_TYPE_STRING:
  662. *pspec =
  663. g_param_spec_string (name,
  664. attrInfo->description.c_str (),
  665. g_strconcat ("KIRO TANGO <-> GLib interface of ", name, NULL),
  666. "DEFAULT",
  667. flags);
  668. break;
  669. case G_TYPE_BOOLEAN:
  670. *pspec =
  671. g_param_spec_boolean (name,
  672. attrInfo->description.c_str (),
  673. g_strconcat ("KIRO TANGO <-> GLib interface of ", name, NULL),
  674. FALSE,
  675. flags);
  676. break;
  677. default:
  678. *pspec =
  679. g_param_spec_gtype (name,
  680. attrInfo->description.c_str (),
  681. g_strconcat ("KIRO TANGO <-> GLib interface of ", name, NULL),
  682. type,
  683. flags);
  684. }
  685. #undef __M_PSCPEC
  686. }
  687. void
  688. uca_kiro_camera_clone_interface(const gchar* address, UcaKiroCamera *kiro_camera)
  689. {
  690. UcaKiroCameraPrivate *priv = UCA_KIRO_CAMERA_GET_PRIVATE (kiro_camera);
  691. UcaKiroCameraClass *klass = UCA_KIRO_CAMERA_GET_CLASS (kiro_camera);
  692. GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
  693. gboolean start_found, stop_found, readout_found, unit_found = FALSE;
  694. try {
  695. Tango::CommandInfoList *cmd_list = priv->tango_device->command_list_query ();
  696. for (vector<Tango::CommandInfo>::iterator iter = cmd_list->begin (); iter != cmd_list->end (); ++iter) {
  697. gint start_cmp = g_strcmp0((*iter).cmd_name.c_str (), "StartRecording");
  698. if (0 == start_cmp) {
  699. start_found = TRUE;
  700. }
  701. gint stop_cmp = g_strcmp0 ((*iter).cmd_name.c_str (), "StopRecording");
  702. if (0 == stop_cmp) {
  703. stop_found = TRUE;
  704. }
  705. gint unit_cmp = g_strcmp0((*iter).cmd_name.c_str (), "GetAttributeUnit");
  706. if (0 == unit_cmp) {
  707. unit_found = TRUE;
  708. }
  709. gint readout_cmp = g_strcmp0((*iter).cmd_name.c_str (), "Readout");
  710. if (0 == readout_cmp) {
  711. readout_found = TRUE;
  712. }
  713. }
  714. if ( !start_found || !stop_found ) {
  715. g_warning ("The Server at '%s' does not provide the necessary 'StartRecording' and 'StopRecording' interface\n", priv->kiro_tango_address);
  716. g_set_error (&initable_iface_error, UCA_KIRO_CAMERA_ERROR, UCA_KIRO_CAMERA_ERROR_BAD_CAMERA_INTERFACE,
  717. "The Server at '%s' does not provide the necessary 'StartRecording' and 'StopRecording' interface\n", priv->kiro_tango_address);
  718. priv->construction_error = TRUE;
  719. return;
  720. }
  721. vector<string> *attr_list = priv->tango_device->get_attribute_list ();
  722. GList *non_base_attributes = NULL;
  723. guint non_base_attributes_count = 0;
  724. for (vector<string>::iterator iter = attr_list->begin (); iter != attr_list->end (); ++iter) {
  725. Tango::AttributeInfoEx attrInfo = priv->tango_device->attribute_query (*iter);
  726. gint uca_base_prop_id = get_property_id_from_name ((*iter).c_str ());
  727. if (-1 < uca_base_prop_id) {
  728. guint is_name_attr = g_strcmp0 ((*iter).c_str (), "name");
  729. if (0 == is_name_attr) {
  730. Tango::DeviceAttribute t_attr;
  731. priv->tango_device->read_attribute ("name", t_attr);
  732. string reply_name;
  733. t_attr >> reply_name;
  734. g_free (priv->remote_name);
  735. priv->remote_name = g_strdup (reply_name.c_str ());
  736. }
  737. kiro_properties[uca_base_prop_id] = g_object_class_find_property (gobject_class, uca_camera_props[uca_base_prop_id]);
  738. g_object_class_override_property(G_OBJECT_CLASS (UCA_KIRO_CAMERA_GET_CLASS (kiro_camera)), uca_base_prop_id, uca_camera_props[uca_base_prop_id]);
  739. }
  740. else {
  741. non_base_attributes = g_list_append (non_base_attributes, (gpointer)(*iter).c_str ());
  742. non_base_attributes_count++;
  743. }
  744. }
  745. if (non_base_attributes_count > 0) {
  746. priv->kiro_dynamic_attributes = new GParamSpec* [N_PROPERTIES + non_base_attributes_count];
  747. UcaKiroCameraClass *klass = UCA_KIRO_CAMERA_GET_CLASS (kiro_camera);
  748. GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
  749. for (guint idx = 0; idx < non_base_attributes_count; idx++) {
  750. const gchar *attr_name = (const gchar*)g_list_nth_data (non_base_attributes, idx);
  751. Tango::AttributeInfoEx attrInfo = priv->tango_device->attribute_query (string(attr_name));
  752. if (Tango::AttrDataFormat::IMAGE == attrInfo.data_format || Tango::AttrDataFormat::FMT_UNKNOWN == attrInfo.data_format) {
  753. g_print ("Attribute '%s' has unknown DataFormat. Skipping.\n", attr_name);
  754. continue;
  755. }
  756. build_param_spec (&(priv->kiro_dynamic_attributes[N_PROPERTIES + idx]), &attrInfo);
  757. g_object_class_install_property (gobject_class, N_PROPERTIES + idx, priv->kiro_dynamic_attributes[N_PROPERTIES + idx]);
  758. if (unit_found) {
  759. Tango::DeviceData arg_name;
  760. arg_name << attr_name;
  761. Tango::DeviceData cmd_reply = priv->tango_device->command_inout("GetAttributeUnit", arg_name);
  762. gint unit;
  763. cmd_reply >> unit;
  764. uca_camera_register_unit (UCA_CAMERA (kiro_camera), attr_name, (UcaUnit)unit);
  765. }
  766. }
  767. }
  768. }
  769. catch (Tango::DevFailed &e) {
  770. Tango::Except::print_exception (e);
  771. g_set_error (&initable_iface_error, UCA_KIRO_CAMERA_ERROR, UCA_KIRO_CAMERA_ERROR_TANGO_EXCEPTION_OCCURED,
  772. "A TANGO exception was raised: '%s'", (const char *)e.errors[0].desc);
  773. priv->construction_error = TRUE;
  774. }
  775. }
  776. // ---------------------------------------------------------- //
  777. // END: TANGO <-> GLib //
  778. // ---------------------------------------------------------- //
  779. static void
  780. uca_kiro_camera_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
  781. {
  782. g_return_if_fail(UCA_IS_KIRO_CAMERA (object));
  783. UcaKiroCameraPrivate *priv = UCA_KIRO_CAMERA_GET_PRIVATE (object);
  784. switch (property_id) {
  785. case PROP_KIRO_TANGO_ADDRESS:
  786. priv->kiro_tango_address = g_value_dup_string (value);
  787. break;
  788. default:
  789. try_handle_write_tango_property (object, property_id, value, pspec);
  790. return;
  791. }
  792. }
  793. static void
  794. uca_kiro_camera_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
  795. {
  796. UcaKiroCameraPrivate *priv = UCA_KIRO_CAMERA_GET_PRIVATE (object);
  797. switch (property_id) {
  798. case PROP_NAME:
  799. g_value_set_string (value, "KIRO camera");
  800. break;
  801. case PROP_KIRO_ADDRESS:
  802. g_value_set_string (value, priv->kiro_address);
  803. break;
  804. case PROP_KIRO_PORT:
  805. g_value_set_uint (value, priv->kiro_port_uint);
  806. break;
  807. case PROP_KIRO_TANGO_ADDRESS:
  808. g_value_set_string (value, priv->kiro_tango_address);
  809. break;
  810. case PROP_KIRO_REMOTE_NAME:
  811. g_value_set_string (value, priv->remote_name);
  812. break;
  813. default:
  814. try_handle_read_tango_property (object, property_id, value, pspec);
  815. break;
  816. }
  817. }
  818. static void
  819. uca_kiro_camera_finalize(GObject *object)
  820. {
  821. UcaKiroCameraPrivate *priv = UCA_KIRO_CAMERA_GET_PRIVATE(object);
  822. if (priv->thread_running) {
  823. priv->thread_running = FALSE;
  824. g_thread_join (priv->grab_thread);
  825. }
  826. if (priv->receive_buffer) {
  827. kiro_sb_free (priv->receive_buffer);
  828. priv->receive_buffer = NULL;
  829. }
  830. priv->kiro_connected = FALSE;
  831. if (priv->dummy_data) {
  832. g_free (priv->dummy_data);
  833. priv->dummy_data = NULL;
  834. }
  835. if (priv->tango_device) {
  836. delete (priv->tango_device);
  837. priv->tango_device = NULL;
  838. }
  839. g_free (priv->kiro_address);
  840. g_free (priv->kiro_port);
  841. g_free (priv->kiro_tango_address);
  842. G_OBJECT_CLASS (uca_kiro_camera_parent_class)->finalize(object);
  843. }
  844. static gboolean
  845. ufo_kiro_camera_initable_init (GInitable *initable,
  846. GCancellable *cancellable,
  847. GError **error)
  848. {
  849. g_return_val_if_fail (UCA_IS_KIRO_CAMERA (initable), FALSE);
  850. UcaKiroCameraPrivate *priv = UCA_KIRO_CAMERA_GET_PRIVATE (UCA_KIRO_CAMERA (initable));
  851. if(priv->construction_error) {
  852. g_propagate_error (error, initable_iface_error);
  853. return FALSE;
  854. }
  855. return TRUE;
  856. }
  857. static void
  858. uca_kiro_initable_iface_init (GInitableIface *iface)
  859. {
  860. iface->init = ufo_kiro_camera_initable_init;
  861. }
  862. static void
  863. uca_kiro_camera_constructed (GObject *object)
  864. {
  865. //Initialization for the KIRO Server and TANGO Interface cloning is moved
  866. //here and done early!
  867. //We want to add dynamic properties and it is too late to do so in the
  868. //real initable part. Therefore, we do it here and 'remember' any errors
  869. //that occur and check them later in the initable part.
  870. UcaKiroCamera *self = UCA_KIRO_CAMERA (object);
  871. UcaKiroCameraPrivate *priv = UCA_KIRO_CAMERA_GET_PRIVATE (self);
  872. GValue address = G_VALUE_INIT;
  873. g_value_init(&address, G_TYPE_STRING);
  874. uca_kiro_camera_get_property (object, PROP_KIRO_TANGO_ADDRESS, &address, NULL);
  875. gint address_not_none = g_strcmp0(g_value_get_string (&address), "NONE");
  876. if (0 == address_not_none) {
  877. g_warning ("kiro-tango-address was not set! Can not connect to server...\n");
  878. priv->construction_error = TRUE;
  879. g_set_error (&initable_iface_error, UCA_KIRO_CAMERA_ERROR, UCA_KIRO_CAMERA_ERROR_MISSING_TANGO_ADDRESS,
  880. "'kiro-tango-address' property was not set during construction.");
  881. }
  882. else {
  883. try {
  884. priv->tango_device = new Tango::DeviceProxy(g_value_get_string (&address));
  885. Tango::DbData kiro_credentials;
  886. kiro_credentials.push_back (Tango::DbDatum("KiroAddress"));
  887. kiro_credentials.push_back (Tango::DbDatum("KiroPort"));
  888. priv->tango_device->get_property(kiro_credentials);
  889. string kiro_address, kiro_port;
  890. kiro_credentials[0] >> kiro_address;
  891. kiro_credentials[1] >> kiro_port;
  892. if (0 > kiro_sb_clone (priv->receive_buffer, kiro_address.c_str (), kiro_port.c_str ())) {
  893. g_warning ("Unable to connect to server at address: %s, port: %s\n", kiro_address.c_str (), kiro_port.c_str ());
  894. priv->construction_error = TRUE;
  895. g_set_error (&initable_iface_error, UCA_KIRO_CAMERA_ERROR, UCA_KIRO_CAMERA_ERROR_KIRO_CONNECTION_FAILED,
  896. "Failed to establish a KIRO InfiniBand connection.");
  897. }
  898. else {
  899. priv->kiro_connected = TRUE;
  900. uca_kiro_camera_clone_interface (g_value_get_string (&address), self);
  901. }
  902. }
  903. catch (Tango::DevFailed &e) {
  904. Tango::Except::print_exception (e);
  905. g_set_error (&initable_iface_error, UCA_KIRO_CAMERA_ERROR, UCA_KIRO_CAMERA_ERROR_TANGO_EXCEPTION_OCCURED,
  906. "A TANGO exception was raised: '%s'", (const char *)e.errors[0].desc);
  907. priv->construction_error = TRUE;
  908. }
  909. }
  910. G_OBJECT_CLASS (uca_kiro_camera_parent_class)->constructed(object);
  911. }
  912. static void
  913. uca_kiro_camera_class_init(UcaKiroCameraClass *klass)
  914. {
  915. GObjectClass *gobject_class = G_OBJECT_CLASS( klass);
  916. gobject_class->set_property = uca_kiro_camera_set_property;
  917. gobject_class->get_property = uca_kiro_camera_get_property;
  918. gobject_class->finalize = uca_kiro_camera_finalize;
  919. gobject_class->constructed = uca_kiro_camera_constructed;
  920. UcaCameraClass *camera_class = UCA_CAMERA_CLASS (klass);
  921. camera_class->start_recording = uca_kiro_camera_start_recording;
  922. camera_class->stop_recording = uca_kiro_camera_stop_recording;
  923. camera_class->grab = uca_kiro_camera_grab;
  924. camera_class->trigger = uca_kiro_camera_trigger;
  925. for (guint i = 0; kiro_overrideables[i] != 0; i++)
  926. g_object_class_override_property (gobject_class, kiro_overrideables[i], uca_camera_props[kiro_overrideables[i]]);
  927. kiro_properties[PROP_KIRO_ADDRESS] =
  928. g_param_spec_string("kiro-address",
  929. "KIRO Server Address",
  930. "Address of the KIRO Server to grab images from",
  931. "NONE",
  932. G_PARAM_READABLE);
  933. kiro_properties[PROP_KIRO_PORT] =
  934. g_param_spec_uint("kiro-port",
  935. "KIRO Server Port",
  936. "Port of the KIRO Server to grab images from",
  937. 1, 65535, 60010,
  938. G_PARAM_READABLE);
  939. kiro_properties[PROP_KIRO_TANGO_ADDRESS] =
  940. g_param_spec_string("kiro-tango-address",
  941. "KIRO TANGO address",
  942. "Address of the KIRO Server in the TANGO environment",
  943. "NONE",
  944. (GParamFlags) (G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
  945. kiro_properties[PROP_KIRO_REMOTE_NAME] =
  946. g_param_spec_string("remote-name",
  947. "Name of the remot camera",
  948. "Name of the camera plugin that is loaded on the KIRO remote site",
  949. "NONE",
  950. G_PARAM_READABLE);
  951. for (guint id = N_BASE_PROPERTIES; id < N_PROPERTIES; id++)
  952. g_object_class_install_property (gobject_class, id, kiro_properties[id]);
  953. g_type_class_add_private (klass, sizeof(UcaKiroCameraPrivate));
  954. }
  955. static void
  956. uca_kiro_camera_init(UcaKiroCamera *self)
  957. {
  958. self->priv = UCA_KIRO_CAMERA_GET_PRIVATE(self);
  959. self->priv->grab_thread = NULL;
  960. self->priv->current_frame = 0;
  961. self->priv->kiro_address = g_strdup ("NONE");
  962. self->priv->kiro_port = g_strdup ("NONE");
  963. self->priv->remote_name = g_strdup ("NONE");
  964. self->priv->kiro_port_uint = 60010;
  965. self->priv->kiro_tango_address = g_strdup ("NONE");
  966. self->priv->construction_error = FALSE;
  967. self->priv->kiro_dynamic_attributes = NULL;
  968. self->priv->receive_buffer = kiro_sb_new ();
  969. kiro_sb_freeze (self->priv->receive_buffer);
  970. }
  971. G_MODULE_EXPORT GType
  972. uca_camera_get_type (void)
  973. {
  974. return UCA_TYPE_KIRO_CAMERA;
  975. }