libsaria: Implement gapless playback
I need to get the next file out of the library or queue without changing it immediately. I then queue it up in the gstreamer pipeline so it will play automatically when the current track finishes.
This commit is contained in:
parent
2783b8d995
commit
0e983e4043
|
@ -4,6 +4,7 @@
|
|||
namespace libsaria
|
||||
{
|
||||
void next();
|
||||
string next_file();
|
||||
void set_pause_after(bool);
|
||||
bool get_pause_after();
|
||||
void toggle_play();
|
||||
|
|
|
@ -24,9 +24,11 @@ namespace libsaria
|
|||
void refresh();
|
||||
|
||||
void next();
|
||||
string next_file();
|
||||
void add_path(string);
|
||||
void remove_path(string);
|
||||
void play_id(ino_t &);
|
||||
string find_filepath(ino_t &);
|
||||
TrackTag *get_info(ino_t &);
|
||||
void for_each(SourceModel *);
|
||||
void for_each_path(void (*)(struct PathInfo &));
|
||||
|
|
|
@ -15,6 +15,7 @@ namespace libsaria
|
|||
unsigned int size();
|
||||
|
||||
void next();
|
||||
string next_file();
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,10 +2,12 @@
|
|||
#include <libsaria/audio.h>
|
||||
#include <libsaria/controls.h>
|
||||
#include <libsaria/print.h>
|
||||
#include <libsaria/library.h>
|
||||
#include <libsaria/callback.h>
|
||||
#include "audio.h"
|
||||
|
||||
GstElement *player = NULL;
|
||||
GstElement *alsa = NULL;
|
||||
GstBus *bus = NULL;
|
||||
|
||||
static void parse_error(GstMessage *error)
|
||||
|
@ -49,6 +51,16 @@ static gboolean on_message(GstBus *bus, GstMessage *message, gpointer data)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static void about_to_finish(GstElement *playbin, gpointer data)
|
||||
{
|
||||
string file;
|
||||
|
||||
println("About to finish!");
|
||||
file = libsaria::next_file();
|
||||
if (file != "")
|
||||
load_file(playbin, file);
|
||||
}
|
||||
|
||||
static void audio_changed(GstElement *playbin, gpointer data)
|
||||
{
|
||||
GQuark quark = g_quark_from_string("audio-changed");
|
||||
|
@ -68,9 +80,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);
|
||||
|
||||
set_volume(1.0);
|
||||
|
|
|
@ -23,6 +23,14 @@ namespace libsaria
|
|||
audio::play();
|
||||
}
|
||||
|
||||
string next_file()
|
||||
{
|
||||
if (queue::size() > 0)
|
||||
return queue::next_file();
|
||||
else
|
||||
return library::next_file();
|
||||
}
|
||||
|
||||
void set_pause_after(bool state)
|
||||
{
|
||||
pause_after_current = state;
|
||||
|
|
|
@ -157,6 +157,14 @@ namespace libsaria
|
|||
}
|
||||
}
|
||||
|
||||
string library::find_filepath(ino_t &id)
|
||||
{
|
||||
list<TrackTag *>::iterator it;
|
||||
if (find_id(id, it))
|
||||
return (*it)->get_filepath();
|
||||
return "";
|
||||
}
|
||||
|
||||
TrackTag *library::get_info(ino_t &id)
|
||||
{
|
||||
list<TrackTag *>::iterator it;
|
||||
|
@ -165,20 +173,28 @@ namespace libsaria
|
|||
return NULL;
|
||||
}
|
||||
|
||||
void library::next()
|
||||
string library::next_file()
|
||||
{
|
||||
string filepath = "";
|
||||
|
||||
if (libsaria::library::size() == 0) {
|
||||
libsaria::audio::stop();
|
||||
return;
|
||||
}
|
||||
if (libsaria::library::size() == 0)
|
||||
return filepath;
|
||||
|
||||
do {
|
||||
pick_next();
|
||||
filepath = (*cur_track)->get_filepath();
|
||||
} while (filepath == "");
|
||||
libsaria::audio::load(filepath);
|
||||
|
||||
return filepath;
|
||||
}
|
||||
|
||||
void library::next()
|
||||
{
|
||||
string filepath = next_file();
|
||||
if (filepath != "")
|
||||
libsaria::audio::load(filepath);
|
||||
else
|
||||
libsaria::audio::stop();
|
||||
}
|
||||
|
||||
unsigned int library::size()
|
||||
|
|
|
@ -9,6 +9,13 @@ using namespace std;
|
|||
|
||||
static deque<ino_t> playqueue;
|
||||
|
||||
static void pop_queue(ino_t &inode)
|
||||
{
|
||||
inode = playqueue.front();
|
||||
playqueue.pop_front();
|
||||
trigger_callback(QUEUE_REFRESH);
|
||||
}
|
||||
|
||||
namespace libsaria
|
||||
{
|
||||
|
||||
|
@ -35,11 +42,18 @@ namespace libsaria
|
|||
return playqueue.size();
|
||||
}
|
||||
|
||||
string queue::next_file()
|
||||
{
|
||||
ino_t inode;
|
||||
pop_queue(inode);
|
||||
return library::find_filepath(inode);
|
||||
}
|
||||
|
||||
void queue::next()
|
||||
{
|
||||
library::play_id(playqueue.front());
|
||||
playqueue.pop_front();
|
||||
trigger_callback(QUEUE_REFRESH);
|
||||
ino_t inode;
|
||||
pop_queue(inode);
|
||||
library::play_id(inode);
|
||||
}
|
||||
|
||||
} /* Namespace: libsaria */
|
||||
|
|
Loading…
Reference in New Issue