From 528349cd826c13d0fedf6b2d2925def6607e2604 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 6 Sep 2004 21:55:49 +0000 Subject: make it work git-svn-id: file:///home/lennart/svn/public/pavumeter/trunk@4 c62a5a7b-6fe3-0310-9d5a-afe6de46906b --- src/Makefile | 2 +- src/vumeter.cc | 113 +++++++++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 95 insertions(+), 20 deletions(-) diff --git a/src/Makefile b/src/Makefile index d38d19d..cb795ec 100644 --- a/src/Makefile +++ b/src/Makefile @@ -2,7 +2,7 @@ all: pavumeter pavumeter: vumeter.cc - $(CXX) $^ -o $@ `pkg-config gtkmm-2.4 --cflags --libs` -I ../../polypaudio -lpolyp -lpolyp-mainloop-glib -L../../polypaudio/polyp/.libs -Wall -W -pipe -O0 -g + $(CXX) $^ -o $@ `pkg-config gtkmm-2.4 --cflags --libs` -I ../../polypaudio -lpolyp -lpolyp-mainloop-glib -lpolyp-error -L../../polypaudio/polyp/.libs -Wall -W -pipe -O0 -g clean: rm -f *.o pavumeter diff --git a/src/vumeter.cc b/src/vumeter.cc index bc6ad58..594cf67 100644 --- a/src/vumeter.cc +++ b/src/vumeter.cc @@ -1,8 +1,12 @@ +/* $Id$ */ + #include #include #include #include +#include +#include #include class MainWindow : public Gtk::Window { @@ -23,10 +27,17 @@ protected: Gtk::Table table; std::vector channels; + float *levels; + virtual void addChannel(const Glib::ustring &l); + virtual bool on_delete_event(GdkEventAny* e); + virtual bool on_timeout(); + + sigc::connection timeout_signal_connection; public: virtual void pushData(const float *d, size_t l); + virtual void showLevels(); }; MainWindow::MainWindow(unsigned nchan) : @@ -55,6 +66,12 @@ MainWindow::MainWindow(unsigned nchan) : } g_assert(channels.size() == nchan); + + levels = new float[nchan]; + for (unsigned c = 0; c < nchan; c++) + levels[c] = 0; + + timeout_signal_connection = Glib::signal_timeout().connect(sigc::mem_fun(*this, &MainWindow::on_timeout), 50); show_all(); } @@ -65,6 +82,14 @@ MainWindow::~MainWindow() { channels.pop_back(); delete i; } + + delete[] levels; + timeout_signal_connection.disconnect(); +} + +bool MainWindow::on_delete_event(GdkEventAny*) { + Gtk::Main::quit(); + return false; } void MainWindow::addChannel(const Glib::ustring &l) { @@ -83,47 +108,55 @@ MainWindow::ChannelInfo::ChannelInfo(MainWindow &w, const Glib::ustring &l) { w.table.attach(*progress, 1, 2, w.channels.size(), w.channels.size()+1, Gtk::EXPAND|Gtk::FILL, (Gtk::AttachOptions) 0); } + void MainWindow::pushData(const float *d, unsigned samples) { - float *max; unsigned nchan = channels.size(); - max = (float*) g_malloc(sizeof(float)*nchan); - g_assert(max); - - for (unsigned c = 0; c < nchan; c++) - max[c] = 0; + g_assert(levels); while (samples >= nchan) { for (unsigned c = 0; c < nchan; c++) { float v = fabs(d[c]); - if (v > max[c]) - max[c] = v; + if (v > levels[c]) + levels[c] = v; } d += nchan; samples -= nchan; } +} + +void MainWindow::showLevels() { + unsigned nchan = channels.size(); + g_assert(levels); + for (unsigned c = 0; c < nchan; c++) { ChannelInfo *i = channels[c]; - i->progress->set_fraction(max[c]); + i->progress->set_fraction(levels[c]); } - g_free(max); + for (unsigned c = 0; c < nchan; c++) + levels[c] = 0; +} + + +bool MainWindow::on_timeout() { + showLevels(); + return true; } static MainWindow *mainWindow = NULL; static struct pa_context *context = NULL; static struct pa_stream *stream = NULL; -static const struct pa_sample_spec sample_spec = { - PA_SAMPLE_FLOAT32, 44100, 2 -}; +static struct pa_sample_spec sample_spec = { (enum pa_sample_format) 0, 0, 0 }; +static char* sink_name = NULL; static void stream_read_callback(struct pa_stream *, const void *p, size_t l, void *) { g_assert(mainWindow); -/* mainWindow->pushData((const float*) p, l/sizeof(float));*/ + mainWindow->pushData((const float*) p, l/sizeof(float)); } static void stream_state_callback(struct pa_stream *s, void *) { @@ -138,11 +171,49 @@ static void stream_state_callback(struct pa_stream *s, void *) { break; case PA_STREAM_FAILED: + g_message("Connection failed: %s", pa_strerror(pa_context_errno(context))); + case PA_STREAM_TERMINATED: Gtk::Main::quit(); } } +static void context_get_sink_info_callback(struct pa_context *c, const struct pa_sink_info *si, int is_last, void *) { + char t[256]; + + if (is_last) + return; + + if (!si) { + g_message("Failed to get sink information: %s", pa_strerror(pa_context_errno(context))); + Gtk::Main::quit(); + return; + } + + sample_spec.format = PA_SAMPLE_FLOAT32; + sample_spec.rate = si->sample_spec.rate; + sample_spec.channels = si->sample_spec.channels; + + pa_sample_spec_snprint(t, sizeof(t), &sample_spec); + g_message("Using sample format: %s", t); + + stream = pa_stream_new(c, "vumeter", &sample_spec); + pa_stream_set_state_callback(stream, stream_state_callback, NULL); + pa_stream_set_read_callback(stream, stream_read_callback, NULL); + pa_stream_connect_record(stream, NULL, NULL); +} + +static void context_get_server_info_callback(struct pa_context *c, const struct pa_server_info*si, void *) { + if (!si) { + g_message("Failed to get server information: %s", pa_strerror(pa_context_errno(context))); + Gtk::Main::quit(); + return; + } + + sink_name = g_strdup(si->default_sink_name); + pa_operation_unref(pa_context_get_sink_info_by_name(c, sink_name, context_get_sink_info_callback, NULL)); +} + static void context_state_callback(struct pa_context *c, void *) { switch (pa_context_get_state(c)) { case PA_CONTEXT_UNCONNECTED: @@ -153,14 +224,18 @@ static void context_state_callback(struct pa_context *c, void *) { case PA_CONTEXT_READY: g_assert(!stream); - stream = pa_stream_new(c, "vumeter", &sample_spec); - pa_stream_set_state_callback(stream, stream_state_callback, NULL); - pa_stream_set_read_callback(stream, stream_read_callback, NULL); - pa_stream_connect_record(stream, "input", NULL); + + if (sink_name) + pa_operation_unref(pa_context_get_sink_info_by_name(c, sink_name, context_get_sink_info_callback, NULL)); + else + pa_operation_unref(pa_context_get_server_info(c, context_get_server_info_callback, NULL)); + break; - case PA_CONTEXT_TERMINATED: case PA_CONTEXT_FAILED: + g_message("Connection failed: %s", pa_strerror(pa_context_errno(context))); + + case PA_CONTEXT_TERMINATED: Gtk::Main::quit(); } } -- cgit