A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 719 lines 21 kB view raw
1/*************************************************************************** 2 * __________ __ ___. 3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7 * \/ \/ \/ \/ \/ 8 * $Id$ 9 * 10 * Copyright (C) 2005 Karl Kurbjun based on midi2wav by Stepan Moskovchenko 11 * 12 * This program is free software; you can redistribute it and/or 13 * modify it under the terms of the GNU General Public License 14 * as published by the Free Software Foundation; either version 2 15 * of the License, or (at your option) any later version. 16 * 17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 18 * KIND, either express or implied. 19 * 20 ****************************************************************************/ 21#include "plugin.h" 22#include "guspat.h" 23#include "midiutil.h" 24#include "synth.h" 25#include "sequencer.h" 26#include "midifile.h" 27 28 29/* variable button definitions */ 30#if (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD) 31#define MIDI_QUIT BUTTON_OFF 32#define MIDI_FFWD BUTTON_RIGHT 33#define MIDI_VOL_UP BUTTON_UP 34#define MIDI_VOL_DOWN BUTTON_DOWN 35#define MIDI_REWIND BUTTON_LEFT 36#define MIDI_RC_QUIT BUTTON_RC_STOP 37#define MIDI_PLAYPAUSE BUTTON_ON 38 39#elif (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) || \ 40 (CONFIG_KEYPAD == IPOD_1G2G_PAD) 41#define MIDI_QUIT (BUTTON_SELECT | BUTTON_MENU) 42#define MIDI_FFWD BUTTON_RIGHT 43#define MIDI_REWIND BUTTON_LEFT 44#define MIDI_VOL_UP BUTTON_SCROLL_FWD 45#define MIDI_VOL_DOWN BUTTON_SCROLL_BACK 46#define MIDI_PLAYPAUSE BUTTON_PLAY 47 48 49#elif (CONFIG_KEYPAD == GIGABEAT_PAD) 50#define MIDI_QUIT BUTTON_POWER 51#define MIDI_FFWD BUTTON_RIGHT 52#define MIDI_REWIND BUTTON_LEFT 53#define MIDI_VOL_UP BUTTON_UP 54#define MIDI_VOL_DOWN BUTTON_DOWN 55#define MIDI_PLAYPAUSE BUTTON_A 56 57 58#elif (CONFIG_KEYPAD == GIGABEAT_S_PAD) 59#define MIDI_QUIT BUTTON_POWER 60#define MIDI_FFWD BUTTON_RIGHT 61#define MIDI_REWIND BUTTON_LEFT 62#define MIDI_VOL_UP BUTTON_UP 63#define MIDI_VOL_DOWN BUTTON_DOWN 64#define MIDI_PLAYPAUSE BUTTON_PLAY 65 66 67#elif (CONFIG_KEYPAD == SANSA_E200_PAD) 68#define MIDI_QUIT BUTTON_POWER 69#define MIDI_FFWD BUTTON_RIGHT 70#define MIDI_REWIND BUTTON_LEFT 71#define MIDI_VOL_UP BUTTON_SCROLL_FWD 72#define MIDI_VOL_DOWN BUTTON_SCROLL_BACK 73#define MIDI_PLAYPAUSE BUTTON_UP 74 75#elif (CONFIG_KEYPAD == SANSA_FUZE_PAD) 76#define MIDI_QUIT (BUTTON_HOME|BUTTON_REPEAT) 77#define MIDI_FFWD BUTTON_RIGHT 78#define MIDI_REWIND BUTTON_LEFT 79#define MIDI_VOL_UP BUTTON_SCROLL_FWD 80#define MIDI_VOL_DOWN BUTTON_SCROLL_BACK 81#define MIDI_PLAYPAUSE BUTTON_UP 82 83 84#elif (CONFIG_KEYPAD == SANSA_C200_PAD) || \ 85(CONFIG_KEYPAD == SANSA_CLIP_PAD) || \ 86(CONFIG_KEYPAD == SANSA_M200_PAD) 87#define MIDI_QUIT BUTTON_POWER 88#define MIDI_FFWD BUTTON_RIGHT 89#define MIDI_REWIND BUTTON_LEFT 90#define MIDI_VOL_UP BUTTON_VOL_UP 91#define MIDI_VOL_DOWN BUTTON_VOL_DOWN 92#define MIDI_PLAYPAUSE BUTTON_UP 93 94 95#elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD 96#define MIDI_QUIT BUTTON_POWER 97#define MIDI_FFWD BUTTON_RIGHT 98#define MIDI_REWIND BUTTON_LEFT 99#define MIDI_VOL_UP BUTTON_UP 100#define MIDI_VOL_DOWN BUTTON_DOWN 101#define MIDI_PLAYPAUSE BUTTON_PLAY 102 103 104#elif CONFIG_KEYPAD == IRIVER_H10_PAD 105#define MIDI_QUIT BUTTON_POWER 106#define MIDI_FFWD BUTTON_RIGHT 107#define MIDI_REWIND BUTTON_LEFT 108#define MIDI_VOL_UP BUTTON_SCROLL_UP 109#define MIDI_VOL_DOWN BUTTON_SCROLL_DOWN 110#define MIDI_PLAYPAUSE BUTTON_PLAY 111 112 113#elif CONFIG_KEYPAD == MROBE500_PAD 114#define MIDI_QUIT BUTTON_POWER 115#define MIDI_FFWD BUTTON_RIGHT 116#define MIDI_REWIND BUTTON_LEFT 117#define MIDI_VOL_UP BUTTON_RC_PLAY 118#define MIDI_VOL_DOWN BUTTON_RC_DOWN 119#define MIDI_PLAYPAUSE BUTTON_RC_HEART 120 121 122#elif (CONFIG_KEYPAD == MROBE100_PAD) 123#define MIDI_QUIT BUTTON_POWER 124#define MIDI_FFWD BUTTON_RIGHT 125#define MIDI_REWIND BUTTON_LEFT 126#define MIDI_VOL_UP BUTTON_UP 127#define MIDI_VOL_DOWN BUTTON_DOWN 128#define MIDI_PLAYPAUSE BUTTON_DISPLAY 129 130 131#elif CONFIG_KEYPAD == IAUDIO_M3_PAD 132#define MIDI_QUIT BUTTON_RC_REC 133#define MIDI_FFWD BUTTON_RC_FF 134#define MIDI_REWIND BUTTON_RC_REW 135#define MIDI_VOL_UP BUTTON_RC_VOL_UP 136#define MIDI_VOL_DOWN BUTTON_RC_VOL_DOWN 137#define MIDI_PLAYPAUSE BUTTON_RC_PLAY 138 139 140#elif CONFIG_KEYPAD == COWON_D2_PAD 141#define MIDI_QUIT BUTTON_POWER 142 143#elif CONFIG_KEYPAD == CREATIVEZVM_PAD 144#define MIDI_QUIT BUTTON_BACK 145#define MIDI_FFWD BUTTON_RIGHT 146#define MIDI_REWIND BUTTON_LEFT 147#define MIDI_VOL_UP BUTTON_UP 148#define MIDI_VOL_DOWN BUTTON_DOWN 149#define MIDI_PLAYPAUSE BUTTON_PLAY 150 151#elif CONFIG_KEYPAD == CREATIVE_ZENXFI3_PAD 152#define MIDI_QUIT (BUTTON_PLAY|BUTTON_REPEAT) 153#define MIDI_FFWD BUTTON_MENU 154#define MIDI_REWIND BUTTON_BACK 155#define MIDI_VOL_UP BUTTON_VOL_UP 156#define MIDI_VOL_DOWN BUTTON_VOL_DOWN 157#define MIDI_PLAYPAUSE (BUTTON_PLAY|BUTTON_REL) 158 159#elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD 160#define MIDI_QUIT BUTTON_POWER 161#define MIDI_FFWD BUTTON_RIGHT 162#define MIDI_REWIND BUTTON_LEFT 163#define MIDI_VOL_UP BUTTON_UP 164#define MIDI_VOL_DOWN BUTTON_DOWN 165#define MIDI_PLAYPAUSE BUTTON_MENU 166 167#elif CONFIG_KEYPAD == PHILIPS_HDD6330_PAD 168#define MIDI_QUIT BUTTON_POWER 169#define MIDI_FFWD BUTTON_RIGHT 170#define MIDI_REWIND BUTTON_LEFT 171#define MIDI_VOL_UP BUTTON_UP 172#define MIDI_VOL_DOWN BUTTON_DOWN 173#define MIDI_PLAYPAUSE BUTTON_MENU 174 175#elif CONFIG_KEYPAD == PHILIPS_SA9200_PAD 176#define MIDI_QUIT BUTTON_POWER 177#define MIDI_FFWD BUTTON_NEXT 178#define MIDI_REWIND BUTTON_PREV 179#define MIDI_VOL_UP BUTTON_UP 180#define MIDI_VOL_DOWN BUTTON_DOWN 181#define MIDI_PLAYPAUSE BUTTON_MENU 182 183#elif CONFIG_KEYPAD == ONDAVX747_PAD 184#define MIDI_QUIT BUTTON_POWER 185#elif CONFIG_KEYPAD == ONDAVX777_PAD 186#define MIDI_QUIT BUTTON_POWER 187 188#elif (CONFIG_KEYPAD == SAMSUNG_YH820_PAD) || \ 189 (CONFIG_KEYPAD == SAMSUNG_YH92X_PAD) 190#define MIDI_QUIT (BUTTON_PLAY|BUTTON_REPEAT) 191#define MIDI_FFWD BUTTON_RIGHT 192#define MIDI_REWIND BUTTON_LEFT 193#define MIDI_VOL_UP BUTTON_UP 194#define MIDI_VOL_DOWN BUTTON_DOWN 195#define MIDI_PLAYPAUSE BUTTON_PLAY 196 197#elif CONFIG_KEYPAD == PBELL_VIBE500_PAD 198#define MIDI_QUIT BUTTON_REC 199#define MIDI_FFWD BUTTON_NEXT 200#define MIDI_REWIND BUTTON_PREV 201#define MIDI_VOL_UP BUTTON_UP 202#define MIDI_VOL_DOWN BUTTON_DOWN 203#define MIDI_PLAYPAUSE BUTTON_PLAY 204 205#elif CONFIG_KEYPAD == MPIO_HD200_PAD 206#define MIDI_QUIT (BUTTON_REC | BUTTON_PLAY) 207#define MIDI_FFWD BUTTON_FF 208#define MIDI_REWIND BUTTON_REW 209#define MIDI_VOL_UP BUTTON_VOL_UP 210#define MIDI_VOL_DOWN BUTTON_VOL_DOWN 211#define MIDI_PLAYPAUSE BUTTON_PLAY 212 213#elif CONFIG_KEYPAD == MPIO_HD300_PAD 214#define MIDI_QUIT (BUTTON_MENU | BUTTON_REPEAT) 215#define MIDI_FFWD BUTTON_FF 216#define MIDI_REWIND BUTTON_REW 217#define MIDI_VOL_UP BUTTON_UP 218#define MIDI_VOL_DOWN BUTTON_DOWN 219#define MIDI_PLAYPAUSE BUTTON_PLAY 220 221#elif CONFIG_KEYPAD == SANSA_FUZEPLUS_PAD 222#define MIDI_QUIT BUTTON_POWER 223#define MIDI_FFWD BUTTON_RIGHT 224#define MIDI_REWIND BUTTON_LEFT 225#define MIDI_VOL_UP BUTTON_UP 226#define MIDI_VOL_DOWN BUTTON_DOWN 227#define MIDI_PLAYPAUSE BUTTON_PLAYPAUSE 228 229#elif CONFIG_KEYPAD == SANSA_CONNECT_PAD 230#define MIDI_QUIT BUTTON_POWER 231#define MIDI_FFWD BUTTON_RIGHT 232#define MIDI_REWIND BUTTON_LEFT 233#define MIDI_VOL_UP BUTTON_UP 234#define MIDI_VOL_DOWN BUTTON_DOWN 235#define MIDI_PLAYPAUSE BUTTON_SELECT 236 237#elif CONFIG_KEYPAD == SAMSUNG_YPR0_PAD 238#define MIDI_QUIT BUTTON_BACK 239#define MIDI_FFWD BUTTON_RIGHT 240#define MIDI_REWIND BUTTON_LEFT 241#define MIDI_VOL_UP BUTTON_UP 242#define MIDI_VOL_DOWN BUTTON_DOWN 243#define MIDI_PLAYPAUSE BUTTON_USER 244 245#elif (CONFIG_KEYPAD == HM60X_PAD) || \ 246 (CONFIG_KEYPAD == HM801_PAD) 247#define MIDI_QUIT BUTTON_POWER 248#define MIDI_FFWD BUTTON_RIGHT 249#define MIDI_REWIND BUTTON_LEFT 250#define MIDI_VOL_UP BUTTON_UP 251#define MIDI_VOL_DOWN BUTTON_DOWN 252#define MIDI_PLAYPAUSE BUTTON_SELECT 253 254#elif (CONFIG_KEYPAD == SONY_NWZ_PAD) 255#define MIDI_QUIT BUTTON_BACK 256#define MIDI_FFWD BUTTON_RIGHT 257#define MIDI_REWIND BUTTON_LEFT 258#define MIDI_VOL_UP BUTTON_UP 259#define MIDI_VOL_DOWN BUTTON_DOWN 260#define MIDI_PLAYPAUSE BUTTON_PLAY 261 262#elif (CONFIG_KEYPAD == CREATIVE_ZEN_PAD) 263#define MIDI_QUIT BUTTON_BACK 264#define MIDI_FFWD BUTTON_RIGHT 265#define MIDI_REWIND BUTTON_LEFT 266#define MIDI_VOL_UP BUTTON_UP 267#define MIDI_VOL_DOWN BUTTON_DOWN 268#define MIDI_PLAYPAUSE BUTTON_PLAYPAUSE 269 270#elif CONFIG_KEYPAD == DX50_PAD 271#define MIDI_QUIT BUTTON_POWER 272#define MIDI_FFWD BUTTON_RIGHT 273#define MIDI_REWIND BUTTON_LEFT 274#define MIDI_VOL_UP BUTTON_VOL_UP 275#define MIDI_VOL_DOWN BUTTON_VOL_DOWN 276 277#elif CONFIG_KEYPAD == CREATIVE_ZENXFI2_PAD 278#define MIDI_QUIT BUTTON_POWER 279 280#elif CONFIG_KEYPAD == AGPTEK_ROCKER_PAD 281#define MIDI_QUIT BUTTON_POWER 282#define MIDI_FFWD BUTTON_RIGHT 283#define MIDI_REWIND BUTTON_LEFT 284#define MIDI_VOL_UP BUTTON_VOLUP 285#define MIDI_VOL_DOWN BUTTON_VOLDOWN 286#define MIDI_PLAYPAUSE BUTTON_SELECT 287 288#elif CONFIG_KEYPAD == XDUOO_X3_PAD || CONFIG_KEYPAD == XDUOO_X3II_PAD || CONFIG_KEYPAD == XDUOO_X20_PAD 289#define MIDI_QUIT BUTTON_POWER 290#define MIDI_FFWD BUTTON_NEXT 291#define MIDI_REWIND BUTTON_PREV 292#define MIDI_VOL_UP BUTTON_VOL_UP 293#define MIDI_VOL_DOWN BUTTON_VOL_DOWN 294#define MIDI_PLAYPAUSE BUTTON_PLAY 295 296#elif CONFIG_KEYPAD == FIIO_M3K_LINUX_PAD 297#define MIDI_QUIT BUTTON_POWER 298#define MIDI_FFWD BUTTON_NEXT 299#define MIDI_REWIND BUTTON_PREV 300#define MIDI_VOL_UP BUTTON_VOL_UP 301#define MIDI_VOL_DOWN BUTTON_VOL_DOWN 302#define MIDI_PLAYPAUSE BUTTON_PLAY 303 304#elif CONFIG_KEYPAD == IHIFI_770_PAD || CONFIG_KEYPAD == IHIFI_800_PAD 305#define MIDI_QUIT BUTTON_POWER 306#define MIDI_FFWD BUTTON_VOL_DOWN 307#define MIDI_REWIND BUTTON_HOME 308#define MIDI_VOL_UP BUTTON_PREV 309#define MIDI_VOL_DOWN BUTTON_NEXT 310#define MIDI_PLAYPAUSE BUTTON_PLAY 311 312#elif CONFIG_KEYPAD == EROSQ_PAD 313#define MIDI_QUIT BUTTON_POWER 314#define MIDI_FFWD BUTTON_NEXT 315#define MIDI_REWIND BUTTON_PREV 316#define MIDI_VOL_UP BUTTON_VOL_UP 317#define MIDI_VOL_DOWN BUTTON_VOL_DOWN 318#define MIDI_PLAYPAUSE BUTTON_PLAY 319 320#elif CONFIG_KEYPAD == FIIO_M3K_PAD 321#define MIDI_QUIT BUTTON_POWER 322#define MIDI_FFWD BUTTON_LEFT 323#define MIDI_REWIND BUTTON_RIGHT 324#define MIDI_VOL_UP BUTTON_VOL_UP 325#define MIDI_VOL_DOWN BUTTON_VOL_DOWN 326#define MIDI_PLAYPAUSE BUTTON_PLAY 327 328#elif CONFIG_KEYPAD == SHANLING_Q1_PAD 329/* use touchscreen */ 330 331#elif CONFIG_KEYPAD == MA_PAD 332#define MIDI_QUIT BUTTON_BACK 333#define MIDI_FFWD BUTTON_RIGHT 334#define MIDI_REWIND BUTTON_LEFT 335#define MIDI_VOL_UP BUTTON_UP 336#define MIDI_VOL_DOWN BUTTON_DOWN 337#define MIDI_PLAYPAUSE BUTTON_PLAY 338 339#elif CONFIG_KEYPAD == RG_NANO_PAD 340#define MIDI_QUIT BUTTON_START 341#define MIDI_FFWD BUTTON_RIGHT 342#define MIDI_REWIND BUTTON_LEFT 343#define MIDI_VOL_UP BUTTON_UP 344#define MIDI_VOL_DOWN BUTTON_DOWN 345#define MIDI_PLAYPAUSE BUTTON_A 346 347#else 348#error No keymap defined! 349#endif 350 351#ifdef HAVE_TOUCHSCREEN 352#ifndef MIDI_QUIT 353#define MIDI_QUIT BUTTON_TOPLEFT 354#endif 355#ifndef MIDI_FFWD 356#define MIDI_FFWD BUTTON_MIDRIGHT 357#endif 358#ifndef MIDI_REWIND 359#define MIDI_REWIND BUTTON_MIDLEFT 360#endif 361#ifndef MIDI_VOL_UP 362#define MIDI_VOL_UP BUTTON_TOPMIDDLE 363#endif 364#ifndef MIDI_VOL_DOWN 365#define MIDI_VOL_DOWN BUTTON_BOTTOMMIDDLE 366#endif 367#ifndef MIDI_PLAYPAUSE 368#define MIDI_PLAYPAUSE BUTTON_CENTER 369#endif 370#endif 371 372#undef SYNC 373 374#ifdef SIMULATOR 375#define SYNC 376#endif 377 378#ifndef ALIGNED_ATTR 379#define ALIGNED_ATTR(x) __attribute__((aligned(x))) 380#endif 381 382struct MIDIfile * mf IBSS_ATTR; 383 384int number_of_samples IBSS_ATTR; /* the number of samples in the current tick */ 385int playing_time IBSS_ATTR; /* How many seconds into the file have we been playing? */ 386int samples_this_second IBSS_ATTR; /* How many samples produced during this second so far? */ 387long bpm IBSS_ATTR; 388 389#ifndef SYNC 390/* Small silence clip. ~5.80ms @ 44.1kHz */ 391static int32_t silence[256] ALIGNED_ATTR(4) = { 0 }; 392 393static int32_t gmbuf[BUF_SIZE * NBUF] ALIGNED_ATTR(4); 394 395static volatile bool swap = false; 396static volatile bool lastswap = true; 397#else 398static int32_t gmbuf[BUF_SIZE] ALIGNED_ATTR(4); 399#endif 400 401static volatile size_t samples_in_buf; 402 403static volatile bool midi_end = false; 404static volatile bool quit = false; 405 406static int32_t samp_buf[MAX_SAMPLES * 2] IBSS_ATTR; 407 408static struct dsp_config *dsp; 409static struct dsp_buffer src; 410static struct dsp_buffer dst; 411 412static inline void synthbuf(void) 413{ 414 int32_t *outptr; 415 int available = BUF_SIZE; 416 417#ifndef SYNC 418 if (lastswap == swap) 419 return; 420 421 outptr = (swap ? gmbuf : gmbuf+BUF_SIZE); 422#else 423 outptr = gmbuf; 424#endif 425 426#if defined(HAVE_ADJUSTABLE_CPU_FREQ) 427 rb->cpu_boost(true); 428#endif 429 /* synth samples for as many whole ticks as we can fit in the buffer */ 430 while (available > 0) 431 { 432 if ((dst.remcount <= 0) && !midi_end) 433 { 434 int nsamples = synthSamples(samp_buf, number_of_samples); 435 if (nsamples < number_of_samples) 436 number_of_samples -= nsamples; 437 else if (!tick()) 438 midi_end = true; /* no more midi data to play */ 439 src.remcount = nsamples; 440 src.pin[0] = &samp_buf[0]; 441 src.pin[1] = &samp_buf[1]; 442 src.proc_mask = 0; 443 } 444 dst.remcount = 0; 445 dst.bufcount = available; 446 dst.p16out = (int16_t *)outptr; 447 rb->dsp_process(dsp, &src, &dst, true); 448 if (dst.remcount > 0) 449 { 450 outptr += dst.remcount; 451 available -= dst.remcount; 452 } 453 else if (midi_end) 454 break; 455 } 456 457 /* how many samples did we write to the buffer? */ 458 samples_in_buf = BUF_SIZE - available; 459#ifndef SYNC 460 lastswap = swap; 461#endif 462#if defined(HAVE_ADJUSTABLE_CPU_FREQ) 463 rb->cpu_boost(false); 464#endif 465} 466 467static void get_more(const void** start, size_t* size) 468{ 469#ifndef SYNC 470 swap = !swap; 471 if(lastswap == swap) 472 { 473 *start = silence; 474 *size = sizeof(silence); 475 swap = !swap; 476 return; 477 } 478 else if (samples_in_buf) 479 *start = swap ? (gmbuf + BUF_SIZE) : gmbuf; 480#else 481 synthbuf(); /* For some reason midiplayer crashes when an update is forced */ 482 if (samples_in_buf) 483 *start = gmbuf; 484#endif 485 else 486 { 487 *start = NULL; 488 quit = true; /* this was the last buffer to play */ 489 } 490 *size = samples_in_buf*sizeof(int32_t); 491} 492 493static int midimain(const void * filename) 494{ 495 int a, notes_used, vol; 496 bool is_playing = true; /* false = paused */ 497 498#if defined(HAVE_ADJUSTABLE_CPU_FREQ) 499 rb->cpu_boost(true); 500#endif 501 midi_debug("Loading file"); 502 mf = loadFile(filename); 503 504 if (mf == NULL) 505 { 506 midi_debug("Error loading file."); 507#if defined(HAVE_ADJUSTABLE_CPU_FREQ) 508 rb->cpu_boost(false); 509#endif 510 return -1; 511 } 512 513 if (initSynth(mf, ROCKBOX_DIR "/patchset/patchset.cfg", 514 ROCKBOX_DIR "/patchset/drums.cfg") == -1) 515 { 516#if defined(HAVE_ADJUSTABLE_CPU_FREQ) 517 rb->cpu_boost(false); 518#endif 519 return -1; 520 } 521 522 rb->talk_force_shutup(); 523 rb->pcm_play_stop(); 524#if INPUT_SRC_CAPS != 0 525 /* Select playback */ 526 rb->audio_set_input_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK); 527 rb->audio_set_output_source(AUDIO_SRC_PLAYBACK); 528#endif 529 530 dst.remcount = 0; 531 dsp = rb->dsp_get_config(CODEC_IDX_AUDIO); 532 rb->dsp_configure(dsp, DSP_RESET, 0); 533 rb->dsp_configure(dsp, DSP_FLUSH, 0); 534 rb->dsp_configure(dsp, DSP_SET_OUT_FREQUENCY, rb->mixer_get_frequency()); 535#ifdef HAVE_PITCHCONTROL 536 rb->sound_set_pitch(PITCH_SPEED_100); 537 rb->dsp_set_timestretch(PITCH_SPEED_100); 538#endif 539 rb->dsp_configure(dsp, DSP_SET_SAMPLE_DEPTH, 22); 540 rb->dsp_configure(dsp, DSP_SET_FREQUENCY, SAMPLE_RATE); /* 44100 22050 11025 */ 541 rb->dsp_configure(dsp, DSP_SET_STEREO_MODE, STEREO_INTERLEAVED); 542 543 /* 544 * tick() will do one MIDI clock tick. Then, there's a loop here that 545 * will generate the right number of samples per MIDI tick. The whole 546 * MIDI playback is timed in terms of this value.. there are no forced 547 * delays or anything. It just produces enough samples for each tick, and 548 * the playback of these samples is what makes the timings right. 549 * 550 * This seems to work quite well. On a laptop, anyway. 551 */ 552 553 midi_debug("Okay, starting sequencing"); 554 555 bpm = mf->div*1000000/tempo; 556 number_of_samples = SAMPLE_RATE/bpm; 557 558 /* Skip over any junk in the beginning of the file, so start playing */ 559 /* after the first note event */ 560 do 561 { 562 notes_used = 0; 563 for (a = 0; a < MAX_VOICES; a++) 564 if (voices[a].isUsed) 565 notes_used++; 566 tick(); 567 } while (notes_used == 0); 568 569#if defined(HAVE_ADJUSTABLE_CPU_FREQ) 570 rb->cpu_boost(false); 571#endif 572 573 playing_time = 0; 574 samples_this_second = 0; 575 576#ifndef SYNC 577 synthbuf(); 578#endif 579 580 rb->pcmbuf_fade(false, true); 581 rb->mixer_channel_play_data(PCM_MIXER_CHAN_PLAYBACK, get_more, NULL, 0); 582 583 while (!quit) 584 { 585 #ifndef SYNC 586 synthbuf(); 587 #endif 588 rb->yield(); 589 590 /* Prevent idle poweroff */ 591 rb->reset_poweroff_timer(); 592 593 /* Code taken from Oscilloscope plugin */ 594 switch (rb->button_get(false)) 595 { 596 case MIDI_VOL_UP: 597 case MIDI_VOL_UP | BUTTON_REPEAT: 598 { 599 vol = rb->global_status->volume; 600 if (vol < rb->sound_max(SOUND_VOLUME)) 601 { 602 vol++; 603 rb->sound_set(SOUND_VOLUME, vol); 604 } 605 break; 606 } 607 608 case MIDI_VOL_DOWN: 609 case MIDI_VOL_DOWN | BUTTON_REPEAT: 610 { 611 vol = rb->global_status->volume; 612 if (vol > rb->sound_min(SOUND_VOLUME)) 613 { 614 vol--; 615 rb->sound_set(SOUND_VOLUME, vol); 616 } 617 break; 618 } 619 620 case MIDI_REWIND: 621 { 622 /* Rewinding is tricky. Basically start the file over */ 623 /* but run through the tracks without the synth running */ 624 rb->mixer_channel_stop(PCM_MIXER_CHAN_PLAYBACK); 625 rb->dsp_configure(dsp, DSP_FLUSH, 0); 626 dst.remcount = 0; 627#if defined(HAVE_ADJUSTABLE_CPU_FREQ) 628 rb->cpu_boost(true); 629#endif 630 seekBackward(5); 631#if defined(HAVE_ADJUSTABLE_CPU_FREQ) 632 rb->cpu_boost(false); 633#endif 634#ifndef SYNC 635 lastswap = !swap; 636 synthbuf(); 637#endif 638 midi_debug("Rewind to %d:%02d\n", playing_time/60, playing_time%60); 639 if (is_playing) 640 rb->mixer_channel_play_data(PCM_MIXER_CHAN_PLAYBACK, get_more, NULL, 0); 641 break; 642 } 643 644 case MIDI_FFWD: 645 { 646 rb->mixer_channel_stop(PCM_MIXER_CHAN_PLAYBACK); 647 rb->dsp_configure(dsp, DSP_FLUSH, 0); 648 dst.remcount = 0; 649#if defined(HAVE_ADJUSTABLE_CPU_FREQ) 650 rb->cpu_boost(true); 651#endif 652 seekForward(5); 653#if defined(HAVE_ADJUSTABLE_CPU_FREQ) 654 rb->cpu_boost(false); 655#endif 656#ifndef SYNC 657 lastswap = !swap; 658 synthbuf(); 659#endif 660 midi_debug("Skip to %d:%02d\n", playing_time/60, playing_time%60); 661 if (is_playing) 662 rb->mixer_channel_play_data(PCM_MIXER_CHAN_PLAYBACK, get_more, NULL, 0); 663 break; 664 } 665 666 case MIDI_PLAYPAUSE: 667 { 668 is_playing = !is_playing; 669 midi_debug("%s %d:%02d\n", 670 is_playing ? "Playing from" : "Paused at", 671 playing_time/60, playing_time%60); 672 rb->mixer_channel_play_pause(PCM_MIXER_CHAN_PLAYBACK, is_playing); 673 break; 674 } 675 676#ifdef MIDI_RC_QUIT 677 case MIDI_RC_QUIT: 678#endif 679 case MIDI_QUIT: 680 quit = true; 681 } 682 } 683 684 rb->pcmbuf_fade(false, false); 685 rb->mixer_channel_stop(PCM_MIXER_CHAN_PLAYBACK); 686 687 return 0; 688} 689 690enum plugin_status plugin_start(const void* parameter) 691{ 692 int retval; 693 694 if (parameter == NULL) 695 { 696 rb->splash(HZ*2, " Play .MID file "); 697 return PLUGIN_OK; 698 } 699 rb->lcd_setfont(FONT_SYSFIXED); 700 701 midi_debug("%s", parameter); 702 /* rb->splash(HZ, true, parameter); */ 703 704#ifdef RB_PROFILE 705 rb->profile_thread(); 706#endif 707 708 retval = midimain(parameter); 709 710#ifdef RB_PROFILE 711 rb->profstop(); 712#endif 713 714 rb->splash(HZ, "FINISHED PLAYING"); 715 716 if (retval == -1) 717 return PLUGIN_ERROR; 718 return PLUGIN_OK; 719}