1 /* Media proxy */
2
3 /*
4 * Copyright (c) 2021 Nordic Semiconductor ASA
5 *
6 * SPDX-License-Identifier: Apache-2.0
7 */
8
9 #include <zephyr/sys/check.h>
10
11 #include <zephyr/bluetooth/services/ots.h>
12 #include <zephyr/bluetooth/audio/media_proxy.h>
13 #include <zephyr/bluetooth/audio/mcc.h>
14
15 #include "media_proxy_internal.h"
16 #include "mcs_internal.h"
17
18 #include <zephyr/logging/log.h>
19
20 LOG_MODULE_REGISTER(media_proxy, CONFIG_MCTL_LOG_LEVEL);
21
22 /* Media player */
23 struct media_player {
24 struct media_proxy_pl_calls *calls;
25 struct bt_conn *conn; /* TODO: Treat local and remote player differently */
26 bool registered;
27 };
28
29 /* Synchronous controller - controller using the synchronous API */
30 struct scontroller {
31 struct media_proxy_sctrl_cbs *cbs;
32 };
33
34 /* Asynchronous controller - controller using the asynchronous API */
35 struct controller {
36 struct media_proxy_ctrl_cbs *cbs;
37 };
38 /* Media proxy */
39 struct mprx {
40
41 #if defined(CONFIG_MCTL_LOCAL_PLAYER_REMOTE_CONTROL)
42 /* Controller using the synchronous interface - e.g. remote controller via
43 * the media control service
44 */
45 struct scontroller sctrlr;
46 #endif /* CONFIG_MCTL_LOCAL_PLAYER_REMOTE_CONTROL */
47
48 #if defined(CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL)
49 /* Controller using the callback interface - i.e. upper layer */
50 struct controller ctrlr;
51 #endif /* CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL */
52
53 #if defined(CONFIG_MCTL_LOCAL_PLAYER_CONTROL)
54 /* The local media player */
55 struct media_player local_player;
56 #endif /* CONFIG_MCTL_LOCAL_PLAYER_CONTROL */
57
58 /* Control of remote players is currently only supported over Bluetooth, via MCC */
59 #if defined(CONFIG_MCTL_REMOTE_PLAYER_CONTROL)
60 /* Remote media player - to have a player instance for the user */
61 struct media_player remote_player;
62
63 /* MCC callbacks */
64 struct bt_mcc_cb mcc_cbs;
65 #endif /* CONFIG_MCTL_REMOTE_PLAYER_CONTROL */
66 };
67
68 static struct mprx mprx = { 0 };
69
70
71 #if defined(CONFIG_MCTL_LOCAL_PLAYER_REMOTE_CONTROL)
72 /* Synchronous controller calls ***********************************************/
73
74 /* The synchronous controller is the media control service, representing a remote controller.
75 * It only gets access to the local player, not remote players.
76 * I.e., the calls from the synchronous controller are always routed to the local_player.
77 */
78
media_proxy_sctrl_register(struct media_proxy_sctrl_cbs * sctrl_cbs)79 int media_proxy_sctrl_register(struct media_proxy_sctrl_cbs *sctrl_cbs)
80 {
81 mprx.sctrlr.cbs = sctrl_cbs;
82 return 0;
83 };
84
media_proxy_sctrl_get_player_name(void)85 const char *media_proxy_sctrl_get_player_name(void)
86 {
87 /* TODO: Add check for whether function pointer is non-NULL everywhere */
88 return mprx.local_player.calls->get_player_name();
89 }
90
91 #ifdef CONFIG_BT_MPL_OBJECTS
media_proxy_sctrl_get_icon_id(void)92 uint64_t media_proxy_sctrl_get_icon_id(void)
93 {
94 return mprx.local_player.calls->get_icon_id();
95 }
96 #endif /* CONFIG_BT_MPL_OBJECTS */
97
media_proxy_sctrl_get_icon_url(void)98 const char *media_proxy_sctrl_get_icon_url(void)
99 {
100 return mprx.local_player.calls->get_icon_url();
101 }
102
media_proxy_sctrl_get_track_title(void)103 const char *media_proxy_sctrl_get_track_title(void)
104 {
105 return mprx.local_player.calls->get_track_title();
106 }
107
media_proxy_sctrl_get_track_duration(void)108 int32_t media_proxy_sctrl_get_track_duration(void)
109 {
110 return mprx.local_player.calls->get_track_duration();
111 }
112
media_proxy_sctrl_get_track_position(void)113 int32_t media_proxy_sctrl_get_track_position(void)
114 {
115 return mprx.local_player.calls->get_track_position();
116 }
117
media_proxy_sctrl_set_track_position(int32_t position)118 void media_proxy_sctrl_set_track_position(int32_t position)
119 {
120 mprx.local_player.calls->set_track_position(position);
121 }
122
media_proxy_sctrl_get_playback_speed(void)123 int8_t media_proxy_sctrl_get_playback_speed(void)
124 {
125 return mprx.local_player.calls->get_playback_speed();
126 }
127
media_proxy_sctrl_set_playback_speed(int8_t speed)128 void media_proxy_sctrl_set_playback_speed(int8_t speed)
129 {
130 mprx.local_player.calls->set_playback_speed(speed);
131 }
132
media_proxy_sctrl_get_seeking_speed(void)133 int8_t media_proxy_sctrl_get_seeking_speed(void)
134 {
135 return mprx.local_player.calls->get_seeking_speed();
136 }
137
138 #ifdef CONFIG_BT_MPL_OBJECTS
media_proxy_sctrl_get_track_segments_id(void)139 uint64_t media_proxy_sctrl_get_track_segments_id(void)
140 {
141 return mprx.local_player.calls->get_track_segments_id();
142 }
143
media_proxy_sctrl_get_current_track_id(void)144 uint64_t media_proxy_sctrl_get_current_track_id(void)
145 {
146 return mprx.local_player.calls->get_current_track_id();
147 }
148
media_proxy_sctrl_set_current_track_id(uint64_t id)149 void media_proxy_sctrl_set_current_track_id(uint64_t id)
150 {
151 mprx.local_player.calls->set_current_track_id(id);
152 }
153
media_proxy_sctrl_get_next_track_id(void)154 uint64_t media_proxy_sctrl_get_next_track_id(void)
155 {
156 return mprx.local_player.calls->get_next_track_id();
157 }
158
media_proxy_sctrl_set_next_track_id(uint64_t id)159 void media_proxy_sctrl_set_next_track_id(uint64_t id)
160 {
161 mprx.local_player.calls->set_next_track_id(id);
162 }
163
media_proxy_sctrl_get_parent_group_id(void)164 uint64_t media_proxy_sctrl_get_parent_group_id(void)
165 {
166 return mprx.local_player.calls->get_parent_group_id();
167 }
168
media_proxy_sctrl_get_current_group_id(void)169 uint64_t media_proxy_sctrl_get_current_group_id(void)
170 {
171 return mprx.local_player.calls->get_current_group_id();
172 }
173
media_proxy_sctrl_set_current_group_id(uint64_t id)174 void media_proxy_sctrl_set_current_group_id(uint64_t id)
175 {
176 mprx.local_player.calls->set_current_group_id(id);
177 }
178 #endif /* CONFIG_BT_MPL_OBJECTS */
179
media_proxy_sctrl_get_playing_order(void)180 uint8_t media_proxy_sctrl_get_playing_order(void)
181 {
182 return mprx.local_player.calls->get_playing_order();
183 }
184
media_proxy_sctrl_set_playing_order(uint8_t order)185 void media_proxy_sctrl_set_playing_order(uint8_t order)
186 {
187 mprx.local_player.calls->set_playing_order(order);
188 }
189
media_proxy_sctrl_get_playing_orders_supported(void)190 uint16_t media_proxy_sctrl_get_playing_orders_supported(void)
191 {
192 return mprx.local_player.calls->get_playing_orders_supported();
193 }
194
media_proxy_sctrl_get_media_state(void)195 uint8_t media_proxy_sctrl_get_media_state(void)
196 {
197 return mprx.local_player.calls->get_media_state();
198 }
199
media_proxy_sctrl_send_command(const struct mpl_cmd * cmd)200 void media_proxy_sctrl_send_command(const struct mpl_cmd *cmd)
201 {
202 mprx.local_player.calls->send_command(cmd);
203 }
204
media_proxy_sctrl_get_commands_supported(void)205 uint32_t media_proxy_sctrl_get_commands_supported(void)
206 {
207 return mprx.local_player.calls->get_commands_supported();
208 }
209
210 #ifdef CONFIG_BT_MPL_OBJECTS
media_proxy_sctrl_send_search(const struct mpl_search * search)211 void media_proxy_sctrl_send_search(const struct mpl_search *search)
212 {
213 mprx.local_player.calls->send_search(search);
214 }
215
media_proxy_sctrl_get_search_results_id(void)216 uint64_t media_proxy_sctrl_get_search_results_id(void)
217 {
218 return mprx.local_player.calls->get_search_results_id();
219 }
220 void media_proxy_sctrl_search_results_id_cb(uint64_t id);
221 #endif /* CONFIG_BT_MPL_OBJECTS */
222
media_proxy_sctrl_get_content_ctrl_id(void)223 uint8_t media_proxy_sctrl_get_content_ctrl_id(void)
224 {
225 return mprx.local_player.calls->get_content_ctrl_id();
226 }
227 #endif /* CONFIG_MCTL_LOCAL_PLAYER_REMOTE_CONTROL */
228
229
230 #if defined(CONFIG_MCTL_REMOTE_PLAYER_CONTROL)
231 /* Media control client callbacks *********************************************/
232
mcc_discover_mcs_cb(struct bt_conn * conn,int err)233 static void mcc_discover_mcs_cb(struct bt_conn *conn, int err)
234 {
235 if (err) {
236 LOG_ERR("Discovery failed (%d)", err);
237 }
238
239 LOG_DBG("Disovered player");
240
241 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->discover_player) {
242 mprx.ctrlr.cbs->discover_player(&mprx.remote_player, err);
243 } else {
244 LOG_DBG("No callback");
245 }
246 }
247
mcc_read_player_name_cb(struct bt_conn * conn,int err,const char * name)248 static void mcc_read_player_name_cb(struct bt_conn *conn, int err, const char *name)
249 {
250 /* Debug statements for at least a couple of the callbacks, to show flow */
251 LOG_DBG("MCC player name callback");
252
253 if (err) {
254 LOG_ERR("Player name failed");
255 }
256
257 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->player_name_recv) {
258 mprx.ctrlr.cbs->player_name_recv(&mprx.remote_player, err, name);
259 } else {
260 LOG_DBG("No callback");
261 }
262 }
263
264 #ifdef CONFIG_MCTL_REMOTE_PLAYER_CONTROL_OBJECTS
mcc_read_icon_obj_id_cb(struct bt_conn * conn,int err,uint64_t id)265 static void mcc_read_icon_obj_id_cb(struct bt_conn *conn, int err, uint64_t id)
266 {
267 LOG_DBG("Icon Object ID callback");
268
269 if (err) {
270 LOG_ERR("Icon Object ID read failed (%d)", err);
271 }
272
273 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->icon_id_recv) {
274 mprx.ctrlr.cbs->icon_id_recv(&mprx.remote_player, err, id);
275 } else {
276 LOG_DBG("No callback");
277 }
278 }
279 #endif /* CONFIG_MCTL_REMOTE_PLAYER_CONTROL_OBJECTS */
280
281 #if defined(CONFIG_BT_MCC_READ_MEDIA_PLAYER_ICON_URL)
mcc_read_icon_url_cb(struct bt_conn * conn,int err,const char * url)282 static void mcc_read_icon_url_cb(struct bt_conn *conn, int err, const char *url)
283 {
284 if (err) {
285 LOG_ERR("Icon URL read failed (%d)", err);
286 }
287
288 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->icon_url_recv) {
289 mprx.ctrlr.cbs->icon_url_recv(&mprx.remote_player, err, url);
290 } else {
291 LOG_DBG("No callback");
292 }
293 }
294 #endif /* defined(CONFIG_BT_MCC_READ_MEDIA_PLAYER_ICON_URL) */
295
mcc_track_changed_ntf_cb(struct bt_conn * conn,int err)296 static void mcc_track_changed_ntf_cb(struct bt_conn *conn, int err)
297 {
298 if (err) {
299 LOG_ERR("Track change notification failed (%d)", err);
300 return;
301 }
302
303 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->track_changed_recv) {
304 mprx.ctrlr.cbs->track_changed_recv(&mprx.remote_player, err);
305 } else {
306 LOG_DBG("No callback");
307 }
308 }
309
310 #if defined(CONFIG_BT_MCC_READ_TRACK_TITLE)
mcc_read_track_title_cb(struct bt_conn * conn,int err,const char * title)311 static void mcc_read_track_title_cb(struct bt_conn *conn, int err, const char *title)
312 {
313 if (err) {
314 LOG_ERR("Track title read failed (%d)", err);
315 }
316
317 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->track_title_recv) {
318 mprx.ctrlr.cbs->track_title_recv(&mprx.remote_player, err, title);
319 } else {
320 LOG_DBG("No callback");
321 }
322 }
323 #endif /* defined(CONFIG_BT_MCC_READ_TRACK_TITLE) */
324
325 #if defined(CONFIG_BT_MCC_READ_TRACK_DURATION)
mcc_read_track_duration_cb(struct bt_conn * conn,int err,int32_t dur)326 static void mcc_read_track_duration_cb(struct bt_conn *conn, int err, int32_t dur)
327 {
328 if (err) {
329 LOG_ERR("Track duration read failed (%d)", err);
330 }
331
332 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->track_duration_recv) {
333 mprx.ctrlr.cbs->track_duration_recv(&mprx.remote_player, err, dur);
334 } else {
335 LOG_DBG("No callback");
336 }
337 }
338 #endif /* defined(CONFIG_BT_MCC_READ_TRACK_DURATION) */
339
340 #if defined(CONFIG_BT_MCC_READ_TRACK_POSITION)
mcc_read_track_position_cb(struct bt_conn * conn,int err,int32_t pos)341 static void mcc_read_track_position_cb(struct bt_conn *conn, int err, int32_t pos)
342 {
343 if (err) {
344 LOG_ERR("Track position read failed (%d)", err);
345 }
346
347 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->track_position_recv) {
348 mprx.ctrlr.cbs->track_position_recv(&mprx.remote_player, err, pos);
349 } else {
350 LOG_DBG("No callback");
351 }
352 }
353 #endif /* defined(CONFIG_BT_MCC_READ_TRACK_POSITION) */
354
355 #if defined(CONFIG_BT_MCC_SET_TRACK_POSITION)
mcc_set_track_position_cb(struct bt_conn * conn,int err,int32_t pos)356 static void mcc_set_track_position_cb(struct bt_conn *conn, int err, int32_t pos)
357 {
358 if (err) {
359 LOG_ERR("Track Position set failed (%d)", err);
360 }
361
362 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->track_position_write) {
363 mprx.ctrlr.cbs->track_position_write(&mprx.remote_player, err, pos);
364 } else {
365 LOG_DBG("No callback");
366 }
367 }
368 #endif /* defined(CONFIG_BT_MCC_SET_TRACK_POSITION) */
369
370 #if defined(CONFIG_BT_MCC_READ_PLAYBACK_SPEED)
mcc_read_playback_speed_cb(struct bt_conn * conn,int err,int8_t speed)371 static void mcc_read_playback_speed_cb(struct bt_conn *conn, int err, int8_t speed)
372 {
373 if (err) {
374 LOG_ERR("Playback speed read failed (%d)", err);
375 }
376
377 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->playback_speed_recv) {
378 mprx.ctrlr.cbs->playback_speed_recv(&mprx.remote_player, err, speed);
379 } else {
380 LOG_DBG("No callback");
381 }
382 }
383 #endif /* defined (CONFIG_BT_MCC_READ_PLAYBACK_SPEED) */
384
385 #if defined(CONFIG_BT_MCC_SET_PLAYBACK_SPEED)
mcc_set_playback_speed_cb(struct bt_conn * conn,int err,int8_t speed)386 static void mcc_set_playback_speed_cb(struct bt_conn *conn, int err, int8_t speed)
387 {
388 if (err) {
389 LOG_ERR("Playback speed set failed (%d)", err);
390 }
391
392 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->playback_speed_write) {
393 mprx.ctrlr.cbs->playback_speed_write(&mprx.remote_player, err, speed);
394 } else {
395 LOG_DBG("No callback");
396 }
397 }
398 #endif /* defined (CONFIG_BT_MCC_SET_PLAYBACK_SPEED) */
399
400 #if defined(CONFIG_BT_MCC_READ_SEEKING_SPEED)
mcc_read_seeking_speed_cb(struct bt_conn * conn,int err,int8_t speed)401 static void mcc_read_seeking_speed_cb(struct bt_conn *conn, int err, int8_t speed)
402 {
403 if (err) {
404 LOG_ERR("Seeking speed read failed (%d)", err);
405 }
406
407 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->seeking_speed_recv) {
408 mprx.ctrlr.cbs->seeking_speed_recv(&mprx.remote_player, err, speed);
409 } else {
410 LOG_DBG("No callback");
411 }
412 }
413 #endif /* defined (CONFIG_BT_MCC_READ_SEEKING_SPEED) */
414
415 #ifdef CONFIG_MCTL_REMOTE_PLAYER_CONTROL_OBJECTS
mcc_read_segments_obj_id_cb(struct bt_conn * conn,int err,uint64_t id)416 static void mcc_read_segments_obj_id_cb(struct bt_conn *conn, int err, uint64_t id)
417 {
418 if (err) {
419 LOG_ERR("Track Segments Object ID read failed (%d)", err);
420 }
421
422 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->track_segments_id_recv) {
423 mprx.ctrlr.cbs->track_segments_id_recv(&mprx.remote_player, err, id);
424 } else {
425 LOG_DBG("No callback");
426 }
427 }
428
mcc_read_current_track_obj_id_cb(struct bt_conn * conn,int err,uint64_t id)429 static void mcc_read_current_track_obj_id_cb(struct bt_conn *conn, int err, uint64_t id)
430 {
431 if (err) {
432 LOG_ERR("Current Track Object ID read failed (%d)", err);
433 }
434
435 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->current_track_id_recv) {
436 mprx.ctrlr.cbs->current_track_id_recv(&mprx.remote_player, err, id);
437 } else {
438 LOG_DBG("No callback");
439 }
440 }
441
442 /* TODO: current track set callback - must be added to MCC first */
443
mcc_read_next_track_obj_id_cb(struct bt_conn * conn,int err,uint64_t id)444 static void mcc_read_next_track_obj_id_cb(struct bt_conn *conn, int err, uint64_t id)
445 {
446 if (err) {
447 LOG_ERR("Next Track Object ID read failed (%d)", err);
448 }
449
450 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->next_track_id_recv) {
451 mprx.ctrlr.cbs->next_track_id_recv(&mprx.remote_player, err, id);
452 } else {
453 LOG_DBG("No callback");
454 }
455 }
456
457 /* TODO: next track set callback - must be added to MCC first */
458
mcc_read_parent_group_obj_id_cb(struct bt_conn * conn,int err,uint64_t id)459 static void mcc_read_parent_group_obj_id_cb(struct bt_conn *conn, int err, uint64_t id)
460 {
461 if (err) {
462 LOG_ERR("Parent Group Object ID read failed (%d)", err);
463 }
464
465 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->parent_group_id_recv) {
466 mprx.ctrlr.cbs->parent_group_id_recv(&mprx.remote_player, err, id);
467 } else {
468 LOG_DBG("No callback");
469 }
470 }
471
mcc_read_current_group_obj_id_cb(struct bt_conn * conn,int err,uint64_t id)472 static void mcc_read_current_group_obj_id_cb(struct bt_conn *conn, int err, uint64_t id)
473 {
474 if (err) {
475 LOG_ERR("Current Group Object ID read failed (%d)", err);
476 }
477
478 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->current_group_id_recv) {
479 mprx.ctrlr.cbs->current_group_id_recv(&mprx.remote_player, err, id);
480 } else {
481 LOG_DBG("No callback");
482 }
483 }
484
485 /* TODO: current group set callback - must be added to MCC first */
486
487 #endif /* CONFIG_MCTL_REMOTE_PLAYER_CONTROL_OBJECTS */
488
489 #if defined(CONFIG_BT_MCC_READ_PLAYING_ORDER)
mcc_read_playing_order_cb(struct bt_conn * conn,int err,uint8_t order)490 static void mcc_read_playing_order_cb(struct bt_conn *conn, int err, uint8_t order)
491 {
492 if (err) {
493 LOG_ERR("Playing order read failed (%d)", err);
494 }
495
496 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->playing_order_recv) {
497 mprx.ctrlr.cbs->playing_order_recv(&mprx.remote_player, err, order);
498 } else {
499 LOG_DBG("No callback");
500 }
501 }
502 #endif /* defined(CONFIG_BT_MCC_READ_PLAYING_ORDER) */
503
504 #if defined(CONFIG_BT_MCC_SET_PLAYING_ORDER)
mcc_set_playing_order_cb(struct bt_conn * conn,int err,uint8_t order)505 static void mcc_set_playing_order_cb(struct bt_conn *conn, int err, uint8_t order)
506 {
507 if (err) {
508 LOG_ERR("Playing order set failed (%d)", err);
509 }
510
511 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->playing_order_write) {
512 mprx.ctrlr.cbs->playing_order_write(&mprx.remote_player, err, order);
513 } else {
514 LOG_DBG("No callback");
515 }
516 }
517 #endif /* defined(CONFIG_BT_MCC_SET_PLAYING_ORDER) */
518
519 #if defined(CONFIG_BT_MCC_READ_PLAYING_ORDER_SUPPORTED)
mcc_read_playing_orders_supported_cb(struct bt_conn * conn,int err,uint16_t orders)520 static void mcc_read_playing_orders_supported_cb(struct bt_conn *conn, int err, uint16_t orders)
521 {
522 if (err) {
523 LOG_ERR("Playing orders supported read failed (%d)", err);
524 }
525
526 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->playing_orders_supported_recv) {
527 mprx.ctrlr.cbs->playing_orders_supported_recv(&mprx.remote_player, err, orders);
528 } else {
529 LOG_DBG("No callback");
530 }
531 }
532 #endif /* defined(CONFIG_BT_MCC_READ_PLAYING_ORDER_SUPPORTED) */
533
534 #if defined(CONFIG_BT_MCC_READ_MEDIA_STATE)
mcc_read_media_state_cb(struct bt_conn * conn,int err,uint8_t state)535 static void mcc_read_media_state_cb(struct bt_conn *conn, int err, uint8_t state)
536 {
537 if (err) {
538 LOG_ERR("Media State read failed (%d)", err);
539 }
540
541 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->media_state_recv) {
542 mprx.ctrlr.cbs->media_state_recv(&mprx.remote_player, err, state);
543 } else {
544 LOG_DBG("No callback");
545 }
546 }
547 #endif /* defined(CONFIG_BT_MCC_READ_MEDIA_STATE) */
548
549 #if defined(CONFIG_BT_MCC_SET_MEDIA_CONTROL_POINT)
mcc_send_cmd_cb(struct bt_conn * conn,int err,const struct mpl_cmd * cmd)550 static void mcc_send_cmd_cb(struct bt_conn *conn, int err, const struct mpl_cmd *cmd)
551 {
552 if (err) {
553 LOG_ERR("Command send failed (%d) - opcode: %d, param: %d", err, cmd->opcode,
554 cmd->param);
555 }
556
557 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->command_send) {
558 mprx.ctrlr.cbs->command_send(&mprx.remote_player, err, cmd);
559 } else {
560 LOG_DBG("No callback");
561 }
562 }
563 #endif /* defined(CONFIG_BT_MCC_SET_MEDIA_CONTROL_POINT) */
564
mcc_cmd_ntf_cb(struct bt_conn * conn,int err,const struct mpl_cmd_ntf * ntf)565 static void mcc_cmd_ntf_cb(struct bt_conn *conn, int err,
566 const struct mpl_cmd_ntf *ntf)
567 {
568 if (err) {
569 LOG_ERR("Command notification error (%d) - command opcode: %d, result: %d", err,
570 ntf->requested_opcode, ntf->result_code);
571 }
572
573 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->command_recv) {
574 mprx.ctrlr.cbs->command_recv(&mprx.remote_player, err, ntf);
575 } else {
576 LOG_DBG("No callback");
577 }
578 }
579
580 #if defined(CONFIG_BT_MCC_READ_MEDIA_CONTROL_POINT_OPCODES_SUPPORTED)
mcc_read_opcodes_supported_cb(struct bt_conn * conn,int err,uint32_t opcodes)581 static void mcc_read_opcodes_supported_cb(struct bt_conn *conn, int err, uint32_t opcodes)
582 {
583 if (err) {
584 LOG_ERR("Opcodes supported read failed (%d)", err);
585 }
586
587 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->commands_supported_recv) {
588 mprx.ctrlr.cbs->commands_supported_recv(&mprx.remote_player, err, opcodes);
589 } else {
590 LOG_DBG("No callback");
591 }
592 }
593 #endif /* defined(CONFIG_BT_MCC_READ_MEDIA_CONTROL_POINT_OPCODES_SUPPORTED) */
594
595 #ifdef CONFIG_MCTL_REMOTE_PLAYER_CONTROL_OBJECTS
mcc_send_search_cb(struct bt_conn * conn,int err,const struct mpl_search * search)596 static void mcc_send_search_cb(struct bt_conn *conn, int err, const struct mpl_search *search)
597 {
598 if (err) {
599 LOG_ERR("Search send failed (%d)", err);
600 }
601
602 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->search_send) {
603 mprx.ctrlr.cbs->search_send(&mprx.remote_player, err, search);
604 } else {
605 LOG_DBG("No callback");
606 }
607 }
608
mcc_search_ntf_cb(struct bt_conn * conn,int err,uint8_t result_code)609 static void mcc_search_ntf_cb(struct bt_conn *conn, int err, uint8_t result_code)
610 {
611 if (err) {
612 LOG_ERR("Search notification error (%d), result code: %d", err, result_code);
613 }
614
615 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->search_recv) {
616 mprx.ctrlr.cbs->search_recv(&mprx.remote_player, err, result_code);
617 } else {
618 LOG_DBG("No callback");
619 }
620 }
621
mcc_read_search_results_obj_id_cb(struct bt_conn * conn,int err,uint64_t id)622 static void mcc_read_search_results_obj_id_cb(struct bt_conn *conn, int err, uint64_t id)
623 {
624 if (err) {
625 LOG_ERR("Search Results Object ID read failed (%d)", err);
626 }
627
628 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->search_results_id_recv) {
629 mprx.ctrlr.cbs->search_results_id_recv(&mprx.remote_player, err, id);
630 } else {
631 LOG_DBG("No callback");
632 }
633 }
634 #endif /* CONFIG_MCTL_REMOTE_PLAYER_CONTROL_OBJECTS */
635
636 #if defined(CONFIG_BT_MCC_READ_CONTENT_CONTROL_ID)
mcc_read_content_control_id_cb(struct bt_conn * conn,int err,uint8_t ccid)637 static void mcc_read_content_control_id_cb(struct bt_conn *conn, int err, uint8_t ccid)
638 {
639 if (err) {
640 LOG_ERR("Content Control ID read failed (%d)", err);
641 }
642
643 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->content_ctrl_id_recv) {
644 mprx.ctrlr.cbs->content_ctrl_id_recv(&mprx.remote_player, err, ccid);
645 } else {
646 LOG_DBG("No callback");
647 }
648 }
649 #endif /* defined(CONFIG_BT_MCC_READ_CONTENT_CONTROL_ID) */
650
651 #endif /* CONFIG_MCTL_REMOTE_PLAYER_CONTROL */
652
653
654 /* Asynchronous controller calls **********************************************/
655
656 #if defined(CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL)
media_proxy_ctrl_register(struct media_proxy_ctrl_cbs * ctrl_cbs)657 int media_proxy_ctrl_register(struct media_proxy_ctrl_cbs *ctrl_cbs)
658 {
659 CHECKIF(ctrl_cbs == NULL) {
660 LOG_DBG("NULL callback pointer");
661 return -EINVAL;
662 }
663
664 mprx.ctrlr.cbs = ctrl_cbs;
665
666 if (mprx.local_player.registered) {
667 if (mprx.ctrlr.cbs->local_player_instance) {
668 mprx.ctrlr.cbs->local_player_instance(&mprx.local_player, 0);
669 }
670 }
671
672 /* TODO: Return error code if too many controllers registered */
673 return 0;
674 };
675 #endif /* CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL */
676
677 #ifdef CONFIG_MCTL_REMOTE_PLAYER_CONTROL
disconnected(struct bt_conn * conn,uint8_t reason)678 static void disconnected(struct bt_conn *conn, uint8_t reason)
679 {
680 if (mprx.remote_player.conn == conn) {
681 bt_conn_unref(mprx.remote_player.conn);
682 mprx.remote_player.conn = NULL;
683 }
684 }
685
686 BT_CONN_CB_DEFINE(conn_callbacks) = {
687 .disconnected = disconnected,
688 };
689
media_proxy_ctrl_discover_player(struct bt_conn * conn)690 int media_proxy_ctrl_discover_player(struct bt_conn *conn)
691 {
692 int err;
693
694 CHECKIF(!conn) {
695 LOG_DBG("NUll conn pointer");
696 return -EINVAL;
697 }
698
699 /* Initialize MCC */
700 mprx.mcc_cbs.discover_mcs = mcc_discover_mcs_cb;
701 mprx.mcc_cbs.read_player_name = mcc_read_player_name_cb;
702 #ifdef CONFIG_MCTL_REMOTE_PLAYER_CONTROL_OBJECTS
703 mprx.mcc_cbs.read_icon_obj_id = mcc_read_icon_obj_id_cb;
704 #endif /* CONFIG_MCTL_REMOTE_PLAYER_CONTROL_OBJECTS */
705 #if defined(CONFIG_BT_MCC_READ_MEDIA_PLAYER_ICON_URL)
706 mprx.mcc_cbs.read_icon_url = mcc_read_icon_url_cb;
707 #endif /* defined(CONFIG_BT_MCC_READ_MEDIA_PLAYER_ICON_URL) */
708 mprx.mcc_cbs.track_changed_ntf = mcc_track_changed_ntf_cb;
709 #if defined(CONFIG_BT_MCC_READ_TRACK_TITLE)
710 mprx.mcc_cbs.read_track_title = mcc_read_track_title_cb;
711 #endif /* defined(CONFIG_BT_MCC_READ_TRACK_TITLE) */
712 #if defined(CONFIG_BT_MCC_READ_TRACK_DURATION)
713 mprx.mcc_cbs.read_track_duration = mcc_read_track_duration_cb;
714 #endif /* defined(CONFIG_BT_MCC_READ_TRACK_DURATION) */
715 #if defined(CONFIG_BT_MCC_READ_TRACK_POSITION)
716 mprx.mcc_cbs.read_track_position = mcc_read_track_position_cb;
717 #endif /* defined(CONFIG_BT_MCC_READ_TRACK_POSITION) */
718 #if defined(CONFIG_BT_MCC_SET_TRACK_POSITION)
719 mprx.mcc_cbs.set_track_position = mcc_set_track_position_cb;
720 #endif /* defined(CONFIG_BT_MCC_SET_TRACK_POSITION) */
721 #if defined(CONFIG_BT_MCC_READ_PLAYBACK_SPEED)
722 mprx.mcc_cbs.read_playback_speed = mcc_read_playback_speed_cb;
723 #endif /* defined (CONFIG_BT_MCC_READ_PLAYBACK_SPEED) */
724 #if defined(CONFIG_BT_MCC_SET_PLAYBACK_SPEED)
725 mprx.mcc_cbs.set_playback_speed = mcc_set_playback_speed_cb;
726 #endif /* defined (CONFIG_BT_MCC_SET_PLAYBACK_SPEED) */
727 #if defined(CONFIG_BT_MCC_READ_SEEKING_SPEED)
728 mprx.mcc_cbs.read_seeking_speed = mcc_read_seeking_speed_cb;
729 #endif /* defined (CONFIG_BT_MCC_READ_SEEKING_SPEED) */
730 #ifdef CONFIG_MCTL_REMOTE_PLAYER_CONTROL_OBJECTS
731 mprx.mcc_cbs.read_segments_obj_id = mcc_read_segments_obj_id_cb;
732 mprx.mcc_cbs.read_current_track_obj_id = mcc_read_current_track_obj_id_cb;
733 mprx.mcc_cbs.read_next_track_obj_id = mcc_read_next_track_obj_id_cb;
734 mprx.mcc_cbs.read_parent_group_obj_id = mcc_read_parent_group_obj_id_cb;
735 mprx.mcc_cbs.read_current_group_obj_id = mcc_read_current_group_obj_id_cb;
736 #endif /* CONFIG_MCTL_REMOTE_PLAYER_CONTROL_OBJECTS */
737 #if defined(CONFIG_BT_MCC_READ_PLAYING_ORDER)
738 mprx.mcc_cbs.read_playing_order = mcc_read_playing_order_cb;
739 #endif /* defined(CONFIG_BT_MCC_READ_PLAYING_ORDER) */
740 #if defined(CONFIG_BT_MCC_SET_PLAYING_ORDER)
741 mprx.mcc_cbs.set_playing_order = mcc_set_playing_order_cb;
742 #endif /* defined(CONFIG_BT_MCC_SET_PLAYING_ORDER) */
743 #if defined(CONFIG_BT_MCC_READ_PLAYING_ORDER_SUPPORTED)
744 mprx.mcc_cbs.read_playing_orders_supported = mcc_read_playing_orders_supported_cb;
745 #endif /* defined(CONFIG_BT_MCC_READ_PLAYING_ORDER_SUPPORTED) */
746 #if defined(CONFIG_BT_MCC_READ_MEDIA_STATE)
747 mprx.mcc_cbs.read_media_state = mcc_read_media_state_cb;
748 #endif /* defined(CONFIG_BT_MCC_READ_MEDIA_STATE) */
749 #if defined(CONFIG_BT_MCC_SET_MEDIA_CONTROL_POINT)
750 mprx.mcc_cbs.send_cmd = mcc_send_cmd_cb;
751 #endif /* defined(CONFIG_BT_MCC_SET_MEDIA_CONTROL_POINT) */
752 mprx.mcc_cbs.cmd_ntf = mcc_cmd_ntf_cb;
753 #if defined(CONFIG_BT_MCC_READ_MEDIA_CONTROL_POINT_OPCODES_SUPPORTED)
754 mprx.mcc_cbs.read_opcodes_supported = mcc_read_opcodes_supported_cb;
755 #endif /* defined(CONFIG_BT_MCC_READ_MEDIA_CONTROL_POINT_OPCODES_SUPPORTED) */
756 #ifdef CONFIG_MCTL_REMOTE_PLAYER_CONTROL_OBJECTS
757 mprx.mcc_cbs.send_search = mcc_send_search_cb;
758 mprx.mcc_cbs.search_ntf = mcc_search_ntf_cb;
759 mprx.mcc_cbs.read_search_results_obj_id = mcc_read_search_results_obj_id_cb;
760 #endif /* CONFIG_MCTL_REMOTE_PLAYER_CONTROL_OBJECTS */
761 #if defined(CONFIG_BT_MCC_READ_CONTENT_CONTROL_ID)
762 mprx.mcc_cbs.read_content_control_id = mcc_read_content_control_id_cb;
763 #endif /* defined(CONFIG_BT_MCC_READ_CONTENT_CONTROL_ID) */
764
765 err = bt_mcc_init(&mprx.mcc_cbs);
766 if (err) {
767 LOG_ERR("Failed to initialize MCC");
768 return err;
769 }
770
771 /* Start discovery of remote MCS, subscribe to notifications */
772 err = bt_mcc_discover_mcs(conn, 1);
773 if (err) {
774 LOG_ERR("Discovery failed");
775 return err;
776 }
777
778 if (mprx.remote_player.conn != NULL) {
779 bt_conn_unref(mprx.remote_player.conn);
780 }
781 mprx.remote_player.conn = bt_conn_ref(conn);
782 mprx.remote_player.registered = true; /* TODO: Do MCC init and "registration" at startup */
783
784 return 0;
785 }
786 #endif /* CONFIG_MCTL_REMOTE_PLAYER_CONTROL */
787
788
789 #if defined(CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL) || defined(CONFIG_MCTL_REMOTE_PLAYER_CONTROL)
media_proxy_ctrl_get_player_name(struct media_player * player)790 int media_proxy_ctrl_get_player_name(struct media_player *player)
791 {
792 CHECKIF(player == NULL) {
793 LOG_DBG("player is NULL");
794 return -EINVAL;
795 }
796
797 #if defined(CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL)
798 if (mprx.local_player.registered && player == &mprx.local_player) {
799 LOG_DBG("Local player");
800 if (mprx.local_player.calls->get_player_name) {
801 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->player_name_recv) {
802 const char *name = mprx.local_player.calls->get_player_name();
803
804 mprx.ctrlr.cbs->player_name_recv(&mprx.local_player, 0, name);
805 } else {
806 LOG_DBG("No callback");
807 }
808
809 return 0;
810 }
811
812 LOG_DBG("No call");
813 return -EOPNOTSUPP;
814 }
815 #endif /* CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL */
816
817 #if defined(CONFIG_MCTL_REMOTE_PLAYER_CONTROL)
818 if (mprx.remote_player.registered && player == &mprx.remote_player) {
819 LOG_DBG("Remote player");
820 return bt_mcc_read_player_name(mprx.remote_player.conn);
821 }
822 #endif /* CONFIG_MCTL_REMOTE_PLAYER_CONTROL */
823
824 return -EINVAL;
825 }
826
media_proxy_ctrl_get_icon_id(struct media_player * player)827 int media_proxy_ctrl_get_icon_id(struct media_player *player)
828 {
829 CHECKIF(player == NULL) {
830 LOG_DBG("player is NULL");
831 return -EINVAL;
832 }
833
834 #if defined(CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL)
835 if (mprx.local_player.registered && player == &mprx.local_player) {
836 if (mprx.local_player.calls->get_icon_id) {
837 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->icon_id_recv) {
838 const uint64_t id = mprx.local_player.calls->get_icon_id();
839
840 mprx.ctrlr.cbs->icon_id_recv(&mprx.local_player, 0, id);
841 } else {
842 LOG_DBG("No callback");
843 }
844
845 return 0;
846 }
847
848 LOG_DBG("No call");
849 return -EOPNOTSUPP;
850 }
851 #endif /* CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL */
852
853 #if defined(CONFIG_MCTL_REMOTE_PLAYER_CONTROL_OBJECTS)
854 if (mprx.remote_player.registered && player == &mprx.remote_player) {
855 return bt_mcc_read_icon_obj_id(mprx.remote_player.conn);
856 }
857 #endif /* CONFIG_MCTL_REMOTE_PLAYER_CONTROL_OBJECTS */
858
859 return -EINVAL;
860 }
861
media_proxy_ctrl_get_icon_url(struct media_player * player)862 int media_proxy_ctrl_get_icon_url(struct media_player *player)
863 {
864 CHECKIF(player == NULL) {
865 LOG_DBG("player is NULL");
866 return -EINVAL;
867 }
868
869 #if defined(CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL)
870 if (mprx.local_player.registered && player == &mprx.local_player) {
871 if (mprx.local_player.calls->get_icon_url) {
872 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->icon_url_recv) {
873 const char *url = mprx.local_player.calls->get_icon_url();
874
875 mprx.ctrlr.cbs->icon_url_recv(player, 0, url);
876 } else {
877 LOG_DBG("No callback");
878 }
879
880 return 0;
881 }
882
883 LOG_DBG("No call");
884 return -EOPNOTSUPP;
885 }
886 #endif /* CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL */
887
888 #if defined(CONFIG_MCTL_REMOTE_PLAYER_CONTROL) && defined(CONFIG_BT_MCC_READ_MEDIA_PLAYER_ICON_URL)
889 if (mprx.remote_player.registered && player == &mprx.remote_player) {
890 return bt_mcc_read_icon_url(mprx.remote_player.conn);
891 }
892 #endif /* CONFIG_MCTL_REMOTE_PLAYER_CONTROL && CONFIG_BT_MCC_READ_MEDIA_PLAYER_ICON_URL */
893
894 return -EINVAL;
895 }
896
media_proxy_ctrl_get_track_title(struct media_player * player)897 int media_proxy_ctrl_get_track_title(struct media_player *player)
898 {
899 CHECKIF(player == NULL) {
900 LOG_DBG("player is NULL");
901 return -EINVAL;
902 }
903
904 #if defined(CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL)
905 if (mprx.local_player.registered && player == &mprx.local_player) {
906 if (mprx.local_player.calls->get_track_title) {
907 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->track_title_recv) {
908
909 const char *title = mprx.local_player.calls->get_track_title();
910 mprx.ctrlr.cbs->track_title_recv(player, 0, title);
911 } else {
912 LOG_DBG("No callback");
913 }
914
915 return 0;
916 }
917
918 LOG_DBG("No call");
919 return -EOPNOTSUPP;
920 }
921 #endif /* CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL */
922
923 #if defined(CONFIG_MCTL_REMOTE_PLAYER_CONTROL) && defined(CONFIG_BT_MCC_READ_TRACK_TITLE)
924 if (mprx.remote_player.registered && player == &mprx.remote_player) {
925 return bt_mcc_read_track_title(mprx.remote_player.conn);
926 }
927 #endif /* CONFIG_MCTL_REMOTE_PLAYER_CONTROL && CONFIG_BT_MCC_READ_TRACK_TITLE */
928
929 return -EINVAL;
930 }
931
media_proxy_ctrl_get_track_duration(struct media_player * player)932 int media_proxy_ctrl_get_track_duration(struct media_player *player)
933 {
934 CHECKIF(player == NULL) {
935 LOG_DBG("player is NULL");
936 return -EINVAL;
937 }
938
939 #if defined(CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL)
940 if (mprx.local_player.registered && player == &mprx.local_player) {
941 if (mprx.local_player.calls->get_track_duration) {
942 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->track_duration_recv) {
943 const int32_t duration =
944 mprx.local_player.calls->get_track_duration();
945
946 mprx.ctrlr.cbs->track_duration_recv(player, 0, duration);
947 } else {
948 LOG_DBG("No callback");
949 }
950
951 return 0;
952 }
953
954 LOG_DBG("No call");
955 return -EOPNOTSUPP;
956 }
957 #endif /* CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL */
958
959 #if defined(CONFIG_MCTL_REMOTE_PLAYER_CONTROL) && defined(CONFIG_BT_MCC_READ_TRACK_DURATION)
960 if (mprx.remote_player.registered && player == &mprx.remote_player) {
961 return bt_mcc_read_track_duration(mprx.remote_player.conn);
962 }
963 #endif /* CONFIG_MCTL_REMOTE_PLAYER_CONTROL && CONFIG_BT_MCC_READ_TRACK_DURATION */
964
965 return -EINVAL;
966 }
967
media_proxy_ctrl_get_track_position(struct media_player * player)968 int media_proxy_ctrl_get_track_position(struct media_player *player)
969 {
970 CHECKIF(player == NULL) {
971 LOG_DBG("player is NULL");
972 return -EINVAL;
973 }
974
975 #if defined(CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL)
976 if (mprx.local_player.registered && player == &mprx.local_player) {
977 if (mprx.local_player.calls->get_track_position) {
978 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->track_position_recv) {
979 const int32_t position =
980 mprx.local_player.calls->get_track_position();
981
982 mprx.ctrlr.cbs->track_position_recv(player, 0, position);
983 } else {
984 LOG_DBG("No callback");
985 }
986
987 return 0;
988 }
989
990 LOG_DBG("No call");
991 return -EOPNOTSUPP;
992 }
993 #endif /* CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL */
994
995 #if defined(CONFIG_MCTL_REMOTE_PLAYER_CONTROL) && defined(CONFIG_BT_MCC_READ_TRACK_POSITION)
996 if (mprx.remote_player.registered && player == &mprx.remote_player) {
997 return bt_mcc_read_track_position(mprx.remote_player.conn);
998 }
999 #endif /* CONFIG_MCTL_REMOTE_PLAYER_CONTROL && CONFIG_BT_MCC_READ_TRACK_POSITION */
1000
1001 return -EINVAL;
1002 }
1003
media_proxy_ctrl_set_track_position(struct media_player * player,int32_t position)1004 int media_proxy_ctrl_set_track_position(struct media_player *player, int32_t position)
1005 {
1006 CHECKIF(player == NULL) {
1007 LOG_DBG("player is NULL");
1008 return -EINVAL;
1009 }
1010
1011 #if defined(CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL)
1012 if (mprx.local_player.registered && player == &mprx.local_player) {
1013 if (mprx.local_player.calls->set_track_position) {
1014 mprx.local_player.calls->set_track_position(position);
1015
1016 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->track_position_write) {
1017 mprx.ctrlr.cbs->track_position_write(player, 0, position);
1018 } else {
1019 LOG_DBG("No callback");
1020 }
1021
1022 return 0;
1023 }
1024
1025 LOG_DBG("No call");
1026 return -EOPNOTSUPP;
1027 }
1028 #endif /* CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL */
1029
1030 #if defined(CONFIG_MCTL_REMOTE_PLAYER_CONTROL) && CONFIG_BT_MCC_SET_TRACK_POSITION
1031 if (mprx.remote_player.registered && player == &mprx.remote_player) {
1032 return bt_mcc_set_track_position(mprx.remote_player.conn, position);
1033 }
1034 #endif /* CONFIG_MCTL_REMOTE_PLAYER_CONTROL && CONFIG_BT_MCC_SET_TRACK_POSITION */
1035
1036 return -EINVAL;
1037 }
1038
media_proxy_ctrl_get_playback_speed(struct media_player * player)1039 int media_proxy_ctrl_get_playback_speed(struct media_player *player)
1040 {
1041 CHECKIF(player == NULL) {
1042 LOG_DBG("player is NULL");
1043 return -EINVAL;
1044 }
1045
1046 #if defined(CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL)
1047 if (mprx.local_player.registered && player == &mprx.local_player) {
1048 if (mprx.local_player.calls->get_playback_speed) {
1049 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->playback_speed_recv) {
1050 const int8_t speed = mprx.local_player.calls->get_playback_speed();
1051
1052 mprx.ctrlr.cbs->playback_speed_recv(player, 0, speed);
1053 } else {
1054 LOG_DBG("No callback");
1055 }
1056
1057 return 0;
1058 }
1059
1060 LOG_DBG("No call");
1061 return -EOPNOTSUPP;
1062 }
1063 #endif /* CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL */
1064
1065 #if defined(CONFIG_MCTL_REMOTE_PLAYER_CONTROL) && defined(CONFIG_BT_MCC_READ_PLAYBACK_SPEED)
1066 if (mprx.remote_player.registered && player == &mprx.remote_player) {
1067 return bt_mcc_read_playback_speed(mprx.remote_player.conn);
1068 }
1069 #endif /* CONFIG_MCTL_REMOTE_PLAYER_CONTROL && CONFIG_BT_MCC_READ_PLAYBACK_SPEED */
1070
1071 return -EINVAL;
1072 }
1073
media_proxy_ctrl_set_playback_speed(struct media_player * player,int8_t speed)1074 int media_proxy_ctrl_set_playback_speed(struct media_player *player, int8_t speed)
1075 {
1076 CHECKIF(player == NULL) {
1077 LOG_DBG("player is NULL");
1078 return -EINVAL;
1079 }
1080
1081 #if defined(CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL)
1082 if (mprx.local_player.registered && player == &mprx.local_player) {
1083 if (mprx.local_player.calls->set_playback_speed) {
1084 mprx.local_player.calls->set_playback_speed(speed);
1085
1086 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->playback_speed_write) {
1087 mprx.ctrlr.cbs->playback_speed_write(player, 0, speed);
1088 } else {
1089 LOG_DBG("No callback");
1090 }
1091
1092 return 0;
1093 }
1094
1095 LOG_DBG("No call");
1096 return -EOPNOTSUPP;
1097 }
1098 #endif /* CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL */
1099
1100 #if defined(CONFIG_MCTL_REMOTE_PLAYER_CONTROL) && defined(CONFIG_BT_MCC_SET_PLAYBACK_SPEED)
1101 if (mprx.remote_player.registered && player == &mprx.remote_player) {
1102 return bt_mcc_set_playback_speed(mprx.remote_player.conn, speed);
1103 }
1104 #endif /* CONFIG_MCTL_REMOTE_PLAYER_CONTROL && CONFIG_BT_MCC_SET_PLAYBACK_SPEED */
1105
1106 return -EINVAL;
1107 }
1108
media_proxy_ctrl_get_seeking_speed(struct media_player * player)1109 int media_proxy_ctrl_get_seeking_speed(struct media_player *player)
1110 {
1111 CHECKIF(player == NULL) {
1112 LOG_DBG("player is NULL");
1113 return -EINVAL;
1114 }
1115
1116 #if defined(CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL)
1117 if (mprx.local_player.registered && player == &mprx.local_player) {
1118 if (mprx.local_player.calls->get_seeking_speed) {
1119 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->seeking_speed_recv) {
1120 const int8_t speed = mprx.local_player.calls->get_seeking_speed();
1121
1122 mprx.ctrlr.cbs->seeking_speed_recv(player, 0, speed);
1123 } else {
1124 LOG_DBG("No callback");
1125 }
1126
1127 return 0;
1128 }
1129
1130 LOG_DBG("No call");
1131 return -EOPNOTSUPP;
1132 }
1133 #endif /* CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL */
1134
1135 #if defined(CONFIG_MCTL_REMOTE_PLAYER_CONTROL) && defined(CONFIG_BT_MCC_READ_SEEKING_SPEED)
1136 if (mprx.remote_player.registered && player == &mprx.remote_player) {
1137 return bt_mcc_read_seeking_speed(mprx.remote_player.conn);
1138 }
1139 #endif /* CONFIG_MCTL_REMOTE_PLAYER_CONTROL && CONFIG_BT_MCC_READ_SEEKING_SPEED */
1140
1141 return -EINVAL;
1142 }
1143
media_proxy_ctrl_get_track_segments_id(struct media_player * player)1144 int media_proxy_ctrl_get_track_segments_id(struct media_player *player)
1145 {
1146 CHECKIF(player == NULL) {
1147 LOG_DBG("player is NULL");
1148 return -EINVAL;
1149 }
1150
1151 #if defined(CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL)
1152 if (mprx.local_player.registered && player == &mprx.local_player) {
1153 if (mprx.local_player.calls->get_track_segments_id) {
1154 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->track_segments_id_recv) {
1155 const uint64_t id =
1156 mprx.local_player.calls->get_track_segments_id();
1157
1158 mprx.ctrlr.cbs->track_segments_id_recv(player, 0, id);
1159 } else {
1160 LOG_DBG("No callback");
1161 }
1162
1163 return 0;
1164 }
1165
1166 LOG_DBG("No call");
1167 return -EOPNOTSUPP;
1168 }
1169 #endif /* CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL */
1170
1171 #if defined(CONFIG_MCTL_REMOTE_PLAYER_CONTROL_OBJECTS)
1172 if (mprx.remote_player.registered && player == &mprx.remote_player) {
1173 return bt_mcc_read_segments_obj_id(mprx.remote_player.conn);
1174 }
1175 #endif /* CONFIG_MCTL_REMOTE_PLAYER_CONTROL_OBJECTS */
1176
1177 return -EINVAL;
1178 }
1179
media_proxy_ctrl_get_current_track_id(struct media_player * player)1180 int media_proxy_ctrl_get_current_track_id(struct media_player *player)
1181 {
1182 CHECKIF(player == NULL) {
1183 LOG_DBG("player is NULL");
1184 return -EINVAL;
1185 }
1186
1187 #if defined(CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL)
1188 if (mprx.local_player.registered && player == &mprx.local_player) {
1189 if (mprx.local_player.calls->get_current_track_id) {
1190 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->current_track_id_recv) {
1191 const uint64_t id = mprx.local_player.calls->get_current_track_id();
1192
1193 mprx.ctrlr.cbs->current_track_id_recv(player, 0, id);
1194 } else {
1195 LOG_DBG("No callback");
1196 }
1197
1198 return 0;
1199 }
1200
1201 LOG_DBG("No call");
1202 return -EOPNOTSUPP;
1203 }
1204 #endif /* CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL */
1205
1206 #if defined(CONFIG_MCTL_REMOTE_PLAYER_CONTROL_OBJECTS)
1207 if (mprx.remote_player.registered && player == &mprx.remote_player) {
1208 return bt_mcc_read_current_track_obj_id(mprx.remote_player.conn);
1209 }
1210 #endif /* CONFIG_MCTL_REMOTE_PLAYER_CONTROL_OBJECTS */
1211
1212 return -EINVAL;
1213 }
1214
media_proxy_ctrl_set_current_track_id(struct media_player * player,uint64_t id)1215 int media_proxy_ctrl_set_current_track_id(struct media_player *player, uint64_t id)
1216 {
1217 CHECKIF(player == NULL) {
1218 LOG_DBG("player is NULL");
1219 return -EINVAL;
1220 }
1221
1222 #if defined(CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL)
1223 CHECKIF(!BT_MCS_VALID_OBJ_ID(id)) {
1224 LOG_DBG("Object ID 0x%016llx invalid", id);
1225
1226 return -EINVAL;
1227 }
1228
1229 if (mprx.local_player.registered && player == &mprx.local_player) {
1230 if (mprx.local_player.calls->set_current_track_id) {
1231 mprx.local_player.calls->set_current_track_id(id);
1232
1233 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->current_track_id_write) {
1234 mprx.ctrlr.cbs->current_track_id_write(player, 0, id);
1235 } else {
1236 LOG_DBG("No callback");
1237 }
1238
1239 return 0;
1240 }
1241
1242 LOG_DBG("No call");
1243 return -EOPNOTSUPP;
1244 }
1245 #endif /* CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL */
1246
1247 #if defined(CONFIG_MCTL_REMOTE_PLAYER_CONTROL_OBJECTS)
1248 if (mprx.remote_player.registered && player == &mprx.remote_player) {
1249 /* TODO: Uncomment when function is implemented */
1250 /* return bt_mcc_set_current_track_obj_id(mprx.remote_player.conn, position); */
1251 }
1252 #endif /* CONFIG_MCTL_REMOTE_PLAYER_CONTROL_OBJECTS */
1253
1254 return -EINVAL;
1255 }
1256
media_proxy_ctrl_get_next_track_id(struct media_player * player)1257 int media_proxy_ctrl_get_next_track_id(struct media_player *player)
1258 {
1259 CHECKIF(player == NULL) {
1260 LOG_DBG("player is NULL");
1261 return -EINVAL;
1262 }
1263
1264 #if defined(CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL)
1265 if (mprx.local_player.registered && player == &mprx.local_player) {
1266 if (mprx.local_player.calls->get_next_track_id) {
1267 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->next_track_id_recv) {
1268 const uint64_t id = mprx.local_player.calls->get_next_track_id();
1269
1270 mprx.ctrlr.cbs->next_track_id_recv(player, 0, id);
1271 } else {
1272 LOG_DBG("No callback");
1273 }
1274
1275 return 0;
1276 }
1277
1278 LOG_DBG("No call");
1279 return -EOPNOTSUPP;
1280 }
1281 #endif /* CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL */
1282
1283 #if defined(CONFIG_MCTL_REMOTE_PLAYER_CONTROL_OBJECTS)
1284 if (mprx.remote_player.registered && player == &mprx.remote_player) {
1285 return bt_mcc_read_next_track_obj_id(mprx.remote_player.conn);
1286 }
1287 #endif /* CONFIG_MCTL_REMOTE_PLAYER_CONTROL_OBJECTS */
1288
1289 return -EINVAL;
1290 }
1291
media_proxy_ctrl_set_next_track_id(struct media_player * player,uint64_t id)1292 int media_proxy_ctrl_set_next_track_id(struct media_player *player, uint64_t id)
1293 {
1294 CHECKIF(player == NULL) {
1295 LOG_DBG("player is NULL");
1296 return -EINVAL;
1297 }
1298
1299 #if defined(CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL)
1300 CHECKIF(!BT_MCS_VALID_OBJ_ID(id)) {
1301 LOG_DBG("Object ID 0x%016llx invalid", id);
1302
1303 return -EINVAL;
1304 }
1305
1306 if (mprx.local_player.registered && player == &mprx.local_player) {
1307 if (mprx.local_player.calls->set_next_track_id) {
1308 mprx.local_player.calls->set_next_track_id(id);
1309
1310 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->next_track_id_write) {
1311 mprx.ctrlr.cbs->next_track_id_write(player, 0, id);
1312 } else {
1313 LOG_DBG("No callback");
1314 }
1315
1316 return 0;
1317 }
1318
1319 LOG_DBG("No call");
1320 return -EOPNOTSUPP;
1321 }
1322 #endif /* CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL */
1323
1324 #if defined(CONFIG_MCTL_REMOTE_PLAYER_CONTROL_OBJECTS)
1325 if (mprx.remote_player.registered && player == &mprx.remote_player) {
1326 /* TODO: Uncomment when function is implemented */
1327 /* return bt_mcc_set_next_track_obj_id(mprx.remote_player.conn, position); */
1328 }
1329 #endif /* CONFIG_MCTL_REMOTE_PLAYER_CONTROL_OBJECTS */
1330
1331 return -EINVAL;
1332 }
1333
media_proxy_ctrl_get_parent_group_id(struct media_player * player)1334 int media_proxy_ctrl_get_parent_group_id(struct media_player *player)
1335 {
1336 CHECKIF(player == NULL) {
1337 LOG_DBG("player is NULL");
1338 return -EINVAL;
1339 }
1340
1341 #if defined(CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL)
1342 if (mprx.local_player.registered && player == &mprx.local_player) {
1343 if (mprx.local_player.calls->get_parent_group_id) {
1344 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->parent_group_id_recv) {
1345 const uint64_t id = mprx.local_player.calls->get_parent_group_id();
1346
1347 mprx.ctrlr.cbs->parent_group_id_recv(player, 0, id);
1348 } else {
1349 LOG_DBG("No callback");
1350 }
1351
1352 return 0;
1353 }
1354
1355 LOG_DBG("No call");
1356 return -EOPNOTSUPP;
1357 }
1358 #endif /* CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL */
1359
1360 #if defined(CONFIG_MCTL_REMOTE_PLAYER_CONTROL_OBJECTS)
1361 if (mprx.remote_player.registered && player == &mprx.remote_player) {
1362 return bt_mcc_read_parent_group_obj_id(mprx.remote_player.conn);
1363 }
1364 #endif /* CONFIG_MCTL_REMOTE_PLAYER_CONTROL_OBJECTS */
1365
1366 return -EINVAL;
1367 }
1368
media_proxy_ctrl_get_current_group_id(struct media_player * player)1369 int media_proxy_ctrl_get_current_group_id(struct media_player *player)
1370 {
1371 CHECKIF(player == NULL) {
1372 LOG_DBG("player is NULL");
1373 return -EINVAL;
1374 }
1375
1376 #if defined(CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL)
1377 if (mprx.local_player.registered && player == &mprx.local_player) {
1378 if (mprx.local_player.calls->get_current_group_id) {
1379 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->current_group_id_recv) {
1380 const uint64_t id = mprx.local_player.calls->get_current_group_id();
1381
1382 mprx.ctrlr.cbs->current_group_id_recv(player, 0, id);
1383 } else {
1384 LOG_DBG("No callback");
1385 }
1386
1387 return 0;
1388 }
1389
1390 LOG_DBG("No call");
1391 return -EOPNOTSUPP;
1392 }
1393 #endif /* CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL */
1394
1395 #if defined(CONFIG_MCTL_REMOTE_PLAYER_CONTROL_OBJECTS)
1396 if (mprx.remote_player.registered && player == &mprx.remote_player) {
1397 return bt_mcc_read_current_group_obj_id(mprx.remote_player.conn);
1398 }
1399 #endif /* CONFIG_MCTL_REMOTE_PLAYER_CONTROL_OBJECTS */
1400
1401 return -EINVAL;
1402 }
1403
media_proxy_ctrl_set_current_group_id(struct media_player * player,uint64_t id)1404 int media_proxy_ctrl_set_current_group_id(struct media_player *player, uint64_t id)
1405 {
1406 CHECKIF(player == NULL) {
1407 LOG_DBG("player is NULL");
1408 return -EINVAL;
1409 }
1410
1411 #if defined(CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL)
1412 CHECKIF(!BT_MCS_VALID_OBJ_ID(id)) {
1413 LOG_DBG("Object ID 0x%016llx invalid", id);
1414
1415 return -EINVAL;
1416 }
1417
1418 if (mprx.local_player.registered && player == &mprx.local_player) {
1419 if (mprx.local_player.calls->set_current_group_id) {
1420 mprx.local_player.calls->set_current_group_id(id);
1421
1422 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->current_group_id_write) {
1423 mprx.ctrlr.cbs->current_group_id_write(player, 0, id);
1424 } else {
1425 LOG_DBG("No callback");
1426 }
1427
1428 return 0;
1429 }
1430
1431 LOG_DBG("No call");
1432 return -EOPNOTSUPP;
1433 }
1434 #endif /* CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL */
1435
1436 #if defined(CONFIG_MCTL_REMOTE_PLAYER_CONTROL_OBJECTS)
1437 if (mprx.remote_player.registered && player == &mprx.remote_player) {
1438 /* TODO: Uncomment when function is implemented */
1439 /* return bt_mcc_set_current_group_obj_id(mprx.remote_player.conn, position); */
1440 }
1441 #endif /* CONFIG_MCTL_REMOTE_PLAYER_CONTROL_OBJECTS */
1442
1443 return -EINVAL;
1444 }
1445
media_proxy_ctrl_get_playing_order(struct media_player * player)1446 int media_proxy_ctrl_get_playing_order(struct media_player *player)
1447 {
1448 CHECKIF(player == NULL) {
1449 LOG_DBG("player is NULL");
1450 return -EINVAL;
1451 }
1452
1453 #if defined(CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL)
1454 if (mprx.local_player.registered && player == &mprx.local_player) {
1455 if (mprx.local_player.calls->get_playing_order) {
1456 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->playing_order_recv) {
1457 const uint8_t order = mprx.local_player.calls->get_playing_order();
1458
1459 mprx.ctrlr.cbs->playing_order_recv(player, 0, order);
1460 } else {
1461 LOG_DBG("No callback");
1462 }
1463
1464 return 0;
1465 }
1466
1467 LOG_DBG("No call");
1468 return -EOPNOTSUPP;
1469 }
1470 #endif /* CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL */
1471
1472 #if defined(CONFIG_MCTL_REMOTE_PLAYER_CONTROL) && defined(CONFIG_BT_MCC_READ_PLAYING_ORDER)
1473 if (mprx.remote_player.registered && player == &mprx.remote_player) {
1474 LOG_DBG("Remote player");
1475 return bt_mcc_read_playing_order(mprx.remote_player.conn);
1476 }
1477 #endif /* CONFIG_MCTL_REMOTE_PLAYER_CONTROL && CONFIG_BT_MCC_READ_PLAYING_ORDER */
1478
1479 return -EINVAL;
1480 }
1481
media_proxy_ctrl_set_playing_order(struct media_player * player,uint8_t order)1482 int media_proxy_ctrl_set_playing_order(struct media_player *player, uint8_t order)
1483 {
1484 CHECKIF(player == NULL) {
1485 LOG_DBG("player is NULL");
1486 return -EINVAL;
1487 }
1488
1489 #if defined(CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL)
1490 if (mprx.local_player.registered && player == &mprx.local_player) {
1491 if (mprx.local_player.calls->set_playing_order) {
1492 mprx.local_player.calls->set_playing_order(order);
1493
1494 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->playing_order_write) {
1495 mprx.ctrlr.cbs->playing_order_write(player, 0, order);
1496 } else {
1497 LOG_DBG("No callback");
1498 }
1499
1500 return 0;
1501 }
1502
1503 LOG_DBG("No call");
1504 return -EOPNOTSUPP;
1505 }
1506 #endif /* CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL */
1507
1508 #if defined(CONFIG_MCTL_REMOTE_PLAYER_CONTROL) && defined(CONFIG_BT_MCC_SET_PLAYING_ORDER)
1509 if (mprx.remote_player.registered && player == &mprx.remote_player) {
1510 return bt_mcc_set_playing_order(mprx.remote_player.conn, order);
1511 }
1512 #endif /* CONFIG_MCTL_REMOTE_PLAYER_CONTROL && CONFIG_BT_MCC_SET_PLAYING_ORDER */
1513
1514 return -EINVAL;
1515 }
1516
media_proxy_ctrl_get_playing_orders_supported(struct media_player * player)1517 int media_proxy_ctrl_get_playing_orders_supported(struct media_player *player)
1518 {
1519 CHECKIF(player == NULL) {
1520 LOG_DBG("player is NULL");
1521 return -EINVAL;
1522 }
1523
1524 #if defined(CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL)
1525 if (mprx.local_player.registered && player == &mprx.local_player) {
1526 if (mprx.local_player.calls->get_playing_orders_supported) {
1527 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->playing_orders_supported_recv) {
1528 const uint16_t orders =
1529 mprx.local_player.calls->get_playing_orders_supported();
1530
1531 mprx.ctrlr.cbs->playing_orders_supported_recv(player, 0, orders);
1532 } else {
1533 LOG_DBG("No callback");
1534 }
1535
1536 return 0;
1537 }
1538
1539 LOG_DBG("No call");
1540 return -EOPNOTSUPP;
1541 }
1542 #endif /* CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL */
1543
1544 #if defined(CONFIG_MCTL_REMOTE_PLAYER_CONTROL) && \
1545 defined(CONFIG_BT_MCC_READ_PLAYING_ORDER_SUPPORTED)
1546 if (mprx.remote_player.registered && player == &mprx.remote_player) {
1547 return bt_mcc_read_playing_orders_supported(mprx.remote_player.conn);
1548 }
1549 #endif /* CONFIG_MCTL_REMOTE_PLAYER_CONTROL && CONFIG_BT_MCC_READ_PLAYING_ORDER_SUPPORTED */
1550
1551 return -EINVAL;
1552 }
1553
media_proxy_ctrl_get_media_state(struct media_player * player)1554 int media_proxy_ctrl_get_media_state(struct media_player *player)
1555 {
1556 CHECKIF(player == NULL) {
1557 LOG_DBG("player is NULL");
1558 return -EINVAL;
1559 }
1560
1561 #if defined(CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL)
1562 if (mprx.local_player.registered && player == &mprx.local_player) {
1563 if (mprx.local_player.calls->get_media_state) {
1564 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->media_state_recv) {
1565 const uint8_t state = mprx.local_player.calls->get_media_state();
1566
1567 mprx.ctrlr.cbs->media_state_recv(player, 0, state);
1568 } else {
1569 LOG_DBG("No callback");
1570 }
1571
1572 return 0;
1573 }
1574
1575 LOG_DBG("No call");
1576 return -EOPNOTSUPP;
1577 }
1578 #endif /* CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL */
1579
1580 #if defined(CONFIG_MCTL_REMOTE_PLAYER_CONTROL) && defined(CONFIG_BT_MCC_READ_MEDIA_STATE)
1581 if (mprx.remote_player.registered && player == &mprx.remote_player) {
1582 return bt_mcc_read_media_state(mprx.remote_player.conn);
1583 }
1584 #endif /* CONFIG_MCTL_REMOTE_PLAYER_CONTROL && CONFIG_BT_MCC_READ_MEDIA_STATE */
1585
1586 return -EINVAL;
1587 }
1588
media_proxy_ctrl_send_command(struct media_player * player,const struct mpl_cmd * cmd)1589 int media_proxy_ctrl_send_command(struct media_player *player, const struct mpl_cmd *cmd)
1590 {
1591 CHECKIF(player == NULL || cmd == NULL) {
1592 LOG_DBG("NULL pointer");
1593 return -EINVAL;
1594 }
1595
1596 #if defined(CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL)
1597 if (mprx.local_player.registered && player == &mprx.local_player) {
1598 if (mprx.local_player.calls->send_command) {
1599 mprx.local_player.calls->send_command(cmd);
1600
1601 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->command_send) {
1602 mprx.ctrlr.cbs->command_send(player, 0, cmd);
1603 } else {
1604 LOG_DBG("No callback");
1605 }
1606
1607 return 0;
1608 }
1609
1610 LOG_DBG("No call");
1611 return -EOPNOTSUPP;
1612 }
1613 #endif /* CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL */
1614
1615 #if defined(CONFIG_MCTL_REMOTE_PLAYER_CONTROL) && defined(CONFIG_BT_MCC_SET_MEDIA_CONTROL_POINT)
1616 if (mprx.remote_player.registered && player == &mprx.remote_player) {
1617 return bt_mcc_send_cmd(mprx.remote_player.conn, cmd);
1618 }
1619 #endif /* CONFIG_MCTL_REMOTE_PLAYER_CONTROL && CONFIG_BT_MCC_SET_MEDIA_CONTROL_POINT */
1620
1621 return -EINVAL;
1622 }
1623
media_proxy_ctrl_get_commands_supported(struct media_player * player)1624 int media_proxy_ctrl_get_commands_supported(struct media_player *player)
1625 {
1626 CHECKIF(player == NULL) {
1627 LOG_DBG("player is NULL");
1628 return -EINVAL;
1629 }
1630
1631 #if defined(CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL)
1632 if (mprx.local_player.registered && player == &mprx.local_player) {
1633 if (mprx.local_player.calls->get_commands_supported) {
1634 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->commands_supported_recv) {
1635 const uint32_t opcodes =
1636 mprx.local_player.calls->get_commands_supported();
1637
1638 mprx.ctrlr.cbs->commands_supported_recv(player, 0, opcodes);
1639 } else {
1640 LOG_DBG("No callback");
1641 }
1642
1643 return 0;
1644 }
1645
1646 LOG_DBG("No call");
1647 return -EOPNOTSUPP;
1648 }
1649 #endif /* CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL */
1650
1651 #if defined(CONFIG_MCTL_REMOTE_PLAYER_CONTROL) && \
1652 defined(CONFIG_BT_MCC_READ_MEDIA_CONTROL_POINT_OPCODES_SUPPORTED)
1653 if (mprx.remote_player.registered && player == &mprx.remote_player) {
1654 return bt_mcc_read_opcodes_supported(mprx.remote_player.conn);
1655 }
1656 #endif /* CONFIG_MCTL_REMOTE_PLAYER_CONTROL &&
1657 * CONFIG_BT_MCC_READ_MEDIA_CONTROL_POINT_OPCODES_SUPPORTED
1658 */
1659
1660 return -EINVAL;
1661 }
1662
media_proxy_ctrl_send_search(struct media_player * player,const struct mpl_search * search)1663 int media_proxy_ctrl_send_search(struct media_player *player, const struct mpl_search *search)
1664 {
1665 CHECKIF(player == NULL || search == NULL) {
1666 LOG_DBG("NULL pointer");
1667 return -EINVAL;
1668 }
1669
1670 #if defined(CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL)
1671 if (mprx.local_player.registered && player == &mprx.local_player) {
1672 if (mprx.local_player.calls->send_search) {
1673 mprx.local_player.calls->send_search(search);
1674
1675 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->search_send) {
1676 mprx.ctrlr.cbs->search_send(player, 0, search);
1677 } else {
1678 LOG_DBG("No callback");
1679 }
1680
1681 return 0;
1682 }
1683
1684 LOG_DBG("No call");
1685 return -EOPNOTSUPP;
1686 }
1687 #endif /* CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL */
1688
1689 #if defined(CONFIG_MCTL_REMOTE_PLAYER_CONTROL_OBJECTS)
1690 if (mprx.remote_player.registered && player == &mprx.remote_player) {
1691 return bt_mcc_send_search(mprx.remote_player.conn, search);
1692 }
1693 #endif /* CONFIG_MCTL_REMOTE_PLAYER_CONTROL_OBJECTS */
1694
1695 return -EINVAL;
1696 }
1697
media_proxy_ctrl_get_search_results_id(struct media_player * player)1698 int media_proxy_ctrl_get_search_results_id(struct media_player *player)
1699 {
1700 CHECKIF(player == NULL) {
1701 LOG_DBG("player is NULL");
1702 return -EINVAL;
1703 }
1704
1705 #if defined(CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL)
1706 if (mprx.local_player.registered && player == &mprx.local_player) {
1707 if (mprx.local_player.calls->get_search_results_id) {
1708 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->search_results_id_recv) {
1709 const uint64_t id =
1710 mprx.local_player.calls->get_search_results_id();
1711
1712 mprx.ctrlr.cbs->search_results_id_recv(player, 0, id);
1713 } else {
1714 LOG_DBG("No callback");
1715 }
1716
1717 return 0;
1718 }
1719
1720 LOG_DBG("No call");
1721 return -EOPNOTSUPP;
1722 }
1723 #endif /* CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL */
1724
1725 #if defined(CONFIG_MCTL_REMOTE_PLAYER_CONTROL_OBJECTS)
1726 if (mprx.remote_player.registered && player == &mprx.remote_player) {
1727 return bt_mcc_read_search_results_obj_id(mprx.remote_player.conn);
1728 }
1729 #endif /* CONFIG_MCTL_REMOTE_PLAYER_CONTROL_OBJECTS */
1730
1731 return -EINVAL;
1732 }
1733
media_proxy_ctrl_get_content_ctrl_id(struct media_player * player)1734 uint8_t media_proxy_ctrl_get_content_ctrl_id(struct media_player *player)
1735 {
1736 CHECKIF(player == NULL) {
1737 LOG_DBG("player is NULL");
1738 return -EINVAL;
1739 }
1740
1741 #if defined(CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL)
1742 if (mprx.local_player.registered && player == &mprx.local_player) {
1743 if (mprx.local_player.calls->get_content_ctrl_id) {
1744 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->content_ctrl_id_recv) {
1745 const uint8_t ccid = mprx.local_player.calls->get_content_ctrl_id();
1746
1747 mprx.ctrlr.cbs->content_ctrl_id_recv(player, 0, ccid);
1748 } else {
1749 LOG_DBG("No callback");
1750 }
1751
1752 return 0;
1753 }
1754
1755 LOG_DBG("No call");
1756 return -EOPNOTSUPP;
1757 }
1758 #endif /* CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL */
1759
1760 #if defined(CONFIG_MCTL_REMOTE_PLAYER_CONTROL) && defined(CONFIG_BT_MCC_READ_CONTENT_CONTROL_ID)
1761 if (mprx.remote_player.registered && player == &mprx.remote_player) {
1762 return bt_mcc_read_content_control_id(mprx.remote_player.conn);
1763 }
1764 #endif /* CONFIG_MCTL_REMOTE_PLAYER_CONTROL && CONFIG_BT_MCC_READ_CONTENT_CONTROL_ID */
1765
1766 return -EINVAL;
1767 }
1768 #endif /* CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL || CONFIG_MCTL_REMOTE_PLAYER_CONTROL */
1769
1770
1771
1772 #if defined(CONFIG_MCTL_LOCAL_PLAYER_CONTROL)
1773 /* Player calls *******************************************/
1774
pl_calls_is_valid(const struct media_proxy_pl_calls * pl_calls)1775 static bool pl_calls_is_valid(const struct media_proxy_pl_calls *pl_calls)
1776 {
1777 if (pl_calls == NULL) {
1778 LOG_DBG("pl_calls is NULL");
1779 return false;
1780 }
1781
1782 if (pl_calls->get_player_name == NULL) {
1783 LOG_DBG("get_player_name is NULL");
1784 return false;
1785 }
1786
1787 #ifdef CONFIG_BT_MPL_OBJECTS
1788 if (pl_calls->get_icon_id == NULL) {
1789 LOG_DBG("get_icon_id is NULL");
1790 return false;
1791 }
1792 #endif /* CONFIG_BT_MPL_OBJECTS */
1793
1794 if (pl_calls->get_icon_url == NULL) {
1795 LOG_DBG("get_icon_url is NULL");
1796 return false;
1797 }
1798
1799 if (pl_calls->get_track_title == NULL) {
1800 LOG_DBG("get_track_title is NULL");
1801 return false;
1802 }
1803
1804 if (pl_calls->get_track_duration == NULL) {
1805 LOG_DBG("get_track_duration is NULL");
1806 return false;
1807 }
1808
1809 if (pl_calls->get_track_position == NULL) {
1810 LOG_DBG("get_track_position is NULL");
1811 return false;
1812 }
1813
1814 if (pl_calls->set_track_position == NULL) {
1815 LOG_DBG("set_track_position is NULL");
1816 return false;
1817 }
1818
1819 if (pl_calls->get_playback_speed == NULL) {
1820 LOG_DBG("get_playback_speed is NULL");
1821 return false;
1822 }
1823
1824 if (pl_calls->set_playback_speed == NULL) {
1825 LOG_DBG("set_playback_speed is NULL");
1826 return false;
1827 }
1828
1829 if (pl_calls->get_seeking_speed == NULL) {
1830 LOG_DBG("get_seeking_speed is NULL");
1831 return false;
1832 }
1833
1834 #ifdef CONFIG_BT_MPL_OBJECTS
1835 if (pl_calls->get_track_segments_id == NULL) {
1836 LOG_DBG("get_track_segments_id is NULL");
1837 return false;
1838 }
1839
1840 if (pl_calls->get_current_track_id == NULL) {
1841 LOG_DBG("get_current_track_id is NULL");
1842 return false;
1843 }
1844
1845 if (pl_calls->set_current_track_id == NULL) {
1846 LOG_DBG("set_current_track_id is NULL");
1847 return false;
1848 }
1849
1850 if (pl_calls->get_next_track_id == NULL) {
1851 LOG_DBG("get_next_track_id is NULL");
1852 return false;
1853 }
1854
1855 if (pl_calls->set_next_track_id == NULL) {
1856 LOG_DBG("set_next_track_id is NULL");
1857 return false;
1858 }
1859
1860 if (pl_calls->get_parent_group_id == NULL) {
1861 LOG_DBG("get_parent_group_id is NULL");
1862 return false;
1863 }
1864
1865 if (pl_calls->get_current_group_id == NULL) {
1866 LOG_DBG("get_current_group_id is NULL");
1867 return false;
1868 }
1869
1870 if (pl_calls->set_current_group_id == NULL) {
1871 LOG_DBG("set_current_group_id is NULL");
1872 return false;
1873 }
1874
1875 #endif /* CONFIG_BT_MPL_OBJECTS */
1876 if (pl_calls->get_playing_order == NULL) {
1877 LOG_DBG("get_playing_order is NULL");
1878 return false;
1879 }
1880
1881 if (pl_calls->set_playing_order == NULL) {
1882 LOG_DBG("set_playing_order is NULL");
1883 return false;
1884 }
1885
1886 if (pl_calls->get_playing_orders_supported == NULL) {
1887 LOG_DBG("get_playing_orders_supported is NULL");
1888 return false;
1889 }
1890
1891 if (pl_calls->get_media_state == NULL) {
1892 LOG_DBG("get_media_state is NULL");
1893 return false;
1894 }
1895
1896 if (pl_calls->send_command == NULL) {
1897 LOG_DBG("send_command is NULL");
1898 return false;
1899 }
1900
1901 if (pl_calls->get_commands_supported == NULL) {
1902 LOG_DBG("get_commands_supported is NULL");
1903 return false;
1904 }
1905
1906 #ifdef CONFIG_BT_MPL_OBJECTS
1907 if (pl_calls->send_search == NULL) {
1908 LOG_DBG("send_search is NULL");
1909 return false;
1910 }
1911
1912 if (pl_calls->get_search_results_id == NULL) {
1913 LOG_DBG("get_search_results_id is NULL");
1914 return false;
1915 }
1916
1917 #endif /* CONFIG_BT_MPL_OBJECTS */
1918 if (pl_calls->get_content_ctrl_id == NULL) {
1919 LOG_DBG("get_content_ctrl_id is NULL");
1920 return false;
1921 }
1922
1923 return true;
1924 }
1925
media_proxy_pl_register(struct media_proxy_pl_calls * pl_calls)1926 int media_proxy_pl_register(struct media_proxy_pl_calls *pl_calls)
1927 {
1928 CHECKIF(!pl_calls_is_valid(pl_calls)) {
1929 return -EINVAL;
1930 }
1931
1932 if (mprx.local_player.registered) {
1933 LOG_DBG("Player already registered");
1934 return -EALREADY;
1935 }
1936
1937 mprx.local_player.calls = pl_calls;
1938 mprx.local_player.registered = true;
1939
1940 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->local_player_instance) {
1941 mprx.ctrlr.cbs->local_player_instance(&mprx.local_player, 0);
1942 }
1943
1944 return 0;
1945 };
1946
1947 /* Player callbacks ********************************/
1948
1949 /* All callbacks here must come from the local player - mprx.local_player */
1950
media_proxy_pl_name_cb(const char * name)1951 void media_proxy_pl_name_cb(const char *name)
1952 {
1953 mprx.sctrlr.cbs->player_name(name);
1954
1955 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->player_name_recv) {
1956 mprx.ctrlr.cbs->player_name_recv(&mprx.local_player, 0, name);
1957 } else {
1958 LOG_DBG("No ctrlr player name callback");
1959 }
1960 }
1961
media_proxy_pl_icon_url_cb(const char * url)1962 void media_proxy_pl_icon_url_cb(const char *url)
1963 {
1964 mprx.sctrlr.cbs->icon_url(url);
1965
1966 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->player_name_recv) {
1967 mprx.ctrlr.cbs->icon_url_recv(&mprx.local_player, 0, url);
1968 } else {
1969 LOG_DBG("No ctrlr player icon URL callback");
1970 }
1971 }
1972
media_proxy_pl_track_changed_cb(void)1973 void media_proxy_pl_track_changed_cb(void)
1974 {
1975 mprx.sctrlr.cbs->track_changed();
1976
1977 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->track_changed_recv) {
1978 mprx.ctrlr.cbs->track_changed_recv(&mprx.local_player, 0);
1979 } else {
1980 LOG_DBG("No ctrlr track changed callback");
1981 }
1982 }
1983
media_proxy_pl_track_title_cb(char * title)1984 void media_proxy_pl_track_title_cb(char *title)
1985 {
1986 mprx.sctrlr.cbs->track_title(title);
1987
1988 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->track_title_recv) {
1989 mprx.ctrlr.cbs->track_title_recv(&mprx.local_player, 0, title);
1990 } else {
1991 LOG_DBG("No ctrlr track title callback");
1992 }
1993 }
1994
media_proxy_pl_track_duration_cb(int32_t duration)1995 void media_proxy_pl_track_duration_cb(int32_t duration)
1996 {
1997 mprx.sctrlr.cbs->track_duration(duration);
1998
1999 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->track_duration_recv) {
2000 mprx.ctrlr.cbs->track_duration_recv(&mprx.local_player, 0, duration);
2001 } else {
2002 LOG_DBG("No ctrlr track duration callback");
2003 }
2004 }
2005
media_proxy_pl_track_position_cb(int32_t position)2006 void media_proxy_pl_track_position_cb(int32_t position)
2007 {
2008 mprx.sctrlr.cbs->track_position(position);
2009
2010 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->track_position_recv) {
2011 mprx.ctrlr.cbs->track_position_recv(&mprx.local_player, 0, position);
2012 } else {
2013 LOG_DBG("No ctrlr track position callback");
2014 }
2015 }
2016
media_proxy_pl_playback_speed_cb(int8_t speed)2017 void media_proxy_pl_playback_speed_cb(int8_t speed)
2018 {
2019 mprx.sctrlr.cbs->playback_speed(speed);
2020
2021 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->playback_speed_recv) {
2022 mprx.ctrlr.cbs->playback_speed_recv(&mprx.local_player, 0, speed);
2023 } else {
2024 LOG_DBG("No ctrlr playback speed callback");
2025 }
2026 }
2027
media_proxy_pl_seeking_speed_cb(int8_t speed)2028 void media_proxy_pl_seeking_speed_cb(int8_t speed)
2029 {
2030 mprx.sctrlr.cbs->seeking_speed(speed);
2031
2032 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->seeking_speed_recv) {
2033 mprx.ctrlr.cbs->seeking_speed_recv(&mprx.local_player, 0, speed);
2034 } else {
2035 LOG_DBG("No ctrlr seeking speed callback");
2036 }
2037 }
2038
2039 #ifdef CONFIG_BT_MPL_OBJECTS
media_proxy_pl_current_track_id_cb(uint64_t id)2040 void media_proxy_pl_current_track_id_cb(uint64_t id)
2041 {
2042 mprx.sctrlr.cbs->current_track_id(id);
2043
2044 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->current_track_id_recv) {
2045 mprx.ctrlr.cbs->current_track_id_recv(&mprx.local_player, 0, id);
2046 } else {
2047 LOG_DBG("No ctrlr current track id callback");
2048 }
2049 }
2050
media_proxy_pl_next_track_id_cb(uint64_t id)2051 void media_proxy_pl_next_track_id_cb(uint64_t id)
2052 {
2053 mprx.sctrlr.cbs->next_track_id(id);
2054
2055 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->next_track_id_recv) {
2056 mprx.ctrlr.cbs->next_track_id_recv(&mprx.local_player, 0, id);
2057 } else {
2058 LOG_DBG("No ctrlr next track id callback");
2059 }
2060 }
2061
media_proxy_pl_parent_group_id_cb(uint64_t id)2062 void media_proxy_pl_parent_group_id_cb(uint64_t id)
2063 {
2064 mprx.sctrlr.cbs->parent_group_id(id);
2065
2066 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->parent_group_id_recv) {
2067 mprx.ctrlr.cbs->parent_group_id_recv(&mprx.local_player, 0, id);
2068 } else {
2069 LOG_DBG("No ctrlr parent group id callback");
2070 }
2071 }
2072
media_proxy_pl_current_group_id_cb(uint64_t id)2073 void media_proxy_pl_current_group_id_cb(uint64_t id)
2074 {
2075 mprx.sctrlr.cbs->current_group_id(id);
2076
2077 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->current_group_id_recv) {
2078 mprx.ctrlr.cbs->current_group_id_recv(&mprx.local_player, 0, id);
2079 } else {
2080 LOG_DBG("No ctrlr current group id callback");
2081 }
2082 }
2083 #endif /* CONFIG_BT_MPL_OBJECTS */
2084
media_proxy_pl_playing_order_cb(uint8_t order)2085 void media_proxy_pl_playing_order_cb(uint8_t order)
2086 {
2087 mprx.sctrlr.cbs->playing_order(order);
2088
2089 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->playing_order_recv) {
2090 mprx.ctrlr.cbs->playing_order_recv(&mprx.local_player, 0, order);
2091 } else {
2092 LOG_DBG("No ctrlr playing order callback");
2093 }
2094 }
2095
media_proxy_pl_media_state_cb(uint8_t state)2096 void media_proxy_pl_media_state_cb(uint8_t state)
2097 {
2098 mprx.sctrlr.cbs->media_state(state);
2099
2100 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->media_state_recv) {
2101 mprx.ctrlr.cbs->media_state_recv(&mprx.local_player, 0, state);
2102 } else {
2103 LOG_DBG("No ctrlr media state callback");
2104 }
2105 }
2106
media_proxy_pl_command_cb(const struct mpl_cmd_ntf * cmd_ntf)2107 void media_proxy_pl_command_cb(const struct mpl_cmd_ntf *cmd_ntf)
2108 {
2109 CHECKIF(cmd_ntf == NULL) {
2110 LOG_WRN("cmd_ntf is NULL");
2111 return;
2112 }
2113
2114 mprx.sctrlr.cbs->command(cmd_ntf);
2115
2116 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->command_recv) {
2117 mprx.ctrlr.cbs->command_recv(&mprx.local_player, 0, cmd_ntf);
2118 } else {
2119 LOG_DBG("No ctrlr command callback");
2120 }
2121 }
2122
media_proxy_pl_commands_supported_cb(uint32_t opcodes)2123 void media_proxy_pl_commands_supported_cb(uint32_t opcodes)
2124 {
2125 mprx.sctrlr.cbs->commands_supported(opcodes);
2126
2127 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->commands_supported_recv) {
2128 mprx.ctrlr.cbs->commands_supported_recv(&mprx.local_player, 0, opcodes);
2129 } else {
2130 LOG_DBG("No ctrlr commands supported callback");
2131 }
2132 }
2133
2134 #ifdef CONFIG_BT_MPL_OBJECTS
media_proxy_pl_search_cb(uint8_t result_code)2135 void media_proxy_pl_search_cb(uint8_t result_code)
2136 {
2137 mprx.sctrlr.cbs->search(result_code);
2138
2139 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->search_recv) {
2140 mprx.ctrlr.cbs->search_recv(&mprx.local_player, 0, result_code);
2141 } else {
2142 LOG_DBG("No ctrlr search callback");
2143 }
2144 }
2145
media_proxy_pl_search_results_id_cb(uint64_t id)2146 void media_proxy_pl_search_results_id_cb(uint64_t id)
2147 {
2148 mprx.sctrlr.cbs->search_results_id(id);
2149
2150 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->search_results_id_recv) {
2151 mprx.ctrlr.cbs->search_results_id_recv(&mprx.local_player, 0, id);
2152 } else {
2153 LOG_DBG("No ctrlr search results id callback");
2154 }
2155 }
2156 #endif /* CONFIG_BT_MPL_OBJECTS */
2157 #endif /* CONFIG_MCTL_LOCAL_PLAYER_CONTROL */
2158