Want more features on Pastebin? Sign Up, it's FREE!
Guest

Warble

By: a guest on Jun 22nd, 2011  |  syntax: Diff  |  size: 54.34 KB  |  views: 70  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1.  apps/codec_thread.c                |    7 +
  2.  apps/codecs.c                      |    4 +-
  3.  apps/codecs.h                      |   11 +-
  4.  apps/codecs/adx.c                  |    2 +-
  5.  apps/codecs/libtremor/SOURCES      |    1 -
  6.  apps/codecs/libtremor/ctype.c      |    4 -
  7.  apps/codecs/libtremor/info.c       |    1 -
  8.  apps/codecs/libtremor/vorbisfile.c |    1 -
  9.  apps/codecs/mod.c                  |   11 +-
  10.  apps/codecs/nsf.c                  |   13 +-
  11.  apps/codecs/spc.c                  |   10 +-
  12.  apps/codecs/wav.c                  |    4 +-
  13.  apps/main.c                        |    6 +-
  14.  apps/metadata.c                    |    8 +-
  15.  apps/metadata.h                    |    2 +-
  16.  apps/metadata/adx.c                |    1 -
  17.  apps/metadata/aiff.c               |    1 -
  18.  apps/metadata/ape.c                |    1 -
  19.  apps/metadata/asap.c               |    1 -
  20.  apps/metadata/asf.c                |    1 -
  21.  apps/metadata/flac.c               |    1 -
  22.  apps/metadata/metadata_common.c    |   11 +-
  23.  apps/metadata/monkeys.c            |    1 -
  24.  apps/metadata/mp4.c                |    1 -
  25.  apps/metadata/nsf.c                |    1 -
  26.  apps/metadata/ogg.c                |    1 -
  27.  apps/metadata/rm.c                 |    1 -
  28.  apps/metadata/sid.c                |    1 -
  29.  apps/metadata/spc.c                |    1 -
  30.  apps/metadata/tta.c                |    1 -
  31.  apps/metadata/vorbis.c             |    2 -
  32.  apps/metadata/vox.c                |    1 -
  33.  apps/metadata/wavpack.c            |    1 -
  34.  apps/playback.c                    |    3 +-
  35.  apps/plugins/test_codec.c          |    9 +-
  36.  apps/screen_access.c               |    1 +
  37.  apps/settings.h                    |    3 +-
  38.  apps/tdspeed.c                     |   22 +-
  39.  warble/Makefile                    |   63 +++
  40.  warble/autoconf.h                  |   16 +
  41.  warble/warble.c                    |  824 ++++++++++++++++++++++++++++++++++++
  42.  41 files changed, 974 insertions(+), 81 deletions(-)
  43.  
  44. diff --git a/apps/codec_thread.c b/apps/codec_thread.c
  45. index a7bff74..3e18ce4 100644
  46. --- a/apps/codec_thread.c
  47. +++ b/apps/codec_thread.c
  48. @@ -30,6 +30,7 @@
  49.  #include "buffering.h"
  50.  #include "dsp.h"
  51.  #include "metadata.h"
  52. +#include "settings.h"
  53.  
  54.  /* Define LOGF_ENABLE to enable logf output in this file */
  55.  /*#define LOGF_ENABLE*/
  56. @@ -402,6 +403,11 @@ static enum codec_command_action
  57.      }
  58.  }
  59.  
  60. +static bool codec_should_loop_callback(void)
  61. +{
  62. +    return global_settings.repeat_mode == REPEAT_ONE;
  63. +}
  64. +
  65.  /* Initialize codec API */
  66.  void codec_init_codec_api(void)
  67.  {
  68. @@ -418,6 +424,7 @@ void codec_init_codec_api(void)
  69.      ci.set_offset          = audio_codec_update_offset;
  70.      ci.configure           = codec_configure_callback;
  71.      ci.get_command         = codec_get_command_callback;
  72. +    ci.should_loop         = codec_should_loop_callback;
  73.  }
  74.  
  75.  
  76. diff --git a/apps/codecs.c b/apps/codecs.c
  77. index cd4a9d5..c2efbaa 100644
  78. --- a/apps/codecs.c
  79. +++ b/apps/codecs.c
  80. @@ -50,6 +50,7 @@
  81.  #include "sound.h"
  82.  #include "splash.h"
  83.  #include "general.h"
  84. +#include "rbpaths.h"
  85.  
  86.  #define LOGF_ENABLE
  87.  #include "logf.h"
  88. @@ -97,6 +98,7 @@ struct codec_api ci = {
  89.      NULL, /* set_offset */
  90.      NULL, /* configure */
  91.      NULL, /* get_command */
  92. +    NULL, /* should_loop */
  93.      
  94.      /* kernel/ system */
  95.  #if defined(CPU_ARM) && CONFIG_PLATFORM & PLATFORM_NATIVE
  96. @@ -127,7 +129,6 @@ struct codec_api ci = {
  97.      memmove,
  98.      memcmp,
  99.      memchr,
  100. -    strcasestr,
  101.  #if defined(DEBUG) || defined(SIMULATOR)
  102.      debugf,
  103.  #endif
  104. @@ -136,7 +137,6 @@ struct codec_api ci = {
  105.  #endif
  106.  
  107.      (qsort_func)qsort,
  108. -    &global_settings,
  109.  
  110.  #ifdef RB_PROFILE
  111.      profile_thread,
  112. diff --git a/apps/codecs.h b/apps/codecs.h
  113. index e240811..a699711 100644
  114. --- a/apps/codecs.h
  115. +++ b/apps/codecs.h
  116. @@ -44,7 +44,6 @@
  117.  #endif
  118.  #include "dsp.h"
  119.  #endif
  120. -#include "settings.h"
  121.  
  122.  #include "gcc_extensions.h"
  123.  #include "load_code.h"
  124. @@ -75,12 +74,12 @@
  125.  #define CODEC_ENC_MAGIC 0x52454E43 /* RENC */
  126.  
  127.  /* increase this every time the api struct changes */
  128. -#define CODEC_API_VERSION 42
  129. +#define CODEC_API_VERSION 43
  130.  
  131.  /* update this to latest version if a change to the api struct breaks
  132.     backwards compatibility (and please take the opportunity to sort in any
  133.     new function which are "waiting" at the end of the function table) */
  134. -#define CODEC_MIN_API_VERSION 42
  135. +#define CODEC_MIN_API_VERSION 43
  136.  
  137.  /* reasons for calling codec main entrypoint */
  138.  enum codec_entry_call_reason {
  139. @@ -145,6 +144,8 @@ struct codec_api {
  140.      void (*configure)(int setting, intptr_t value);
  141.      /* Obtain command action on what to do next */
  142.      enum codec_command_action (*get_command)(intptr_t *param);
  143. +    /* Determine whether the loop should be used, if applicable. */
  144. +    bool (*should_loop)(void);
  145.  
  146.      /* kernel/ system */
  147.  #if defined(CPU_ARM) && CONFIG_PLATFORM & PLATFORM_NATIVE
  148. @@ -180,7 +181,6 @@ struct codec_api {
  149.      void* (*memmove)(void *out, const void *in, size_t n);
  150.      int (*memcmp)(const void *s1, const void *s2, size_t n);
  151.      void *(*memchr)(const void *s1, int c, size_t n);
  152. -    char *(*strcasestr) (const char* phaystack, const char* pneedle);
  153.  
  154.  #if defined(DEBUG) || defined(SIMULATOR)
  155.      void (*debugf)(const char *fmt, ...) ATTRIBUTE_PRINTF(1, 2);
  156. @@ -193,9 +193,6 @@ struct codec_api {
  157.      void (*qsort)(void *base, size_t nmemb, size_t size,
  158.                    int(*compar)(const void *, const void *));
  159.  
  160. -    /* The ADX codec accesses global_settings to test for REPEAT_ONE mode */
  161. -    struct user_settings* global_settings;
  162. -
  163.  #ifdef RB_PROFILE
  164.      void (*profile_thread)(void);
  165.      void (*profstop)(void);
  166. diff --git a/apps/codecs/adx.c b/apps/codecs/adx.c
  167. index e75e7dc..1318aff 100644
  168. --- a/apps/codecs/adx.c
  169. +++ b/apps/codecs/adx.c
  170. @@ -239,7 +239,7 @@ enum codec_status codec_run(void)
  171.          if (bufoff > end_adr-18*channels && looping) {
  172.              DEBUGF("ADX: loop!\n");
  173.              /* check for endless looping */
  174. -            if (ci->global_settings->repeat_mode==REPEAT_ONE) {
  175. +            if (ci->should_loop()) {
  176.                  loop_count=0;
  177.                  fade_count = -1; /* disable fade */
  178.              } else {
  179. diff --git a/apps/codecs/libtremor/SOURCES b/apps/codecs/libtremor/SOURCES
  180. index c622699..4076694 100644
  181. --- a/apps/codecs/libtremor/SOURCES
  182. +++ b/apps/codecs/libtremor/SOURCES
  183. @@ -12,5 +12,4 @@ sharedbook.c
  184.  synthesis.c
  185.  vorbisfile.c
  186.  window.c
  187. -ctype.c
  188.  oggmalloc.c
  189. diff --git a/apps/codecs/libtremor/ctype.c b/apps/codecs/libtremor/ctype.c
  190. deleted file mode 100644
  191. index 9f22047..0000000
  192. --- a/apps/codecs/libtremor/ctype.c
  193. +++ /dev/null
  194. @@ -1,4 +0,0 @@
  195. -#include "config.h"
  196. -#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
  197. -#include "libc/ctype.c"
  198. -#endif
  199. diff --git a/apps/codecs/libtremor/info.c b/apps/codecs/libtremor/info.c
  200. index b21d08d..b3451d3 100644
  201. --- a/apps/codecs/libtremor/info.c
  202. +++ b/apps/codecs/libtremor/info.c
  203. @@ -20,7 +20,6 @@
  204.  
  205.  #include "config-tremor.h"
  206.  #include <string.h>
  207. -#include <ctype.h>
  208.  #include "ogg.h"
  209.  #include "ivorbiscodec.h"
  210.  #include "codec_internal.h"
  211. diff --git a/apps/codecs/libtremor/vorbisfile.c b/apps/codecs/libtremor/vorbisfile.c
  212. index 5721178..cdc1853 100644
  213. --- a/apps/codecs/libtremor/vorbisfile.c
  214. +++ b/apps/codecs/libtremor/vorbisfile.c
  215. @@ -21,7 +21,6 @@
  216.  #include <errno.h>
  217.  #include <string.h>
  218.  #include <math.h>
  219. -#include "system.h"
  220.  
  221.  #include "ivorbiscodec.h"
  222.  #include "ivorbisfile.h"
  223. diff --git a/apps/codecs/mod.c b/apps/codecs/mod.c
  224. index 3dfaac6..862dd86 100644
  225. --- a/apps/codecs/mod.c
  226. +++ b/apps/codecs/mod.c
  227. @@ -37,7 +37,6 @@
  228.  #include <stdio.h>
  229.  #include <string.h>
  230.  #include <stdlib.h>
  231. -#include <ctype.h>
  232.  
  233.  
  234.  CODEC_HEADER
  235. @@ -1132,12 +1131,16 @@ void synthrender(int32_t *renderbuffer, int samplecount)
  236.                  if (modplayer.currentline == 64)
  237.                  {
  238.                      modplayer.patterntableposition++;
  239. -                    if (modplayer.patterntableposition >= modsong.songlength)
  240. +                    if (modplayer.patterntableposition >= modsong.songlength) {
  241.                          /* This is for Noise Tracker
  242.                           * modplayer.patterntableposition =
  243.                           *    modsong.songendjumpposition;
  244.                           * More compatible approach is restart from 0 */
  245. -                        modplayer.patterntableposition=0;
  246. +                        if (ci->should_loop())
  247. +                            modplayer.patterntableposition = 0;
  248. +                        else
  249. +                            modplayer.patterntableposition = 127;
  250. +                    }
  251.                      modplayer.currentline = 0;
  252.                  }
  253.              }
  254. @@ -1278,6 +1281,8 @@ enum codec_status codec_run(void)
  255.          }
  256.  
  257.          if(old_patterntableposition != modplayer.patterntableposition) {
  258. +          if (modplayer.patterntableposition == 127)
  259. +              break;
  260.            ci->set_elapsed(modplayer.patterntableposition*1000+500);
  261.            old_patterntableposition=modplayer.patterntableposition;
  262.          }
  263. diff --git a/apps/codecs/nsf.c b/apps/codecs/nsf.c
  264. index d626d52..334934f 100644
  265. --- a/apps/codecs/nsf.c
  266. +++ b/apps/codecs/nsf.c
  267. @@ -4324,14 +4324,13 @@ jammed:
  268.  static int track = 0;
  269.  static char last_path[MAX_PATH];
  270.  static int dontresettrack = 0;
  271. -static bool repeat_one = false;
  272.  
  273.  static void set_codec_track(int t, int d) {
  274.      int track,fade,def=0;
  275.      SetTrack(t);
  276.  
  277. -    /* for REPEAT_ONE we disable track limits */
  278. -    if (!repeat_one) {
  279. +    /* for loop mode we disable track limits */
  280. +    if (!ci->should_loop()) {
  281.          if (!bIsExtended || nTrackTime[t]==-1) {track=60*2*1000; def=1;}
  282.          else track=nTrackTime[t];
  283.          if (!bIsExtended || nTrackFade[t]==-1) fade=5*1000;
  284. @@ -4384,8 +4383,6 @@ enum codec_status codec_run(void)
  285.          return CODEC_ERROR;
  286.      }
  287.  
  288. -    repeat_one = ci->global_settings->repeat_mode == REPEAT_ONE;
  289. -    
  290.  init_nsf:    
  291.      if(!NSFCore_Initialize()) {
  292.          DEBUGF("NSF: NSFCore_Initialize failed\n"); return CODEC_ERROR;}
  293. @@ -4401,7 +4398,7 @@ init_nsf:
  294.          /* if this is the first time we're seeing this file, or if we haven't
  295.             been asked to preserve the track number, default to the proper
  296.             initial track */
  297. -        if (bIsExtended && !repeat_one && nPlaylistSize>0) {
  298. +        if (bIsExtended && !ci->should_loop() && nPlaylistSize>0) {
  299.              /* decide to use the playlist */
  300.              usingplaylist=1;
  301.              track=0;
  302. @@ -4466,8 +4463,8 @@ init_nsf:
  303.      
  304.      print_timers(last_path,track);
  305.  
  306. -    if (repeat_one) {
  307. -        /* in repeat one mode just advance to the next track */
  308. +    if (ci->should_loop()) {
  309. +        /* in loop mode just advance to the next track */
  310.          track++;
  311.          if (track>=nTrackCount) track=0;
  312.          dontresettrack=1;
  313. diff --git a/apps/codecs/spc.c b/apps/codecs/spc.c
  314. index 6b21f9a..8974b8b 100644
  315. --- a/apps/codecs/spc.c
  316. +++ b/apps/codecs/spc.c
  317. @@ -477,7 +477,7 @@ static int play_track( void )
  318.          sampleswritten += WAV_CHUNK_SIZE;
  319.  
  320.          /* is track timed? */
  321. -        if (ci->global_settings->repeat_mode!=REPEAT_ONE && ci->id3->length) {
  322. +        if (!ci->should_loop() && ci->id3->length) {
  323.              unsigned long curtime = sampleswritten*1000LL/SAMPLE_RATE;
  324.              unsigned long lasttimesample = (sampleswritten-WAV_CHUNK_SIZE);
  325.  
  326. @@ -513,10 +513,10 @@ static int play_track( void )
  327.  
  328.          spc_play_send_samples(samples);
  329.  
  330. -        if (ci->global_settings->repeat_mode!=REPEAT_ONE)
  331. -            ci->set_elapsed(sampleswritten*1000LL/SAMPLE_RATE);
  332. -        else
  333. +        if (ci->should_loop())
  334.              ci->set_elapsed(0);
  335. +        else
  336. +            ci->set_elapsed(sampleswritten*1000LL/SAMPLE_RATE);
  337.      }
  338.      
  339.      EXIT_TIMER(total);
  340. @@ -569,7 +569,7 @@ enum codec_status codec_run(void)
  341.  
  342.          LoadID666(buffer+0x2e);
  343.  
  344. -        if (ci->global_settings->repeat_mode!=REPEAT_ONE && ID666.length==0) {
  345. +        if (!ci->should_loop() && ID666.length==0) {
  346.              ID666.length=3*60*1000; /* 3 minutes */
  347.              ID666.fade=5*1000; /* 5 seconds */
  348.          }
  349. diff --git a/apps/codecs/wav.c b/apps/codecs/wav.c
  350. index f6f83b1..d43961a 100644
  351. --- a/apps/codecs/wav.c
  352. +++ b/apps/codecs/wav.c
  353. @@ -28,12 +28,12 @@ CODEC_HEADER
  354.  /* WAVE (RIFF) codec:
  355.   *
  356.   *  For a good documentation on WAVE files, see:
  357. - *  http://www.tsp.ece.mcgill.ca/MMSP/Documents/AudioFormats/WAVE/WAVE.html
  358. + *  http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/WAVE/WAVE.html
  359.   *  and
  360.   *  http://www.sonicspot.com/guide/wavefiles.html
  361.   *
  362.   *  For sample WAV files, see:
  363. - *  http://www.tsp.ece.mcgill.ca/MMSP/Documents/AudioFormats/WAVE/Samples.html
  364. + *  http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/WAVE/Samples.html
  365.   *
  366.   */
  367.  
  368. diff --git a/apps/main.c b/apps/main.c
  369. index 0b566b5..26c5bfa 100644
  370. --- a/apps/main.c
  371. +++ b/apps/main.c
  372. @@ -407,7 +407,8 @@ static void init(void)
  373.  
  374.      scrobbler_init();
  375.  #if CONFIG_CODEC == SWCODEC && defined (HAVE_PITCHSCREEN)
  376. -    tdspeed_init();
  377. +    if (global_settings.timestretch_enabled)
  378. +        tdspeed_init();
  379.  #endif /* CONFIG_CODEC == SWCODEC */
  380.  
  381.      audio_init();
  382. @@ -670,7 +671,8 @@ static void init(void)
  383.      filetype_init();
  384.      scrobbler_init();
  385.  #if CONFIG_CODEC == SWCODEC && defined (HAVE_PITCHSCREEN)
  386. -    tdspeed_init();
  387. +    if (global_settings.timestretch_enabled)
  388. +        tdspeed_init();
  389.  #endif /* CONFIG_CODEC == SWCODEC */
  390.      theme_init_buffer();
  391.  
  392. diff --git a/apps/metadata.c b/apps/metadata.c
  393. index cbb5b42..4649324 100644
  394. --- a/apps/metadata.c
  395. +++ b/apps/metadata.c
  396. @@ -20,12 +20,10 @@
  397.   ****************************************************************************/
  398.  #include <stdio.h>
  399.  #include <stdlib.h>
  400. -#include <ctype.h>
  401.  #include "string-extra.h"
  402.  
  403.  #include "debug.h"
  404.  #include "logf.h"
  405. -#include "settings.h"
  406.  #include "cuesheet.h"
  407.  #include "metadata.h"
  408.  
  409. @@ -552,9 +550,9 @@ void fill_metadata_from_path(struct mp3entry *id3, const char *trackname)
  410.  
  411.  enum { AUTORESUMABLE_UNKNOWN = 0, AUTORESUMABLE_TRUE, AUTORESUMABLE_FALSE };
  412.  
  413. -bool autoresumable(struct mp3entry *id3)
  414. +bool autoresumable(struct mp3entry *id3, const char *autoresume_paths)
  415.  {
  416. -    char *endp, *path;
  417. +    const char *endp, *path;
  418.      size_t len;
  419.      bool is_resumable;
  420.  
  421. @@ -565,7 +563,7 @@ bool autoresumable(struct mp3entry *id3)
  422.  
  423.      if (id3->path)
  424.      {
  425. -        for (path = global_settings.autoresume_paths;
  426. +        for (path = autoresume_paths;
  427.               *path;                     /* search terms left? */
  428.               path++)
  429.          {
  430. diff --git a/apps/metadata.h b/apps/metadata.h
  431. index a191e43..e5cbf37 100644
  432. --- a/apps/metadata.h
  433. +++ b/apps/metadata.h
  434. @@ -324,7 +324,7 @@ bool format_buffers_with_offset(int afmt);
  435.  #endif
  436.  
  437.  #ifdef HAVE_TAGCACHE
  438. -bool autoresumable(struct mp3entry *id3);
  439. +bool autoresumable(struct mp3entry *id3, const char *autoresume_paths);
  440.  #endif
  441.  
  442.  #endif
  443. diff --git a/apps/metadata/adx.c b/apps/metadata/adx.c
  444. index 4e18254..e427f66 100644
  445. --- a/apps/metadata/adx.c
  446. +++ b/apps/metadata/adx.c
  447. @@ -21,7 +21,6 @@
  448.  #include <stdio.h>
  449.  #include <string.h>
  450.  #include <stdlib.h>
  451. -#include <ctype.h>
  452.  #include <inttypes.h>
  453.  
  454.  #include "system.h"
  455. diff --git a/apps/metadata/aiff.c b/apps/metadata/aiff.c
  456. index 654f37c..52582d7 100644
  457. --- a/apps/metadata/aiff.c
  458. +++ b/apps/metadata/aiff.c
  459. @@ -21,7 +21,6 @@
  460.  #include <stdio.h>
  461.  #include <string.h>
  462.  #include <stdlib.h>
  463. -#include <ctype.h>
  464.  #include <inttypes.h>
  465.  
  466.  #include "system.h"
  467. diff --git a/apps/metadata/ape.c b/apps/metadata/ape.c
  468. index 44fc69a..4ddb9b0 100644
  469. --- a/apps/metadata/ape.c
  470. +++ b/apps/metadata/ape.c
  471. @@ -21,7 +21,6 @@
  472.  #include <stdio.h>
  473.  #include <string.h>
  474.  #include <stdlib.h>
  475. -#include <ctype.h>
  476.  #include <inttypes.h>
  477.  
  478.  #include "system.h"
  479. diff --git a/apps/metadata/asap.c b/apps/metadata/asap.c
  480. index 9e7f227..27c848b 100644
  481. --- a/apps/metadata/asap.c
  482. +++ b/apps/metadata/asap.c
  483. @@ -21,7 +21,6 @@
  484.  #include <stdio.h>
  485.  #include <string.h>
  486.  #include <stdlib.h>
  487. -#include <ctype.h>
  488.  #include <inttypes.h>
  489.  
  490.  #include "system.h"
  491. diff --git a/apps/metadata/asf.c b/apps/metadata/asf.c
  492. index 56d5c87..a758852 100644
  493. --- a/apps/metadata/asf.c
  494. +++ b/apps/metadata/asf.c
  495. @@ -22,7 +22,6 @@
  496.  #include <stdio.h>
  497.  #include <string.h>
  498.  #include <stdlib.h>
  499. -#include <ctype.h>
  500.  #include <inttypes.h>
  501.  
  502.  #include "metadata.h"
  503. diff --git a/apps/metadata/flac.c b/apps/metadata/flac.c
  504. index 2993717..33a6bf3 100644
  505. --- a/apps/metadata/flac.c
  506. +++ b/apps/metadata/flac.c
  507. @@ -21,7 +21,6 @@
  508.  #include <stdio.h>
  509.  #include <string.h>
  510.  #include <stdlib.h>
  511. -#include <ctype.h>
  512.  #include <inttypes.h>
  513.  
  514.  #include "system.h"
  515. diff --git a/apps/metadata/metadata_common.c b/apps/metadata/metadata_common.c
  516. index e620514..f3602d7 100644
  517. --- a/apps/metadata/metadata_common.c
  518. +++ b/apps/metadata/metadata_common.c
  519. @@ -29,7 +29,6 @@
  520.  #include "metadata_common.h"
  521.  #include "metadata_parsers.h"
  522.  #include "replaygain.h"
  523. -#include "misc.h"
  524.  
  525.  /* Read a string from the file. Read up to size bytes, or, if eos != -1,
  526.   * until the eos character is found (eos is not stored in buf, unless it is
  527. @@ -194,7 +193,10 @@ uint32_t get_itunes_int32(char* value, int count)
  528.      
  529.      while (count-- > 0)
  530.      {
  531. -        value = skip_whitespace(value);
  532. +        while (isspace(*value))
  533. +        {
  534. +            value++;
  535. +        }
  536.          
  537.          while (*value && !isspace(*value))
  538.          {
  539. @@ -202,7 +204,10 @@ uint32_t get_itunes_int32(char* value, int count)
  540.          }
  541.      }
  542.      
  543. -    value = skip_whitespace(value);
  544. +    while (isspace(*value))
  545. +    {
  546. +        value++;
  547. +    }
  548.      
  549.      while (*value && ((c = strchr(hexdigits, toupper(*value))) != NULL))
  550.      {
  551. diff --git a/apps/metadata/monkeys.c b/apps/metadata/monkeys.c
  552. index 4aff141..c049d26 100644
  553. --- a/apps/metadata/monkeys.c
  554. +++ b/apps/metadata/monkeys.c
  555. @@ -21,7 +21,6 @@
  556.  #include <stdio.h>
  557.  #include <string.h>
  558.  #include <stdlib.h>
  559. -#include <ctype.h>
  560.  #include <inttypes.h>
  561.  
  562.  #include "system.h"
  563. diff --git a/apps/metadata/mp4.c b/apps/metadata/mp4.c
  564. index 4feb56c..025ffd1 100644
  565. --- a/apps/metadata/mp4.c
  566. +++ b/apps/metadata/mp4.c
  567. @@ -21,7 +21,6 @@
  568.  #include <stdio.h>
  569.  #include <string.h>
  570.  #include <stdlib.h>
  571. -#include <ctype.h>
  572.  #include <inttypes.h>
  573.  
  574.  #include "system.h"
  575. diff --git a/apps/metadata/nsf.c b/apps/metadata/nsf.c
  576. index 29fd847..b9c8266 100644
  577. --- a/apps/metadata/nsf.c
  578. +++ b/apps/metadata/nsf.c
  579. @@ -1,7 +1,6 @@
  580.  #include <stdio.h>
  581.  #include <string.h>
  582.  #include <stdlib.h>
  583. -#include <ctype.h>
  584.  #include <inttypes.h>
  585.  
  586.  #include "system.h"
  587. diff --git a/apps/metadata/ogg.c b/apps/metadata/ogg.c
  588. index 3a3cb29..2657fe4 100644
  589. --- a/apps/metadata/ogg.c
  590. +++ b/apps/metadata/ogg.c
  591. @@ -21,7 +21,6 @@
  592.  #include <stdio.h>
  593.  #include <string.h>
  594.  #include <stdlib.h>
  595. -#include <ctype.h>
  596.  #include <inttypes.h>
  597.  
  598.  #include "system.h"
  599. diff --git a/apps/metadata/rm.c b/apps/metadata/rm.c
  600. index 27f541c..7ffd1aa 100644
  601. --- a/apps/metadata/rm.c
  602. +++ b/apps/metadata/rm.c
  603. @@ -21,7 +21,6 @@
  604.  #include <stdio.h>
  605.  #include <string.h>
  606.  #include <stdlib.h>
  607. -#include <ctype.h>
  608.  #include <inttypes.h>
  609.  
  610.  #include <codecs/librm/rm.h>
  611. diff --git a/apps/metadata/sid.c b/apps/metadata/sid.c
  612. index 50b879b..51ba380 100644
  613. --- a/apps/metadata/sid.c
  614. +++ b/apps/metadata/sid.c
  615. @@ -21,7 +21,6 @@
  616.  #include <stdio.h>
  617.  #include <string.h>
  618.  #include <stdlib.h>
  619. -#include <ctype.h>
  620.  #include <inttypes.h>
  621.  
  622.  #include "system.h"
  623. diff --git a/apps/metadata/spc.c b/apps/metadata/spc.c
  624. index 1c02062..50ea751 100644
  625. --- a/apps/metadata/spc.c
  626. +++ b/apps/metadata/spc.c
  627. @@ -21,7 +21,6 @@
  628.  #include <stdio.h>
  629.  #include <string.h>
  630.  #include <stdlib.h>
  631. -#include <ctype.h>
  632.  #include <inttypes.h>
  633.  
  634.  #include "system.h"
  635. diff --git a/apps/metadata/tta.c b/apps/metadata/tta.c
  636. index 1d3d95f..8ef3754 100644
  637. --- a/apps/metadata/tta.c
  638. +++ b/apps/metadata/tta.c
  639. @@ -21,7 +21,6 @@
  640.  #include <stdio.h>
  641.  #include <string.h>
  642.  #include <stdlib.h>
  643. -#include <ctype.h>
  644.  #include <inttypes.h>
  645.  
  646.  #include "system.h"
  647. diff --git a/apps/metadata/vorbis.c b/apps/metadata/vorbis.c
  648. index f6d3af1..60b1523 100644
  649. --- a/apps/metadata/vorbis.c
  650. +++ b/apps/metadata/vorbis.c
  651. @@ -21,14 +21,12 @@
  652.  #include <stdio.h>
  653.  #include <string.h>
  654.  #include <stdlib.h>
  655. -#include <ctype.h>
  656.  #include <inttypes.h>
  657.  
  658.  #include "system.h"
  659.  #include "metadata.h"
  660.  #include "metadata_common.h"
  661.  #include "metadata_parsers.h"
  662. -#include "structec.h"
  663.  
  664.  /* Define LOGF_ENABLE to enable logf output in this file */
  665.  /*#define LOGF_ENABLE*/
  666. diff --git a/apps/metadata/vox.c b/apps/metadata/vox.c
  667. index f6bc849..64ccfea 100644
  668. --- a/apps/metadata/vox.c
  669. +++ b/apps/metadata/vox.c
  670. @@ -21,7 +21,6 @@
  671.  #include <stdio.h>
  672.  #include <string.h>
  673.  #include <stdlib.h>
  674. -#include <ctype.h>
  675.  #include <inttypes.h>
  676.  
  677.  #include "system.h"
  678. diff --git a/apps/metadata/wavpack.c b/apps/metadata/wavpack.c
  679. index f2811df..bfb92b7 100644
  680. --- a/apps/metadata/wavpack.c
  681. +++ b/apps/metadata/wavpack.c
  682. @@ -21,7 +21,6 @@
  683.  #include <stdio.h>
  684.  #include <string.h>
  685.  #include <stdlib.h>
  686. -#include <ctype.h>
  687.  #include <inttypes.h>
  688.  
  689.  #include "system.h"
  690. diff --git a/apps/playback.c b/apps/playback.c
  691. index 2775e8a..29f3db8 100644
  692. --- a/apps/playback.c
  693. +++ b/apps/playback.c
  694. @@ -1291,7 +1291,8 @@ static bool audio_start_codec(bool auto_skip)
  695.                  break;
  696.              default:
  697.                  /* Not "never resume" - pass resume filter? */
  698. -                resume = autoresumable(cur_id3);
  699. +                resume = autoresumable(cur_id3,
  700. +                                       global_settings.autoresume_paths);
  701.              }
  702.          }
  703.  
  704. diff --git a/apps/plugins/test_codec.c b/apps/plugins/test_codec.c
  705. index 5c98201..9309f22 100644
  706. --- a/apps/plugins/test_codec.c
  707. +++ b/apps/plugins/test_codec.c
  708. @@ -509,6 +509,12 @@ static enum codec_command_action get_command(intptr_t *param)
  709.      (void)param;
  710.  }
  711.  
  712. +/* Some codecs call this to determine whether they should loop. */
  713. +static bool should_loop(void)
  714. +{
  715. +    return false;
  716. +}
  717. +
  718.  static void set_offset(size_t value)
  719.  {
  720.      ci.id3->offset = value;
  721. @@ -565,6 +571,7 @@ static void init_ci(void)
  722.      ci.set_offset = set_offset;
  723.      ci.configure = configure;
  724.      ci.get_command = get_command;
  725. +    ci.should_loop = should_loop;
  726.  
  727.      /* --- "Core" functions --- */
  728.  
  729. @@ -582,7 +589,6 @@ static void init_ci(void)
  730.      ci.memmove = rb->memmove;
  731.      ci.memcmp = rb->memcmp;
  732.      ci.memchr = rb->memchr;
  733. -    ci.strcasestr = rb->strcasestr;
  734.  #if defined(DEBUG) || defined(SIMULATOR)
  735.      ci.debugf = rb->debugf;
  736.  #endif
  737. @@ -591,7 +597,6 @@ static void init_ci(void)
  738.  #endif
  739.  
  740.      ci.qsort = rb->qsort;
  741. -    ci.global_settings = rb->global_settings;
  742.  
  743.  #ifdef RB_PROFILE
  744.      ci.profile_thread = rb->profile_thread;
  745. diff --git a/apps/screen_access.c b/apps/screen_access.c
  746. index b83e842..1b466ea 100644
  747. --- a/apps/screen_access.c
  748. +++ b/apps/screen_access.c
  749. @@ -33,6 +33,7 @@
  750.  #include "backlight.h"
  751.  #include "screen_access.h"
  752.  #include "backdrop.h"
  753. +#include "statusbar.h"
  754.  
  755.  /* some helper functions to calculate metrics on the fly */
  756.  static int screen_helper_getcharwidth(void)
  757. diff --git a/apps/settings.h b/apps/settings.h
  758. index 05965b3..9678bef 100644
  759. --- a/apps/settings.h
  760. +++ b/apps/settings.h
  761. @@ -27,8 +27,9 @@
  762.  #include "inttypes.h"
  763.  #include "config.h"
  764.  #include "audiohw.h" /* for the AUDIOHW_* defines */
  765. -#include "statusbar.h" /* for the statusbar values */
  766. +#ifdef HAVE_QUICKSCREEN
  767.  #include "quickscreen.h"
  768. +#endif
  769.  #include "button.h"
  770.  #if CONFIG_CODEC == SWCODEC
  771.  #include "audio.h"
  772. diff --git a/apps/tdspeed.c b/apps/tdspeed.c
  773. index 61f47f9..04f1210 100644
  774. --- a/apps/tdspeed.c
  775. +++ b/apps/tdspeed.c
  776. @@ -28,7 +28,6 @@
  777.  #include "buffer.h"
  778.  #include "system.h"
  779.  #include "tdspeed.h"
  780. -#include "settings.h"
  781.  
  782.  #define assert(cond)
  783.  
  784. @@ -57,18 +56,15 @@ static int32_t *outbuf[2] = { NULL, NULL };
  785.  
  786.  void tdspeed_init()
  787.  {
  788. -    if (global_settings.timestretch_enabled)
  789. -    {
  790. -        /* Allocate buffers */
  791. -        if (overlap_buffer[0] == NULL)
  792. -            overlap_buffer[0] = (int32_t *) buffer_alloc(FIXED_BUFSIZE * sizeof(int32_t));
  793. -        if (overlap_buffer[1] == NULL)
  794. -            overlap_buffer[1] = (int32_t *) buffer_alloc(FIXED_BUFSIZE * sizeof(int32_t));
  795. -        if (outbuf[0] == NULL)
  796. -            outbuf[0] = (int32_t *) buffer_alloc(TDSPEED_OUTBUFSIZE * sizeof(int32_t));
  797. -        if (outbuf[1] == NULL)
  798. -            outbuf[1] = (int32_t *) buffer_alloc(TDSPEED_OUTBUFSIZE * sizeof(int32_t));
  799. -    }
  800. +    /* Allocate buffers */
  801. +    if (overlap_buffer[0] == NULL)
  802. +        overlap_buffer[0] = (int32_t *) buffer_alloc(FIXED_BUFSIZE * sizeof(int32_t));
  803. +    if (overlap_buffer[1] == NULL)
  804. +        overlap_buffer[1] = (int32_t *) buffer_alloc(FIXED_BUFSIZE * sizeof(int32_t));
  805. +    if (outbuf[0] == NULL)
  806. +        outbuf[0] = (int32_t *) buffer_alloc(TDSPEED_OUTBUFSIZE * sizeof(int32_t));
  807. +    if (outbuf[1] == NULL)
  808. +        outbuf[1] = (int32_t *) buffer_alloc(TDSPEED_OUTBUFSIZE * sizeof(int32_t));
  809.  }
  810.  
  811.  
  812. diff --git a/warble/Makefile b/warble/Makefile
  813. new file mode 100644
  814. index 0000000..472067d
  815. --- /dev/null
  816. +++ b/warble/Makefile
  817. @@ -0,0 +1,63 @@
  818. +default: all
  819. +
  820. +ROOTDIR = $(shell readlink -e ..)
  821. +BUILDDIR = $(shell pwd)/build
  822. +APPSDIR = $(ROOTDIR)/apps
  823. +TOOLSDIR = $(ROOTDIR)/tools
  824. +CODECDIR = $(BUILDDIR)/apps/codecs
  825. +DEPFILE = $(BUILDDIR)/make.dep
  826. +APP_TYPE = sdl-app
  827. +
  828. +INCLUDES = -I$(shell pwd)
  829. +INCLUDES += -I$(APPSDIR) -I$(APPSDIR)/codecs -I$(APPSDIR)/codecs/lib -I$(APPSDIR)/gui -I$(APPSDIR)/metadata -I$(APPSDIR)/recorder
  830. +INCLUDES += -I$(ROOTDIR)/firmware/export -I$(ROOTDIR)/firmware/include -I$(ROOTDIR)/firmware/target/hosted/sdl
  831. +
  832. +CFLAGS = -D__PCTOOL__ -DSIMULATOR=1 -D"IBSS_ATTR=" -DROCKBOX_LITTLE_ENDIAN=1 -D"ICODE_ATTR=" -D"ICONST_ATTR=" -DROCKBOX $(INCLUDES)
  833. +CFLAGS += -O0 -ggdb -DDEBUG -DDEBUGF=debugf -DLOGF_ENABLE
  834. +PPCFLAGS = $(CFLAGS)
  835. +
  836. +SHARED_CFLAGS = -fPIC -fvisibility=hidden
  837. +SHARED_LDFLAG = -shared
  838. +
  839. +WARBLE_OBJS = $(BUILDDIR)/warble.o
  840. +WARBLE_CFLAGS = '-DCODECDIR="$(CODECDIR)"' $(shell sdl-config --cflags)
  841. +WARBLE_LDFLAGS = -lm -ldl $(shell sdl-config --libs)
  842. +
  843. +include $(ROOTDIR)/tools/functions.make
  844. +include $(APPSDIR)/codecs/codecs.make
  845. +CODECFLAGS += -ffreestanding -nostdlib
  846. +
  847. +SRC = $(ROOTDIR)/apps/metadata.c $(ROOTDIR)/apps/replaygain.c $(ROOTDIR)/firmware/common/strlcpy.c $(ROOTDIR)/firmware/common/unicode.c $(ROOTDIR)/firmware/common/structec.c $(ROOTDIR)/apps/mp3data.c $(ROOTDIR)/apps/fixedpoint.c $(ROOTDIR)/uisimulator/common/io.c
  848. +SRC += $(ROOTDIR)/apps/dsp.c $(ROOTDIR)/apps/eq.c $(ROOTDIR)/apps/tdspeed.c
  849. +SRC += $(patsubst %,$(ROOTDIR)/apps/metadata/%.c,a52 adx aiff ape asap asf au flac id3tags metadata_common mod monkeys mp3 mp4 mpc nsf ogg oma rm sid smaf spc tta vorbis vox wave wavpack)
  850. +
  851. +OBJ := $(SRC:.c=.o)
  852. +OBJ := $(OBJ:.S=.o)
  853. +OBJ := $(subst $(ROOTDIR),$(BUILDDIR),$(OBJ))
  854. +
  855. +all: $(DEPFILE) warble $(CODECS)
  856. +
  857. +dep $(DEPFILE):
  858. +       $(SILENT)mkdir -p $(dir $(DEPFILE))
  859. +       $(call PRINTS,Generating dependencies)
  860. +       $(call mkdepfile,$(DEPFILE)_,$(SRC))
  861. +       $(call mkdepfile,$(DEPFILE)_,$(OTHER_SRC))
  862. +       $(call mkdepfile,$(DEPFILE)_,$(ASMDEFS_SRC))
  863. +       @mv $(DEPFILE)_ $(DEPFILE)
  864. +
  865. +-include $(DEPFILE)
  866. +
  867. +warble: $(WARBLE_OBJS) $(OBJ)
  868. +       $(call PRINTS,LD $@)$(CC) $(LDFLAGS) $^ -o $@ $(WARBLE_LDFLAGS)
  869. +
  870. +$(BUILDDIR)/%.o: %.c
  871. +       $(SILENT)mkdir -p $(dir $@)
  872. +       $(call PRINTS,CC $<)$(CC) $(CFLAGS) -c $< -o $@ $(WARBLE_CFLAGS)
  873. +
  874. +$(BUILDDIR)/%.o: $(ROOTDIR)/%.c
  875. +       $(SILENT)mkdir -p $(dir $@)
  876. +       $(call PRINTS,CC $<)$(CC) $(CFLAGS) -c $< -o $@
  877. +
  878. +clean:
  879. +       $(SILENT)echo Cleaning build directory
  880. +       $(SILENT)rm -rf warble $(BUILDDIR)/*
  881. diff --git a/warble/autoconf.h b/warble/autoconf.h
  882. new file mode 100644
  883. index 0000000..d79a720
  884. --- /dev/null
  885. +++ b/warble/autoconf.h
  886. @@ -0,0 +1,16 @@
  887. +#ifndef __BUILD_AUTOCONF_H
  888. +#define __BUILD_AUTOCONF_H
  889. +
  890. +#define CONFIG_CODEC SWCODEC
  891. +#define TARGET_ID 73 /* sdlapp */
  892. +#define MEMORYSIZE 64
  893. +#define ROCKBOX_LITTLE_ENDIAN 1
  894. +#define HAVE_PITCHSCREEN
  895. +#define HAVE_SW_TONE_CONTROLS
  896. +#define HAVE_SW_VOLUME_CONTROL
  897. +#define VOLUME_MIN -100
  898. +#define VOLUME_MAX 100
  899. +#define SW_VOLUME_MIN -100
  900. +#define SW_VOLUME_MAX 100
  901. +
  902. +#endif /* __BUILD_AUTOCONF_H */
  903. diff --git a/warble/warble.c b/warble/warble.c
  904. new file mode 100644
  905. index 0000000..08a8982
  906. --- /dev/null
  907. +++ b/warble/warble.c
  908. @@ -0,0 +1,824 @@
  909. +/***************************************************************************
  910. + *             __________               __   ___.
  911. + *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
  912. + *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
  913. + *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
  914. + *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
  915. + *                     \/            \/     \/    \/            \/
  916. + *
  917. + * Copyright (C) 2011 Sean Bartell
  918. + *
  919. + * This program is free software; you can redistribute it and/or
  920. + * modify it under the terms of the GNU General Public License
  921. + * as published by the Free Software Foundation; either version 2
  922. + * of the License, or (at your option) any later version.
  923. + *
  924. + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
  925. + * KIND, either express or implied.
  926. + *
  927. + ****************************************************************************/
  928. +
  929. +#define _BSD_SOURCE /* htole64 from endian.h */
  930. +#include <sys/types.h>
  931. +#include <SDL.h>
  932. +#include <dlfcn.h>
  933. +#include <endian.h>
  934. +#include <fcntl.h>
  935. +#include <math.h>
  936. +#include <stdarg.h>
  937. +#include <stdio.h>
  938. +#include <stdlib.h>
  939. +#include <string.h>
  940. +#include <sys/stat.h>
  941. +#include <unistd.h>
  942. +#include "buffering.h" /* TYPE_PACKET_AUDIO */
  943. +#include "codecs.h"
  944. +#include "debug.h"
  945. +#include "dsp.h"
  946. +#include "metadata.h"
  947. +#include "settings.h"
  948. +#include "sound.h"
  949. +
  950. +/***************** EXPORTED *****************/
  951. +
  952. +struct user_settings global_settings;
  953. +volatile long current_tick = 0;
  954. +
  955. +void yield()
  956. +{
  957. +}
  958. +
  959. +void *buffer_alloc(size_t size)
  960. +{
  961. +    return malloc(size);
  962. +}
  963. +
  964. +void mutex_init(struct mutex *m)
  965. +{
  966. +}
  967. +
  968. +void mutex_lock(struct mutex *m)
  969. +{
  970. +}
  971. +
  972. +void mutex_unlock(struct mutex *m)
  973. +{
  974. +}
  975. +
  976. +/***************** INTERNAL *****************/
  977. +
  978. +static enum { MODE_PLAY, MODE_WRITE } mode;
  979. +static bool use_dsp = true;
  980. +static bool enable_loop = false;
  981. +static bool verbose = false;
  982. +static const char *config = "";
  983. +
  984. +static int input_fd;
  985. +static enum codec_command_action codec_action;
  986. +static intptr_t codec_action_param = 0;
  987. +static unsigned long num_output_samples = 0;
  988. +static struct codec_api ci;
  989. +
  990. +static struct {
  991. +    intptr_t freq;
  992. +    intptr_t stereo_mode;
  993. +    intptr_t depth;
  994. +    int channels;
  995. +} format;
  996. +
  997. +/***** MODE_WRITE *****/
  998. +
  999. +#define WAVE_HEADER_SIZE 0x2e
  1000. +#define WAVE_FORMAT_PCM 1
  1001. +#define WAVE_FORMAT_IEEE_FLOAT 3
  1002. +static int output_fd;
  1003. +static bool write_raw = false;
  1004. +static bool write_header_written = false;
  1005. +
  1006. +static void write_init(const char *output_fn)
  1007. +{
  1008. +    mode = MODE_WRITE;
  1009. +    if (!strcmp(output_fn, "-")) {
  1010. +        output_fd = STDOUT_FILENO;
  1011. +    } else {
  1012. +        output_fd = creat(output_fn, 0666);
  1013. +        if (output_fd == -1) {
  1014. +            perror(output_fn);
  1015. +            exit(1);
  1016. +        }
  1017. +    }
  1018. +}
  1019. +
  1020. +static void set_le16(char *buf, uint16_t val)
  1021. +{
  1022. +    buf[0] = val;
  1023. +    buf[1] = val >> 8;
  1024. +}
  1025. +
  1026. +static void set_le32(char *buf, uint32_t val)
  1027. +{
  1028. +    buf[0] = val;
  1029. +    buf[1] = val >> 8;
  1030. +    buf[2] = val >> 16;
  1031. +    buf[3] = val >> 24;
  1032. +}
  1033. +
  1034. +static void write_wav_header()
  1035. +{
  1036. +    int channels, sample_size, freq, type;
  1037. +    if (use_dsp) {
  1038. +        channels = 2;
  1039. +        sample_size = 16;
  1040. +        freq = NATIVE_FREQUENCY;
  1041. +        type = WAVE_FORMAT_PCM;
  1042. +    } else {
  1043. +        channels = format.channels;
  1044. +        sample_size = 64;
  1045. +        freq = format.freq;
  1046. +        type = WAVE_FORMAT_IEEE_FLOAT;
  1047. +    }
  1048. +
  1049. +    /* The size fields are normally overwritten by write_quit(). If that fails,
  1050. +     * this fake size ensures the file can still be played. */
  1051. +    off_t total_size = 0x7fffff00 + WAVE_HEADER_SIZE;
  1052. +    char header[WAVE_HEADER_SIZE] = {"RIFF____WAVEfmt \x12\0\0\0"
  1053. +                                     "________________\0\0data____"};
  1054. +    set_le32(header + 0x04, total_size - 8);
  1055. +    set_le16(header + 0x14, type);
  1056. +    set_le16(header + 0x16, channels);
  1057. +    set_le32(header + 0x18, freq);
  1058. +    set_le32(header + 0x1c, freq * channels * sample_size / 8);
  1059. +    set_le16(header + 0x20, channels * sample_size / 8);
  1060. +    set_le16(header + 0x22, sample_size);
  1061. +    set_le32(header + 0x2a, total_size - WAVE_HEADER_SIZE);
  1062. +    write(output_fd, header, sizeof(header));
  1063. +    write_header_written = true;
  1064. +}
  1065. +
  1066. +static void write_quit()
  1067. +{
  1068. +    if (!write_raw) {
  1069. +        /* Write the correct size fields in the header. If lseek fails (e.g.
  1070. +         * for a pipe) nothing is written. */
  1071. +        off_t total_size = lseek(output_fd, 0, SEEK_CUR);
  1072. +        if (total_size != (off_t)-1) {
  1073. +            char buf[4];
  1074. +            set_le32(buf, total_size - 8);
  1075. +            lseek(output_fd, 4, SEEK_SET);
  1076. +            write(output_fd, buf, 4);
  1077. +            set_le32(buf, total_size - WAVE_HEADER_SIZE);
  1078. +            lseek(output_fd, 0x2a, SEEK_SET);
  1079. +            write(output_fd, buf, 4);
  1080. +        }
  1081. +    }
  1082. +    if (output_fd != STDOUT_FILENO)
  1083. +        close(output_fd);
  1084. +}
  1085. +
  1086. +static uint64_t make_float64(int32_t sample, int shift)
  1087. +{
  1088. +    /* TODO: be more portable */
  1089. +    double val = ldexp(sample, -shift);
  1090. +    return *(uint64_t*)&val;
  1091. +}
  1092. +
  1093. +static void write_pcm(int16_t *pcm, int count)
  1094. +{
  1095. +    if (!write_header_written)
  1096. +        write_wav_header();
  1097. +    int i;
  1098. +    for (i = 0; i < 2 * count; i++)
  1099. +        pcm[i] = htole16(pcm[i]);
  1100. +    write(output_fd, pcm, 4 * count);
  1101. +}
  1102. +
  1103. +static void write_pcm_raw(int32_t *pcm, int count)
  1104. +{
  1105. +    if (write_raw) {
  1106. +        write(output_fd, pcm, count * sizeof(*pcm));
  1107. +    } else {
  1108. +        if (!write_header_written)
  1109. +            write_wav_header();
  1110. +        int i;
  1111. +        uint64_t buf[count];
  1112. +
  1113. +        for (i = 0; i < count; i++)
  1114. +            buf[i] = htole64(make_float64(pcm[i], format.depth));
  1115. +        write(output_fd, buf, count * sizeof(*buf));
  1116. +    }
  1117. +}
  1118. +
  1119. +/***** MODE_PLAY *****/
  1120. +
  1121. +/* MODE_PLAY uses a double buffer: one half is read by the playback thread and
  1122. + * the other half is written to by the main thread. When a thread is done with
  1123. + * its current half, it waits for the other thread and then switches. The main
  1124. + * advantage of this method is its simplicity; the main disadvantage is that it
  1125. + * has long latency. ALSA buffer underruns still occur sometimes, but this is
  1126. + * SDL's fault. */
  1127. +
  1128. +#define PLAYBACK_BUFFER_SIZE 0x10000
  1129. +static bool playback_running = false;
  1130. +static char playback_buffer[2][PLAYBACK_BUFFER_SIZE];
  1131. +static int playback_play_ind, playback_decode_ind;
  1132. +static int playback_play_pos, playback_decode_pos;
  1133. +static SDL_sem *playback_play_sema, *playback_decode_sema;
  1134. +
  1135. +static void playback_init()
  1136. +{
  1137. +    mode = MODE_PLAY;
  1138. +    if (SDL_Init(SDL_INIT_AUDIO)) {
  1139. +        fprintf(stderr, "error: Can't initialize SDL: %s\n", SDL_GetError());
  1140. +        exit(1);
  1141. +    }
  1142. +    playback_play_ind = 1;
  1143. +    playback_play_pos = PLAYBACK_BUFFER_SIZE;
  1144. +    playback_decode_ind = 0;
  1145. +    playback_decode_pos = 0;
  1146. +    playback_play_sema = SDL_CreateSemaphore(0);
  1147. +    playback_decode_sema = SDL_CreateSemaphore(0);
  1148. +}
  1149. +
  1150. +static void playback_callback(void *userdata, Uint8 *stream, int len)
  1151. +{
  1152. +    while (len > 0) {
  1153. +        if (!playback_running && playback_play_ind == playback_decode_ind
  1154. +                && playback_play_pos >= playback_decode_pos) {
  1155. +            /* end of data */
  1156. +            memset(stream, 0, len);
  1157. +            SDL_SemPost(playback_play_sema);
  1158. +            return;
  1159. +        }
  1160. +        if (playback_play_pos >= PLAYBACK_BUFFER_SIZE) {
  1161. +            SDL_SemPost(playback_play_sema);
  1162. +            SDL_SemWait(playback_decode_sema);
  1163. +            playback_play_ind = !playback_play_ind;
  1164. +            playback_play_pos = 0;
  1165. +        }
  1166. +        char *play_buffer = playback_buffer[playback_play_ind];
  1167. +        int copy_len = MIN(len, PLAYBACK_BUFFER_SIZE - playback_play_pos);
  1168. +        memcpy(stream, play_buffer + playback_play_pos, copy_len);
  1169. +        len -= copy_len;
  1170. +        stream += copy_len;
  1171. +        playback_play_pos += copy_len;
  1172. +    }
  1173. +}
  1174. +
  1175. +static void playback_start()
  1176. +{
  1177. +    playback_running = true;
  1178. +    SDL_AudioSpec spec = {0};
  1179. +    spec.freq = NATIVE_FREQUENCY;
  1180. +    spec.format = AUDIO_S16SYS;
  1181. +    spec.channels = 2;
  1182. +    spec.samples = 0x400;
  1183. +    spec.callback = playback_callback;
  1184. +    spec.userdata = NULL;
  1185. +    if (SDL_OpenAudio(&spec, NULL)) {
  1186. +        fprintf(stderr, "error: Can't open SDL audio: %s\n", SDL_GetError());
  1187. +        exit(1);
  1188. +    }
  1189. +    SDL_PauseAudio(0);
  1190. +}
  1191. +
  1192. +static void playback_quit()
  1193. +{
  1194. +    if (!playback_running)
  1195. +        playback_start();
  1196. +    memset(playback_buffer[playback_decode_ind] + playback_decode_pos, 0,
  1197. +           PLAYBACK_BUFFER_SIZE - playback_decode_pos);
  1198. +    playback_running = false;
  1199. +    SDL_SemPost(playback_decode_sema);
  1200. +    SDL_SemWait(playback_play_sema);
  1201. +    SDL_SemWait(playback_play_sema);
  1202. +    SDL_Quit();
  1203. +}
  1204. +
  1205. +static void playback_pcm(int16_t *pcm, int count)
  1206. +{
  1207. +    const char *stream = (const char *)pcm;
  1208. +    count *= 4;
  1209. +
  1210. +    while (count > 0) {
  1211. +        if (playback_decode_pos >= PLAYBACK_BUFFER_SIZE) {
  1212. +            if (!playback_running)
  1213. +                playback_start();
  1214. +            SDL_SemPost(playback_decode_sema);
  1215. +            SDL_SemWait(playback_play_sema);
  1216. +            playback_decode_ind = !playback_decode_ind;
  1217. +            playback_decode_pos = 0;
  1218. +        }
  1219. +        char *decode_buffer = playback_buffer[playback_decode_ind];
  1220. +        int copy_len = MIN(count, PLAYBACK_BUFFER_SIZE - playback_decode_pos);
  1221. +        memcpy(decode_buffer + playback_decode_pos, stream, copy_len);
  1222. +        stream += copy_len;
  1223. +        count -= copy_len;
  1224. +        playback_decode_pos += copy_len;
  1225. +    }
  1226. +}
  1227. +
  1228. +/***** ALL MODES *****/
  1229. +
  1230. +static void perform_config()
  1231. +{
  1232. +    while (config) {
  1233. +        const char *name = config;
  1234. +        const char *eq = strchr(config, '=');
  1235. +        if (!eq)
  1236. +            break;
  1237. +        const char *val = eq + 1;
  1238. +        const char *end = val + strcspn(val, ": \t\n");
  1239. +
  1240. +        if (!strncmp(name, "wait=", 5)) {
  1241. +            if (atoi(val) > num_output_samples)
  1242. +                return;
  1243. +        } else if (!strncmp(name, "dither=", 7)) {
  1244. +            dsp_dither_enable(atoi(val) ? true : false);
  1245. +        } else if (!strncmp(name, "halt=", 5)) {
  1246. +            if (atoi(val))
  1247. +                codec_action = CODEC_ACTION_HALT;
  1248. +        } else if (!strncmp(name, "loop=", 5)) {
  1249. +            enable_loop = atoi(val) != 0;
  1250. +        } else if (!strncmp(name, "offset=", 7)) {
  1251. +            ci.id3->offset = atoi(val);
  1252. +        } else if (!strncmp(name, "rate=", 5)) {
  1253. +            sound_set_pitch(atof(val) * PITCH_SPEED_100);
  1254. +        } else if (!strncmp(name, "seek=", 5)) {
  1255. +            codec_action = CODEC_ACTION_SEEK_TIME;
  1256. +            codec_action_param = atoi(val);
  1257. +        } else if (!strncmp(name, "tempo=", 6)) {
  1258. +            dsp_set_timestretch(atof(val) * PITCH_SPEED_100);
  1259. +        } else if (!strncmp(name, "vol=", 4)) {
  1260. +            global_settings.volume = atoi(val);
  1261. +            dsp_callback(DSP_CALLBACK_SET_SW_VOLUME, 0);
  1262. +        } else {
  1263. +            fprintf(stderr, "error: unrecognized config \"%.*s\"\n", eq - name, name);
  1264. +            exit(1);
  1265. +        }
  1266. +
  1267. +        if (*end)
  1268. +            config = end + 1;
  1269. +        else
  1270. +            config = NULL;
  1271. +    }
  1272. +}
  1273. +
  1274. +static void *ci_codec_get_buffer(size_t *size)
  1275. +{
  1276. +    static char buffer[64 * 1024 * 1024];
  1277. +    char *ptr = buffer;
  1278. +    *size = sizeof(buffer);
  1279. +    ALIGN_BUFFER(ptr, *size, CACHEALIGN_SIZE);
  1280. +    return ptr;
  1281. +}
  1282. +
  1283. +static void ci_pcmbuf_insert(const void *ch1, const void *ch2, int count)
  1284. +{
  1285. +    num_output_samples += count;
  1286. +
  1287. +    if (use_dsp) {
  1288. +        const char *src[2] = {ch1, ch2};
  1289. +        while (count > 0) {
  1290. +            int out_count = dsp_output_count(ci.dsp, count);
  1291. +            int in_count = MIN(dsp_input_count(ci.dsp, out_count), count);
  1292. +            int16_t buf[2 * out_count];
  1293. +            out_count = dsp_process(ci.dsp, (char *)buf, src, in_count);
  1294. +            if (mode == MODE_WRITE)
  1295. +                write_pcm(buf, out_count);
  1296. +            else if (mode == MODE_PLAY)
  1297. +                playback_pcm(buf, out_count);
  1298. +            count -= in_count;
  1299. +        }
  1300. +    } else {
  1301. +        /* Convert to 32-bit interleaved. */
  1302. +        count *= format.channels;
  1303. +        int i;
  1304. +        int32_t buf[count];
  1305. +        if (format.depth > 16) {
  1306. +            if (format.stereo_mode == STEREO_NONINTERLEAVED) {
  1307. +                for (i = 0; i < count; i += 2) {
  1308. +                    buf[i+0] = ((int32_t*)ch1)[i/2];
  1309. +                    buf[i+1] = ((int32_t*)ch2)[i/2];
  1310. +                }
  1311. +            } else {
  1312. +                memcpy(buf, ch1, sizeof(buf));
  1313. +            }
  1314. +        } else {
  1315. +            if (format.stereo_mode == STEREO_NONINTERLEAVED) {
  1316. +                for (i = 0; i < count; i += 2) {
  1317. +                    buf[i+0] = ((int16_t*)ch1)[i/2];
  1318. +                    buf[i+1] = ((int16_t*)ch2)[i/2];
  1319. +                }
  1320. +            } else {
  1321. +                for (i = 0; i < count; i++) {
  1322. +                    buf[i] = ((int16_t*)ch1)[i];
  1323. +                }
  1324. +            }
  1325. +        }
  1326. +
  1327. +        if (mode == MODE_WRITE)
  1328. +            write_pcm_raw(buf, count);
  1329. +    }
  1330. +
  1331. +    perform_config();
  1332. +}
  1333. +
  1334. +static void ci_set_elapsed(unsigned long value)
  1335. +{
  1336. +    //debugf("Time elapsed: %lu\n", value);
  1337. +}
  1338. +
  1339. +static char *input_buffer = 0;
  1340. +
  1341. +/*
  1342. + * Read part of the input file into a provided buffer.
  1343. + *
  1344. + * The entire size requested will be provided except at the end of the file.
  1345. + * The current file position will be moved, just like with advance_buffer, but
  1346. + * the offset is not updated. This invalidates buffers returned by
  1347. + * request_buffer.
  1348. + */
  1349. +static size_t ci_read_filebuf(void *ptr, size_t size)
  1350. +{
  1351. +    free(input_buffer);
  1352. +    input_buffer = NULL;
  1353. +
  1354. +    ssize_t actual = read(input_fd, ptr, size);
  1355. +    if (actual < 0)
  1356. +        actual = 0;
  1357. +    ci.curpos += actual;
  1358. +    return actual;
  1359. +}
  1360. +
  1361. +/*
  1362. + * Request a buffer containing part of the input file.
  1363. + *
  1364. + * The size provided will be the requested size, or the remaining size of the
  1365. + * file, whichever is smaller. Packet audio has an additional maximum of 32
  1366. + * KiB. The returned buffer remains valid until the next time read_filebuf,
  1367. + * request_buffer, advance_buffer, or seek_buffer is called.
  1368. + */
  1369. +static void *ci_request_buffer(size_t *realsize, size_t reqsize)
  1370. +{
  1371. +    free(input_buffer);
  1372. +    if (get_audio_base_data_type(ci.id3->codectype) == TYPE_PACKET_AUDIO)
  1373. +        reqsize = MIN(reqsize, 32 * 1024);
  1374. +    input_buffer = malloc(reqsize);
  1375. +    *realsize = read(input_fd, input_buffer, reqsize);
  1376. +    if (*realsize < 0)
  1377. +        *realsize = 0;
  1378. +    lseek(input_fd, -*realsize, SEEK_CUR);
  1379. +    return input_buffer;
  1380. +}
  1381. +
  1382. +/*
  1383. + * Advance the current position in the input file.
  1384. + *
  1385. + * This automatically updates the current offset. This invalidates buffers
  1386. + * returned by request_buffer.
  1387. + */
  1388. +static void ci_advance_buffer(size_t amount)
  1389. +{
  1390. +    free(input_buffer);
  1391. +    input_buffer = NULL;
  1392. +
  1393. +    lseek(input_fd, amount, SEEK_CUR);
  1394. +    ci.curpos += amount;
  1395. +    ci.id3->offset = ci.curpos;
  1396. +}
  1397. +
  1398. +/*
  1399. + * Seek to a position in the input file.
  1400. + *
  1401. + * This invalidates buffers returned by request_buffer.
  1402. + */
  1403. +static bool ci_seek_buffer(size_t newpos)
  1404. +{
  1405. +    free(input_buffer);
  1406. +    input_buffer = NULL;
  1407. +
  1408. +    off_t actual = lseek(input_fd, newpos, SEEK_SET);
  1409. +    if (actual >= 0)
  1410. +        ci.curpos = actual;
  1411. +    return actual != -1;
  1412. +}
  1413. +
  1414. +static void ci_seek_complete()
  1415. +{
  1416. +}
  1417. +
  1418. +static void ci_set_offset(size_t value)
  1419. +{
  1420. +    ci.id3->offset = value;
  1421. +}
  1422. +
  1423. +static void ci_configure(int setting, intptr_t value)
  1424. +{
  1425. +    if (use_dsp) {
  1426. +        dsp_configure(ci.dsp, setting, value);
  1427. +    } else {
  1428. +        if (setting == DSP_SET_FREQUENCY
  1429. +                || setting == DSP_SWITCH_FREQUENCY)
  1430. +            format.freq = value;
  1431. +        else if (setting == DSP_SET_SAMPLE_DEPTH)
  1432. +            format.depth = value;
  1433. +        else if (setting == DSP_SET_STEREO_MODE) {
  1434. +            format.stereo_mode = value;
  1435. +            format.channels = (value == STEREO_MONO) ? 1 : 2;
  1436. +        }
  1437. +    }
  1438. +}
  1439. +
  1440. +static enum codec_command_action ci_get_command(intptr_t *param)
  1441. +{
  1442. +    enum codec_command_action ret = codec_action;
  1443. +    *param = codec_action_param;
  1444. +    codec_action = CODEC_ACTION_NULL;
  1445. +    return ret;
  1446. +}
  1447. +
  1448. +static bool ci_should_loop()
  1449. +{
  1450. +    return enable_loop;
  1451. +}
  1452. +
  1453. +static unsigned ci_sleep(unsigned ticks)
  1454. +{
  1455. +    return 0;
  1456. +}
  1457. +
  1458. +static void ci_cpucache_flush()
  1459. +{
  1460. +}
  1461. +
  1462. +static void ci_cpucache_invalidate()
  1463. +{
  1464. +}
  1465. +
  1466. +static struct codec_api ci = {
  1467. +
  1468. +    0,                   /* filesize */
  1469. +    0,                   /* curpos */
  1470. +    NULL,                /* id3 */
  1471. +    -1,                  /* audio_hid */
  1472. +    NULL,                /* struct dsp_config *dsp */
  1473. +    ci_codec_get_buffer, /* codec_get_buffer */
  1474. +    ci_pcmbuf_insert,    /* pcmbuf_insert */
  1475. +    ci_set_elapsed,      /* set_elapsed */
  1476. +    ci_read_filebuf,     /* read_filebuf */
  1477. +    ci_request_buffer,   /* request_buffer */
  1478. +    ci_advance_buffer,   /* advance_buffer */
  1479. +    ci_seek_buffer,      /* seek_buffer */
  1480. +    ci_seek_complete,    /* seek_complete */
  1481. +    ci_set_offset,       /* set_offset */
  1482. +    ci_configure,        /* configure */
  1483. +    ci_get_command,      /* get_command */
  1484. +    ci_should_loop,      /* should_loop */
  1485. +    
  1486. +    ci_sleep,
  1487. +    yield,
  1488. +
  1489. +#if NUM_CORES > 1
  1490. +    ci_create_thread,
  1491. +    ci_thread_thaw,
  1492. +    ci_thread_wait,
  1493. +    ci_semaphore_init,
  1494. +    ci_semaphore_wait,
  1495. +    ci_semaphore_release,
  1496. +#endif
  1497. +
  1498. +    ci_cpucache_flush,
  1499. +    ci_cpucache_invalidate,
  1500. +
  1501. +    /* strings and memory */
  1502. +    strcpy,
  1503. +    strlen,
  1504. +    strcmp,
  1505. +    strcat,
  1506. +    memset,
  1507. +    memcpy,
  1508. +    memmove,
  1509. +    memcmp,
  1510. +    memchr,
  1511. +#if defined(DEBUG) || defined(SIMULATOR)
  1512. +    debugf,
  1513. +#endif
  1514. +#ifdef ROCKBOX_HAS_LOGF
  1515. +    debugf, /* logf */
  1516. +#endif
  1517. +
  1518. +    qsort,
  1519. +
  1520. +#ifdef HAVE_RECORDING
  1521. +    ci_enc_get_inputs,
  1522. +    ci_enc_set_parameters,
  1523. +    ci_enc_get_chunk,
  1524. +    ci_enc_finish_chunk,
  1525. +    ci_enc_get_pcm_data,
  1526. +    ci_enc_unget_pcm_data,
  1527. +
  1528. +    /* file */
  1529. +    open,
  1530. +    close,
  1531. +    read,
  1532. +    lseek,
  1533. +    write,
  1534. +    ci_round_value_to_list32,
  1535. +
  1536. +#endif /* HAVE_RECORDING */
  1537. +};
  1538. +
  1539. +static void print_mp3entry(const struct mp3entry *id3, FILE *f)
  1540. +{
  1541. +    fprintf(f, "Path: %s\n", id3->path);
  1542. +    if (id3->title) fprintf(f, "Title: %s\n", id3->title);
  1543. +    if (id3->artist) fprintf(f, "Artist: %s\n", id3->artist);
  1544. +    if (id3->album) fprintf(f, "Album: %s\n", id3->album);
  1545. +    if (id3->genre_string) fprintf(f, "Genre: %s\n", id3->genre_string);
  1546. +    if (id3->disc_string || id3->discnum) fprintf(f, "Disc: %s (%d)\n", id3->disc_string, id3->discnum);
  1547. +    if (id3->track_string || id3->tracknum) fprintf(f, "Track: %s (%d)\n", id3->track_string, id3->tracknum);
  1548. +    if (id3->year_string || id3->year) fprintf(f, "Year: %s (%d)\n", id3->year_string, id3->year);
  1549. +    if (id3->composer) fprintf(f, "Composer: %s\n", id3->composer);
  1550. +    if (id3->comment) fprintf(f, "Comment: %s\n", id3->comment);
  1551. +    if (id3->albumartist) fprintf(f, "Album artist: %s\n", id3->albumartist);
  1552. +    if (id3->grouping) fprintf(f, "Grouping: %s\n", id3->grouping);
  1553. +    if (id3->layer) fprintf(f, "Layer: %d\n", id3->layer);
  1554. +    if (id3->id3version) fprintf(f, "ID3 version: %u\n", (int)id3->id3version);
  1555. +    fprintf(f, "Codec: %s\n", audio_formats[id3->codectype].label);
  1556. +    fprintf(f, "Bitrate: %d kb/s\n", id3->bitrate);
  1557. +    fprintf(f, "Frequency: %lu Hz\n", id3->frequency);
  1558. +    if (id3->id3v2len) fprintf(f, "ID3v2 length: %lu\n", id3->id3v2len);
  1559. +    if (id3->id3v1len) fprintf(f, "ID3v1 length: %lu\n", id3->id3v1len);
  1560. +    if (id3->first_frame_offset) fprintf(f, "First frame offset: %lu\n", id3->first_frame_offset);
  1561. +    fprintf(f, "File size without headers: %lu\n", id3->filesize);
  1562. +    fprintf(f, "Song length: %lu ms\n", id3->length);
  1563. +    if (id3->lead_trim || id3->tail_trim) fprintf(f, "Trim: %d/%d\n", id3->lead_trim, id3->tail_trim);
  1564. +    if (id3->samples) fprintf(f, "Number of samples: %lu\n", id3->samples);
  1565. +    if (id3->frame_count) fprintf(f, "Number of frames: %lu\n", id3->frame_count);
  1566. +    if (id3->bytesperframe) fprintf(f, "Bytes per frame: %lu\n", id3->bytesperframe);
  1567. +    if (id3->vbr) fprintf(f, "VBR: true\n");
  1568. +    if (id3->has_toc) fprintf(f, "Has TOC: true\n");
  1569. +    if (id3->channels) fprintf(f, "Number of channels: %u\n", id3->channels);
  1570. +    if (id3->extradata_size) fprintf(f, "Size of extra data: %u\n", id3->extradata_size);
  1571. +    if (id3->needs_upsampling_correction) fprintf(f, "Needs upsampling correction: true\n");
  1572. +    /* TODO: replaygain; albumart; cuesheet */
  1573. +    if (id3->mb_track_id) fprintf(f, "Musicbrainz track ID: %s\n", id3->mb_track_id);
  1574. +}
  1575. +
  1576. +static void decode_file(const char *input_fn)
  1577. +{
  1578. +    /* Set up global settings */
  1579. +    memset(&global_settings, 0, sizeof(global_settings));
  1580. +    global_settings.timestretch_enabled = true;
  1581. +    dsp_timestretch_enable(true);
  1582. +    tdspeed_init();
  1583. +
  1584. +    /* Open file */
  1585. +    if (!strcmp(input_fn, "-")) {
  1586. +        input_fd = STDIN_FILENO;
  1587. +    } else {
  1588. +        input_fd = open(input_fn, O_RDONLY);
  1589. +        if (input_fd == -1) {
  1590. +            perror(input_fn);
  1591. +            exit(1);
  1592. +        }
  1593. +    }
  1594. +
  1595. +    /* Set up ci */
  1596. +    struct mp3entry id3;
  1597. +    if (!get_metadata(&id3, input_fd, input_fn)) {
  1598. +        fprintf(stderr, "error: metadata parsing failed\n");
  1599. +        exit(1);
  1600. +    }
  1601. +    print_mp3entry(&id3, stderr);
  1602. +    ci.filesize = filesize(input_fd);
  1603. +    ci.id3 = &id3;
  1604. +    if (use_dsp) {
  1605. +        ci.dsp = (struct dsp_config *)dsp_configure(NULL, DSP_MYDSP, CODEC_IDX_AUDIO);
  1606. +        dsp_configure(ci.dsp, DSP_RESET, 0);
  1607. +        dsp_dither_enable(false);
  1608. +    }
  1609. +    perform_config();
  1610. +
  1611. +    /* Load codec */
  1612. +    char str[MAX_PATH];
  1613. +    snprintf(str, sizeof(str), CODECDIR"/%s.codec", audio_formats[id3.codectype].codec_root_fn);
  1614. +    debugf("Loading %s\n", str);
  1615. +    void *dlcodec = dlopen(str, RTLD_NOW);
  1616. +    if (!dlcodec) {
  1617. +        fprintf(stderr, "error: dlopen failed: %s\n", dlerror());
  1618. +        exit(1);
  1619. +    }
  1620. +    struct codec_header *c_hdr = NULL;
  1621. +    c_hdr = dlsym(dlcodec, "__header");
  1622. +    if (c_hdr->lc_hdr.magic != CODEC_MAGIC) {
  1623. +        fprintf(stderr, "error: %s invalid: incorrect magic\n", str);
  1624. +        exit(1);
  1625. +    }
  1626. +    if (c_hdr->lc_hdr.target_id != TARGET_ID) {
  1627. +        fprintf(stderr, "error: %s invalid: incorrect target id\n", str);
  1628. +        exit(1);
  1629. +    }
  1630. +    if (c_hdr->lc_hdr.api_version != CODEC_API_VERSION) {
  1631. +        fprintf(stderr, "error: %s invalid: incorrect API version\n", str);
  1632. +        exit(1);
  1633. +    }
  1634. +
  1635. +    /* Run the codec */
  1636. +    *c_hdr->api = &ci;
  1637. +    if (c_hdr->entry_point(CODEC_LOAD) != CODEC_OK) {
  1638. +        fprintf(stderr, "error: codec returned error from codec_main\n");
  1639. +        exit(1);
  1640. +    }
  1641. +    if (c_hdr->run_proc() != CODEC_OK) {
  1642. +        fprintf(stderr, "error: codec error\n");
  1643. +    }
  1644. +    c_hdr->entry_point(CODEC_UNLOAD);
  1645. +
  1646. +    /* Close */
  1647. +    dlclose(dlcodec);
  1648. +    if (input_fd != STDIN_FILENO)
  1649. +        close(input_fd);
  1650. +}
  1651. +
  1652. +static void print_help(const char *progname)
  1653. +{
  1654. +    fprintf(stderr, "Usage:\n"
  1655. +                    "        Play: %s [options] INPUTFILE\n"
  1656. +                    "Write to WAV: %s [options] INPUTFILE OUTPUTFILE\n"
  1657. +                    "\n"
  1658. +                    "general options:\n"
  1659. +                    "  -c a=1:b=2    Configuration (see below)\n"
  1660. +                    "  -h            Show this help\n"
  1661. +                    "\n"
  1662. +                    "write to WAV options:\n"
  1663. +                    "  -f            Write raw codec output converted to 64-bit float\n"
  1664. +                    "  -r            Write raw 32-bit codec output without WAV header\n"
  1665. +                    "\n"
  1666. +                    "configuration:\n"
  1667. +                    "  dither=<0|1>  Enable/disable dithering [0]\n"
  1668. +                    "  halt=<0|1>    Stop decoding if 1 [0]\n"
  1669. +                    "  loop=<0|1>    Enable/disable looping [0]\n"
  1670. +                    "  offset=<n>    Start at byte offset within the file [0]\n"
  1671. +                    "  rate=<n>      Multiply rate by <n> [1.0]\n"
  1672. +                    "  seek=<n>      Seek <n> ms into the file\n"
  1673. +                    "  tempo=<n>     Timestretch by <n> [1.0]\n"
  1674. +                    "  vol=<n>       Set volume to <n> dB [0]\n"
  1675. +                    "  wait=<n>      Don't apply remaining configuration until\n"
  1676. +                    "                <n> total samples have output\n"
  1677. +                    "\n"
  1678. +                    "examples:\n"
  1679. +                    "  # Play while looping; stop after 44100 output samples\n"
  1680. +                    "  %s in.adx -c loop=1:wait=44100:halt=1\n"
  1681. +                    "  # Lower pitch 1 octave and write to out.wav\n"
  1682. +                    "  %s in.ogg -c rate=0.5:tempo=2 out.wav\n"
  1683. +                    , progname, progname, progname, progname);
  1684. +}
  1685. +
  1686. +int main(int argc, char **argv)
  1687. +{
  1688. +    int opt;
  1689. +    while ((opt = getopt(argc, argv, "c:fhr")) != -1) {
  1690. +        switch (opt) {
  1691. +        case 'c':
  1692. +            config = optarg;
  1693. +            break;
  1694. +        case 'f':
  1695. +            use_dsp = false;
  1696. +            break;
  1697. +        case 'r':
  1698. +            use_dsp = false;
  1699. +            write_raw = true;
  1700. +            break;
  1701. +        case 'h': /* fallthrough */
  1702. +        default:
  1703. +            print_help(argv[0]);
  1704. +            exit(1);
  1705. +        }
  1706. +    }
  1707. +
  1708. +    if (argc == optind + 2) {
  1709. +        write_init(argv[optind + 1]);
  1710. +    } else if (argc == optind + 1) {
  1711. +        if (!use_dsp) {
  1712. +            fprintf(stderr, "error: -r can't be used for playback\n");
  1713. +            print_help(argv[0]);
  1714. +            exit(1);
  1715. +        }
  1716. +        playback_init();
  1717. +    } else {
  1718. +        if (argc > 1)
  1719. +            fprintf(stderr, "error: wrong number of arguments\n");
  1720. +        print_help(argv[0]);
  1721. +        exit(1);
  1722. +    }
  1723. +
  1724. +    decode_file(argv[optind]);
  1725. +
  1726. +    if (mode == MODE_WRITE)
  1727. +        write_quit();
  1728. +    else if (mode == MODE_PLAY)
  1729. +        playback_quit();
  1730. +
  1731. +    return 0;
  1732. +}
clone this paste RAW Paste Data