commit 0b121ec1c5ce99535d35a6a54c9252bd9f552a7d
parent 4e71509218bbaad75a9106505129e1976d251b82
Author: Alexander Kojevnikov <alexander@kojevnikov.com>
Date: Sun, 19 Aug 2012 12:05:57 -0700
Proper notification using custom events
Diffstat:
5 files changed, 148 insertions(+), 25 deletions(-)
diff --git a/src/Makefile.am b/src/Makefile.am
@@ -5,6 +5,8 @@ spek_SOURCES = \
spek-audio-desc.hh \
spek-audio.c \
spek-audio.h \
+ spek-events.cc \
+ spek-events.hh \
spek-fft.c \
spek-fft.h \
spek-palette.c \
diff --git a/src/spek-events.cc b/src/spek-events.cc
@@ -0,0 +1,45 @@
+/* spek-events.cc
+ *
+ * Copyright (C) 2012 Alexander Kojevnikov <alexander@kojevnikov.com>
+ *
+ * Spek is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Spek is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Spek. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "spek-events.hh"
+
+//IMPLEMENT_DYNAMIC_CLASS(SpekHaveSampleEvent, wxEvent)
+DEFINE_EVENT_TYPE(SPEK_HAVE_SAMPLE)
+
+SpekHaveSampleEvent::SpekHaveSampleEvent(int bands, int sample, float *values, bool free_values)
+ : wxEvent(), bands(bands), sample(sample), values(values), free_values(free_values)
+{
+ SetEventType(SPEK_HAVE_SAMPLE);
+}
+
+SpekHaveSampleEvent::SpekHaveSampleEvent(const SpekHaveSampleEvent& other)
+{
+ SetEventType(SPEK_HAVE_SAMPLE);
+ this->bands = other.bands;
+ this->sample = other.sample;
+ this->values = (float *)malloc(this->bands * sizeof(float));
+ memcpy(this->values, other.values, this->bands * sizeof(float));
+ this->free_values = true;
+}
+
+SpekHaveSampleEvent::~SpekHaveSampleEvent()
+{
+ if (this->free_values) {
+ free(this->values);
+ }
+}
diff --git a/src/spek-events.hh b/src/spek-events.hh
@@ -0,0 +1,53 @@
+/* spek-events.hh
+ *
+ * Copyright (C) 2012 Alexander Kojevnikov <alexander@kojevnikov.com>
+ *
+ * Spek is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Spek is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Spek. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef SPEK_EVENTS_HH_
+#define SPEK_EVENTS_HH_
+
+#include <wx/wx.h>
+
+class SpekHaveSampleEvent: public wxEvent
+{
+public:
+ SpekHaveSampleEvent(int bands, int sample, float *values, bool free_values);
+ SpekHaveSampleEvent(const SpekHaveSampleEvent& other);
+ ~SpekHaveSampleEvent();
+
+ int get_bands() const { return this->bands; }
+ int get_sample() const { return this->sample; }
+ const float *get_values() const { return this->values; }
+
+ wxEvent *Clone() const { return new SpekHaveSampleEvent(*this); }
+// DECLARE_DYNAMIC_CLASS(SpekHaveSampleEvent);
+
+private:
+ int bands;
+ int sample;
+ float *values;
+ bool free_values;
+};
+
+typedef void (wxEvtHandler::*SpekHaveSampleEventFunction)(SpekHaveSampleEvent&);
+
+DECLARE_EVENT_TYPE(SPEK_HAVE_SAMPLE, wxID_ANY)
+
+#define SPEK_EVT_HAVE_SAMPLE(fn) \
+ DECLARE_EVENT_TABLE_ENTRY(SPEK_HAVE_SAMPLE, -1, -1, \
+ (wxObjectEventFunction) (SpekHaveSampleEventFunction) &fn, (wxObject *) NULL ),
+
+#endif
diff --git a/src/spek-spectrogram.cc b/src/spek-spectrogram.cc
@@ -21,6 +21,7 @@
#include "spek-audio.h"
#include "spek-audio-desc.hh"
+#include "spek-events.hh"
#include "spek-palette.h"
#include "spek-pipeline.h"
#include "spek-platform.hh"
@@ -32,6 +33,7 @@ BEGIN_EVENT_TABLE(SpekSpectrogram, wxPanel)
EVT_IDLE(SpekSpectrogram::on_idle)
EVT_PAINT(SpekSpectrogram::on_paint)
EVT_SIZE(SpekSpectrogram::on_size)
+ SPEK_EVT_HAVE_SAMPLE(SpekSpectrogram::on_have_sample)
END_EVENT_TABLE()
enum
@@ -72,6 +74,11 @@ SpekSpectrogram::SpekSpectrogram(wxFrame *parent) :
}
}
+SpekSpectrogram::~SpekSpectrogram()
+{
+ this->stop();
+}
+
void SpekSpectrogram::open(const wxString& path)
{
this->path = path;
@@ -109,6 +116,30 @@ void SpekSpectrogram::on_size(wxSizeEvent& evt)
}
}
+void SpekSpectrogram::on_have_sample(SpekHaveSampleEvent& event)
+{
+ static double log10_threshold = log10(-THRESHOLD);
+ int bands = event.get_bands();
+ int sample = event.get_sample();
+ const float *values = event.get_values();
+
+ for (int y = 0; y < bands; y++) {
+ double level = log10(1.0 - THRESHOLD + values[y]) / log10_threshold;
+ if (level > 1.0) level = 1.0;
+ uint32_t color = spek_palette_spectrum(level);
+ this->image.SetRGB(
+ sample,
+ bands - y - 1,
+ color >> 16,
+ (color >> 8) & 0xFF,
+ color & 0xFF
+ );
+ }
+
+ // TODO: refresh only one pixel column
+ this->Refresh();
+}
+
static wxString time_formatter(int unit)
{
// TODO: i18n
@@ -261,36 +292,16 @@ void SpekSpectrogram::render(wxDC& dc)
density_ruler.draw(dc);
}
-void SpekSpectrogram::pipeline_cb(int sample, float *values, void *cb_data)
+static void pipeline_cb(int sample, float *values, void *cb_data)
{
- static double log10_threshold = log10(-THRESHOLD);
+ SpekHaveSampleEvent event(BANDS, sample, values, false);
SpekSpectrogram *s = (SpekSpectrogram *)cb_data;
-
- for (int y = 0; y < BANDS; y++) {
- double level = log10(1.0 - THRESHOLD + values[y]) / log10_threshold;
- if (level > 1.0) level = 1.0;
- uint32_t color = spek_palette_spectrum(level);
- s->image.SetRGB(
- sample,
- BANDS - y - 1,
- color >> 16,
- (color >> 8) & 0xFF,
- color & 0xFF
- );
- }
-
- s->Refresh(); // TODO: refresh only one pixel column
- wxWakeUpIdle();
+ wxPostEvent(s, event);
}
-
void SpekSpectrogram::start()
{
- if (this->pipeline) {
- spek_pipeline_close(this->pipeline);
- this->pipeline = NULL;
- this->properties = NULL;
- }
+ this->stop();
// The number of samples is the number of pixels available for the image.
// The number of bands is fixed, FFT results are very different for
@@ -317,6 +328,15 @@ void SpekSpectrogram::start()
Refresh();
}
+void SpekSpectrogram::stop()
+{
+ if (this->pipeline) {
+ spek_pipeline_close(this->pipeline);
+ this->pipeline = NULL;
+ this->properties = NULL;
+ }
+}
+
// Trim `s` so that it fits into `length`.
static wxString trim(wxDC& dc, const wxString& s, int length, bool trim_end)
{
diff --git a/src/spek-spectrogram.hh b/src/spek-spectrogram.hh
@@ -21,6 +21,7 @@
#include <wx/wx.h>
+class SpekHaveSampleEvent;
struct spek_audio_properties;
struct spek_pipeline;
@@ -28,6 +29,7 @@ class SpekSpectrogram : public wxPanel
{
public:
SpekSpectrogram(wxFrame *parent);
+ ~SpekSpectrogram();
void open(const wxString& path);
void save(const wxString& path);
@@ -35,10 +37,11 @@ private:
void on_idle(wxIdleEvent& evt);
void on_paint(wxPaintEvent& evt);
void on_size(wxSizeEvent& evt);
+ void on_have_sample(SpekHaveSampleEvent& evt);
void render(wxDC& dc);
void start();
- static void pipeline_cb(int sample, float *values, void *cb_data);
+ void stop();
spek_pipeline *pipeline;
const spek_audio_properties *properties;