infrared_remote.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. #include "infrared_remote.h"
  2. #include <stdlib.h>
  3. #include <m-string.h>
  4. #include <m-array.h>
  5. #include <toolbox/path.h>
  6. #include <storage/storage.h>
  7. #include <furi/common_defines.h>
  8. #define TAG "InfraredRemote"
  9. ARRAY_DEF(InfraredButtonArray, InfraredRemoteButton*, M_PTR_OPLIST);
  10. struct InfraredRemote {
  11. InfraredButtonArray_t buttons;
  12. string_t name;
  13. string_t path;
  14. };
  15. static void infrared_remote_clear_buttons(InfraredRemote* remote) {
  16. InfraredButtonArray_it_t it;
  17. for(InfraredButtonArray_it(it, remote->buttons); !InfraredButtonArray_end_p(it);
  18. InfraredButtonArray_next(it)) {
  19. infrared_remote_button_free(*InfraredButtonArray_cref(it));
  20. }
  21. InfraredButtonArray_reset(remote->buttons);
  22. }
  23. InfraredRemote* infrared_remote_alloc() {
  24. InfraredRemote* remote = malloc(sizeof(InfraredRemote));
  25. InfraredButtonArray_init(remote->buttons);
  26. string_init(remote->name);
  27. string_init(remote->path);
  28. return remote;
  29. }
  30. void infrared_remote_free(InfraredRemote* remote) {
  31. infrared_remote_clear_buttons(remote);
  32. InfraredButtonArray_clear(remote->buttons);
  33. string_clear(remote->path);
  34. string_clear(remote->name);
  35. free(remote);
  36. }
  37. void infrared_remote_reset(InfraredRemote* remote) {
  38. infrared_remote_clear_buttons(remote);
  39. string_reset(remote->name);
  40. string_reset(remote->path);
  41. }
  42. void infrared_remote_set_name(InfraredRemote* remote, const char* name) {
  43. string_set_str(remote->name, name);
  44. }
  45. const char* infrared_remote_get_name(InfraredRemote* remote) {
  46. return string_get_cstr(remote->name);
  47. }
  48. void infrared_remote_set_path(InfraredRemote* remote, const char* path) {
  49. string_set_str(remote->path, path);
  50. }
  51. const char* infrared_remote_get_path(InfraredRemote* remote) {
  52. return string_get_cstr(remote->path);
  53. }
  54. size_t infrared_remote_get_button_count(InfraredRemote* remote) {
  55. return InfraredButtonArray_size(remote->buttons);
  56. }
  57. InfraredRemoteButton* infrared_remote_get_button(InfraredRemote* remote, size_t index) {
  58. furi_assert(index < InfraredButtonArray_size(remote->buttons));
  59. return *InfraredButtonArray_get(remote->buttons, index);
  60. }
  61. bool infrared_remote_add_button(InfraredRemote* remote, const char* name, InfraredSignal* signal) {
  62. InfraredRemoteButton* button = infrared_remote_button_alloc();
  63. infrared_remote_button_set_name(button, name);
  64. infrared_remote_button_set_signal(button, signal);
  65. InfraredButtonArray_push_back(remote->buttons, button);
  66. return infrared_remote_store(remote);
  67. }
  68. bool infrared_remote_rename_button(InfraredRemote* remote, const char* new_name, size_t index) {
  69. furi_assert(index < InfraredButtonArray_size(remote->buttons));
  70. InfraredRemoteButton* button = *InfraredButtonArray_get(remote->buttons, index);
  71. infrared_remote_button_set_name(button, new_name);
  72. return infrared_remote_store(remote);
  73. }
  74. bool infrared_remote_delete_button(InfraredRemote* remote, size_t index) {
  75. furi_assert(index < InfraredButtonArray_size(remote->buttons));
  76. InfraredRemoteButton* button;
  77. InfraredButtonArray_pop_at(&button, remote->buttons, index);
  78. infrared_remote_button_free(button);
  79. return infrared_remote_store(remote);
  80. }
  81. bool infrared_remote_store(InfraredRemote* remote) {
  82. Storage* storage = furi_record_open("storage");
  83. FlipperFormat* ff = flipper_format_file_alloc(storage);
  84. const char* path = string_get_cstr(remote->path);
  85. FURI_LOG_I(TAG, "store file: \'%s\'", path);
  86. bool success = flipper_format_file_open_always(ff, path) &&
  87. flipper_format_write_header_cstr(ff, "IR signals file", 1);
  88. if(success) {
  89. InfraredButtonArray_it_t it;
  90. for(InfraredButtonArray_it(it, remote->buttons); !InfraredButtonArray_end_p(it);
  91. InfraredButtonArray_next(it)) {
  92. InfraredRemoteButton* button = *InfraredButtonArray_cref(it);
  93. success = infrared_signal_save(
  94. infrared_remote_button_get_signal(button),
  95. ff,
  96. infrared_remote_button_get_name(button));
  97. if(!success) {
  98. break;
  99. }
  100. }
  101. }
  102. flipper_format_free(ff);
  103. furi_record_close("storage");
  104. return success;
  105. }
  106. bool infrared_remote_load(InfraredRemote* remote, string_t path) {
  107. Storage* storage = furi_record_open("storage");
  108. FlipperFormat* ff = flipper_format_file_alloc(storage);
  109. string_t buf;
  110. string_init(buf);
  111. FURI_LOG_I(TAG, "load file: \'%s\'", string_get_cstr(path));
  112. bool success = flipper_format_file_open_existing(ff, string_get_cstr(path));
  113. if(success) {
  114. uint32_t version;
  115. success = flipper_format_read_header(ff, buf, &version) &&
  116. !string_cmp_str(buf, "IR signals file") && (version == 1);
  117. }
  118. if(success) {
  119. path_extract_filename(path, buf, true);
  120. infrared_remote_clear_buttons(remote);
  121. infrared_remote_set_name(remote, string_get_cstr(buf));
  122. infrared_remote_set_path(remote, string_get_cstr(path));
  123. for(bool can_read = true; can_read;) {
  124. InfraredRemoteButton* button = infrared_remote_button_alloc();
  125. can_read = infrared_signal_read(infrared_remote_button_get_signal(button), ff, buf);
  126. if(can_read) {
  127. infrared_remote_button_set_name(button, string_get_cstr(buf));
  128. InfraredButtonArray_push_back(remote->buttons, button);
  129. } else {
  130. infrared_remote_button_free(button);
  131. }
  132. }
  133. }
  134. string_clear(buf);
  135. flipper_format_free(ff);
  136. furi_record_close("storage");
  137. return success;
  138. }
  139. bool infrared_remote_remove(InfraredRemote* remote) {
  140. Storage* storage = furi_record_open("storage");
  141. FS_Error status = storage_common_remove(storage, string_get_cstr(remote->path));
  142. infrared_remote_reset(remote);
  143. furi_record_close("storage");
  144. return (status == FSE_OK || status == FSE_NOT_EXIST);
  145. }