The player software that runs on the PC is designed in a modular fashion, it has object oriented principals built in, but it is written in C. The reason for this is that back in 2000 when I started the project, I was not a good enough C++ programmer to undertake this task.
The modular nature of the source tree and interfaces has enabled me to write several modules with similar tasks. There are 3 display modules, one each for the serial, parallel and the controller displays. Each one satisfies the the interface so the rest of the player code doesn't need to know which front panel it is communicating with.
The main function sets up each of the peripheral modules by calling their *_init functions. Then it enters a while loop to service each module as necessary.
Each module init function is responsible for initializing the module. For example the display_init() opens the serial port and initializes the frontpanel, the mp3_init function spins the mp3 player thread and the monitoring thread that are used.
The while loop basically services each of the modules as required. Its first task is to accept the user input from the buttons module, it then uses that input to affect the behaviour of the rest of the modules ie. if the up volume is pressed, then sound_set_volume is called to set the new volume level and db_store is called to save the new volume state. Each time through the loop while playing mp3, the mp3 monitoring module is checked and the elapsed time is sent to the display.
The loop timing is controlled by the buttons module, it's get function has a select statement that ensures the loop is run at a 1Hz. If the buttons have been affected, then the mainloop frequency goes up as select returns as soon as there is input to be read. This provides the responsiveness required, yet also means the display is not getting flooded with messages.