summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2004-09-06 21:55:49 +0000
committerLennart Poettering <lennart@poettering.net>2004-09-06 21:55:49 +0000
commit528349cd826c13d0fedf6b2d2925def6607e2604 (patch)
tree21a2cc6d63b3acddbadfc157639807cad74740ce
parent54e219fe520264406bc9c4962e57fde15d31711d (diff)
make it work
git-svn-id: file:///home/lennart/svn/public/pavumeter/trunk@4 c62a5a7b-6fe3-0310-9d5a-afe6de46906b
-rw-r--r--src/Makefile2
-rw-r--r--src/vumeter.cc113
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 <signal.h>
#include <gtkmm.h>
#include <polyp/polyplib-context.h>
#include <polyp/polyplib-stream.h>
+#include <polyp/polyplib-error.h>
+#include <polyp/polyplib-introspect.h>
#include <polyp/glib-mainloop.h>
class MainWindow : public Gtk::Window {
@@ -23,10 +27,17 @@ protected:
Gtk::Table table;
std::vector<ChannelInfo*> 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();
}
}