gui: Implement control buttons
Play, pause, stop and so on. I also update labels and progress bars during playback. Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
This commit is contained in:
parent
a865ac36a3
commit
c346a5860a
|
@ -1,12 +1,14 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2014 (c) Anna Schumaker.
|
* Copyright 2014 (c) Anna Schumaker.
|
||||||
*/
|
*/
|
||||||
|
#include <audio.h>
|
||||||
#include <deck.h>
|
#include <deck.h>
|
||||||
#include <ocarina.h>
|
#include <ocarina.h>
|
||||||
|
|
||||||
Gtk::Window *ocarina_init()
|
Gtk::Window *ocarina_init(int *argc, char ***argv)
|
||||||
{
|
{
|
||||||
Gtk::Window *window = connect_wires();
|
Gtk::Window *window = connect_wires();
|
||||||
|
audio::init(argc, argv);
|
||||||
deck::init();
|
deck::init();
|
||||||
library::init();
|
library::init();
|
||||||
return window;
|
return window;
|
||||||
|
@ -15,8 +17,8 @@ Gtk::Window *ocarina_init()
|
||||||
#ifndef CONFIG_TEST
|
#ifndef CONFIG_TEST
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
Gtk::Main ocarina(argc, argv);
|
Gtk::Main ocarina(&argc, &argv);
|
||||||
Gtk::Window *window = ocarina_init();
|
Gtk::Window *window = ocarina_init(argc, argv);
|
||||||
Gtk::Main::run(*window);
|
Gtk::Main::run(*window);
|
||||||
cleanup_tabs();
|
cleanup_tabs();
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -362,7 +362,7 @@ Manager</property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkScale" id="scale1">
|
<object class="GtkScale" id="o_position_scale">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">True</property>
|
<property name="can_focus">True</property>
|
||||||
<property name="adjustment">o_progress</property>
|
<property name="adjustment">o_progress</property>
|
||||||
|
@ -627,7 +627,7 @@ Manager</property>
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">False</property>
|
<property name="can_focus">False</property>
|
||||||
<property name="xalign">0</property>
|
<property name="xalign">0</property>
|
||||||
<property name="label" translatable="yes"><span size='xx-large'>A Random Song Title</span></property>
|
<property name="label" translatable="yes"><span size='xx-large'></span></property>
|
||||||
<property name="use_markup">True</property>
|
<property name="use_markup">True</property>
|
||||||
</object>
|
</object>
|
||||||
<packing>
|
<packing>
|
||||||
|
@ -641,7 +641,7 @@ Manager</property>
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">False</property>
|
<property name="can_focus">False</property>
|
||||||
<property name="xalign">0</property>
|
<property name="xalign">0</property>
|
||||||
<property name="label" translatable="yes"><span size='x-large'>By: Some Artist</span></property>
|
<property name="label" translatable="yes"><span size='x-large'></span></property>
|
||||||
<property name="use_markup">True</property>
|
<property name="use_markup">True</property>
|
||||||
</object>
|
</object>
|
||||||
<packing>
|
<packing>
|
||||||
|
@ -655,7 +655,7 @@ Manager</property>
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">False</property>
|
<property name="can_focus">False</property>
|
||||||
<property name="xalign">0</property>
|
<property name="xalign">0</property>
|
||||||
<property name="label" translatable="yes"><span size='x-large'>From: Some Album</span></property>
|
<property name="label" translatable="yes"><span size='x-large'></span></property>
|
||||||
<property name="use_markup">True</property>
|
<property name="use_markup">True</property>
|
||||||
</object>
|
</object>
|
||||||
<packing>
|
<packing>
|
||||||
|
|
10
gui/tabs.cpp
10
gui/tabs.cpp
|
@ -183,12 +183,18 @@ void OcarinaTab::on_runtime_changed()
|
||||||
*/
|
*/
|
||||||
static void on_track_added(Playqueue *pq, unsigned int row)
|
static void on_track_added(Playqueue *pq, unsigned int row)
|
||||||
{
|
{
|
||||||
tab_map[pq]->on_row_inserted(row);
|
std::map<Playqueue *, OcarinaTab *>::iterator it;
|
||||||
|
it = tab_map.find(pq);
|
||||||
|
if (it != tab_map.end())
|
||||||
|
it->second->on_row_inserted(row);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void on_track_deleted(Playqueue *pq, unsigned int row)
|
static void on_track_deleted(Playqueue *pq, unsigned int row)
|
||||||
{
|
{
|
||||||
tab_map[pq]->on_row_deleted(row);
|
std::map<Playqueue *, OcarinaTab *>::iterator it;
|
||||||
|
it = tab_map.find(pq);
|
||||||
|
if (it != tab_map.end())
|
||||||
|
it->second->on_row_deleted(row);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void on_switch_page(Gtk::Widget *page, unsigned int num)
|
static void on_switch_page(Gtk::Widget *page, unsigned int num)
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2014 (c) Anna Schumaker.
|
* Copyright 2014 (c) Anna Schumaker.
|
||||||
*/
|
*/
|
||||||
|
#include <audio.h>
|
||||||
#include <callback.h>
|
#include <callback.h>
|
||||||
#include <idle.h>
|
#include <idle.h>
|
||||||
#include <library.h>
|
#include <library.h>
|
||||||
|
@ -8,13 +9,49 @@
|
||||||
#include <ocarina.h>
|
#include <ocarina.h>
|
||||||
#include <print.h>
|
#include <print.h>
|
||||||
|
|
||||||
|
static bool audio_playing = false;
|
||||||
static Glib::RefPtr<Gtk::Builder> builder;
|
static Glib::RefPtr<Gtk::Builder> builder;
|
||||||
void enable_idle();
|
void enable_idle();
|
||||||
|
void enable_timeout();
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
void get_object(const std::string &, Glib::RefPtr<T> &);
|
void get_object(const std::string &, Glib::RefPtr<T> &);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Control functions
|
||||||
|
*/
|
||||||
|
static void on_play()
|
||||||
|
{
|
||||||
|
get_button("o_play")->hide();
|
||||||
|
get_button("o_pause")->show();
|
||||||
|
audio_playing = true;
|
||||||
|
enable_timeout();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_pause()
|
||||||
|
{
|
||||||
|
get_button("o_play")->show();
|
||||||
|
get_button("o_pause")->hide();
|
||||||
|
audio_playing = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_track_loaded(library :: Song &song)
|
||||||
|
{
|
||||||
|
Gtk::Label *title, *artist, *album, *duration;
|
||||||
|
builder->get_widget("o_title", title);
|
||||||
|
builder->get_widget("o_artist", artist);
|
||||||
|
builder->get_widget("o_album", album);
|
||||||
|
builder->get_widget("o_total_time", duration);
|
||||||
|
|
||||||
|
title->set_markup("<span size='xx-large'>" + song.track->title + "</span>");
|
||||||
|
artist->set_markup("<span size='x-large'>By: " + song.artist->primary_key + "</span>");
|
||||||
|
album->set_markup("<span size='x-large'>From: " + song.album->name + "</span>");
|
||||||
|
duration->set_text(song.track->length_str);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Collection manager functions
|
* Collection manager functions
|
||||||
*/
|
*/
|
||||||
|
@ -163,6 +200,31 @@ void enable_idle()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Timeout function
|
||||||
|
*/
|
||||||
|
bool on_timeout()
|
||||||
|
{
|
||||||
|
Gtk::Label *position;
|
||||||
|
Glib::RefPtr<Gtk::Adjustment> bar;
|
||||||
|
|
||||||
|
builder->get_widget("o_cur_position", position);
|
||||||
|
get_object("o_progress", bar);
|
||||||
|
|
||||||
|
position->set_text(audio :: position_str());
|
||||||
|
bar->set_upper(audio :: duration());
|
||||||
|
bar->set_value(audio :: position());
|
||||||
|
|
||||||
|
return audio_playing;
|
||||||
|
}
|
||||||
|
|
||||||
|
void enable_timeout()
|
||||||
|
{
|
||||||
|
Glib::signal_timeout().connect(sigc::ptr_fun(on_timeout), 500);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Ocarina functions
|
* Ocarina functions
|
||||||
*/
|
*/
|
||||||
|
@ -202,6 +264,17 @@ Gtk::Window *connect_wires()
|
||||||
builder->get_widget("o_window", window);
|
builder->get_widget("o_window", window);
|
||||||
|
|
||||||
|
|
||||||
|
/* Controls */
|
||||||
|
cb->on_play = on_play;
|
||||||
|
cb->on_pause = on_pause;
|
||||||
|
cb->on_track_loaded = on_track_loaded;
|
||||||
|
connect_button("o_play", audio::play);
|
||||||
|
connect_button("o_pause", audio::pause);
|
||||||
|
connect_button("o_stop", audio::stop);
|
||||||
|
connect_button("o_prev", audio::previous);
|
||||||
|
connect_button("o_next", audio::next);
|
||||||
|
|
||||||
|
|
||||||
/* Collection manager */
|
/* Collection manager */
|
||||||
cb->on_library_add = on_library_add;
|
cb->on_library_add = on_library_add;
|
||||||
cb->on_library_update = on_library_update;
|
cb->on_library_update = on_library_update;
|
||||||
|
|
|
@ -8,6 +8,8 @@ extern "C" {
|
||||||
#include <gst/gst.h>
|
#include <gst/gst.h>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
namespace audio
|
namespace audio
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -23,6 +25,7 @@ namespace audio
|
||||||
|
|
||||||
void seek_to(long);
|
void seek_to(long);
|
||||||
long position();
|
long position();
|
||||||
|
std::string position_str();
|
||||||
long duration();
|
long duration();
|
||||||
|
|
||||||
void pause_after(bool, unsigned int);
|
void pause_after(bool, unsigned int);
|
||||||
|
|
|
@ -9,6 +9,11 @@
|
||||||
|
|
||||||
|
|
||||||
struct Callbacks {
|
struct Callbacks {
|
||||||
|
/* Audio callbacks */
|
||||||
|
void (*on_play)();
|
||||||
|
void (*on_pause)();
|
||||||
|
void (*on_track_loaded)(library :: Song &);
|
||||||
|
|
||||||
/* Library callbacks */
|
/* Library callbacks */
|
||||||
void (*on_library_add)(unsigned int, library :: Library *);
|
void (*on_library_add)(unsigned int, library :: Library *);
|
||||||
void (*on_library_update)(unsigned int, library :: Library *);
|
void (*on_library_update)(unsigned int, library :: Library *);
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
#include <gtkmm.h>
|
#include <gtkmm.h>
|
||||||
|
|
||||||
/* main.cpp */
|
/* main.cpp */
|
||||||
Gtk::Window *ocarina_init();
|
Gtk::Window *ocarina_init(int *, char ***);
|
||||||
|
|
||||||
/* model.cpp */
|
/* model.cpp */
|
||||||
class PlayqueueModel : public Gtk::TreeModel, public Glib::Object {
|
class PlayqueueModel : public Gtk::TreeModel, public Glib::Object {
|
||||||
|
|
|
@ -2,9 +2,11 @@
|
||||||
* Copyright 2013 (c) Anna Schumaker.
|
* Copyright 2013 (c) Anna Schumaker.
|
||||||
*/
|
*/
|
||||||
#include <audio.h>
|
#include <audio.h>
|
||||||
|
#include <callback.h>
|
||||||
#include <deck.h>
|
#include <deck.h>
|
||||||
#include <library.h>
|
#include <library.h>
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
static GstElement *ocarina_player;
|
static GstElement *ocarina_player;
|
||||||
|
@ -89,6 +91,7 @@ static bool load_song(library :: Song &song)
|
||||||
g_object_set(G_OBJECT(ocarina_player), "uri", escaped, NULL);
|
g_object_set(G_OBJECT(ocarina_player), "uri", escaped, NULL);
|
||||||
g_free(escaped);
|
g_free(escaped);
|
||||||
|
|
||||||
|
get_callbacks()->on_track_loaded(song);
|
||||||
return change_state(state);
|
return change_state(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,14 +118,16 @@ void audio :: play()
|
||||||
{
|
{
|
||||||
if (track_loaded == false)
|
if (track_loaded == false)
|
||||||
return;
|
return;
|
||||||
change_state(GST_STATE_PLAYING);
|
if (change_state(GST_STATE_PLAYING))
|
||||||
|
get_callbacks()->on_play();
|
||||||
}
|
}
|
||||||
|
|
||||||
void audio :: pause()
|
void audio :: pause()
|
||||||
{
|
{
|
||||||
if (track_loaded == false)
|
if (track_loaded == false)
|
||||||
return;
|
return;
|
||||||
change_state(GST_STATE_PAUSED);
|
if (change_state(GST_STATE_PAUSED))
|
||||||
|
get_callbacks()->on_pause();
|
||||||
}
|
}
|
||||||
|
|
||||||
void audio :: stop()
|
void audio :: stop()
|
||||||
|
@ -192,6 +197,20 @@ long audio :: position()
|
||||||
return position;
|
return position;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string audio :: position_str()
|
||||||
|
{
|
||||||
|
std::stringstream ss;
|
||||||
|
long cur = position() / GST_SECOND;
|
||||||
|
unsigned int minutes = cur / 60;
|
||||||
|
unsigned int seconds = cur % 60;
|
||||||
|
|
||||||
|
ss << minutes << ":";
|
||||||
|
if (seconds < 10)
|
||||||
|
ss << "0";
|
||||||
|
ss << seconds;
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
long audio :: duration()
|
long audio :: duration()
|
||||||
{
|
{
|
||||||
long duration;
|
long duration;
|
||||||
|
|
|
@ -4,12 +4,18 @@
|
||||||
#include <callback.h>
|
#include <callback.h>
|
||||||
|
|
||||||
|
|
||||||
|
static void no_op() {}
|
||||||
static void no_op(unsigned int) {}
|
static void no_op(unsigned int) {}
|
||||||
static void no_op(unsigned int id, library :: Library *path) {}
|
static void no_op(unsigned int id, library :: Library *path) {}
|
||||||
static void no_op(Playqueue *, unsigned int) {}
|
static void no_op(Playqueue *, unsigned int) {}
|
||||||
|
static void no_op(library :: Song &) {}
|
||||||
|
|
||||||
|
|
||||||
static struct Callbacks callbacks = {
|
static struct Callbacks callbacks = {
|
||||||
|
.on_play = no_op,
|
||||||
|
.on_pause = no_op,
|
||||||
|
.on_track_loaded = no_op,
|
||||||
|
|
||||||
.on_library_add = no_op,
|
.on_library_add = no_op,
|
||||||
.on_library_update = no_op,
|
.on_library_update = no_op,
|
||||||
.on_library_track_add = no_op,
|
.on_library_track_add = no_op,
|
||||||
|
|
|
@ -73,6 +73,42 @@ bool test_1()
|
||||||
on_collection_toggled("3");
|
on_collection_toggled("3");
|
||||||
break;
|
break;
|
||||||
case 9:
|
case 9:
|
||||||
|
change_page(1);
|
||||||
|
break;
|
||||||
|
case 10:
|
||||||
|
change_page(0);
|
||||||
|
break;
|
||||||
|
case 11:
|
||||||
|
click_button("o_next");
|
||||||
|
break;
|
||||||
|
case 12:
|
||||||
|
click_button("o_play");
|
||||||
|
break;
|
||||||
|
case 13:
|
||||||
|
click_button("o_pause");
|
||||||
|
break;
|
||||||
|
case 14:
|
||||||
|
click_button("o_play");
|
||||||
|
break;
|
||||||
|
case 15:
|
||||||
|
click_button("o_stop");
|
||||||
|
break;
|
||||||
|
case 16:
|
||||||
|
click_button("o_next");
|
||||||
|
break;
|
||||||
|
case 17:
|
||||||
|
click_button("o_next");
|
||||||
|
break;
|
||||||
|
case 18:
|
||||||
|
click_button("o_prev");
|
||||||
|
break;
|
||||||
|
case 19:
|
||||||
|
click_button("o_play");
|
||||||
|
break;
|
||||||
|
case 20:
|
||||||
|
case 21:
|
||||||
|
case 22:
|
||||||
|
case 23:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
end_test();
|
end_test();
|
||||||
|
@ -162,7 +198,7 @@ int main(int argc, char **argv)
|
||||||
library::init();
|
library::init();
|
||||||
library::reset();
|
library::reset();
|
||||||
|
|
||||||
Gtk::Window *window = ocarina_init();
|
Gtk::Window *window = ocarina_init(&argc, &argv);
|
||||||
|
|
||||||
schedule_test(test_0);
|
schedule_test(test_0);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue