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:
Anna Schumaker 2014-01-22 22:31:42 -05:00 committed by Anna Schumaker
parent a865ac36a3
commit c346a5860a
10 changed files with 163 additions and 13 deletions

View File

@ -1,12 +1,14 @@
/*
* Copyright 2014 (c) Anna Schumaker.
*/
#include <audio.h>
#include <deck.h>
#include <ocarina.h>
Gtk::Window *ocarina_init()
Gtk::Window *ocarina_init(int *argc, char ***argv)
{
Gtk::Window *window = connect_wires();
audio::init(argc, argv);
deck::init();
library::init();
return window;
@ -15,8 +17,8 @@ Gtk::Window *ocarina_init()
#ifndef CONFIG_TEST
int main(int argc, char **argv)
{
Gtk::Main ocarina(argc, argv);
Gtk::Window *window = ocarina_init();
Gtk::Main ocarina(&argc, &argv);
Gtk::Window *window = ocarina_init(argc, argv);
Gtk::Main::run(*window);
cleanup_tabs();
return 0;

View File

@ -362,7 +362,7 @@ Manager</property>
</packing>
</child>
<child>
<object class="GtkScale" id="scale1">
<object class="GtkScale" id="o_position_scale">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="adjustment">o_progress</property>
@ -627,7 +627,7 @@ Manager</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">&lt;span size='xx-large'&gt;A Random Song Title&lt;/span&gt;</property>
<property name="label" translatable="yes">&lt;span size='xx-large'&gt;&lt;/span&gt;</property>
<property name="use_markup">True</property>
</object>
<packing>
@ -641,7 +641,7 @@ Manager</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">&lt;span size='x-large'&gt;By: Some Artist&lt;/span&gt;</property>
<property name="label" translatable="yes">&lt;span size='x-large'&gt;&lt;/span&gt;</property>
<property name="use_markup">True</property>
</object>
<packing>
@ -655,7 +655,7 @@ Manager</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">&lt;span size='x-large'&gt;From: Some Album&lt;/span&gt;</property>
<property name="label" translatable="yes">&lt;span size='x-large'&gt;&lt;/span&gt;</property>
<property name="use_markup">True</property>
</object>
<packing>

View File

@ -183,12 +183,18 @@ void OcarinaTab::on_runtime_changed()
*/
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)
{
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)

View File

@ -1,6 +1,7 @@
/*
* Copyright 2014 (c) Anna Schumaker.
*/
#include <audio.h>
#include <callback.h>
#include <idle.h>
#include <library.h>
@ -8,13 +9,49 @@
#include <ocarina.h>
#include <print.h>
static bool audio_playing = false;
static Glib::RefPtr<Gtk::Builder> builder;
void enable_idle();
void enable_timeout();
template <class 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
*/
@ -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
*/
@ -202,6 +264,17 @@ Gtk::Window *connect_wires()
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 */
cb->on_library_add = on_library_add;
cb->on_library_update = on_library_update;

View File

@ -8,6 +8,8 @@ extern "C" {
#include <gst/gst.h>
}
#include <string>
namespace audio
{
@ -23,6 +25,7 @@ namespace audio
void seek_to(long);
long position();
std::string position_str();
long duration();
void pause_after(bool, unsigned int);

View File

@ -9,6 +9,11 @@
struct Callbacks {
/* Audio callbacks */
void (*on_play)();
void (*on_pause)();
void (*on_track_loaded)(library :: Song &);
/* Library callbacks */
void (*on_library_add)(unsigned int, library :: Library *);
void (*on_library_update)(unsigned int, library :: Library *);

View File

@ -8,7 +8,7 @@
#include <gtkmm.h>
/* main.cpp */
Gtk::Window *ocarina_init();
Gtk::Window *ocarina_init(int *, char ***);
/* model.cpp */
class PlayqueueModel : public Gtk::TreeModel, public Glib::Object {

View File

@ -2,9 +2,11 @@
* Copyright 2013 (c) Anna Schumaker.
*/
#include <audio.h>
#include <callback.h>
#include <deck.h>
#include <library.h>
#include <sstream>
#include <string.h>
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_free(escaped);
get_callbacks()->on_track_loaded(song);
return change_state(state);
}
@ -115,14 +118,16 @@ void audio :: play()
{
if (track_loaded == false)
return;
change_state(GST_STATE_PLAYING);
if (change_state(GST_STATE_PLAYING))
get_callbacks()->on_play();
}
void audio :: pause()
{
if (track_loaded == false)
return;
change_state(GST_STATE_PAUSED);
if (change_state(GST_STATE_PAUSED))
get_callbacks()->on_pause();
}
void audio :: stop()
@ -192,6 +197,20 @@ long audio :: 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 duration;

View File

@ -4,12 +4,18 @@
#include <callback.h>
static void no_op() {}
static void no_op(unsigned int) {}
static void no_op(unsigned int id, library :: Library *path) {}
static void no_op(Playqueue *, unsigned int) {}
static void no_op(library :: Song &) {}
static struct Callbacks callbacks = {
.on_play = no_op,
.on_pause = no_op,
.on_track_loaded = no_op,
.on_library_add = no_op,
.on_library_update = no_op,
.on_library_track_add = no_op,

View File

@ -73,6 +73,42 @@ bool test_1()
on_collection_toggled("3");
break;
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;
default:
end_test();
@ -162,7 +198,7 @@ int main(int argc, char **argv)
library::init();
library::reset();
Gtk::Window *window = ocarina_init();
Gtk::Window *window = ocarina_init(&argc, &argv);
schedule_test(test_0);