videohubctrl can be used to control Blackmagic Design Videohub SDI router device over the network.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

videohubctrl.c 5.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. /*
  2. * Blackmagic Design Videohub control application
  3. * Copyright (C) 2014 Unix Solutions Ltd.
  4. * Written by Georgi Chorbadzhiyski
  5. *
  6. * Released under MIT license.
  7. * See LICENSE-MIT.txt for license terms.
  8. *
  9. */
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #include <getopt.h>
  14. #include <unistd.h>
  15. #include "data.h"
  16. #include "cmd.h"
  17. #include "net.h"
  18. #include "util.h"
  19. #include "version.h"
  20. #include "libfuncs/libfuncs.h"
  21. int verbose;
  22. int quiet;
  23. static struct videohub_data maindata;
  24. static int show_info = 1;
  25. static int show_monitor = 0;
  26. static const char *program_id = PROGRAM_NAME " Version: " VERSION " Git: " GIT_VER;
  27. static const char short_options[] = "s:p:qvhVim";
  28. static const struct option long_options[] = {
  29. { "host", required_argument, NULL, 's' },
  30. { "port", required_argument, NULL, 'p' },
  31. { "quiet", no_argument, NULL, 'q' },
  32. { "verbose", no_argument, NULL, 'v' },
  33. { "help", no_argument, NULL, 'h' },
  34. { "version", no_argument, NULL, 'V' },
  35. { "info", no_argument, NULL, 'i' },
  36. { "monitor", no_argument, NULL, 'm' },
  37. { 0, 0, 0, 0 }
  38. };
  39. static void show_help(struct videohub_data *data) {
  40. printf("\n");
  41. printf(" Usage: " PROGRAM_NAME " --host <host> [..commands..]\n");
  42. printf("\n");
  43. printf("Main options:\n");
  44. printf(" -s --host <hostname> | Set device hostname.\n");
  45. printf(" -p --port <port_number> | Set device port (default: 9990).\n");
  46. printf("\n");
  47. printf("Misc options:\n");
  48. printf(" -v --verbose | Increase logging verbosity.\n");
  49. printf(" -q --quiet | Suppress warnings.\n");
  50. printf(" -h --help | Show help screen.\n");
  51. printf(" -V --version | Show program version.\n");
  52. printf("\n");
  53. printf("Commands:\n");
  54. printf(" -i --info | Show device info (default command).\n");
  55. printf(" -m --monitor | Show real time monitor for config changes.\n");
  56. printf("\n");
  57. }
  58. static void parse_options(struct videohub_data *data, int argc, char **argv) {
  59. int j, err = 0;
  60. // Set defaults
  61. data->dev_port = "9990";
  62. while ((j = getopt_long(argc, argv, short_options, long_options, NULL)) != -1) {
  63. switch (j) {
  64. case 's': // --host
  65. data->dev_host = optarg;
  66. break;
  67. case 'p': // --port
  68. data->dev_port = optarg;
  69. break;
  70. case 'v': // --verbose
  71. verbose++;
  72. if (verbose)
  73. quiet = 0; // Disable quiet
  74. break;
  75. case 'q': // --quiet
  76. quiet = !quiet;
  77. break;
  78. case 'i': // --info
  79. show_info = 1;
  80. break;
  81. case 'm': // --monitor
  82. show_monitor = 1;
  83. break;
  84. case 'h': // --help
  85. show_help(data);
  86. exit(EXIT_SUCCESS);
  87. case 'V': // --version
  88. // program_id is already printed on startup, just exit.
  89. exit(EXIT_SUCCESS);
  90. }
  91. }
  92. if (!data->dev_host || !strtoul(data->dev_port, NULL, 10))
  93. err = 1;
  94. if (err) {
  95. show_help(data);
  96. if (!data->dev_host)
  97. fprintf(stderr, "ERROR: host is not set. Use --host option.\n");
  98. exit(EXIT_FAILURE);
  99. }
  100. v("Device address: %s:%s\n", data->dev_host, data->dev_port);
  101. }
  102. static void print_device_desc(struct device_desc *d) {
  103. printf("\n");
  104. printf("Protocol version: %s\n", d->protocol_ver);
  105. printf("Model name: %s\n", d->model_name);
  106. printf("Unique ID: %s\n", d->unique_id);
  107. printf("Video inputs: %u\n", d->num_video_inputs);
  108. printf("Video processing units: %u\n", d->num_video_processing_units);
  109. printf("Video outputs: %u\n", d->num_video_outputs);
  110. printf("Video monitoring outputs: %u\n", d->num_video_monitoring_outputs);
  111. printf("Serial ports: %u\n", d->num_serial_ports);
  112. }
  113. static void printf_line(int len) {
  114. int i;
  115. for (i = 0; i < len; i++)
  116. printf("-");
  117. printf("\n");
  118. }
  119. static void print_device_settings(struct videohub_data *d) {
  120. unsigned int i;
  121. printf("\n");
  122. printf_line(70);
  123. printf("| # | x | %-27s | %-27s |\n", "Input name", "Output name");
  124. printf_line(70);
  125. for(i = 0; i < d->device.num_video_inputs; i++) {
  126. printf("| %2d | %c | %-27s | %-27s |\n",
  127. i + 1,
  128. d->outputs[i].locked ? (d->outputs[i].locked_other ? 'L' : 'O') : ' ',
  129. d->inputs[d->outputs[i].routed_to].name,
  130. d->outputs[i].name
  131. );
  132. }
  133. printf_line(70);
  134. }
  135. static int read_device_command_stream(struct videohub_data *d) {
  136. int ret, ncommands = 0;
  137. char buf[8192 + 1];
  138. memset(buf, 0, sizeof(buf));
  139. while ((ret = fdread_ex(d->dev_fd, buf, sizeof(buf) - 1, 5, 0, 0)) >= 0) {
  140. ncommands += parse_text_buffer(d, buf);
  141. memset(buf, 0, sizeof(buf));
  142. }
  143. return ncommands;
  144. }
  145. int main(int argc, char **argv) {
  146. struct videohub_data *data = &maindata;
  147. printf("%s\n", program_id);
  148. parse_options(data, argc, argv);
  149. set_log_io_errors(0);
  150. data->dev_fd = connect_client(SOCK_STREAM, data->dev_host, data->dev_port);
  151. if (data->dev_fd < 0)
  152. exit(EXIT_FAILURE);
  153. read_device_command_stream(data);
  154. if (!strlen(data->device.protocol_ver) || !strlen(data->device.model_name))
  155. die("The device does not respond correctly. Is it Videohub?");
  156. if (strstr(data->device.protocol_ver, "2.") != data->device.protocol_ver)
  157. die("Device protocol is %s but this program supports 2.x only.\n",
  158. data->device.protocol_ver);
  159. if (show_monitor) {
  160. while (1) {
  161. printf("\e[2J\e[H"); // Clear screen
  162. printf("%s\n", program_id);
  163. print_device_desc(&data->device);
  164. print_device_settings(data);
  165. fflush(stdout);
  166. do {
  167. sleep(1);
  168. } while (read_device_command_stream(data) == 0);
  169. }
  170. } else if (show_info) {
  171. print_device_desc(&data->device);
  172. print_device_settings(data);
  173. fflush(stdout);
  174. }
  175. shutdown_fd(&data->dev_fd);
  176. return 0;
  177. }