Info for hackers
----------------

-- Document history --

Oct 28, 2006: First version

-- General info --

mhWaveEdit is written completely in C, and tries to be as portable as 
possible. There's no point in being more portable than GTK+ though, 
since we depend on it. 

The only hard dependency is GTK+, version 1.2 or newer. All other 
dependencies should be autodetected by the configure script or at 
runtime. In general I prefer calling separate programs, such as 
Lame and SoX, rather than using libraries, because programs can be 
portably detected at runtime so the user can install these programs 
after installing mhWaveEdit. 

The philosophy is to never remove a feature. If a behavior is changed, 
there should be an option to get the old back (unless it's a bug of 
course).

All settings should be configurable via the Preferences menu, there 
should not be any hidden settings, except for "automatic" things like 
recently opened files etc. Settings are handled through inifile.h.

-- Code conventions --

Most functions returning a boolean return TRUE on failure and FALSE on 
success. The function that fails is usually responsible for displaying 
an error message, so if a function returns TRUE an error message has 
already been displayed. 

I have avoided threads for several reasons. The main reasons are 
that it's not portable, makes the program much more complex and a lot 
harder to debug. Most problems that are solved by threads can be 
solved by other means, for example forking, non-blocking IO, select 
calls, and/or clever coding. Some sound drivers use threads though.

mhWaveEdit doesn't use the GTK+ main loop, instead I have coded my own 
(mainloop in main.h), allowing me to control the priority of the 
different activities.

-- File handling --

File handling is separated into layers. 

The lowest layer is the efile functions in gtkfiles.h, that provides a 
wrapper around the C library IO functions. 

Above that is the Datasource layer. Each Datasource object gives access 
to some audio data. The data can be in a file, in memory or converted 
from another datasource. The Datasources are "immutable", meaning the 
data never changes after the datasource has been created. The objects 
are using the standard GtkObject reference counting scheme so data in 
memory and temporary files are removed when nobody needs them anymore.

The Chunk layer is above the Datasource layer. A Chunk object is a 
collection of data from different Datasource objects. Each Chunk 
contains a list of Datasources, positions and lengths of data. Chunk 
objects are also immutable.

The filetypes.h and tempfile.h functions are in both the Chunk layer and 
the Datasource layer. This is because sometimes temporary data end up 
in multiple files, so a Chunk must be returned to represent the data. 

The Document object contains a Chunk with the file currently being 
edited, along with information on selection, view info, history etc.

The Chunkview object is a graphical GTK component displaying a Document. 

The Mainwindow is a GtkWindow subclass containing a Chunkview and a 
Document.

-- Sound handling --

The sound handling is also separated into layers.

The lowest layer is the sound driver. Each sound driver is in a file 
called sound-xyz.c. The sound drivers are not compiled separately, but 
are included in sound.c

The layer above is the sound.h module. This contains glue code for the 
drivers and handles byte-swapping of output and locking of driver (an 
option to not actually stop the driver when playback stops).

The layer above the sound module is the player.h module. This handles 
many things; reading data from the playing chunk, looping, converting 
speed (optional) and sending the data to the sound driver. Also 
estimating cursor position. The player has a function called player_work 
that has to be called periodically. 

The playback position and speed can be changed at runtime. There are 
also functions for smooth switching of playback between two Chunks to 
allow editing while playing.

The player layer handles sample type conversion if the sound driver 
doesn't support the file's sample type. Sample rate conversion is done 
at the same time when applying varispeed.

Recording is done through the recorddialog.h module, which is above the 
sound.h layer. This contains both the recording dialog component and a 
recording function. This module has it's own main loop and blocks the 
rest of the application while recording.

-- Utility modules --

um.h has functions for displaying messages and getting simple input.

rateest.h contains code for estimating the true playback sample rate and 
detect underruns by studying the time and size of writes to the sound 
driver.

ringbuf.h contains a lock-free ring buffer implementation.

main.h contains apart from the main() function main loop, some utility 
macros and functions. 
