infrared_remote.c 6.3 KB

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