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.

Project Railway!

Background: I was using Rhythmbox to listen to music in GNOME desktop environment. Rhythmbox is an awesome and powerful music player. But several days ago, I think maybe browsing albums in the form of album cover picture grid will look better than browsing albums in album name list, so I start this project.

Project Railway is a Gtk+ music player. It consists of the following parts:

  • railway: GUI part. Controls all widgets. Also, calls the ffmpeg program to generate album cover picture for each album asynchronously with GTask, to not block GUI with time-consuming operation.
  • railwaylibrary: Reads music library and generates arrays of song and album information. And uses GStreamer GstDiscoverer to retrieve song metadata, or “tags”, to sort music in track order.
  • railwaymusic: The actual music player part. Calls GStreamer GstPlayer to do all the work.
  • railwayplaylist: Manages the playlist by cloning a copy of song array.

The resulting music player looks like:

UPD: Support searching by album name or artist name now!