1. 26 Aug, 2008 22 commits
    • Max Kellermann's avatar
      flac: decoder command means EOF · 6df980a9
      Max Kellermann authored
      It was possible for the decoder thread to go into an endless loop
      (flac and oggflac decoders): when a "STOP" command arrived, the Read()
      callback would return 0, but the EOF() callback returned false.  Fix:
      when decoder_get_command()!=NONE, return EOF==true.
      6df980a9
    • Max Kellermann's avatar
      mp3, flac: check for seek command after decoder_read() · f46de2c3
      Max Kellermann authored
      When we introduced decoder_read(), we added code which aborts the read
      operation when a decoder command arrives.  Several plugins however did
      not expect that when they were converted to decoder_read().  Add
      proper checks to the mp3 and flac decoder plugins.
      f46de2c3
    • Max Kellermann's avatar
      check decoder_command!=NONE instead of decoder_command==STOP · e530181e
      Max Kellermann authored
      The code said "decoder_command==STOP" because that was a conversion
      from the old "dc->stop" test.  As we can now check for all commands in
      one test, we can simply rewrite that to decoder_command!=NONE.
      e530181e
    • Max Kellermann's avatar
      added decoder_read() · 940ecf53
      Max Kellermann authored
      On our way to stabilize the decoder API, we will one day remove the
      input stream functions.  The most basic function, read() will be
      provided by decoder_api.h with this patch.  It already contains a loop
      (still with manual polling), error/eof handling and decoder command
      checks.  This kind of code used to be duplicated in all decoder
      plugins.
      940ecf53
    • Max Kellermann's avatar
      added decoder_plugin_register() · 6120635f
      Max Kellermann authored
      With the functions decoder_plugin_register() and
      decoder_plugin_unregister(), decoder plugins can register a
      "secondary" plugin, like the flac input plugin does this for
      "oggflac".
      6120635f
    • Max Kellermann's avatar
      renamed functions in decoder_list.h · e754ed01
      Max Kellermann authored
      InputPlugin to decoder_plugin, and no camelCase.
      e754ed01
    • Max Kellermann's avatar
      no camel case in struct decoder_plugin · 772d3da9
      Max Kellermann authored
      772d3da9
    • Max Kellermann's avatar
      renamed inputPlugin.* to decoder_list.* · 41c5fbbb
      Max Kellermann authored
      Since inputPlugin.c manages the list of registered decoders, we should
      rename the source file.
      41c5fbbb
    • Max Kellermann's avatar
      renamed InputPlugin to struct decoder_plugin · e41be362
      Max Kellermann authored
      "decoder plugin" is a better name than "input plugin", since the
      plugin does not actually do the input - InputStream does.  Also don't
      use typedef, so we can forward-declare it if required.
      e41be362
    • Max Kellermann's avatar
      added decoder_seek_where() and decoder_seek_error() · 17e9cc84
      Max Kellermann authored
      Provide access to seeking for the decoder plugins; they have to know
      where to seek, and they need a way to tell us that seeking has failed.
      17e9cc84
    • Max Kellermann's avatar
      added decoder_command_finished() to decoder_api.h · 78c55e24
      Max Kellermann authored
      Some decoder commands are implemented in the decoder plugins, thus
      they need to have an API call to signal that their current command has
      been finished.  Let them use the new decoder_command_finished()
      instead of the internal dc_command_finished().
      78c55e24
    • Max Kellermann's avatar
      added decoder_get_command() · 817a68b2
      Max Kellermann authored
      Another big patch which hides internal mpd APIs from decoder plugins:
      decoder plugins regularly poll dc->command; expose it with a
      decoder_api.h function.
      817a68b2
    • Max Kellermann's avatar
      moved InputPlugin to decoder_api.h · 08bdb43b
      Max Kellermann authored
      InputPlugin is the API which is implemented by a decoder plugin.  This
      belongs to the public API/ABI, so move it to decoder_api.h.  It will
      later be renamed to something like "decoder_plugin".
      08bdb43b
    • Max Kellermann's avatar
      added parameter total_time to decoder_initialized() · 0d8b551c
      Max Kellermann authored
      Similar to the previous patch: pass total_time instead of manipulating
      dc->totalTime directly.
      0d8b551c
    • Max Kellermann's avatar
      added audio_format parameter to decoder_initialized() · 4590a98f
      Max Kellermann authored
      dc->audioFormat is set once by the decoder plugins before invoking
      decoder_initialized(); hide dc->audioFormat and let the decoder pass
      an AudioFormat pointer to decoder_initialized().
      4590a98f
    • Max Kellermann's avatar
      added decoder_clear() and decoder_flush() · 0d45870c
      Max Kellermann authored
      We are now beginning to remove direct structure accesses from the
      decoder plugins.  decoder_clear() and decoder_flush() mask two very
      common buffer functions.
      0d45870c
    • Max Kellermann's avatar
      added decoder_initialized() · 2bf7ec4f
      Max Kellermann authored
      decoder_initialized() sets the state to DECODE_STATE_DECODE and wakes
      up the player thread.  It is called by the decoder plugin after its
      internal initialization is finished.  More arguments will be added
      later to prevent direct accesses to the DecoderControl struct.
      2bf7ec4f
    • Max Kellermann's avatar
      added struct decoder · 154aa496
      Max Kellermann authored
      The decoder struct should later be made opaque to the decoder plugin,
      because maintaining a stable struct ABI is quite difficult.  The ABI
      should only consist of a small number of stable functions.
      154aa496
    • Max Kellermann's avatar
      added dc_command_finished() · 9e0f7dcd
      Max Kellermann authored
      dc_command_finished() is invoked by the decoder thread when it has
      finished a command (sent by the player thread).  It resets dc.command
      and wakes up the player thread.  This combination was used at a lot of
      places, and by introducing this function, the code will be more
      readable.
      9e0f7dcd
    • Max Kellermann's avatar
      merged start, stop, seek into DecoderControl.command · 8d3942e0
      Max Kellermann authored
      Much of the existing code queries all three variables sequentially.
      Since only one of them can be set at a time, this can be optimized and
      unified by merging all of them into one enum variable.  Later, the
      "command" checks can be expressed in a "switch" statement.
      8d3942e0
    • Max Kellermann's avatar
      clean up CPP includes · b6909da7
      Max Kellermann authored
      Include only headers which are really required.  This speeds up
      compilation and helps detect cross-layer accesses.
      b6909da7
    • Max Kellermann's avatar
      enable -Wpointer-arith, -Wstrict-prototypes · a383f451
      Max Kellermann authored
      Also enable -Wunused-parameter - this forces us to add the gcc
      "unused" attribute to a lot of parameters (mostly library callback
      functions), but it's worth it during code refactorizations.
      a383f451
  2. 13 Apr, 2008 3 commits
  3. 12 Apr, 2008 13 commits
    • Max Kellermann's avatar
      replaced assertion with check · 3919a875
      Max Kellermann authored
      During my tests, it happened that data->position>newPosition.  I have
      not yet fully understood why this can happen; for now, replace this
      with a run-time check.
      
      git-svn-id: https://svn.musicpd.org/mpd/trunk@7334 09075e82-0dd4-0310-85a5-a0d7c8717e4f
      3919a875
    • Max Kellermann's avatar
      multiply num_samples with bytes_per_channel · a25a7624
      Max Kellermann authored
      The patch "convert blocks until the buffer is full" did not update
      data->chunk_length correctly: it added the number of samples, not the
      number of bytes.  Multiply that with bytes_per_channel
      
      git-svn-id: https://svn.musicpd.org/mpd/trunk@7332 09075e82-0dd4-0310-85a5-a0d7c8717e4f
      a25a7624
    • Max Kellermann's avatar
      missing num_channels check in previous patch · f4252ee7
      Max Kellermann authored
      In the patch "special optimized case for 16bit stereo", the check for
      "num_channels==2" was missing.
      
      git-svn-id: https://svn.musicpd.org/mpd/trunk@7331 09075e82-0dd4-0310-85a5-a0d7c8717e4f
      f4252ee7
    • Max Kellermann's avatar
      special optimized case for 16bit stereo · 00fbd7bb
      Max Kellermann authored
      Not having to loop for every sample byte (depending on a variable
      unknown at compile time) saves a lot of CPU cycles.  We could consider
      reimplementing this function with liboil...
      
      git-svn-id: https://svn.musicpd.org/mpd/trunk@7330 09075e82-0dd4-0310-85a5-a0d7c8717e4f
      00fbd7bb
    • Max Kellermann's avatar
      read num_channels once · 3db2b987
      Max Kellermann authored
      Read frame->header.channels once, and pass only this integer to
      flac_convert().
      
      git-svn-id: https://svn.musicpd.org/mpd/trunk@7329 09075e82-0dd4-0310-85a5-a0d7c8717e4f
      3db2b987
    • Max Kellermann's avatar
      assume the buffer is empty in flacWrite() · a91f2a1f
      Max Kellermann authored
      flacWrite() is the only function which sets data->chunk_length.  If we
      flush the buffer before we return, we can assume that it is always
      empty upon entering flacWrite().
      
      git-svn-id: https://svn.musicpd.org/mpd/trunk@7328 09075e82-0dd4-0310-85a5-a0d7c8717e4f
      a91f2a1f
    • Max Kellermann's avatar
      convert blocks until the buffer is full · ca1090f9
      Max Kellermann authored
      Move the inner loop which converts samples to flac_convert().  There
      it is isolated and easier to optimize.  This function does not have to
      worry about buffer boundaries; the caller (i.e. flacWrite())
      calculates how much is left and is responsible for flushing.  That
      saves a lot of superfluous range checks within the loop.
      
      git-svn-id: https://svn.musicpd.org/mpd/trunk@7327 09075e82-0dd4-0310-85a5-a0d7c8717e4f
      ca1090f9
    • Max Kellermann's avatar
      calculate bytes_per_channel, check for buffer flush once · 0673c9a8
      Max Kellermann authored
      Check for flushing the chunk buffer only once per sample, before
      iterating over channels and bytes.  This saves another 5% CPU cycles.
      
      git-svn-id: https://svn.musicpd.org/mpd/trunk@7326 09075e82-0dd4-0310-85a5-a0d7c8717e4f
      0673c9a8
    • Max Kellermann's avatar
      don't calculate bytes per sample within the loop · 51e90440
      Max Kellermann authored
      AudioFormat.bits is volatile, and to read it, 3 pointers had to be
      deferenced.  Calculate this value once.  This speeds up this function
      by 5%.
      
      git-svn-id: https://svn.musicpd.org/mpd/trunk@7325 09075e82-0dd4-0310-85a5-a0d7c8717e4f
      51e90440
    • Max Kellermann's avatar
      use unsigned integers and size_t in the flac plugin · 96eb0119
      Max Kellermann authored
      git-svn-id: https://svn.musicpd.org/mpd/trunk@7324 09075e82-0dd4-0310-85a5-a0d7c8717e4f
      96eb0119
    • Eric Wong's avatar
      Initial cut of fork() => pthreads() for decoder and player · 9cf66d0e
      Eric Wong authored
      I initially started to do a heavy rewrite that changed the way processes
      communicated, but that was too much to do at once.  So this change only
      focuses on replacing the player and decode processes with threads and
      using condition variables instead of polling in loops; so the changeset
      itself is quiet small.
      
      * The shared output buffer variables will still need locking
      to guard against race conditions.  So in this effect, we're probably
      just as buggy as before.  The reduced context-switching overhead of
      using threads instead of processes may even make bugs show up more or
      less often...
      
      * Basic functionality appears to be working for playing local (and NFS)
      audio, including:
      play, pause, stop, seek, previous, next, and main playlist editing
      
      * I haven't tested HTTP streams yet, they should work.
      
      * I've only tested ALSA and Icecast.  ALSA works fine, Icecast
      metadata seems to get screwy at times and breaks song
      advancement in the playlist at times.
      
      * state file loading works, too (after some last-minute hacks with
      non-blocking wakeup functions)
      
      * The non-blocking (*_nb) variants of the task management functions are
      probably overused.  They're more lenient and easier to use because
      much of our code is still based on our previous polling-based system.
      
      * It currently segfaults on exit.  I haven't paid much attention
      to the exit/signal-handling routines other than ensuring it
      compiles.  At least the state file seems to work.  We don't
      do any cleanups of the threads on exit, yet.
      
      * Update is still done in a child process and not in a thread.
      To do this in a thread, we'll need to ensure it does proper
      locking and communication with the main thread; but should
      require less memory in the end because we'll be updating
      the database "in-place" rather than updating a copy and
      then bulk-loading when done.
      
      * We're more sensitive to bugs in 3rd party libraries now.
      My plan is to eventually use a master process which forks()
      and restarts the child when it dies:
      locking and communication with the main thread; but should
      require less memory in the end because we'll be updating
      the database "in-place" rather than updating a copy and
      then bulk-loading when done.
      
      * We're more sensitive to bugs in 3rd party libraries now.
      My plan is to eventually use a master process which forks()
      and restarts the child when it dies:
      
      master - just does waitpid() + fork() in a loop
      \- main thread
      \- decoder thread
      \- player thread
      
      At the beginning of every song, the main thread will set
      a dirty flag and update the state file.  This way, if we
      encounter a song that triggers a segfault killing the
      main thread, the master will start the replacement main
      on the next song.
      
      * The main thread still wakes up every second on select()
      to check for signals; which affects power management.
      
      [merged r7138 from branches/ew]
      
      git-svn-id: https://svn.musicpd.org/mpd/trunk@7240 09075e82-0dd4-0310-85a5-a0d7c8717e4f
      9cf66d0e
    • Max Kellermann's avatar
      use unsigned integers in the flac plugin · 51f5bf93
      Max Kellermann authored
      The counter variables c_samp and c_chan begin at zero and can never be
      negative.
      
      git-svn-id: https://svn.musicpd.org/mpd/trunk@7228 09075e82-0dd4-0310-85a5-a0d7c8717e4f
      51f5bf93
    • Max Kellermann's avatar
      removed unused variable · 4dc709d0
      Max Kellermann authored
      The local variable d_samp is initialized, but never actually used.
      
      git-svn-id: https://svn.musicpd.org/mpd/trunk@7227 09075e82-0dd4-0310-85a5-a0d7c8717e4f
      4dc709d0
  4. 05 Feb, 2008 1 commit
  5. 26 Jan, 2008 1 commit