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:
parent
56f0e801f5
commit
01288e1a86
2
PKGBUILD
2
PKGBUILD
|
@ -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=()
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
|
@ -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();
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
Loading…
Reference in New Issue