kiro-camera-server.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433
  1. /* Copyright (C) 2015 Timo Dritschler <timo.dritschler@kit.edu>
  2. (Karlsruhe Institute of Technology)
  3. This program 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. */
  15. #include <stdlib.h>
  16. #include <string.h>
  17. #include <unistd.h>
  18. #include "uca-kiro-camera.h"
  19. #include "uca/uca-plugin-manager.h"
  20. typedef struct {
  21. gboolean exit_flag;
  22. UcaCamera *cam;
  23. KiroMessenger *messenger;
  24. gulong peer_rank;
  25. gulong *signal_handlers;
  26. GParamSpec **properties;
  27. guint n_properties;
  28. KiroRequest *peer_update_request;
  29. } KiroCsData;
  30. static gulong
  31. pspec_size (GType type)
  32. {
  33. gulong ret = 0;
  34. switch (type) {
  35. case G_TYPE_BOOLEAN:
  36. ret = sizeof (GParamSpecBoolean);
  37. break;
  38. case G_TYPE_CHAR:
  39. ret = sizeof (GParamSpecChar);
  40. break;
  41. case G_TYPE_INT:
  42. ret = sizeof (GParamSpecInt);
  43. break;
  44. case G_TYPE_UINT:
  45. ret = sizeof (GParamSpecUInt);
  46. break;
  47. case G_TYPE_LONG:
  48. ret = sizeof (GParamSpecLong);
  49. break;
  50. case G_TYPE_ULONG:
  51. ret = sizeof (GParamSpecULong);
  52. break;
  53. case G_TYPE_INT64:
  54. ret = sizeof (GParamSpecInt64);
  55. break;
  56. case G_TYPE_UINT64:
  57. ret = sizeof (GParamSpecUInt64);
  58. break;
  59. case G_TYPE_FLOAT:
  60. ret = sizeof (GParamSpecFloat);
  61. break;
  62. case G_TYPE_DOUBLE:
  63. ret = sizeof (GParamSpecDouble);
  64. break;
  65. default:
  66. ret = sizeof (GParamSpec);
  67. }
  68. return ret;
  69. }
  70. static gulong
  71. gtype_size (GType type)
  72. {
  73. gulong ret = 0;
  74. switch (type) {
  75. case G_TYPE_BOOLEAN:
  76. ret = sizeof (gboolean);
  77. break;
  78. case G_TYPE_CHAR:
  79. ret = sizeof (gchar);
  80. break;
  81. case G_TYPE_INT:
  82. ret = sizeof (gint);
  83. break;
  84. case G_TYPE_ENUM:
  85. ret = sizeof (gint);
  86. break;
  87. case G_TYPE_UINT:
  88. ret = sizeof (guint);
  89. break;
  90. case G_TYPE_LONG:
  91. ret = sizeof (glong);
  92. break;
  93. case G_TYPE_ULONG:
  94. ret = sizeof (gulong);
  95. break;
  96. case G_TYPE_INT64:
  97. ret = sizeof (gint64);
  98. break;
  99. case G_TYPE_UINT64:
  100. ret = sizeof (guint64);
  101. break;
  102. case G_TYPE_FLOAT:
  103. ret = sizeof (gfloat);
  104. break;
  105. case G_TYPE_DOUBLE:
  106. ret = sizeof (gdouble);
  107. break;
  108. default:
  109. //ERROR
  110. break;
  111. }
  112. return ret;
  113. }
  114. static void
  115. print_cam_name (gchar *name, gpointer unused)
  116. {
  117. (void) unused;
  118. g_print ("-- %s\n", name);
  119. }
  120. static void
  121. send_clear_callback (KiroRequest *request, gpointer data)
  122. {
  123. (void) data;
  124. if (request->status != KIRO_MESSAGE_SEND_SUCCESS)
  125. g_error ("OH SHIT!");
  126. else
  127. g_debug ("Peer informed successfully");
  128. if (request->message->payload)
  129. g_free (request->message->payload);
  130. g_free (request->message);
  131. g_free (request);
  132. }
  133. static void
  134. peer_inform_update (UcaCamera *cam, GParamSpec *pspec, KiroCsData *data)
  135. {
  136. g_print ("Updated %s.\n", pspec->name);
  137. gpointer buff = g_malloc0 (sizeof (guint64));
  138. g_object_get (G_OBJECT (cam),
  139. pspec->name, buff,
  140. NULL);
  141. KiroMessage *message = g_malloc0 (sizeof (KiroMessage));
  142. message->msg = KIROCS_UPDATE;
  143. message->size = sizeof (PropUpdateScalar);
  144. message->payload = g_malloc0 (message->size);
  145. PropUpdateScalar *update = message->payload;
  146. update->base.id = property_id_from_name (pspec->name, data->n_properties, data->properties);
  147. update->base.size = 1;
  148. update->base.scalar = TRUE;
  149. memcpy (&update->prop_raw, buff, sizeof (guint64));
  150. GError *error = NULL;
  151. kiro_messenger_send_blocking (data->messenger, message, data->peer_rank, &error);
  152. if (error) {
  153. g_free (message);
  154. g_error ("Oh shit! (%s)", error->message);
  155. g_error_free (error);
  156. }
  157. }
  158. static gulong
  159. setup_signal_handler (UcaCamera *cam, GParamSpec *pspec, KiroCsData *data)
  160. {
  161. GString *signal_name = g_string_new ("notify::");
  162. signal_name = g_string_append (signal_name, pspec->name);
  163. gulong ret = g_signal_connect (cam, signal_name->str, G_CALLBACK (peer_inform_update), data);
  164. g_string_free (signal_name, TRUE);
  165. return ret;
  166. }
  167. static KiroContinueFlag
  168. connect_callback (gulong rank, gulong *storage)
  169. {
  170. *storage = rank;
  171. return KIRO_CALLBACK_REMOVE;
  172. }
  173. // MAIN HANDLER //
  174. static void
  175. receive_callback (KiroRequest *request, KiroCsData *data)
  176. {
  177. if (request->message->msg == KIROCS_EXIT) {
  178. g_message ("Peer requested shut down...");
  179. data->exit_flag = TRUE;
  180. }
  181. if (request->message->msg == KIROCS_UPDATE) {
  182. PropUpdate *update = (PropUpdate *)request->message->payload;
  183. g_signal_handler_block (data->cam, data->signal_handlers[update->id]);
  184. //Don't forget the -1, because the index starts at 0, but property IDs
  185. //start at 1...
  186. const gchar *name = data->properties[update->id -1]->name;
  187. g_debug ("Unpacking '%s' with ID %u\n", name, update->id);
  188. if (update->scalar == TRUE) {
  189. PropUpdateScalar *scalar_update = (PropUpdateScalar *)update;
  190. GValue tmp = G_VALUE_INIT;
  191. g_value_init (&tmp, data->properties[update->id -1]->value_type);
  192. g_value_set_from_raw_data (&tmp, &scalar_update->prop_raw);
  193. g_object_set_property (G_OBJECT (data->cam), name, &tmp);
  194. }
  195. g_signal_handler_unblock (data->cam, data->signal_handlers[update->id]);
  196. g_debug ("Done.");
  197. }
  198. if (request->message->msg == KIROCS_FETCH) {
  199. gchar* property_name = (gchar *)request->message->payload;
  200. KiroRequest *request = g_malloc0 (sizeof (KiroRequest));
  201. request->peer_rank = data->peer_rank;
  202. request->callback = send_clear_callback;
  203. request->user_data = NULL;
  204. request->message = g_malloc0 (sizeof (KiroMessage));
  205. request->message->msg = KIROCS_UPDATE;
  206. request->message->size = sizeof (PropUpdateScalar);
  207. request->message->payload = g_malloc0 (request->message->size);
  208. PropUpdateScalar *update = (PropUpdateScalar *)request->message->payload;
  209. g_object_get (data->cam, property_name, &update->prop_raw, NULL);
  210. update->base.id = property_id_from_name (property_name, data->n_properties, data->properties);
  211. update->base.size = 1;
  212. update->base.scalar = TRUE;
  213. GError *error = NULL;
  214. if (!kiro_messenger_send (data->messenger, request, &error)) {
  215. g_error ("Oh shit! '%s'", error->message);
  216. g_error_free (error);
  217. //TODO
  218. //Things
  219. }
  220. }
  221. if (request->message->payload)
  222. g_free (request->message->payload);
  223. g_free (request->message);
  224. kiro_messenger_receive (data->messenger, request);
  225. }
  226. int main (int argc, char *argv[])
  227. {
  228. GOptionContext *context;
  229. GError *error = NULL;
  230. static gchar *camera_name = "mock";
  231. static gchar *addr = "127.0.0.1";
  232. static gchar *port = "60010";
  233. static gboolean list = FALSE;
  234. static GOptionEntry entries[] = {
  235. { "camera", 'c', 0, G_OPTION_ARG_STRING, &camera_name, "Uca camera plugin to load", NULL },
  236. { "address", 'a', 0, G_OPTION_ARG_STRING, &addr, "Address to listen on", NULL },
  237. { "port", 'p', 0, G_OPTION_ARG_STRING, &port, "Port to listen on", NULL },
  238. { "list", 'l', 0, G_OPTION_ARG_NONE, &list, "List all available plugins and exit", NULL },
  239. { NULL }
  240. };
  241. #if !(GLIB_CHECK_VERSION (2, 36, 0))
  242. g_type_init ();
  243. #endif
  244. context = g_option_context_new ("-l | [-c <CAMERA PLUGIN>] [-a <ADDRESS>] [-p <PORT>]");
  245. g_option_context_set_summary (context, "kiro-camera-server provides a remote control host for libuca cameras.\n\
  246. Once the server is started, you can use the uca-kiro-camera plugin to connect to the server\n\
  247. over an InfiniBand network and control the loaded remote camera as if it was connected locally.");
  248. g_option_context_add_main_entries (context, entries, NULL);
  249. if (!g_option_context_parse (context, &argc, &argv, &error)) {
  250. g_print ("Error parsing options: %s\n", error->message);
  251. exit (-1);
  252. }
  253. if (argc >= 2) {
  254. g_print ("%s", g_option_context_get_help (context, TRUE, NULL));
  255. exit (0);
  256. }
  257. KiroCsData data;
  258. data.exit_flag = FALSE;
  259. data.peer_rank = 0;
  260. UcaPluginManager *pm = uca_plugin_manager_new ();
  261. if (list) {
  262. GList *names = uca_plugin_manager_get_available_cameras (pm);
  263. if (!names) {
  264. g_print ("No available plugins found.\n");
  265. }
  266. else {
  267. g_print ("The following Uca camera plugins are available:\n");
  268. g_list_foreach (names, (GFunc) print_cam_name, NULL);
  269. g_list_free_full (names, g_free);
  270. }
  271. g_object_unref (pm);
  272. exit (0);
  273. }
  274. data.cam = uca_plugin_manager_get_camera (pm, camera_name, &error, NULL);
  275. if (!(data.cam)) {
  276. g_print ("Failed to load plugin '%s': %s. Exiting.\n", camera_name, error->message);
  277. g_object_unref (pm);
  278. exit (-1);
  279. }
  280. g_object_unref (pm);
  281. data.messenger = kiro_messenger_new ();
  282. kiro_messenger_start_listen (data.messenger, addr, port, (KiroConnectCallbackFunc) connect_callback, &(data.peer_rank), &error);
  283. if (error) {
  284. g_print ("Failed to launch Kiro Server: %s Exiting.\n", error->message);
  285. g_object_unref (data.cam);
  286. exit (-1);
  287. }
  288. // wait for the first peer
  289. while (data.peer_rank == 0) {};
  290. KiroMessage message;
  291. data.signal_handlers = NULL;
  292. data.properties = g_object_class_list_properties (G_OBJECT_GET_CLASS (data.cam), &data.n_properties);
  293. if (!(*data.properties)) {
  294. g_object_unref (data.messenger);
  295. g_object_unref (data.cam);
  296. g_error ("No properties exposed by camera '%s'.", camera_name);
  297. }
  298. else {
  299. data.signal_handlers = g_malloc0 (sizeof (gulong) * (data.n_properties + 1)); //0 is not a valid property ID
  300. for (guint idx=0; idx < data.n_properties; idx++) {
  301. if (idx >= N_BASE_PROPERTIES - 1) {
  302. //NONE Base Property.
  303. //Inform peer and setup
  304. g_debug ("Asking peer to install property '%s' with ID %u", data.properties[idx]->name, idx + 1);
  305. message.msg = KIROCS_INSTALL;
  306. message.size = sizeof (PropertyRequisition) + strlen (data.properties[idx]->name);
  307. message.payload = g_malloc0 (message.size);
  308. PropertyRequisition *req = message.payload;
  309. req->id = idx + 1;
  310. req->value_type = data.properties[idx]->value_type;
  311. switch (req->value_type) {
  312. case G_TYPE_BOOLEAN:
  313. req->spec.bool_spec = *(GParamSpecBoolean *)data.properties[idx];
  314. break;
  315. default:
  316. g_debug ("FOOBAR");
  317. }
  318. strcpy (req->name, data.properties[idx]->name);
  319. if (!kiro_messenger_send_blocking (data.messenger, &message, data.peer_rank, &error)) {
  320. g_error ("Oh shit!");
  321. //TODO
  322. //Things
  323. }
  324. g_free (req);
  325. }
  326. else
  327. peer_inform_update (data.cam, data.properties[idx], &data);
  328. guint handler_id = setup_signal_handler (data.cam, data.properties[idx], &data);
  329. data.signal_handlers[idx + 1] = handler_id;
  330. g_debug ("Setup handler for property '%s' with handler ID %u", data.properties[idx]->name, handler_id);
  331. }
  332. }
  333. //All done. Send READY
  334. message.msg = KIROCS_READY;
  335. message.size = 0;
  336. message.payload = NULL;
  337. if (!kiro_messenger_send_blocking (data.messenger, &message, data.peer_rank, &error)) {
  338. g_error ("Oh shit!");
  339. //TODO
  340. //Things
  341. }
  342. KiroRequest request;
  343. request.id = 0;
  344. request.callback = (KiroMessageCallbackFunc) receive_callback;
  345. request.user_data = (gpointer) &data;
  346. kiro_messenger_receive (data.messenger, &request);
  347. while (!(data.exit_flag)) {
  348. sleep (5);
  349. //TODO
  350. //Check if connection is still alive, and if not, reinitialize
  351. };
  352. g_free (data.properties);
  353. g_free (data.signal_handlers);
  354. kiro_messenger_free (data.messenger);
  355. g_object_unref (data.cam);
  356. return 0;
  357. };