ocarina/core/audio.cpp

240 lines
4.2 KiB
C++
Raw Normal View History

/**
* Copyright 2013 (c) Anna Schumaker.
*/
#include <core/audio.h>
extern "C" {
#include <core/collection.h>
#include <core/history.h>
#include <core/tempq.h>
#include <core/string.h>
}
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 GstState __audio_cur_state()
{
GstState cur;
gst_element_get_state(audio_player, &cur, NULL, GST_CLOCK_TIME_NONE);
return cur;
}
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, cur_driver->is_playing() ? GST_STATE_PLAYING :
GST_STATE_PAUSED)) {
history_add(audio_track);
return true;
}
return false;
}
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);
}
void audio :: seek_to(int64_t pos)
{
if (audio_track)
cur_driver->seek_to(pos);
}
void audio :: stop()
{
audio_pause();
seek_to(0);
}
int64_t audio :: position()
{
if (audio_track)
return cur_driver->position();
return 0;
}
int64_t audio :: duration()
{
if (audio_track)
return cur_driver->duration();
return 0;
}
void audio :: next()
{
struct track *track = tempq_next();
if (!track)
track = queue_next(collection_get_queue());
if (__audio_load(track, cur_driver->is_playing() ? GST_STATE_PLAYING :
GST_STATE_PAUSED))
history_add(audio_track);
}
void audio :: prev()
{
__audio_load(history_prev(), cur_driver->is_playing() ?
GST_STATE_PLAYING : GST_STATE_PAUSED);
}
struct track *audio :: current_track()
{
return audio_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;
}