arduino-audio-tools
All Classes Namespaces Files Functions Variables Typedefs Enumerations Friends Modules Pages
KARadioProtocol.h
1#pragma once
2
3#include <optional>
4
5#include "AudioTools/CoreAudio/AudioBasic/Str.h"
6#include "AudioTools/CoreAudio/AudioPlayer.h"
7#include "AudioTools/Disk/AudioSource.h"
8#include "AudioPlayerProtocol.h"
9
10#define KA_VERSION "Release: 2.4, Revision: R0"
11
12namespace audio_tools {
13
27 public:
30 addCommand("play", [](AudioPlayer& player, Str& cmd, Str& par, Print& out,
31 KARadioProtocol* self) {
32 if (!par.isEmpty()) {
33 int idx = par.toInt();
34 player.setIndex(idx);
35 }
36 return true;
37 });
38 addCommand("instant", [](AudioPlayer& player, Str& cmd, Str& par,
39 Print& out, KARadioProtocol* self) {
40 player.setPath(par.c_str());
41 return true;
42 });
43 addCommand("volume", [](AudioPlayer& player, Str& cmd, Str& par, Print& out,
44 KARadioProtocol* self) {
45 if (!par.isEmpty()) {
46 int volume = par.toInt();
47 player.setVolume(static_cast<float>(volume) / 254.0f);
48 }
49 return true;
50 });
51 addCommand("volume+", [](AudioPlayer& player, Str& cmd, Str& par,
52 Print& out, KARadioProtocol* self) {
53 int volume = player.volume() * 254.0f;
54 volume += 5;
55 if (volume > 245) {
56 volume = 254;
57 }
58 player.setVolume(static_cast<float>(volume) / 254.0f);
59 return true;
60 });
61 addCommand("volume-", [](AudioPlayer& player, Str& cmd, Str& par,
62 Print& out, KARadioProtocol* self) {
63 int volume = player.volume() * 254.0f;
64 volume -= 5;
65 if (volume < 0) {
66 volume = 0;
67 }
68 player.setVolume(static_cast<float>(volume) / 254.0f);
69 return true;
70 });
71 addCommand("pause", [](AudioPlayer& player, Str& cmd, Str& par, Print& out,
72 KARadioProtocol* self) {
73 player.setActive(false);
74 return true;
75 });
76 addCommand("resume", [](AudioPlayer& player, Str& cmd, Str& par, Print& out,
77 KARadioProtocol* self) {
78 player.setActive(true);
79 return true;
80 });
81 addCommand("stop", [](AudioPlayer& player, Str& cmd, Str& par, Print& out,
82 KARadioProtocol* self) {
83 player.setActive(false);
84 return true;
85 });
86 addCommand("start", [](AudioPlayer& player, Str& cmd, Str& par, Print& out,
87 KARadioProtocol* self) {
88 player.setActive(true);
89 return true;
90 });
91 addCommand("next", [](AudioPlayer& player, Str& cmd, Str& par, Print& out,
92 KARadioProtocol* self) {
93 player.next();
94 return true;
95 });
96 addCommand("prev", [](AudioPlayer& player, Str& cmd, Str& par, Print& out,
97 KARadioProtocol* self) {
98 player.previous();
99 return true;
100 });
101 addCommand("mute", [](AudioPlayer& player, Str& cmd, Str& par, Print& out,
102 KARadioProtocol* self) {
103 if (!par.isEmpty()) {
104 player.setActive(!(par.toInt() == 1));
105 }
106 return true;
107 });
108 addCommand("infos", [](AudioPlayer& player, Str& cmd, Str& par,
109 Print& result, KARadioProtocol* self) {
110 result.print("vol: ");
111 result.println(self->volume);
112 result.print("num: ");
113 result.println(self->index());
114 result.print("stn: "); // station
115 result.println(self->stationName());
116 result.print("tit: "); // title
117 result.println(self->title());
118 result.print("sts: "); // status
119 result.println(player.isActive());
120 return true;
121 });
122 addCommand("version", [](AudioPlayer& player, Str& cmd, Str& par,
123 Print& result, KARadioProtocol* self) {
124 result.print("version: ");
125 result.println(KA_VERSION);
126 return true;
127 });
128 addCommand("list",
129 [](AudioPlayer& player, Str& cmd, Str& par, Print& result,
130 KARadioProtocol* self) { // arg: 0 to 254
131 if (!par.isEmpty()) {
132 player.setIndex(par.toInt());
133 }
134 result.println(self->stationName());
135 return true;
136 });
137 }
138
141 setPlayer(player);
142 }
143
145 void setPlayer(AudioPlayer& player) override {
147 volume = player.volume() * 254.0f;
148 }
149
150 bool processCommand(Stream& input, Print& result) override {
151 return AudioPlayerProtocol::processCommand(input, result);
152 }
153
156 bool processCommand(const char* input, Print& result) override {
157 if (p_player == nullptr) {
158 LOGE("player not set");
159 return false;
160 }
161
162 Str name;
163 Str arg;
164 StrView line = input;
165
166 int start = line.indexOf('?');
167 if (start < 0) start = 0;
168 int endPos = line.length();
169 bool rc = true;
170 while (start >= 0 && start < endPos) {
171 int eqPos = line.indexOf('=', start);
172 int toPos = getEndPos(line, start + 1);
173 if (eqPos >= 0) {
174 name.substring(line, start + 1, eqPos);
175 arg.substring(line, eqPos + 1, toPos);
176 } else {
177 name.substring(line, start + 1, toPos);
178 arg = "";
179 }
180 LOGD("start=%d, eqPos=%d, toPos=%d", start, eqPos, toPos);
181 // remove leading and trailing spaces
182 name.trim();
183 arg.trim();
184 // execute the command
185 rc = processCommand(name, arg, result);
186 // calculate new positions
187 start = toPos;
188 toPos = getEndPos(line, start + 1);
189 }
190 return rc;
191 }
192
194 bool processCommand(Str& name, Str& arg, Print& result) {
195 LOGI("command: %s (%s)", name.c_str(), arg.c_str());
196 assert(p_player != nullptr);
197
198 // ignore empty commands
199 if (name.isEmpty()) return false;
200
201 for (Action& act : actions) {
202 if (name.equals(act.cmd)) {
203 return act.callback(*p_player, name, arg, result, this);
204 } else {
205 LOGD("-> %s vs %s: failed", name.c_str(), act.cmd);
206 }
207 }
208
209 LOGE("Invalid command:", name.c_str());
210 return false;
211 }
212
214 int index() { return p_player->audioSource().index(); }
215
217 const char* title() { return title_str.c_str(); }
218
220 void addCommand(const char* cmd,
221 bool (*cb)(AudioPlayer& player, Str& cmd, Str& par,
222 Print& out, KARadioProtocol* self)) {
223 Action act;
224 act.cmd = cmd;
225 act.callback = cb;
226 actions.push_back(act);
227 }
228
229 protected:
230 int volume = 0;
231 Str title_str = "n/a";
232 struct Action {
233 const char* cmd;
234 bool (*callback)(AudioPlayer& player, Str& cmd, Str& par, Print& out,
235 KARadioProtocol* self) = nullptr;
236 };
237 Vector<Action> actions;
238
239 int getEndPos(StrView& line, int start) {
240 int endPos = line.indexOf('&', start);
241 if (endPos < 0) {
242 endPos = line.length();
243 }
244 return endPos;
245 }
246
247 const char* stationName() {
248 if (p_player != nullptr) {
249 return p_player->audioSource().toStr();
250 }
251 return "";
252 }
253};
254} // namespace audio_tools
Implements a simple audio player which supports the following commands:
Definition AudioPlayer.h:38
AudioSource & audioSource()
Provides the actual audio source.
Definition AudioPlayer.h:208
bool setVolume(float volume) override
sets the volume - values need to be between 0.0 and 1.0
Definition AudioPlayer.h:361
bool next(int offset=1)
Definition AudioPlayer.h:289
float volume() override
Determines the actual volume.
Definition AudioPlayer.h:377
bool isActive()
determines if the player is active
Definition AudioPlayer.h:341
bool previous(int offset=1)
moves to previous file
Definition AudioPlayer.h:316
bool setPath(const char *path)
Moves to the selected file w/o updating the actual file position.
Definition AudioPlayer.h:307
void setActive(bool isActive)
The same like start() / stop()
Definition AudioPlayer.h:347
Definition AudioPlayerProtocol.h:11
virtual bool processCommand(const char *input, Print &result)=0
virtual void setPlayer(AudioPlayer &player)
Defines the player.
Definition AudioPlayerProtocol.h:25
virtual int index()
Returns the actual index of the stream.
Definition AudioSource.h:37
virtual const char * toStr()
provides the actual stream (e.g. file) name or url
Definition AudioSource.h:68
KA-Radio Protocol: We can use the KA-Radio protocol to control the audio player provided by the audio...
Definition KARadioProtocol.h:26
int index()
Provides the actual index.
Definition KARadioProtocol.h:214
KARadioProtocol(AudioPlayer &player)
Default constructor.
Definition KARadioProtocol.h:140
bool processCommand(Stream &input, Print &result) override
Proceess commands passed by Stream (e.g. Serial)
Definition KARadioProtocol.h:150
KARadioProtocol()
Empty constructor: call setPlayer to define the player.
Definition KARadioProtocol.h:29
const char * title()
Provides the actual title.
Definition KARadioProtocol.h:217
bool processCommand(Str &name, Str &arg, Print &result)
Processes a single command.
Definition KARadioProtocol.h:194
void setPlayer(AudioPlayer &player) override
Defines the player.
Definition KARadioProtocol.h:145
void addCommand(const char *cmd, bool(*cb)(AudioPlayer &player, Str &cmd, Str &par, Print &out, KARadioProtocol *self))
Add a new command.
Definition KARadioProtocol.h:220
bool processCommand(const char *input, Print &result) override
Definition KARadioProtocol.h:156
Definition NoArduino.h:62
Str which keeps the data on the heap. We grow the allocated memory only if the copy source is not fit...
Definition Str.h:24
A simple wrapper to provide string functions on existing allocated char*. If the underlying char* is ...
Definition StrView.h:28
virtual bool equals(const char *str)
checks if the string equals indicated parameter string
Definition StrView.h:165
virtual int length()
Definition StrView.h:383
virtual bool isEmpty()
checks if the string is empty
Definition StrView.h:386
virtual void trim()
remove leading and traling spaces
Definition StrView.h:504
virtual void substring(StrView &from, int start, int end)
copies a substring into the current string
Definition StrView.h:477
virtual const char * c_str()
provides the string value as const char*
Definition StrView.h:379
virtual int indexOf(const char c, int start=0)
Definition StrView.h:260
Definition NoArduino.h:142
Vector implementation which provides the most important methods as defined by std::vector....
Definition Vector.h:21
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition AudioCodecsBase.h:10
Definition KARadioProtocol.h:232