Re: Re: being serious about the NG of zinf

Ed Sweetman <[email protected]>
Newsgroups gmane.comp.audio.zinf.devel
Message-ID <[email protected]>
Sam Varshavchik wrote:
> Ed Sweetman writes:
> 
>> Right now I'm opposed to using threads for the main player.
>> Threads could possibly be used in the situation where we're streaming 
>> or playing from the internet. This is because of a couple reasons. We 
>> could have a large output buffer which may make reading from the 
>> stream be in longer intervals than ip allows for timeouts, thus losing 
>> our connection. Also, for streams, we may miss packets during our 
>> requests for more data.
> 
> 
> With most desktop environment, X-Windows, or MS-Windows, sometimes 
> certain operations will lock the entire display, and any process that 
> requests any kind of a UI-related operation will be blocked.  The most 
> common example would be resizing a desktop window.  The entire display 
> will be locked so that the display manager can scribble over the entire 
> display with the rubberband outline of the resizing window.
> 
> If your main application thread is multiplexing between pushing audio 
> out, and updating the display, the audio playback is going to come to a 
> screeching halt pretty quickly.  Not nice.

the gui can sit on a thread by itself via gdk_thread



>> From a purely theoretical design, I think that audio playback needs a 
> 
> minimum of two threads.
> 
> The first thread's only job would be to push audio out.  No other I/O.  
> No dynamic memory allocation from the heap.  It's going to be reading 
> from a reasonably sized memory buffer that the second thread will be 
> filling, and writing the data out to the audio device.  Where possible, 
> it's going to be set to run as a high priority process.  No other 
> syscalls or I/O interaction except for audio out.  You want to minimize 
> any possibility of something else getting in the way.  It's going to be 
> reading from the memory buffer, and periodically updating an output 
> counter that indicates how much audio was played so far.
> 
> The second thread would be reading the audio source; be it a file or an 
> Internet stream, translating it to the native audio format, and 
> constantly filling the input buffer to the first thread.

i'd have to disagree with this two thread model of the pipeline. A 
serial pipeline is more than adaquate to handle audio output (speed 
wise) and the maintainance of the two threads introduces a great amount 
of complexity and overhead compared to not using them. mplayer is serial 
and it manages to do both audio and video output without threading it's 
pipeline.


> Everything else: all user interface and any other ancillary processing, 
> can go into the main application thread.  When the main application 
> wants to start playing a file or a thread, the second thread gets 
> appropriately notified, then it begins reading the audio source and 
> filling the first thread's input buffer.  Then, the main application's 
> remaining task is to periodically update the display based on the fist 
> thread's output counter.
> 
> The main application would have a facility to signal the first thread to 
> pause and resume playback.  Fast-Forward and Rewind is implemented by 
> signaling the first thread to pause, waiting until it indicates that 
> it's paused, then signaling the second thread to reset an refill the 
> input buffer from a different position in the audio stream; then 
> signaling the first thread to resume.

First off you're already getting into why threading is to be avoided. 
Signals.  Whenever you talk about threads you need to talk about signals 
and locking and such.  This is part of the reason why the current player 
has so many problems, it's way too threaded. Serial pipelines do not 
suffer any of these problems.  We simply tell the OS to stop playing by 
whatever method the api the plugin uses uses, then we clear our output 
buffer and input buffer. And begin reading again like nothing happened 
immediately (seeking in either direction) or whenever we want (pausing).

If you're running an OS with a crappy schedular and are afraid some 
other process will eat into your timeslice with disk IO keeping your 
player from reading data in and thus, keeping the player from updating 
the soundcard with data in time, perhaps we can handle this by wrapping 
up the only the read() call in a thread. We dont have to care about 
locking anything or worrying about the player getting conflicting info 
by this asyncronous reading.  The buffer will be able to handle adding 
data without affecting reading from it at the same exact time.  I think 
that's perfectly acceptable instead of having a thread running all the 
time in parallel that we have to remote control. I like the wrapping of 
the input subsystem's read a lot. Sequential calls to read will be 
ignored so we dont create a bunch of threads waiting for hdd access, we 
only want one, and we can work asynchronously perfectly fine. Adding to 
the input buffer can be done without the reading being effected at all 
and since that's all the reading via input subsystem effects we're 
golden. Seeking of course is a non-issue.


> The first thread needs to be aware of the particular buffering behavior 
> of the operating system's audio-out driver.  When audio-out is paused, 
> the first thread needs to also flush the audio-out device, so that the 
> audio is muted immediately, then calculate its best estimate of how much 
> audio data was left buffered up, so if its signaled to resume playback 
> from the same point the playback will pick up exactly where it was 
> stopped; and all the time its output counters reflect its best estimate 
> on what's actually coming out of the speakers.  One of my biggest 
> annoyances with some of the last versions of Freeamp is that it was 
> blissfully unaware of audio buffering by /dev/dsp. Each time you started 
> playing the track timer immediately jumped from 00:00 to 00:04 seconds, 
> then began counting off seconds normally, and once it reached the end of 
> the song it remained stuck on the final second for a little while until 
> /dev/dsp finished flushing everything out.  It was even worse with 
> ESound.  I think the current Zinf's much better in this regard, at least 
> I haven't noticed anything.

Basically what you're annoyed at is the dependency of deciding what time 
it is by measuring how much data we've sent to the audio device or 
library output.  First off this method is not really helpful if we allow 
the player to seek, so it probably wont be used as a method of telling 
what time it is.  So then one might say, how do we decide when to update 
the time and how to handle filling the buffer at the same time.  What we 
could do time the player on a loop that is run in the output plugin that 
queries the audio buffer waiting for a 2byte decrease from the max with 
initial time's starting at position given by the UI. That should be 
sufficient.


Keep the comments/suggestions coming.  I'm going to resist certain ideas 
that differ from the ones i started out with so be prepared.... I want 
to be convinced the ones i'm going to end up going along with are the 
best ones and i'm already convinced my own are pretty good so i'll be 
trying to push them and better ones should be able to trump those that 
aren't.  I'm trying to adhere to certain guidelines i feel the next 
generation of zinf should follow.  If you feel your idea is better at 
doing that than mine or the guidelines are wrong then tell me how before 
the idea and we can get right to the point. Compromising the integrity 
of the program is simply not going to be acceptable so if there are 
features that look like they're going to be simply impossible with the 
accepted described idea but only a niche group of people would require 
it then sorry, they're SOL.  There is a scope to a program and 
undoubtedly some things will lay outside of it. eg. 100% accurate 
seeking and time reporting to name a couple.  I'm much more concerned 
with keeping the code pure than doing things the way they're already 
done in other players. And another saying to give my programmer centric 
ways some backbone...It's better to do few things extremely well than a 
lot of things half assed.



-------------------------------------------------------
This sf.net email is sponsored by:ThinkGeek
Welcome to geek heaven.
http://thinkgeek.com/sf
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.