Set the font to FONT_UI after exiting a plugin (FS#10132). This makes the core Rockbo...
[kugel-rb/myfork.git] / apps / iap.c
blob4d0c473800a4d83e9e9b2395c2a0d8a0c5e8f4c9
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id: iap.c 17400 2008-05-07 14:30:29Z xxxxxx $
10 * Copyright (C) 2002 by Alan Korr & Nick Robinson
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <stdarg.h>
22 #include <memory.h>
23 #include <string.h>
25 #include "iap.h"
26 #include "button.h"
27 #include "config.h"
28 #include "cpu.h"
29 #include "system.h"
30 #include "kernel.h"
31 #include "serial.h"
32 #include "appevents.h"
34 #include "playlist.h"
35 #include "playback.h"
36 #include "audio.h"
37 #include "settings.h"
38 #include "metadata.h"
39 #include "gwps.h"
41 #include "button.h"
42 #include "action.h"
44 #define RX_BUFLEN 260
45 #define TX_BUFLEN 128
47 static volatile int iap_pollspeed = 0;
48 static volatile bool iap_remotetick = true;
49 static bool iap_setupflag = false, iap_updateflag = false;
50 static int iap_changedctr = 0;
52 static unsigned long iap_remotebtn = 0;
53 static int iap_repeatbtn = 0;
54 static bool iap_btnrepeat = false, iap_btnshuffle = false;
56 unsigned char serbuf[RX_BUFLEN];
57 static int serbuf_i = 0;
59 static unsigned char response[TX_BUFLEN];
60 static int responselen;
62 static void iap_task(void)
64 static int count = 0;
66 count += iap_pollspeed;
67 if (count < (500/10)) return;
69 /* exec every 500ms if pollspeed == 1 */
70 count = 0;
71 queue_post(&button_queue, SYS_IAP_PERIODIC, 0);
74 void iap_setup(int ratenum)
76 iap_bitrate_set(ratenum);
77 iap_pollspeed = 0;
78 iap_remotetick = true;
79 iap_updateflag = false;
80 iap_changedctr = 0;
81 iap_setupflag = true;
82 iap_remotebtn = BUTTON_NONE;
83 tick_add_task(iap_task);
84 add_event(PLAYBACK_EVENT_TRACK_CHANGE, false, iap_track_changed);
87 void iap_bitrate_set(int ratenum)
89 switch(ratenum)
91 case 0:
92 serial_bitrate(0);
93 break;
94 case 1:
95 serial_bitrate(9600);
96 break;
97 case 2:
98 serial_bitrate(19200);
99 break;
100 case 3:
101 serial_bitrate(38400);
102 break;
103 case 4:
104 serial_bitrate(57600);
105 break;
109 /* Message format:
110 0xff
111 0x55
112 length
113 mode
114 command (2 bytes)
115 parameters (0-n bytes)
116 checksum (length+mode+parameters+checksum == 0)
119 static void iap_send_pkt(const unsigned char * data, int len)
121 int i, chksum;
123 if(len > TX_BUFLEN-4) len = TX_BUFLEN-4;
124 responselen = len + 4;
126 response[0] = 0xFF;
127 response[1] = 0x55;
129 chksum = response[2] = len;
130 for(i = 0; i < len; i ++)
132 chksum += data[i];
133 response[i+3] = data[i];
136 response[i+3] = 0x100 - (chksum & 0xFF);
138 for(i = 0; i < responselen; i ++)
140 while (!tx_rdy()) ;
141 tx_writec(response[i]);
145 int iap_getc(unsigned char x)
147 static unsigned char last_x = 0;
148 static bool newpkt = true;
149 static unsigned char chksum = 0;
151 /* Restart if the sync word is seen */
152 if(x == 0x55 && last_x == 0xff/* && newpkt*/)
154 serbuf[0] = 0;
155 serbuf_i = 0;
156 chksum = 0;
157 newpkt = false;
159 else
161 if(serbuf_i >= RX_BUFLEN)
162 serbuf_i = 0;
164 serbuf[serbuf_i++] = x;
165 chksum += x;
167 last_x = x;
169 /* Broadcast to queue if we have a complete message */
170 if(serbuf_i && (serbuf_i == serbuf[0]+2))
172 serbuf_i = 0;
173 newpkt = true;
174 if(chksum == 0)
175 queue_post(&button_queue, SYS_IAP_HANDLEPKT, 0);
177 return newpkt;
180 /* called by playback when the next track starts */
181 void iap_track_changed(void *ignored)
183 (void)ignored;
184 iap_changedctr = 1;
187 void iap_periodic(void)
189 if(!iap_setupflag) return;
190 if(!iap_pollspeed) return;
192 unsigned char data[] = {0x04, 0x00, 0x27, 0x04, 0x00, 0x00, 0x00, 0x00};
193 unsigned long time_elapsed = audio_current_track()->elapsed;
195 time_elapsed += wps_state.ff_rewind_count;
197 data[3] = 0x04; // playing
199 /* If info has changed, don't flag it right away */
200 if(iap_changedctr && iap_changedctr++ >= iap_pollspeed * 2)
202 /* track info has changed */
203 iap_changedctr = 0;
204 data[3] = 0x01; // 0x02 has same effect?
205 iap_updateflag = true;
208 data[4] = time_elapsed >> 24;
209 data[5] = time_elapsed >> 16;
210 data[6] = time_elapsed >> 8;
211 data[7] = time_elapsed;
212 iap_send_pkt(data, sizeof(data));
215 void iap_handlepkt(void)
218 if(!iap_setupflag) return;
219 if(serbuf[0] == 0) return;
221 /* if we are waiting for a remote button to go out,
222 delay the handling of the new packet */
223 if(!iap_remotetick)
225 queue_post(&button_queue, SYS_IAP_HANDLEPKT, 0);
226 return;
229 /* Handle Mode 0 */
230 if (serbuf[1] == 0x00)
232 switch (serbuf[2])
234 /* get model info */
235 case 0x0D:
237 unsigned char data[] = {0x00, 0x0E, 0x00, 0x0B, 0x00, 0x10,
238 'R', 'O', 'C', 'K', 'B', 'O', 'X', 0x00};
239 iap_send_pkt(data, sizeof(data));
240 break;
242 /* No idea ??? */
243 case 0x0F:
245 unsigned char data[] = {0x00, 0x10, 0x00, 0x01, 0x05};
246 iap_send_pkt(data, sizeof(data));
247 break;
249 /* FM transmitter sends this: FF 55 06 00 01 05 00 02 01 F1 (mode switch) */
250 case 0x01:
252 if(serbuf[3] == 0x05)
254 sleep(HZ/3);
255 unsigned char data[] = {0x05, 0x02};
256 iap_send_pkt(data, sizeof(data));
258 break;
260 /* FM transmitter sends this: FF 55 0E 00 13 00 00 00 35 00 00 00 04 00 00 00 00 A6 (???)*/
261 case 0x13:
263 unsigned char data[] = {0x00, 0x02, 0x00, 0x13};
264 iap_send_pkt(data, sizeof(data));
265 unsigned char data2[] = {0x00, 0x27, 0x00};
266 iap_send_pkt(data2, sizeof(data2));
267 unsigned char data3[] = {0x05, 0x02};
268 iap_send_pkt(data3, sizeof(data3));
269 break;
271 /* FM transmitter sends this: FF 55 02 00 05 F9 (mode switch: AiR mode) */
272 case 0x05:
274 unsigned char data[] = {0x00, 0x02, 0x06, 0x05, 0x00, 0x00, 0x0B, 0xB8, 0x28};
275 iap_send_pkt(data, sizeof(data));
276 unsigned char data2[] = {0x00, 0x02, 0x00, 0x05};
277 iap_send_pkt(data2, sizeof(data2));
278 break;
280 /* default response is with cmd ok packet */
281 default:
283 unsigned char data[] = {0x00, 0x02, 0x00, 0x00};
284 data[3] = serbuf[2]; //respond with cmd
285 iap_send_pkt(data, sizeof(data));
286 break;
290 /* Handle Mode 2 */
291 else if (serbuf[1] == 0x02)
293 if(serbuf[2] != 0) return;
294 iap_remotebtn = BUTTON_NONE;
295 iap_remotetick = false;
297 if(serbuf[0] >= 3 && serbuf[3] != 0)
299 if(serbuf[3] & 1)
300 iap_remotebtn |= BUTTON_RC_PLAY;
301 if(serbuf[3] & 2)
302 iap_remotebtn |= BUTTON_RC_VOL_UP;
303 if(serbuf[3] & 4)
304 iap_remotebtn |= BUTTON_RC_VOL_DOWN;
305 if(serbuf[3] & 8)
306 iap_remotebtn |= BUTTON_RC_RIGHT;
307 if(serbuf[3] & 16)
308 iap_remotebtn |= BUTTON_RC_LEFT;
310 else if(serbuf[0] >= 4 && serbuf[4] != 0)
312 if(serbuf[4] & 1) /* play */
314 if (audio_status() != AUDIO_STATUS_PLAY)
316 iap_remotebtn |= BUTTON_RC_PLAY;
317 iap_repeatbtn = 2;
318 iap_remotetick = false;
319 iap_changedctr = 1;
322 if(serbuf[4] & 2) /* pause */
324 if (audio_status() == AUDIO_STATUS_PLAY)
326 iap_remotebtn |= BUTTON_RC_PLAY;
327 iap_repeatbtn = 2;
328 iap_remotetick = false;
329 iap_changedctr = 1;
332 if((serbuf[4] & 128) && !iap_btnshuffle) /* shuffle */
334 iap_btnshuffle = true;
335 if(!global_settings.playlist_shuffle)
337 global_settings.playlist_shuffle = 1;
338 settings_save();
339 settings_apply(false);
340 if (audio_status() & AUDIO_STATUS_PLAY)
341 playlist_randomise(NULL, current_tick, true);
343 else if(global_settings.playlist_shuffle)
345 global_settings.playlist_shuffle = 0;
346 settings_save();
347 settings_apply(false);
348 if (audio_status() & AUDIO_STATUS_PLAY)
349 playlist_sort(NULL, true);
352 else
353 iap_btnshuffle = false;
355 else if(serbuf[0] >= 5 && serbuf[5] != 0)
357 if((serbuf[5] & 1) && !iap_btnrepeat) /* repeat */
359 int oldmode = global_settings.repeat_mode;
360 iap_btnrepeat = true;
362 if (oldmode == REPEAT_ONE)
363 global_settings.repeat_mode = REPEAT_OFF;
364 else if (oldmode == REPEAT_ALL)
365 global_settings.repeat_mode = REPEAT_ONE;
366 else if (oldmode == REPEAT_OFF)
367 global_settings.repeat_mode = REPEAT_ALL;
369 settings_save();
370 settings_apply(false);
371 if (audio_status() & AUDIO_STATUS_PLAY)
372 audio_flush_and_reload_tracks();
374 else
375 iap_btnrepeat = false;
377 if(serbuf[5] & 16) /* ffwd */
379 iap_remotebtn |= BUTTON_RC_RIGHT;
381 if(serbuf[5] & 32) /* frwd */
383 iap_remotebtn |= BUTTON_RC_LEFT;
387 /* Handle Mode 3 */
388 else if (serbuf[1] == 0x03)
390 switch(serbuf[2])
392 /* some kind of status packet? */
393 case 0x01:
395 unsigned char data[] = {0x03, 0x02, 0x00, 0x00, 0x00, 0x00};
396 iap_send_pkt(data, sizeof(data));
397 break;
401 /* Handle Mode 4 */
402 else if (serbuf[1] == 0x04)
404 switch (((unsigned long)serbuf[2] << 8) | serbuf[3])
406 /* Get data updated??? flag */
407 case 0x0009:
409 unsigned char data[] = {0x04, 0x00, 0x0A, 0x00};
410 data[3] = iap_updateflag ? 0 : 1;
411 iap_send_pkt(data, sizeof(data));
412 break;
414 /* Set data updated??? flag */
415 case 0x000B:
417 iap_updateflag = serbuf[4] ? 0 : 1;
418 /* respond with cmd ok packet */
419 unsigned char data[] = {0x04, 0x00, 0x01, 0x00, 0x00, 0x0B};
420 iap_send_pkt(data, sizeof(data));
421 break;
423 /* Get iPod size? */
424 case 0x0012:
426 unsigned char data[] = {0x04, 0x00, 0x13, 0x01, 0x0B};
427 iap_send_pkt(data, sizeof(data));
428 break;
430 /* Get count of given types */
431 case 0x0018:
433 unsigned char data[] = {0x04, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00};
434 unsigned long num = 0;
435 switch(serbuf[4]) /* type number */
437 case 0x01: /* total number of playlists */
438 num = 1;
439 break;
440 case 0x05: /* total number of songs */
441 num = 1;
443 data[3] = num >> 24;
444 data[4] = num >> 16;
445 data[5] = num >> 8;
446 data[6] = num;
447 iap_send_pkt(data, sizeof(data));
448 break;
450 /* Get time and status */
451 case 0x001C:
453 unsigned char data[] = {0x04, 0x00, 0x1D, 0x00, 0x00, 0x00,
454 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
455 struct mp3entry *id3 = audio_current_track();
456 unsigned long time_total = id3->length;
457 unsigned long time_elapsed = id3->elapsed;
458 int status = audio_status();
459 data[3] = time_total >> 24;
460 data[4] = time_total >> 16;
461 data[5] = time_total >> 8;
462 data[6] = time_total;
463 data[7] = time_elapsed >> 24;
464 data[8] = time_elapsed >> 16;
465 data[9] = time_elapsed >> 8;
466 data[10] = time_elapsed;
467 if (status == AUDIO_STATUS_PLAY)
468 data[11] = 0x01; /* play */
469 else if (status & AUDIO_STATUS_PAUSE)
470 data[11] = 0x02; /* pause */
471 iap_send_pkt(data, sizeof(data));
472 break;
474 /* Get current pos in playlist */
475 case 0x001E:
477 unsigned char data[] = {0x04, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00};
478 long playlist_pos = playlist_next(0);
479 playlist_pos -= playlist_get_first_index(NULL);
480 if(playlist_pos < 0)
481 playlist_pos += playlist_amount();
482 data[3] = playlist_pos >> 24;
483 data[4] = playlist_pos >> 16;
484 data[5] = playlist_pos >> 8;
485 data[6] = playlist_pos;
486 iap_send_pkt(data, sizeof(data));
487 break;
489 /* Get title of a song number */
490 case 0x0020:
491 /* Get artist of a song number */
492 case 0x0022:
493 /* Get album of a song number */
494 case 0x0024:
496 unsigned char data[70] = {0x04, 0x00, 0xFF};
497 struct mp3entry id3;
498 int fd;
499 long tracknum = (signed long)serbuf[4] << 24 |
500 (signed long)serbuf[5] << 16 |
501 (signed long)serbuf[6] << 8 | serbuf[7];
502 data[2] = serbuf[3] + 1;
503 memcpy(&id3, audio_current_track(), sizeof(id3));
504 tracknum += playlist_get_first_index(NULL);
505 if(tracknum >= playlist_amount())
506 tracknum -= playlist_amount();
508 /* If the tracknumber is not the current one,
509 read id3 from disk */
510 if(playlist_next(0) != tracknum)
512 struct playlist_track_info info;
513 playlist_get_track_info(NULL, tracknum, &info);
514 fd = open(info.filename, O_RDONLY);
515 memset(&id3, 0, sizeof(struct mp3entry));
516 get_metadata(&id3, fd, info.filename);
517 close(fd);
520 /* Return the requested track data */
521 switch(serbuf[3])
523 case 0x20:
524 strncpy((char *)&data[3], id3.title, 64);
525 iap_send_pkt(data, 4+strlen(id3.title));
526 break;
527 case 0x22:
528 strncpy((char *)&data[3], id3.artist, 64);
529 iap_send_pkt(data, 4+strlen(id3.artist));
530 break;
531 case 0x24:
532 strncpy((char *)&data[3], id3.album, 64);
533 iap_send_pkt(data, 4+strlen(id3.album));
534 break;
536 break;
538 /* Set polling mode */
539 case 0x0026:
541 iap_pollspeed = serbuf[4] ? 1 : 0;
542 /*responsed with cmd ok packet */
543 unsigned char data[] = {0x04, 0x00, 0x01, 0x00, 0x00, 0x26};
544 iap_send_pkt(data, sizeof(data));
545 break;
547 /* AiR playback control */
548 case 0x0029:
550 /* respond with cmd ok packet */
551 unsigned char data[] = {0x04, 0x00, 0x01, 0x00, 0x00, 0x29};
552 iap_send_pkt(data, sizeof(data));
553 switch(serbuf[4])
555 case 0x01: /* play/pause */
556 iap_remotebtn = BUTTON_RC_PLAY;
557 iap_repeatbtn = 2;
558 iap_remotetick = false;
559 iap_changedctr = 1;
560 break;
561 case 0x02: /* stop */
562 iap_remotebtn = BUTTON_RC_PLAY|BUTTON_REPEAT;
563 iap_repeatbtn = 2;
564 iap_remotetick = false;
565 iap_changedctr = 1;
566 break;
567 case 0x03: /* skip++ */
568 iap_remotebtn = BUTTON_RC_RIGHT;
569 iap_repeatbtn = 2;
570 iap_remotetick = false;
571 break;
572 case 0x04: /* skip-- */
573 iap_remotebtn = BUTTON_RC_LEFT;
574 iap_repeatbtn = 2;
575 iap_remotetick = false;
576 break;
577 case 0x05: /* ffwd */
578 iap_remotebtn = BUTTON_RC_RIGHT;
579 iap_remotetick = false;
580 if(iap_pollspeed) iap_pollspeed = 5;
581 break;
582 case 0x06: /* frwd */
583 iap_remotebtn = BUTTON_RC_LEFT;
584 iap_remotetick = false;
585 if(iap_pollspeed) iap_pollspeed = 5;
586 break;
587 case 0x07: /* end ffwd/frwd */
588 iap_remotebtn = BUTTON_NONE;
589 iap_remotetick = false;
590 if(iap_pollspeed) iap_pollspeed = 1;
591 break;
593 break;
595 /* Get shuffle mode */
596 case 0x002C:
598 unsigned char data[] = {0x04, 0x00, 0x2D, 0x00};
599 data[3] = global_settings.playlist_shuffle ? 1 : 0;
600 iap_send_pkt(data, sizeof(data));
601 break;
603 /* Set shuffle mode */
604 case 0x002E:
606 if(serbuf[4] && !global_settings.playlist_shuffle)
608 global_settings.playlist_shuffle = 1;
609 settings_save();
610 settings_apply(false);
611 if (audio_status() & AUDIO_STATUS_PLAY)
612 playlist_randomise(NULL, current_tick, true);
614 else if(!serbuf[4] && global_settings.playlist_shuffle)
616 global_settings.playlist_shuffle = 0;
617 settings_save();
618 settings_apply(false);
619 if (audio_status() & AUDIO_STATUS_PLAY)
620 playlist_sort(NULL, true);
624 /* respond with cmd ok packet */
625 unsigned char data[] = {0x04, 0x00, 0x01, 0x00, 0x00, 0x2E};
626 iap_send_pkt(data, sizeof(data));
627 break;
629 /* Get repeat mode */
630 case 0x002F:
632 unsigned char data[] = {0x04, 0x00, 0x30, 0x00};
633 if(global_settings.repeat_mode == REPEAT_OFF)
634 data[3] = 0;
635 else if(global_settings.repeat_mode == REPEAT_ONE)
636 data[3] = 1;
637 else
638 data[3] = 2;
639 iap_send_pkt(data, sizeof(data));
640 break;
642 /* Set repeat mode */
643 case 0x0031:
645 int oldmode = global_settings.repeat_mode;
646 if (serbuf[4] == 0)
647 global_settings.repeat_mode = REPEAT_OFF;
648 else if (serbuf[4] == 1)
649 global_settings.repeat_mode = REPEAT_ONE;
650 else if (serbuf[4] == 2)
651 global_settings.repeat_mode = REPEAT_ALL;
653 if (oldmode != global_settings.repeat_mode)
655 settings_save();
656 settings_apply(false);
657 if (audio_status() & AUDIO_STATUS_PLAY)
658 audio_flush_and_reload_tracks();
661 /* respond with cmd ok packet */
662 unsigned char data[] = {0x04, 0x00, 0x01, 0x00, 0x00, 0x31};
663 iap_send_pkt(data, sizeof(data));
664 break;
666 /* Get Max Screen Size for Picture Upload??? */
667 case 0x0033:
669 unsigned char data[] = {0x04, 0x00, 0x34, 0x01, 0x36, 0x00, 0xA8, 0x01};
670 iap_send_pkt(data, sizeof(data));
671 break;
673 /* Get number songs in current playlist */
674 case 0x0035:
676 unsigned char data[] = {0x04, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00};
677 unsigned long playlist_amt = playlist_amount();
678 data[3] = playlist_amt >> 24;
679 data[4] = playlist_amt >> 16;
680 data[5] = playlist_amt >> 8;
681 data[6] = playlist_amt;
682 iap_send_pkt(data, sizeof(data));
683 break;
685 /* Jump to track number in current playlist */
686 case 0x0037:
688 long tracknum = (signed long)serbuf[4] << 24 |
689 (signed long)serbuf[5] << 16 |
690 (signed long)serbuf[6] << 8 | serbuf[7];
691 if (!wps_state.paused)
692 audio_pause();
693 audio_skip(tracknum - playlist_next(0));
694 if (!wps_state.paused)
695 audio_resume();
697 /* respond with cmd ok packet */
698 unsigned char data[] = {0x04, 0x00, 0x01, 0x00, 0x00, 0x00};
699 data[4] = serbuf[2];
700 data[5] = serbuf[3];
701 iap_send_pkt(data, sizeof(data));
702 break;
704 default:
706 /* default response is with cmd ok packet */
707 unsigned char data[] = {0x04, 0x00, 0x01, 0x00, 0x00, 0x00};
708 data[4] = serbuf[2];
709 data[5] = serbuf[3];
710 iap_send_pkt(data, sizeof(data));
711 break;
715 serbuf[0] = 0;
718 int remote_control_rx(void)
720 int btn = iap_remotebtn;
721 if(iap_repeatbtn)
723 iap_repeatbtn--;
724 if(!iap_repeatbtn)
726 iap_remotebtn = BUTTON_NONE;
727 iap_remotetick = true;
730 else
731 iap_remotetick = true;
733 return btn;