PageRenderTime 50ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/basic_libs/blaa/tools/gtk_run/src/main.cpp

https://gitlab.com/promethe/libs
C++ | 447 lines | 259 code | 63 blank | 125 comment | 27 complexity | a8a1e94b61036e76a559dab0d07c6888 MD5 | raw file
  1. #include <fcntl.h> // O_RDONLY ...
  2. #include <stdio.h>
  3. #include <gtk/gtk.h>
  4. #include <string.h>
  5. #include <stdint.h> //uint32_t
  6. #include <jpeglib.h>
  7. #include "blc.h"
  8. //#include "record.hh"
  9. // Pour les view metre / text boxes */
  10. const float value_max = 1;
  11. const float value_min = 0;
  12. GtkWidget *window;
  13. static uchar *RGB3_from_YUYV = NULL;
  14. pthread_t init_table_thread;
  15. struct blc_channel_info *channels_infos=NULL;
  16. GtkWidget **channels_display;
  17. void getting_range(GtkRange *range, float *value)
  18. {
  19. *value = gtk_range_get_value(range);
  20. }
  21. void getting_spin_value(GtkSpinButton *button, float *value)
  22. {
  23. *value = gtk_spin_button_get_value(button);
  24. }
  25. void getting_check_value(GtkToggleButton *button, float *value)
  26. {
  27. if (gtk_toggle_button_get_active(button)) *value = 1.0;
  28. else *value = 0.0;
  29. }
  30. gboolean update_range(GtkRange *range, GdkFrameClock *frame_clock, float *value)
  31. {
  32. (void) frame_clock;
  33. gtk_range_set_value(range, *value);
  34. return G_SOURCE_CONTINUE;
  35. }
  36. gboolean update_spin_value(GtkSpinButton *button, GdkFrameClock *frame_clock, float *value)
  37. {
  38. (void) frame_clock;
  39. gtk_spin_button_set_value(button, *value);
  40. return G_SOURCE_CONTINUE;
  41. }
  42. gboolean update_check_value(GtkToggleButton *button, GdkFrameClock *frame_clock, float *value)
  43. {
  44. (void) frame_clock;
  45. gtk_toggle_button_set_active(button, (*value > 0.5));
  46. return G_SOURCE_CONTINUE;
  47. }
  48. /** Gtk cannot display a black and white image, therefore we convert it before updating it*/
  49. gboolean update_GREY_image(GtkImage *image, GdkFrameClock *frame_clock, blc_channel *channel)
  50. {
  51. GdkPixbuf *pixbuf;
  52. int i, offset;
  53. uchar *pixels;
  54. (void) frame_clock;
  55. pixbuf = gtk_image_get_pixbuf(image);
  56. pixels = gdk_pixbuf_get_pixels(pixbuf);
  57. offset = (channel->size - 1) * 3;
  58. // Conversion GREY -> RGB3
  59. FOR_INV(i, channel->size)
  60. {
  61. memset(&pixels[offset], channel->data[i], 3);
  62. offset -= 3;
  63. }
  64. gtk_image_set_from_pixbuf(image, pixbuf);
  65. return G_SOURCE_CONTINUE;
  66. }
  67. gboolean update_RGB3_image(GtkImage *image, GdkFrameClock *frame_clock, GdkPixbuf *pixbuf)
  68. {
  69. (void) frame_clock;
  70. gtk_image_set_from_pixbuf(image, pixbuf);
  71. return G_SOURCE_CONTINUE;
  72. }
  73. void jpeg_error(j_common_ptr cinfo, int msg_level)
  74. {
  75. (void) msg_level;
  76. cinfo->err->num_warnings++;
  77. }
  78. gboolean update_JPEG_image(GtkImage *image, GdkFrameClock *frame_clock, blc_channel *channel)
  79. {
  80. JSAMPROW row_pt[1];
  81. GdkPixbuf *pixbuf;
  82. int row_stride;
  83. uchar *pixels;
  84. struct jpeg_decompress_struct cinfo;
  85. struct jpeg_error_mgr jerr;
  86. (void) frame_clock;
  87. pixbuf = gtk_image_get_pixbuf(image);
  88. pixels = gdk_pixbuf_get_pixels(pixbuf);
  89. cinfo.err = jpeg_std_error(&jerr);
  90. cinfo.err->emit_message = jpeg_error;
  91. jpeg_create_decompress(&cinfo);
  92. jpeg_mem_src(&cinfo, (uchar*) channel->data, channel->size);
  93. jpeg_read_header(&cinfo, TRUE);
  94. jpeg_start_decompress(&cinfo);
  95. row_stride = cinfo.output_width * cinfo.output_components;
  96. row_pt[0] = pixels;
  97. while (cinfo.output_scanline < cinfo.output_height)
  98. {
  99. jpeg_read_scanlines(&cinfo, row_pt, 1);
  100. row_pt[0] += row_stride;
  101. }
  102. if (cinfo.err->num_warnings != 0)
  103. {
  104. PRINT_WARNING("Drop image : %s", cinfo.err->jpeg_message_table[cinfo.err->last_jpeg_message]);
  105. cinfo.err->num_warnings = 0;
  106. }
  107. gtk_image_set_from_pixbuf(image, pixbuf);
  108. jpeg_finish_decompress(&cinfo);
  109. jpeg_destroy_decompress(&cinfo);
  110. return G_SOURCE_CONTINUE;
  111. }
  112. // 4:2:2
  113. gboolean update_YUYV_image(GtkImage *image, GdkFrameClock *frame_clock, blc_channel *channel)
  114. {
  115. GdkPixbuf *pixbuf;
  116. int i, j;
  117. uchar *data = (uchar*) channel->data;
  118. uchar *pixels, *tmp_pixels;
  119. int Y, Cb = 128, Cr = 128;
  120. (void) frame_clock;
  121. pixbuf = gtk_image_get_pixbuf(image);
  122. pixels = gdk_pixbuf_get_pixels(pixbuf);
  123. tmp_pixels = pixels;
  124. i = 0;
  125. while (i != (int) channel->size)
  126. {
  127. Y = data[i++];
  128. Cb = data[i++];
  129. j = Y + (Cb << 8) + (Cr << 16);
  130. memcpy(tmp_pixels, RGB3_from_YUYV + j * 3, 3);
  131. Y = data[i++];
  132. Cr = data[i++];
  133. j = Y + (Cb << 8) + (Cr << 16);
  134. memcpy(tmp_pixels + 3, RGB3_from_YUYV + j * 3, 3);
  135. tmp_pixels+=6;
  136. }
  137. gtk_image_set_from_pixbuf(image, pixbuf);
  138. return G_SOURCE_CONTINUE;
  139. }
  140. void* create_RGB3_from_YUYV(void *widget)
  141. {
  142. int Y, Cb, Cr;
  143. int i, j;
  144. float G_tmp;
  145. static uchar R[256], B;
  146. struct timeval time = {0,0};
  147. if (RGB3_from_YUYV == NULL)
  148. {
  149. RGB3_from_YUYV= MANY_ALLOCATIONS(256*256*256*3, uchar);
  150. diff_us_time(&time);
  151. i;
  152. FOR_INV(Y, 256)
  153. {
  154. FOR_INV(j,256) R[j]= CLIP_UCHAR(Y+1.13983*(j-128)); //It does not depend on Cb
  155. FOR_INV(Cb, 256)
  156. {
  157. B = CLIP_UCHAR(Y+2.03211*(Cb-128)); // It does not depend on Cr
  158. G_tmp = - 0.58060*(Cb-128);
  159. FOR_INV(Cr, 256)
  160. {
  161. i = 3 * (Y + (Cb << 8) + (Cr << 16));
  162. // Version Wikipedia
  163. RGB3_from_YUYV[i] = R[Cr];
  164. RGB3_from_YUYV[i + 1] = CLIP_UCHAR(Y-0.39465*(Cr-128) + G_tmp);
  165. RGB3_from_YUYV[i + 2] = B;
  166. }
  167. }
  168. }
  169. printf("time %lfms\n", diff_us_time(&time)/1000.);
  170. }
  171. return NULL;
  172. }
  173. /*
  174. void type_experience::create_display()
  175. {
  176. GtkWidget *grid;
  177. GtkWidget *scrolled_window;
  178. display = gtk_frame_new(name);
  179. scrolled_window = gtk_scrolled_window_new(NULL, NULL);
  180. grid = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
  181. gtk_container_add(GTK_CONTAINER(display), scrolled_window);
  182. gtk_container_add(GTK_CONTAINER(scrolled_window), grid);
  183. gtk_widget_set_vexpand(scrolled_window, TRUE);
  184. gtk_widget_set_hexpand(scrolled_window, TRUE);
  185. }
  186. /// Create a widget displaying the controls accordingly to the type of control
  187. void float_variable::create_display()
  188. {
  189. char label_text[NAME_MAX + 1];
  190. float *values = (float*) data;
  191. GtkWidget *widget = NULL, *grid;
  192. int i;
  193. display = gtk_frame_new(name);
  194. grid = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
  195. gtk_container_add(GTK_CONTAINER(display), grid);
  196. if (display_type != UNDEFINED_DISPLAY)
  197. {
  198. FOR(i, values_nb)
  199. {
  200. switch (display_type)
  201. {
  202. case TEXT_DISPLAY:
  203. widget = gtk_spin_button_new_with_range(value_min, value_max, 0.001);
  204. gtk_widget_add_tick_callback(widget, (GtkTickCallback) update_spin_value, &values[i], NULL);
  205. g_signal_connect(G_OBJECT(widget), "value-changed", G_CALLBACK(getting_spin_value), &values[i]);
  206. break;
  207. case VIEW_METER_DISPLAY:
  208. widget = gtk_scale_new_with_range(GTK_ORIENTATION_VERTICAL, value_min, value_max, 0.001);
  209. gtk_range_set_inverted(GTK_RANGE(widget), TRUE);
  210. gtk_widget_add_tick_callback(widget, (GtkTickCallback) update_range, &values[i], NULL);
  211. g_signal_connect(G_OBJECT(widget), "value-changed", G_CALLBACK(getting_range), &values[i]);
  212. gtk_widget_set_size_request(widget, 40, 128);
  213. break;
  214. case CHECKBOX_DISPLAY:
  215. widget = gtk_check_button_new();
  216. gtk_widget_add_tick_callback(widget, (GtkTickCallback) update_check_value, &values[i], NULL);
  217. g_signal_connect(G_OBJECT(widget), "toggled", G_CALLBACK(getting_check_value), &values[i]);
  218. break;
  219. break;
  220. }
  221. gtk_widget_set_vexpand(widget, TRUE);
  222. gtk_widget_set_hexpand(widget, TRUE);
  223. gtk_container_add(GTK_CONTAINER(grid), widget);
  224. }
  225. }
  226. else
  227. {
  228. snprintf(label_text, NAME_MAX, "Unknown display for %d float values.", values_nb);
  229. widget = gtk_label_new(label_text);
  230. gtk_container_add(GTK_CONTAINER(grid), widget);
  231. }
  232. }
  233. */
  234. /*
  235. /// Create a widget displaying an image accordingly to the type of the image
  236. void image_variable::create_display()
  237. {
  238. GdkPixbuf *pixbuf;
  239. GtkWidget *widget = NULL;
  240. char *image_buffer;
  241. char label_text[NAME_MAX + 1];
  242. sprintf(label_text, "%s %.4s", name, (char*) &pixel_format);
  243. display = gtk_frame_new(label_text);
  244. if (pixel_format == TO_UINT32("GREY") )
  245. {
  246. image_buffer = MANY_ALLOCATIONS(size * 3, char); //In order to be sure that the rowstride will be 'gui.width * 3'
  247. pixbuf = gdk_pixbuf_new_from_data((uchar*) image_buffer, GDK_COLORSPACE_RGB, 0, 8, width, height, width * 3, NULL, NULL);
  248. widget = gtk_image_new_from_pixbuf(pixbuf);
  249. gtk_widget_add_tick_callback(widget, (GtkTickCallback) update_GREY_image, this, NULL);
  250. }
  251. else if (pixel_format == TO_UINT32("RGB3") )
  252. {
  253. pixbuf = gdk_pixbuf_new_from_data((uchar*) data, GDK_COLORSPACE_RGB, 0, 8, width, height, width * 3, NULL, NULL);
  254. widget = gtk_image_new_from_pixbuf(pixbuf);
  255. gtk_widget_add_tick_callback(widget, (GtkTickCallback) update_RGB3_image, pixbuf, NULL);
  256. }
  257. else if (pixel_format == TO_UINT32("JPEG") )
  258. {
  259. image_buffer = MANY_ALLOCATIONS(size * 3, char); //In order to be sure that the rowstride will be 'gui.width * 3'
  260. pixbuf = gdk_pixbuf_new_from_data((uchar*) image_buffer, GDK_COLORSPACE_RGB, 0, 8, width, height, width * 3, NULL, NULL);
  261. widget = gtk_image_new_from_pixbuf(pixbuf);
  262. gtk_widget_add_tick_callback(widget, (GtkTickCallback) update_JPEG_image, this, NULL);
  263. }
  264. else if ((pixel_format == TO_UINT32("YUYV") )|| (pixel_format == TO_UINT32("YUV2"))){
  265. image_buffer = MANY_ALLOCATIONS(size * 3, char); //In order to be sure that the rowstride will be 'gui.width * 3'
  266. pixbuf = gdk_pixbuf_new_from_data((uchar*)image_buffer, GDK_COLORSPACE_RGB, 0, 8, width, height, width * 3, NULL, NULL);
  267. widget = gtk_image_new_from_pixbuf(pixbuf);
  268. pthread_create(&init_table_thread, NULL, create_RGB3_from_YUYV, widget);
  269. gtk_widget_add_tick_callback(GTK_WIDGET(widget), (GtkTickCallback) update_YUYV_image, this, NULL);
  270. }
  271. else widget = gtk_label_new("Unknown format image");
  272. gtk_widget_set_size_request(GTK_WIDGET(display), 32, 32);
  273. gtk_container_add(GTK_CONTAINER(display), widget);
  274. }
  275. */
  276. GtkWidget *create_image_display(blc_channel *channel)
  277. {
  278. GdkPixbuf *pixbuf;
  279. GtkWidget *widget = NULL;
  280. uchar *image_buffer;
  281. char label_text[NAME_MAX + 1];
  282. GtkWidget *display;
  283. blc_image_info image(channel->parameter);
  284. sprintf(label_text, "%s %.4s", channel->name, UINT32_TO_STRING(image.format));
  285. display = gtk_frame_new(label_text);
  286. if (image.format == STRING_TO_UINT32("Y800") )
  287. {
  288. image_buffer = MANY_ALLOCATIONS(image.size * 3, uchar); //In order to be sure that the rowstride will be 'gui.width * 3'
  289. pixbuf = gdk_pixbuf_new_from_data( image_buffer, GDK_COLORSPACE_RGB, 0, 8, image.width, image.height, image.width * 3, NULL, NULL);
  290. widget = gtk_image_new_from_pixbuf(pixbuf);
  291. gtk_widget_add_tick_callback(widget, (GtkTickCallback) update_GREY_image, channel, NULL);
  292. }
  293. else if (image.format == STRING_TO_UINT32("RGB3") )
  294. {
  295. pixbuf = gdk_pixbuf_new_from_data((uchar*)channel->data, GDK_COLORSPACE_RGB, 0, 8, image.width, image.height, image.width * 3, NULL, NULL);
  296. widget = gtk_image_new_from_pixbuf(pixbuf);
  297. gtk_widget_add_tick_callback(widget, (GtkTickCallback) update_RGB3_image, pixbuf, NULL);
  298. }
  299. else if (image.format == STRING_TO_UINT32("JPEG") )
  300. {
  301. image_buffer = MANY_ALLOCATIONS(image.size * 3, uchar); //In order to be sure that the rowstride will be 'gui.width * 3'
  302. pixbuf = gdk_pixbuf_new_from_data( image_buffer, GDK_COLORSPACE_RGB, 0, 8, image.width, image.height, image.width * 3, NULL, NULL);
  303. widget = gtk_image_new_from_pixbuf(pixbuf);
  304. gtk_widget_add_tick_callback(widget, (GtkTickCallback) update_JPEG_image, channel, NULL);
  305. }
  306. else if ((image.format == STRING_TO_UINT32("YUYV"))|| (image.format == STRING_TO_UINT32("yuv2"))){
  307. image_buffer = MANY_ALLOCATIONS(image.size * 3, uchar); //In order to be sure that the rowstride will be 'gui.width * 3'
  308. pixbuf = gdk_pixbuf_new_from_data(image_buffer, GDK_COLORSPACE_RGB, 0, 8, image.width, image.height, image.width * 3, NULL, NULL);
  309. widget = gtk_image_new_from_pixbuf(pixbuf);
  310. pthread_create(&init_table_thread, NULL, create_RGB3_from_YUYV, widget);
  311. gtk_widget_add_tick_callback(GTK_WIDGET(widget), (GtkTickCallback) update_YUYV_image, channel, NULL);
  312. }
  313. else widget = gtk_label_new("Unknown format image");
  314. gtk_widget_set_size_request(GTK_WIDGET(display), 32, 32);
  315. gtk_container_add(GTK_CONTAINER(display), widget);
  316. return display;
  317. }
  318. /** Look for the blc_channels and then create the graphical interface */
  319. static void activate(GtkApplication *app, char *start_filter)
  320. {
  321. struct blc_channel_info *info;
  322. blc_channel **channels;
  323. GtkWidget *layout, *grid;
  324. GtkBin *scrolled_window;
  325. int i, channels_nb;
  326. char title[NAME_MAX + 1];
  327. window = gtk_application_window_new(app);
  328. snprintf(title, NAME_MAX, "blc_channels %s", start_filter);
  329. gtk_window_set_title(GTK_WINDOW(window), title);
  330. gtk_widget_set_size_request(GTK_WIDGET(window), 400, 320);
  331. layout = gtk_box_new(GTK_ORIENTATION_VERTICAL, 3);
  332. grid = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 3);
  333. gtk_container_add(GTK_CONTAINER(window), layout);
  334. // gtk_container_add(GTK_CONTAINER(layout), create_record_interface());
  335. gtk_container_add(GTK_CONTAINER(layout), grid);
  336. channels_nb = blc_channel_get_all_infos(&channels_infos, start_filter);
  337. channels = MANY_ALLOCATIONS(channels_nb, blc_channel*);
  338. FOR (i, channels_nb)
  339. {
  340. info =&channels_infos[i];
  341. channels[i]=new blc_channel(info->name, info->referenced_size, info->sem_abp, info->type, info->parameter);
  342. }
  343. channels_display = MANY_ALLOCATIONS(channels_nb, GtkWidget*);
  344. FOR(i, channels_nb)
  345. {
  346. if (channels[i]->type == STRING_TO_UINT32("IMGE")) channels_display[i] = create_image_display(channels[i]);
  347. else channels_display[i] = gtk_label_new("Unknonwn channel type");
  348. gtk_container_add(GTK_CONTAINER(grid), GTK_WIDGET(channels_display[i]));
  349. }
  350. pthread_join(init_table_thread, NULL);
  351. gtk_widget_show_all(window);
  352. }
  353. /** Classical GTK application.
  354. * The first optional argument is the name of the experience. Otherwise all the existing shared memory are used.
  355. * */
  356. int main(int argc, char **argv)
  357. {
  358. GtkApplication *app;
  359. int status;
  360. char const *start_filter_name = "";
  361. gtk_disable_setlocale();
  362. gtk_init(&argc, &argv);
  363. if (argc == 2)
  364. {
  365. start_filter_name = argv[1];
  366. argc = 1; // To avoid g_application to try to interpret it.
  367. }
  368. app = gtk_application_new(NULL, G_APPLICATION_FLAGS_NONE);
  369. g_signal_connect(app, "activate", G_CALLBACK(activate), (void* )start_filter_name);
  370. status = g_application_run(G_APPLICATION(app), argc, argv);
  371. g_object_unref(app);
  372. return (status);
  373. }