Project Railway Documentation
Background
In recent days I was debugging some strange crashes of Project Railway. The railway process sometimes receives signal SIGSEGV when calling gst_player_new or gst_player_play. After switching to calling the mpg123 program by fork-exec as music playing backend, currently there are no crashes. Maybe I should write some documentation to explain the program.
RailwayMusic
RailwayMusic does the actual work by calling mpg123, using its remote control mode.
void init_music(): Constructor function; launch mpg123 and create read/write file pointers that sends to mpg123; launch music_wait thread.void destroy_music(): Destructor function; cancel and wait for the thread; tells mpg123 to quit and wait for it.void music_play(song_type*): Ask mpg123 to stop and load this song.void music_volume(double): Pass volume to mpg123.void music_pause_trigger(): Pass pause to mpg123.bool music_is_playing(): Get the play state boolean.void* music_wait(void*): Thread that continuously read output of mpg123.int music_update(void*): Update function that run every 1 sec in the main thread to update progress bar and switch to next song if necessary.
RailwayPlaylist
RailwayPlaylist is a simple part to maintain current playlist. It contains the current track index in playlist_ptr.
void init_playlist(): Constructor function; init vars.void destroy_playlist(): Destructor function; cleanup playlist_array if necessary; reset vars.void generate_playlist(song_type*): Generate playlist array by cloning the current song_array.void playlist_next(): Modify playlist_ptr; calls play_song to do actual music playing.void playlist_prev(): Similar to playlist_next.void playlist_play(song_type*): To play a new song that changes the playlist. First destroy and regenerate the playlist, and call play_song.void playlist_set_shuffle(bool): Set shuffle status.void playlist_set_repeat(bool): Set repeat status.
RailwayLib
RailwayLib manages the library of albums and songs, configuration file, and gets music tags to sort songs by track id.
void init_library(): Constructor function; get configuration values; init the gst_discoverer to get tags.void destroy_library(): Destructor function; cleanup resources.void generate_album_list(): To generate album_array; iterate over library directories and artist directories to generate a linked list of albums and convert to array (to find out number of albums and malloc accordingly).void generate_song_list(const album_type*): To generate song_array; iterate over each (regular) song file in a given album directory; create linked list and song array.void destroy_album_list(): Cleanup album array.void destroy_song_list(): Cleanup song array.void generate_album_button_image(GTask*, void*, album_type*, void*): Function for GTask thread to generate album cover picture; Get any song in the album; check if existing picture exist, and if not exist generate one using ffmpeg -n -i <song filename> <image filename>.
Railway
Railway controls all GUI elements and sets their handlers.
void music_position_update_cb(int, int): Update the song progress bar; called from update function in railwaymusic.void music_pause_button_trigger_cb(GtkWidget*, void*): Update the icon of the play/pause trigger button; call railwaymusic to trigger pause.void play_song(song_type*): Setting labels and images in the interface and pass to music_play; called from railwayplaylist.void init_albums(): Create album button grid.void destroy_albums(): Cleanup album button array.void init_window() && void init_control(): Set signal handlers.bool substring_test(const char*, const char*): Substring test (case insensitive).bool search_judge(album_type*, const char*): Test if an album contains the given search term.