core/audio: Move audio_load() out of the audio namespace
And add the on_load() audio operation. Signed-off-by: Anna Schumaker <Anna@OcarinaProject.net>
This commit is contained in:
parent
e0c89556ed
commit
e5c3d8f02e
100
core/audio.cpp
100
core/audio.cpp
|
@ -11,43 +11,52 @@ extern "C" {
|
|||
|
||||
|
||||
static struct file audio_file;
|
||||
static GstElement *audio_player = NULL;
|
||||
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 struct track *cur_track = NULL;
|
||||
static AudioDriver *cur_driver = NULL;
|
||||
|
||||
|
||||
static void save_state()
|
||||
static void __audio_save()
|
||||
{
|
||||
file_open(&audio_file, OPEN_WRITE);
|
||||
file_writef(&audio_file, "%u\n", cur_track->tr_dbe.dbe_index);
|
||||
file_writef(&audio_file, "%u\n", audio_track->tr_dbe.dbe_index);
|
||||
file_close(&audio_file);
|
||||
}
|
||||
|
||||
static void _load_track(struct track *track, bool start_playback)
|
||||
static bool __audio_load(struct track *track, GstState state)
|
||||
{
|
||||
cur_track = track;
|
||||
if (!track)
|
||||
return;
|
||||
gchar *path, *uri;
|
||||
|
||||
cur_driver->load(track);
|
||||
if (start_playback)
|
||||
audio :: play();
|
||||
else
|
||||
audio :: pause();
|
||||
save_state();
|
||||
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);
|
||||
gst_element_set_state(audio_player, state);
|
||||
audio_ops->on_load(track, state);
|
||||
|
||||
__audio_save();
|
||||
g_free(uri);
|
||||
g_free(path);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool continue_playback()
|
||||
static GstState continue_playback()
|
||||
{
|
||||
bool ret = true;
|
||||
GstState ret = GST_STATE_PLAYING;
|
||||
|
||||
if (_pause_enabled) {
|
||||
if (_pause_count == 0) {
|
||||
ret = false;
|
||||
ret = GST_STATE_PAUSED;
|
||||
_pause_enabled = false;
|
||||
} else
|
||||
_pause_count--;
|
||||
|
@ -72,31 +81,32 @@ void AudioDriver :: eos()
|
|||
{
|
||||
struct track *track;
|
||||
|
||||
if (cur_track) {
|
||||
track_played(cur_track);
|
||||
queue_updated(collection_get_queue(), cur_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());
|
||||
_load_track(track, continue_playback());
|
||||
__audio_load(track, continue_playback());
|
||||
}
|
||||
|
||||
|
||||
|
||||
void audio_init(int *argc, char ***argv)
|
||||
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(track_get(track));
|
||||
audio_load(track_get(track));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -104,26 +114,40 @@ 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;
|
||||
}
|
||||
|
||||
void audio :: play()
|
||||
{
|
||||
if (cur_track)
|
||||
if (audio_track)
|
||||
cur_driver->play();
|
||||
}
|
||||
|
||||
void audio :: pause()
|
||||
{
|
||||
if (cur_track)
|
||||
if (audio_track)
|
||||
cur_driver->pause();
|
||||
}
|
||||
|
||||
void audio :: seek_to(int64_t pos)
|
||||
{
|
||||
if (cur_track)
|
||||
if (audio_track)
|
||||
cur_driver->seek_to(pos);
|
||||
}
|
||||
|
||||
|
@ -135,14 +159,14 @@ void audio :: stop()
|
|||
|
||||
int64_t audio :: position()
|
||||
{
|
||||
if (cur_track)
|
||||
if (audio_track)
|
||||
return cur_driver->position();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int64_t audio :: duration()
|
||||
{
|
||||
if (cur_track)
|
||||
if (audio_track)
|
||||
return cur_driver->duration();
|
||||
return 0;
|
||||
}
|
||||
|
@ -152,28 +176,20 @@ void audio :: next()
|
|||
struct track *track = tempq_next();
|
||||
if (!track)
|
||||
track = queue_next(collection_get_queue());
|
||||
_load_track(track, cur_driver->is_playing());
|
||||
if (cur_track)
|
||||
history_add(cur_track);
|
||||
if (__audio_load(track, cur_driver->is_playing() ? GST_STATE_PLAYING :
|
||||
GST_STATE_PAUSED))
|
||||
history_add(audio_track);
|
||||
}
|
||||
|
||||
void audio :: prev()
|
||||
{
|
||||
_load_track(history_prev(), cur_driver->is_playing());
|
||||
}
|
||||
|
||||
void audio :: load_track(struct track *track)
|
||||
{
|
||||
if (!track || track == cur_track)
|
||||
return;
|
||||
|
||||
_load_track(track, cur_driver->is_playing());
|
||||
history_add(cur_track);
|
||||
__audio_load(history_prev(), cur_driver->is_playing() ?
|
||||
GST_STATE_PLAYING : GST_STATE_PAUSED);
|
||||
}
|
||||
|
||||
struct track *audio :: current_track()
|
||||
{
|
||||
return cur_track;
|
||||
return audio_track;
|
||||
}
|
||||
|
||||
void audio :: pause_after(bool enabled, unsigned int n)
|
||||
|
|
|
@ -21,7 +21,7 @@ void core :: init(int *argc, char ***argv, struct core_init_data *init)
|
|||
collection_init(init->collection_ops);
|
||||
history_init(init->history_ops);
|
||||
tempq_init(init->tempq_ops);
|
||||
audio_init(argc, argv);
|
||||
audio_init(argc, argv, init->audio_ops);
|
||||
}
|
||||
|
||||
void core :: deinit()
|
||||
|
|
51
gui/gst.cpp
51
gui/gst.cpp
|
@ -53,38 +53,29 @@ static void set_markup(Gtk::Label *label, const std::string &size,
|
|||
Glib::Markup::escape_text(text) + "</span>");
|
||||
}
|
||||
|
||||
static void on_load(struct track *track, GstState state)
|
||||
{
|
||||
gchar *str = g_strdup_printf("From: %s", track->tr_album->al_name);
|
||||
set_markup(o_album, "x-large", str);
|
||||
g_free(str);
|
||||
|
||||
str = g_strdup_printf("By: %s", track->tr_artist->ar_name);
|
||||
set_markup(o_artist, "x-large", str);
|
||||
g_free(str);
|
||||
|
||||
set_markup(o_title, "xx-large", track->tr_title);
|
||||
|
||||
str = string_sec2str(track->tr_length);
|
||||
o_duration->set_text(str);
|
||||
g_free(str);
|
||||
|
||||
plist :: track_loaded(track);
|
||||
}
|
||||
|
||||
|
||||
class GSTDriver : public AudioDriver
|
||||
{
|
||||
public:
|
||||
void load(struct track *track)
|
||||
{
|
||||
gchar *path = track_path(track);
|
||||
gchar *uri = gst_filename_to_uri(path, NULL);
|
||||
gchar *len = string_sec2str(track->tr_length);
|
||||
gchar *str;
|
||||
|
||||
gst_change_state(GST_STATE_NULL);
|
||||
g_object_set(G_OBJECT(audio_get_player()), "uri", uri, NULL);
|
||||
g_free(uri);
|
||||
|
||||
str = g_strdup_printf("From: %s", track->tr_album->al_name);
|
||||
set_markup(o_album, "x-large", str);
|
||||
g_free(str);
|
||||
|
||||
str = g_strdup_printf("By: %s", track->tr_artist->ar_name);
|
||||
set_markup(o_artist, "x-large", str);
|
||||
g_free(str);
|
||||
|
||||
set_markup(o_title, "xx-large", track->tr_title);
|
||||
|
||||
o_duration->set_text(len);
|
||||
g_free(path);
|
||||
g_free(len);
|
||||
|
||||
plist :: track_loaded(track);
|
||||
}
|
||||
|
||||
void play()
|
||||
{
|
||||
if (gst_change_state(GST_STATE_PLAYING)) {
|
||||
|
@ -142,6 +133,10 @@ public:
|
|||
|
||||
static GSTDriver *gst_driver;
|
||||
|
||||
struct audio_ops audio_ops = {
|
||||
on_load,
|
||||
};
|
||||
|
||||
|
||||
static int parse_gst_error(GstMessage *error)
|
||||
{
|
||||
|
|
|
@ -18,6 +18,7 @@ struct core_init_data init_data = {
|
|||
&history_ops,
|
||||
&playlist_ops,
|
||||
&tempq_ops,
|
||||
&audio_ops,
|
||||
};
|
||||
|
||||
namespace gui
|
||||
|
@ -64,6 +65,7 @@ int main(int argc, char **argv)
|
|||
gst :: init_pre();
|
||||
core :: init(&argc, &argv, &init_data);
|
||||
|
||||
gst :: init();
|
||||
plist :: init();
|
||||
manager :: init();
|
||||
init_tabs();
|
||||
|
|
|
@ -56,7 +56,7 @@ void QueueModel::on_row_changed(unsigned int row)
|
|||
|
||||
void QueueModel::on_path_selected(const Gtk::TreePath &path)
|
||||
{
|
||||
audio :: load_track(track_get(path_to_id(path)));
|
||||
audio_load(track_get(path_to_id(path)));
|
||||
queue_selected(_queue, path[0]);
|
||||
audio :: play();
|
||||
}
|
||||
|
|
|
@ -12,6 +12,12 @@ extern "C" {
|
|||
#include <stdint.h>
|
||||
|
||||
|
||||
struct audio_ops {
|
||||
/* Called when a track is loaded. */
|
||||
void (*on_load)(struct track *, GstState);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* The audio driver class gives us an interface for using multiple
|
||||
* audio frameworks for audio playback.
|
||||
|
@ -25,13 +31,6 @@ public:
|
|||
virtual ~AudioDriver(); /**< AudioDriver destructor. */
|
||||
|
||||
|
||||
/**
|
||||
* Loads an audio file for playback.
|
||||
*
|
||||
* @param track The Track to load.
|
||||
*/
|
||||
virtual void load(struct track *track) = 0;
|
||||
|
||||
/**
|
||||
* Called to begin playback on the currently loaded track.
|
||||
*/
|
||||
|
@ -112,13 +111,6 @@ namespace audio
|
|||
void next(); /**< Find and load the next track that should be played. */
|
||||
void prev(); /**< Call the deck :: previous() function and load the result. */
|
||||
|
||||
/**
|
||||
* Load a specific track for playback.
|
||||
*
|
||||
* @param track The track that should be loaded.
|
||||
*/
|
||||
void load_track(struct track *track);
|
||||
|
||||
/**
|
||||
* @return A pointer to the currently playing track object.
|
||||
*/
|
||||
|
@ -156,11 +148,14 @@ namespace audio
|
|||
|
||||
|
||||
/* Called to initialize the audio manager. */
|
||||
void audio_init(int *, char ***);
|
||||
void audio_init(int *, char ***, struct audio_ops *);
|
||||
|
||||
/* Called to deinitialize the audio manager. */
|
||||
void audio_deinit();
|
||||
|
||||
|
||||
/* Called to load a track for playback. */
|
||||
bool audio_load(struct track *);
|
||||
|
||||
GstElement *audio_get_player();
|
||||
#endif /* OCARINA_CORE_AUDIO_H */
|
||||
|
|
|
@ -12,6 +12,7 @@ struct core_init_data {
|
|||
struct queue_ops *history_ops;
|
||||
struct queue_ops *playlist_ops;
|
||||
struct queue_ops *tempq_ops;
|
||||
struct audio_ops *audio_ops;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -34,6 +34,7 @@ extern struct queue_ops collection_ops;
|
|||
extern struct queue_ops history_ops;
|
||||
extern struct queue_ops playlist_ops;
|
||||
extern struct queue_ops tempq_ops;
|
||||
extern struct audio_ops audio_ops;
|
||||
|
||||
void on_pq_created(queue *, unsigned int);
|
||||
void post_init_queue_tabs();
|
||||
|
|
|
@ -4,11 +4,14 @@
|
|||
#include <core/audio.h>
|
||||
extern "C" {
|
||||
#include <core/collection.h>
|
||||
#include <core/history.h>
|
||||
#include <core/idle.h>
|
||||
}
|
||||
#include <core/core.h>
|
||||
#include "test.h"
|
||||
|
||||
struct track *TRACK_NULL = NULL;
|
||||
static unsigned int load_count = 0;
|
||||
|
||||
|
||||
class TestDriver : public AudioDriver
|
||||
|
@ -22,13 +25,6 @@ public:
|
|||
TestDriver() : playing(false), cur_pos(0), cur_duration(0) {}
|
||||
~TestDriver() {};
|
||||
|
||||
void load(struct track *track)
|
||||
{
|
||||
cur_file = track_path(track);
|
||||
playing = false;
|
||||
cur_pos = 0;
|
||||
}
|
||||
|
||||
void play() { playing = true; }
|
||||
void pause() { playing = false; }
|
||||
|
||||
|
@ -39,26 +35,59 @@ public:
|
|||
int64_t duration() { return cur_duration; }
|
||||
} driver;
|
||||
|
||||
static void test_audio_load(struct track *track, GstState state)
|
||||
{
|
||||
load_count++;
|
||||
}
|
||||
|
||||
static struct audio_ops test_audio_ops = {
|
||||
test_audio_load,
|
||||
};
|
||||
|
||||
static struct core_init_data test_init_data = {
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
&test_audio_ops,
|
||||
};
|
||||
|
||||
|
||||
static void test_init()
|
||||
{
|
||||
test_equal(audio_get_player(), NULL);
|
||||
test_equal(audio :: current_track(), NULL);
|
||||
test_equal(audio_get_player(), NULL);
|
||||
|
||||
core :: init(NULL, NULL, &test_init_data);
|
||||
|
||||
test_equal(audio_load(NULL), false);
|
||||
test_equal(audio :: current_track(), NULL);
|
||||
|
||||
collection_add("tests/Music/Hyrule Symphony");
|
||||
while (idle_run_task()) {};
|
||||
|
||||
test_equal(audio :: current_track(), NULL);
|
||||
test_not_equal(audio_get_player(), NULL);
|
||||
}
|
||||
|
||||
static void test_playback()
|
||||
{
|
||||
test_equal(audio_load(track_get(0)), true);
|
||||
test_equal(load_count, 1);
|
||||
test_equal(audio :: current_track(), track_get(0));
|
||||
test_equal(queue_size(history_get_queue()), 1);
|
||||
|
||||
test_equal(audio_load(NULL), false);
|
||||
test_equal(load_count, 1);
|
||||
test_equal(audio :: current_track(), track_get(0));
|
||||
test_equal(queue_size(history_get_queue()), 1);
|
||||
|
||||
test_equal(audio_load(track_get(0)), false);
|
||||
test_equal(load_count, 1);
|
||||
test_equal(queue_size(history_get_queue()), 1);
|
||||
}
|
||||
|
||||
static void test_deinit()
|
||||
{
|
||||
core :: deinit();
|
||||
|
@ -107,7 +136,7 @@ void test_init2()
|
|||
struct track *track;
|
||||
|
||||
test_cp_data_dir();
|
||||
audio_init(NULL, NULL);
|
||||
audio_init(NULL, NULL, &test_audio_ops);
|
||||
|
||||
track = audio :: current_track();
|
||||
test_equal(track, TRACK_NULL);
|
||||
|
@ -158,17 +187,17 @@ void test_track_controls()
|
|||
audio :: next();
|
||||
test_equal(driver->is_playing(), true);
|
||||
|
||||
audio :: load_track(track);
|
||||
audio_load(track);
|
||||
test_not_equal(audio :: current_track(), track);
|
||||
|
||||
track = track_get(0);
|
||||
audio :: seek_to(4242);
|
||||
audio :: load_track(track);
|
||||
audio_load(track);
|
||||
test_equal(driver->is_playing(), true);
|
||||
test_equal(audio :: position(), (long)0);
|
||||
|
||||
audio :: seek_to(4242);
|
||||
audio :: load_track(track);
|
||||
audio_load(track);
|
||||
test_equal(driver->is_playing(), true);
|
||||
test_equal(audio :: position(), (long)4242);
|
||||
|
||||
|
@ -212,6 +241,7 @@ void test_autopause()
|
|||
|
||||
DECLARE_UNIT_TESTS(
|
||||
UNIT_TEST("Audio Initialization", test_init),
|
||||
UNIT_TEST("Audio Playback", test_playback),
|
||||
UNIT_TEST("Audio Deinitialization", test_deinit),
|
||||
UNIT_TEST("Test Audio Pre-Init", test_pre_init),
|
||||
UNIT_TEST("Test Audio Init 2", test_init2),
|
||||
|
|
Loading…
Reference in New Issue