/** * Copyright 2013 (c) Anna Schumaker. */ #include extern "C" { #include #include #include #include } static struct file audio_file; static struct track *audio_track = NULL; static GstElement *audio_player = NULL; static struct audio_ops *audio_ops = NULL; static bool _pause_enabled = false; static unsigned int _pause_count = 0; static AudioDriver *cur_driver = NULL; static void __audio_save() { file_open(&audio_file, OPEN_WRITE); file_writef(&audio_file, "%u\n", audio_track->tr_dbe.dbe_index); file_close(&audio_file); } static bool __audio_change_state(GstState state) { GstStateChangeReturn ret = GST_STATE_CHANGE_FAILURE; if (audio_cur_state() != state) ret = gst_element_set_state(audio_player, state); return ret != GST_STATE_CHANGE_FAILURE; } static bool __audio_load(struct track *track, GstState state) { gchar *path, *uri; if (!track) return false; path = track_path(track); uri = gst_filename_to_uri(path, NULL); audio_track = track; gst_element_set_state(audio_player, GST_STATE_NULL); g_object_set(G_OBJECT(audio_player), "uri", uri, NULL); __audio_change_state(state); audio_ops->on_load(track, state); __audio_save(); g_free(uri); g_free(path); return true; } static GstState continue_playback() { GstState ret = GST_STATE_PLAYING; if (_pause_enabled) { if (_pause_count == 0) { ret = GST_STATE_PAUSED; _pause_enabled = false; } else _pause_count--; } return ret; } AudioDriver :: AudioDriver() { cur_driver = this; } AudioDriver :: ~AudioDriver() { cur_driver = NULL; } void AudioDriver :: eos() { struct track *track; if (audio_track) { track_played(audio_track); queue_updated(collection_get_queue(), audio_track); } track = tempq_next(); if (!track) track = queue_next(collection_get_queue()); __audio_load(track, continue_playback()); } void audio_init(int *argc, char ***argv, struct audio_ops *ops) { unsigned int track; gst_init(argc, argv); audio_player = gst_element_factory_make("playbin", "ocarina_player"); audio_ops = ops; file_init(&audio_file, "cur_track", 0); if (file_open(&audio_file, OPEN_READ)) { file_readf(&audio_file, "%u", &track); file_close(&audio_file); audio_load(track_get(track)); } } void audio_deinit() { gst_element_set_state(audio_player, GST_STATE_NULL); gst_object_unref(audio_player); audio_player = NULL; audio_track = NULL; gst_deinit(); } bool audio_load(struct track *track) { if (track == audio_track) return false; if (__audio_load(track, audio_cur_state())) { history_add(audio_track); return true; } return false; } struct track *audio_cur_track() { return audio_track; } GstState audio_cur_state() { GstState cur = GST_STATE_NULL; if (audio_player) gst_element_get_state(audio_player, &cur, NULL, GST_CLOCK_TIME_NONE); return cur; } bool audio_play() { if (!audio_track) return false; return __audio_change_state(GST_STATE_PLAYING); } bool audio_pause() { if (!audio_track) return false; return __audio_change_state(GST_STATE_PAUSED); } bool audio_stop() { audio_pause(); return audio_seek(0); } bool audio_seek(gint64 offset) { if (!audio_track) return false; return gst_element_seek_simple(audio_player, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, offset); } gint64 audio_position() { gint64 position; if (gst_element_query_position(audio_player, GST_FORMAT_TIME, &position)) return position; return 0; } int64_t audio_duration() { gint64 duration; if (gst_element_query_duration(audio_player, GST_FORMAT_TIME, &duration)) return duration; if (audio_track) return audio_track->tr_length * GST_SECOND; return 0; } struct track *audio_next() { struct track *track = tempq_next(); if (!track) track = queue_next(collection_get_queue()); if (__audio_load(track, audio_cur_state())) history_add(audio_track); return track; } struct track *audio_prev() { struct track *track = history_prev(); __audio_load(track, audio_cur_state()); return track; } void audio :: pause_after(bool enabled, unsigned int n) { if (n > _pause_count) enabled = true; _pause_enabled = enabled; _pause_count = n; } bool audio :: pause_enabled() { return _pause_enabled; } unsigned int audio :: pause_count() { return _pause_count; } AudioDriver *audio :: get_driver() { return cur_driver; } GstElement *audio_get_player() { return audio_player; }