camera_config.c 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. #include "camera_config.h"
  2. #include "ini.h"
  3. #include "config.h"
  4. #include <wordexp.h>
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #include <unistd.h>
  9. #include <glib.h>
  10. #include <assert.h>
  11. static struct mp_camera_config cameras[MP_MAX_CAMERAS];
  12. static size_t num_cameras = 0;
  13. static char *exif_make;
  14. static char *exif_model;
  15. static bool
  16. find_config(char *conffile)
  17. {
  18. char buf[512];
  19. char *xdg_config_home;
  20. wordexp_t exp_result;
  21. FILE *fp;
  22. // Resolve XDG stuff
  23. if ((xdg_config_home = getenv("XDG_CONFIG_HOME")) == NULL) {
  24. xdg_config_home = "~/.config";
  25. }
  26. wordexp(xdg_config_home, &exp_result, 0);
  27. xdg_config_home = strdup(exp_result.we_wordv[0]);
  28. wordfree(&exp_result);
  29. if (access("/proc/device-tree/compatible", F_OK) != -1) {
  30. // Reads to compatible string of the current device tree, looks like:
  31. // pine64,pinephone-1.2\0allwinner,sun50i-a64\0
  32. fp = fopen("/proc/device-tree/compatible", "r");
  33. fgets(buf, 512, fp);
  34. fclose(fp);
  35. // Check config/%dt.ini in the current working directory
  36. sprintf(conffile, "config/%s.ini", buf);
  37. if(access(conffile, F_OK) != -1) {
  38. printf("Found config file at %s\n", conffile);
  39. return true;
  40. }
  41. // Check for a config file in XDG_CONFIG_HOME
  42. sprintf(conffile, "%s/megapixels/config/%s.ini", xdg_config_home, buf);
  43. if(access(conffile, F_OK) != -1) {
  44. printf("Found config file at %s\n", conffile);
  45. return true;
  46. }
  47. // Check user overridden /etc/megapixels/config/$dt.ini
  48. sprintf(conffile, "%s/megapixels/config/%s.ini", SYSCONFDIR, buf);
  49. if(access(conffile, F_OK) != -1) {
  50. printf("Found config file at %s\n", conffile);
  51. return true;
  52. }
  53. // Check packaged /usr/share/megapixels/config/$dt.ini
  54. sprintf(conffile, "%s/megapixels/config/%s.ini", DATADIR, buf);
  55. if(access(conffile, F_OK) != -1) {
  56. printf("Found config file at %s\n", conffile);
  57. return true;
  58. }
  59. printf("%s not found\n", conffile);
  60. } else {
  61. printf("Could not read device name from device tree\n");
  62. }
  63. // If all else fails, fall back to /etc/megapixels.ini
  64. sprintf(conffile, "/etc/megapixels.ini");
  65. if (access(conffile, F_OK) != -1) {
  66. printf("Found config file at %s\n", conffile);
  67. return true;
  68. }
  69. return false;
  70. }
  71. static int
  72. strtoint(const char *nptr, char **endptr, int base)
  73. {
  74. long x = strtol(nptr, endptr, base);
  75. assert(x <= INT_MAX);
  76. return (int) x;
  77. }
  78. static bool
  79. config_handle_camera_mode(const char *prefix, MPCameraMode * mode, const char *name, const char *value)
  80. {
  81. int prefix_length = strlen(prefix);
  82. if (strncmp(prefix, name, prefix_length) != 0)
  83. return false;
  84. name += prefix_length;
  85. if (strcmp(name, "width") == 0) {
  86. mode->width = strtoint(value, NULL, 10);
  87. } else if (strcmp(name, "height") == 0) {
  88. mode->height = strtoint(value, NULL, 10);
  89. } else if (strcmp(name, "rate") == 0) {
  90. mode->frame_interval.numerator = 1;
  91. mode->frame_interval.denominator = strtoint(value, NULL, 10);
  92. } else if (strcmp(name, "fmt") == 0) {
  93. mode->pixel_format = mp_pixel_format_from_str(value);
  94. if (mode->pixel_format == MP_PIXEL_FMT_UNSUPPORTED) {
  95. g_printerr("Unsupported pixelformat %s\n", value);
  96. exit(1);
  97. }
  98. } else {
  99. return false;
  100. }
  101. return true;
  102. }
  103. static int
  104. config_ini_handler(void *user, const char *section, const char *name,
  105. const char *value)
  106. {
  107. if (strcmp(section, "device") == 0) {
  108. if (strcmp(name, "make") == 0) {
  109. exif_make = strdup(value);
  110. } else if (strcmp(name, "model") == 0) {
  111. exif_model = strdup(value);
  112. } else {
  113. g_printerr("Unknown key '%s' in [device]\n", name);
  114. exit(1);
  115. }
  116. } else {
  117. if (num_cameras == MP_MAX_CAMERAS) {
  118. g_printerr("More cameras defined than NUM_CAMERAS\n");
  119. exit(1);
  120. }
  121. size_t index = 0;
  122. for (; index < num_cameras; ++index) {
  123. if (strcmp(cameras[index].cfg_name, section) == 0) {
  124. break;
  125. }
  126. }
  127. if (index == num_cameras) {
  128. printf("Adding camera %s from config\n", section);
  129. ++num_cameras;
  130. cameras[index].index = index;
  131. strcpy(cameras[index].cfg_name, section);
  132. }
  133. struct mp_camera_config *cc = &cameras[index];
  134. if (config_handle_camera_mode("capture-", &cc->capture_mode, name, value)) {
  135. } else if (config_handle_camera_mode("preview-", &cc->preview_mode, name, value)) {
  136. } else if (strcmp(name, "rotate") == 0) {
  137. cc->rotate = strtoint(value, NULL, 10);
  138. } else if (strcmp(name, "mirrored") == 0) {
  139. cc->mirrored = strcmp(value, "true") == 0;
  140. } else if (strcmp(name, "driver") == 0) {
  141. strcpy(cc->dev_name, value);
  142. } else if (strcmp(name, "media-driver") == 0) {
  143. strcpy(cc->media_dev_name, value);
  144. } else if (strcmp(name, "media-links") == 0) {
  145. char **linkdefs = g_strsplit(value, ",", 0);
  146. for (int i = 0; i < MP_MAX_LINKS && linkdefs[i] != NULL; ++i) {
  147. char **linkdef = g_strsplit(linkdefs[i], "->", 2);
  148. char **porta = g_strsplit(linkdef[0], ":", 2);
  149. char **portb = g_strsplit(linkdef[1], ":", 2);
  150. strcpy(cc->media_links[i].source_name, porta[0]);
  151. strcpy(cc->media_links[i].target_name, portb[0]);
  152. cc->media_links[i].source_port = strtoint(porta[1], NULL, 10);
  153. cc->media_links[i].target_port = strtoint(portb[1], NULL, 10);
  154. g_strfreev(portb);
  155. g_strfreev(porta);
  156. g_strfreev(linkdef);
  157. ++cc->num_media_links;
  158. }
  159. g_strfreev(linkdefs);
  160. } else if (strcmp(name, "colormatrix") == 0) {
  161. sscanf(value, "%f,%f,%f,%f,%f,%f,%f,%f,%f",
  162. cc->colormatrix+0,
  163. cc->colormatrix+1,
  164. cc->colormatrix+2,
  165. cc->colormatrix+3,
  166. cc->colormatrix+4,
  167. cc->colormatrix+5,
  168. cc->colormatrix+6,
  169. cc->colormatrix+7,
  170. cc->colormatrix+8
  171. );
  172. } else if (strcmp(name, "forwardmatrix") == 0) {
  173. sscanf(value, "%f,%f,%f,%f,%f,%f,%f,%f,%f",
  174. cc->forwardmatrix+0,
  175. cc->forwardmatrix+1,
  176. cc->forwardmatrix+2,
  177. cc->forwardmatrix+3,
  178. cc->forwardmatrix+4,
  179. cc->forwardmatrix+5,
  180. cc->forwardmatrix+6,
  181. cc->forwardmatrix+7,
  182. cc->forwardmatrix+8
  183. );
  184. } else if (strcmp(name, "whitelevel") == 0) {
  185. cc->whitelevel = strtoint(value, NULL, 10);
  186. } else if (strcmp(name, "blacklevel") == 0) {
  187. cc->blacklevel = strtoint(value, NULL, 10);
  188. } else if (strcmp(name, "focallength") == 0) {
  189. cc->focallength = strtof(value, NULL);
  190. } else if (strcmp(name, "cropfactor") == 0) {
  191. cc->cropfactor = strtof(value, NULL);
  192. } else if (strcmp(name, "fnumber") == 0) {
  193. cc->fnumber = strtod(value, NULL);
  194. } else if (strcmp(name, "iso-min") == 0) {
  195. cc->iso_min = strtod(value, NULL);
  196. } else if (strcmp(name, "iso-max") == 0) {
  197. cc->iso_max = strtod(value, NULL);
  198. } else {
  199. g_printerr("Unknown key '%s' in [%s]\n", name, section);
  200. exit(1);
  201. }
  202. }
  203. return 1;
  204. }
  205. bool mp_load_config() {
  206. char file[512];
  207. if (!find_config(file)) {
  208. g_printerr("Could not find any config file\n");
  209. return false;
  210. }
  211. int result = ini_parse(file, config_ini_handler, NULL);
  212. if (result == -1) {
  213. g_printerr("Config file not found\n");
  214. } else if (result == -2) {
  215. g_printerr("Could not allocate memory to parse config file\n");
  216. } else if (result != 0) {
  217. g_printerr("Could not parse config file\n");
  218. } else {
  219. return true;
  220. }
  221. return false;
  222. }
  223. const char * mp_get_device_make()
  224. {
  225. return exif_make;
  226. }
  227. const char * mp_get_device_model()
  228. {
  229. return exif_model;
  230. }
  231. const struct mp_camera_config * mp_get_camera_config(size_t index)
  232. {
  233. if (index >= num_cameras)
  234. return NULL;
  235. return &cameras[index];
  236. }