Libsaria: Make alsa controls its own thing

I created a new preference for "Using ALSA" that people can set if they
want to use extra alsa features.  This should allow the UI to provide a
dropdown list of outputs that users can select.  Once a UI is in place,
users can play music either on their computer speakers or pipe it out to
their blu ray players (or other device).

Signed-off-by: Bryan Schumaker <bjschuma@netapp.com>
This commit is contained in:
Bryan Schumaker 2012-02-01 08:29:25 -05:00
parent 56f0e801f5
commit 01288e1a86
7 changed files with 152 additions and 8 deletions

View File

@ -6,7 +6,7 @@ pkgdesc="A simple GTK and gstreamer based music player."
url="http://www.ocarinaproject.net/"
arch=('x86_64' 'i686')
license=('SimPL')
depends=('gtk2' 'gstreamer0.10-base' 'taglib')
depends=('gtk2' 'gstreamer0.10-base' 'gstreamer0.10-base-plugins' 'taglib')
optdepends=('gstreamer0.10-good-plugins' 'gstreamer0.10-bad-plugins' 'gstreamer0.10-ugly-plugins')
makedepends=('scons')
conflicts=()

View File

@ -26,6 +26,7 @@ env.Append(CPPPATH = "include")
env.ParseConfig('pkg-config --cflags --libs gtk+-2.0')
env.ParseConfig('pkg-config --cflags --libs gstreamer-0.10')
env.ParseConfig('pkg-config --cflags --libs gstreamer-interfaces-0.10')
env.ParseConfig('pkg-config --cflags --libs taglib')
def version_h(target, source, env):

View File

@ -5,6 +5,7 @@ extern "C" {
#include <gst/gst.h>
}
#include <list>
#include <string>
using namespace std;
@ -13,8 +14,15 @@ namespace libsaria
namespace audio
{
void init(int, char**);
void swap();
string get_current_file();
/* Alsa controls */
void use_alsa(bool);
bool using_alsa();
list<string> *get_alsa_devices();
void set_device(string &);
/* Playback control functions */
void load_file(string);
void load(string);

91
libsaria/audio/alsa.cpp Normal file
View File

@ -0,0 +1,91 @@
// Copyright (c) 2012 Bryan Schumaker.
#include <gst/interfaces/propertyprobe.h>
#include <libsaria/audio.h>
#include <libsaria/prefs.h>
#include <libsaria/print.h>
#include "audio.h"
#include <list>
using namespace std;
static GstElement *alsa = NULL;
static list<string> devices;
static void probe_devices()
{
GValueArray *array;
GValue *value;
devices.clear();
array = gst_property_probe_probe_and_get_values_name(GST_PROPERTY_PROBE(alsa), "device");
devices.push_back("default");
for (unsigned int i = 0; i < array->n_values; i++) {
value = g_value_array_get_nth(array, i);
devices.push_back(g_value_get_string(value));
}
}
static void set_alsa_device(string device)
{
g_object_set(G_OBJECT(alsa), "device", device.c_str(), NULL);
}
static void add_alsa()
{
println("Adding ALSA");
alsa = gst_element_factory_make("alsasink", "alsa");
probe_devices();
set_audio_sink(alsa);
}
static void remove_alsa()
{
println("Removing ALSA");
set_alsa_device("default");
/* Removing the sink will also deallocate it */
set_audio_sink(NULL);
}
namespace libsaria
{
void audio::use_alsa(bool use)
{
struct StoredAudioState state;
save_audio_state(&state);
if (use == true)
add_alsa();
else
remove_alsa();
load_audio_state(&state);
prefs::set("alsa", use);
}
bool audio::using_alsa()
{
return prefs::get_bool("alsa");
}
void audio::init_alsa()
{
use_alsa(using_alsa());
}
list<string> *audio::get_alsa_devices()
{
return &devices;
}
void audio::set_device(string &device)
{
struct StoredAudioState state;
save_audio_state(&state);
g_object_set(G_OBJECT(alsa), "device", device.c_str(), NULL);
load_audio_state(&state);
}
}; /* Namespace: libsaria */

View File

@ -7,8 +7,8 @@
#include "audio.h"
GstElement *player = NULL;
GstElement *alsa = NULL;
GstBus *bus = NULL;
static bool restoring_state = false;
static void parse_error(GstMessage *error)
{
@ -28,7 +28,8 @@ static void notify_audio_changed()
libsaria::audio::pause();
libsaria::set_pause_after(false);
}
trigger_callback(TRACK_LOADED);
if (restoring_state == false)
trigger_callback(TRACK_LOADED);
}
static gboolean on_message(GstBus *bus, GstMessage *message, gpointer data)
@ -59,6 +60,40 @@ static void audio_changed(GstElement *playbin, gpointer data)
notify_audio_changed();
}
/*
* Set sink to NULL to use the default sink
*/
void set_audio_sink(GstElement *sink)
{
g_object_set(G_OBJECT(player), "audio-sink", sink, NULL);
}
void save_audio_state(struct StoredAudioState *state)
{
state->cur_file = libsaria::audio::get_current_file();
state->position = libsaria::audio::position();
state->was_playing = libsaria::audio::is_playing();
}
void load_audio_state(struct StoredAudioState *state)
{
restoring_state = true;
libsaria::audio::load(state->cur_file);
if (state->was_playing == true)
libsaria::audio::play();
else
libsaria::audio::pause();
/*
* Wait for async play() or pause() to finish, otherwise
* the seek won't succeed
*/
gst_element_get_state(GST_ELEMENT(player), NULL, NULL, GST_CLOCK_TIME_NONE);
libsaria::audio::seek_to(state->position);
restoring_state = false;
}
namespace libsaria
{
@ -68,18 +103,15 @@ namespace libsaria
gst_init(&argc, &argv);
player = gst_element_factory_make("playbin2", "player");
alsa = gst_element_factory_make("alsasink", "alsa");
bus = gst_pipeline_get_bus(GST_PIPELINE(player));
gst_bus_add_watch(bus, on_message, NULL);
/* Without this gapless playback won't work */
g_object_set(G_OBJECT(player), "audio-sink", alsa, NULL);
g_signal_connect(player, "about-to-finish", G_CALLBACK(about_to_finish), NULL);
g_signal_connect(player, "audio-changed", G_CALLBACK(audio_changed), NULL);
init_volume();
init_alsa();
}
};

View File

@ -11,13 +11,25 @@ extern "C" {
extern GstElement *player;
extern GstBus *bus;
struct StoredAudioState
{
string cur_file;
double position;
bool was_playing;
};
void load_file(GstElement *, string);
void set_audio_sink(GstElement *);
void save_audio_state(struct StoredAudioState *);
void load_audio_state(struct StoredAudioState *);
namespace libsaria
{
namespace audio
{
void init_volume();
void init_alsa();
}
}

View File

@ -18,12 +18,12 @@ namespace libsaria
{
srand( time(NULL) );
println("Initializing libsaria");
libsaria::prefs::load();
audio::init(argc, argv);
println("saria dir: %s", get_saria_dir().c_str());
make_saria_dir();
libsaria::library::load();
libsaria::queue::load();
libsaria::prefs::load();
}
void quit()