-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathinfrared_remote.c
236 lines (195 loc) · 8.31 KB
/
infrared_remote.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
/*
This file was taken from the project:
https://github.com/DarkFlippers/unleashed-firmware
The original project is licensed under the GNU GPLv3
Modifications made:
- Added function infrared_remote_get_button_by_name()
- Added function infrared_remote_delete_button_by_name()
- Added function infrared_remote_push_button()
*/
#include "infrared_remote.h"
#include <stdbool.h>
#include <stddef.h>
#include <stdlib.h>
#include <m-array.h>
#include <string.h>
#include <ctype.h>
#include <toolbox/path.h>
#include <storage/storage.h>
#include <core/common_defines.h>
#define TAG "InfraredRemote"
ARRAY_DEF(InfraredButtonArray, InfraredRemoteButton*, M_PTR_OPLIST);
struct InfraredRemote {
InfraredButtonArray_t buttons;
FuriString* name;
FuriString* path;
};
static void infrared_remote_clear_buttons(InfraredRemote* remote) {
InfraredButtonArray_it_t it;
for(InfraredButtonArray_it(it, remote->buttons); !InfraredButtonArray_end_p(it);
InfraredButtonArray_next(it)) {
infrared_remote_button_free(*InfraredButtonArray_cref(it));
}
InfraredButtonArray_reset(remote->buttons);
}
InfraredRemote* infrared_remote_alloc() {
InfraredRemote* remote = malloc(sizeof(InfraredRemote));
InfraredButtonArray_init(remote->buttons);
remote->name = furi_string_alloc();
remote->path = furi_string_alloc();
return remote;
}
void infrared_remote_free(InfraredRemote* remote) {
infrared_remote_clear_buttons(remote);
InfraredButtonArray_clear(remote->buttons);
furi_string_free(remote->path);
furi_string_free(remote->name);
free(remote);
}
void infrared_remote_reset(InfraredRemote* remote) {
infrared_remote_clear_buttons(remote);
furi_string_reset(remote->name);
furi_string_reset(remote->path);
}
void infrared_remote_set_name(InfraredRemote* remote, const char* name) {
furi_string_set(remote->name, name);
}
const char* infrared_remote_get_name(InfraredRemote* remote) {
return furi_string_get_cstr(remote->name);
}
void infrared_remote_set_path(InfraredRemote* remote, const char* path) {
furi_string_set(remote->path, path);
}
const char* infrared_remote_get_path(InfraredRemote* remote) {
return furi_string_get_cstr(remote->path);
}
size_t infrared_remote_get_button_count(InfraredRemote* remote) {
return InfraredButtonArray_size(remote->buttons);
}
InfraredRemoteButton* infrared_remote_get_button(InfraredRemote* remote, size_t index) {
furi_assert(index < InfraredButtonArray_size(remote->buttons));
return *InfraredButtonArray_get(remote->buttons, index);
}
bool infrared_remote_find_button_by_name(InfraredRemote* remote, const char* name, size_t* index) {
for(size_t i = 0; i < InfraredButtonArray_size(remote->buttons); i++) {
InfraredRemoteButton* button = *InfraredButtonArray_get(remote->buttons, i);
FuriString* furi_name = infrared_remote_button_get_furi_name(button);
if(button && !furi_string_cmpi_str(furi_name, name)) {
*index = i;
return true;
}
}
return false;
}
InfraredRemoteButton*
infrared_remote_get_button_by_name(InfraredRemote* remote, const char* name) {
for(size_t i = 0; i < InfraredButtonArray_size(remote->buttons); i++) {
InfraredRemoteButton* button = *InfraredButtonArray_get(remote->buttons, i);
FuriString* furi_name = infrared_remote_button_get_furi_name(button);
if(button && !furi_string_cmpi_str(furi_name, name)) return button;
}
return NULL;
}
bool infrared_remote_add_button(InfraredRemote* remote, const char* name, InfraredSignal* signal) {
InfraredRemoteButton* button = infrared_remote_button_alloc();
infrared_remote_button_set_name(button, name);
infrared_remote_button_set_signal(button, signal);
InfraredButtonArray_push_back(remote->buttons, button);
return infrared_remote_store(remote);
}
void infrared_remote_push_button(InfraredRemote* remote, const char* name, InfraredSignal* signal) {
InfraredRemoteButton* button = infrared_remote_button_alloc();
infrared_remote_button_set_name(button, name);
infrared_remote_button_set_signal(button, signal);
InfraredButtonArray_push_back(remote->buttons, button);
}
bool infrared_remote_rename_button(InfraredRemote* remote, const char* new_name, size_t index) {
furi_assert(index < InfraredButtonArray_size(remote->buttons));
InfraredRemoteButton* button = *InfraredButtonArray_get(remote->buttons, index);
infrared_remote_button_set_name(button, new_name);
return infrared_remote_store(remote);
}
bool infrared_remote_delete_button(InfraredRemote* remote, size_t index) {
furi_assert(index < InfraredButtonArray_size(remote->buttons));
InfraredRemoteButton* button;
InfraredButtonArray_pop_at(&button, remote->buttons, index);
infrared_remote_button_free(button);
return infrared_remote_store(remote);
}
bool infrared_remote_delete_button_by_name(InfraredRemote* remote, const char* name) {
size_t index = 0;
if(!infrared_remote_find_button_by_name(remote, name, &index)) return false;
return infrared_remote_delete_button(remote, index);
}
void infrared_remote_move_button(InfraredRemote* remote, size_t index_orig, size_t index_dest) {
furi_assert(index_orig < InfraredButtonArray_size(remote->buttons));
furi_assert(index_dest < InfraredButtonArray_size(remote->buttons));
InfraredRemoteButton* button;
InfraredButtonArray_pop_at(&button, remote->buttons, index_orig);
InfraredButtonArray_push_at(remote->buttons, index_dest, button);
}
bool infrared_remote_store(InfraredRemote* remote) {
Storage* storage = furi_record_open(RECORD_STORAGE);
FlipperFormat* ff = flipper_format_file_alloc(storage);
const char* path = furi_string_get_cstr(remote->path);
FURI_LOG_I(TAG, "store file: \'%s\'", path);
bool success = flipper_format_file_open_always(ff, path) &&
flipper_format_write_header_cstr(ff, "IR signals file", 1);
if(success) {
InfraredButtonArray_it_t it;
for(InfraredButtonArray_it(it, remote->buttons); !InfraredButtonArray_end_p(it);
InfraredButtonArray_next(it)) {
InfraredRemoteButton* button = *InfraredButtonArray_cref(it);
success = infrared_signal_save(
infrared_remote_button_get_signal(button),
ff,
infrared_remote_button_get_name(button));
if(!success) {
break;
}
}
}
flipper_format_free(ff);
furi_record_close(RECORD_STORAGE);
return success;
}
bool infrared_remote_load(InfraredRemote* remote, FuriString* path) {
Storage* storage = furi_record_open(RECORD_STORAGE);
FlipperFormat* ff = flipper_format_buffered_file_alloc(storage);
FuriString* buf;
buf = furi_string_alloc();
FURI_LOG_I(TAG, "load file: \'%s\'", furi_string_get_cstr(path));
bool success = false;
do {
if(!flipper_format_buffered_file_open_existing(ff, furi_string_get_cstr(path))) break;
uint32_t version;
if(!flipper_format_read_header(ff, buf, &version)) break;
if(!furi_string_equal(buf, "IR signals file") || (version != 1)) break;
path_extract_filename(path, buf, true);
infrared_remote_clear_buttons(remote);
infrared_remote_set_name(remote, furi_string_get_cstr(buf));
infrared_remote_set_path(remote, furi_string_get_cstr(path));
for(bool can_read = true; can_read;) {
InfraredRemoteButton* button = infrared_remote_button_alloc();
can_read = infrared_signal_read(infrared_remote_button_get_signal(button), ff, buf);
if(can_read) {
infrared_remote_button_set_name(button, furi_string_get_cstr(buf));
InfraredButtonArray_push_back(remote->buttons, button);
} else {
infrared_remote_button_free(button);
}
}
success = true;
} while(false);
furi_string_free(buf);
flipper_format_free(ff);
furi_record_close(RECORD_STORAGE);
return success;
}
bool infrared_remote_remove(InfraredRemote* remote) {
Storage* storage = furi_record_open(RECORD_STORAGE);
FS_Error status = storage_common_remove(storage, furi_string_get_cstr(remote->path));
infrared_remote_reset(remote);
furi_record_close(RECORD_STORAGE);
return (status == FSE_OK || status == FSE_NOT_EXIST);
}