1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 07:58:11 +00:00

SoundPlayer: Start working on a GUI sound player application

This can play anything that AWavLoader can load (so obviously only WAV
files at the moment.)

It works by having a timer that wakes up every 100ms and tries to send
a sample buffer to the AudioServer. If our server-side queue is full
then we wait until the next timer iteration and try again.

We display the most recently enqueued sample buffer in a nice little
widget that just plots the samples in green-on-black. :^)
This commit is contained in:
Andreas Kling 2019-09-04 20:18:41 +02:00
parent 6693e56603
commit 1188a036e9
6 changed files with 148 additions and 0 deletions

View file

@ -0,0 +1,9 @@
include ../../Makefile.common
OBJS = \
SampleWidget.o \
main.o
APP = SoundPlayer
include ../Makefile.common

View file

@ -0,0 +1,45 @@
#include "SampleWidget.h"
#include <LibAudio/ABuffer.h>
#include <LibGUI/GPainter.h>
SampleWidget::SampleWidget(GWidget* parent)
: GFrame(parent)
{
set_frame_shape(FrameShape::Container);
set_frame_shadow(FrameShadow::Sunken);
set_frame_thickness(2);
}
SampleWidget::~SampleWidget()
{
}
void SampleWidget::paint_event(GPaintEvent& event)
{
GFrame::paint_event(event);
GPainter painter(*this);
painter.add_clip_rect(event.rect());
painter.fill_rect(frame_inner_rect(), Color::Black);
if (!m_buffer)
return;
// FIXME: Right now we only display as many samples from the buffer as we can fit
// in the frame_inner_rect(). Maybe scale the samples or something?
int samples_to_draw = min(m_buffer->sample_count(), frame_inner_rect().width());
for (int x = 0; x < samples_to_draw; ++x) {
// FIXME: This might look nicer if drawn as lines.
auto& sample = m_buffer->samples()[x];
Point p = { x, frame_inner_rect().center().y() + (int)(sample.left * frame_inner_rect().height()) };
painter.set_pixel(p, Color::Green);
}
}
void SampleWidget::set_buffer(ABuffer* buffer)
{
if (m_buffer == buffer)
return;
m_buffer = buffer;
update();
}

View file

@ -0,0 +1,19 @@
#pragma once
#include <LibGUI/GFrame.h>
class ABuffer;
class SampleWidget final : public GFrame {
C_OBJECT(SampleWidget)
public:
explicit SampleWidget(GWidget* parent);
virtual ~SampleWidget() override;
void set_buffer(ABuffer*);
private:
virtual void paint_event(GPaintEvent&) override;
RefPtr<ABuffer> m_buffer;
};

View file

@ -0,0 +1,72 @@
#include "SampleWidget.h"
#include <LibAudio/ABuffer.h>
#include <LibAudio/AClientConnection.h>
#include <LibAudio/AWavLoader.h>
#include <LibCore/CTimer.h>
#include <LibGUI/GApplication.h>
#include <LibGUI/GBoxLayout.h>
#include <LibGUI/GButton.h>
#include <LibGUI/GWidget.h>
#include <LibGUI/GWindow.h>
#include <stdio.h>
int main(int argc, char** argv)
{
if (argc != 2) {
printf("usage: %s <wav-file>\n", argv[0]);
return 0;
}
GApplication app(argc, argv);
String path = argv[1];
AWavLoader loader(path);
if (loader.has_error()) {
fprintf(stderr, "Failed to load WAV file: %s (%s)\n", path.characters(), loader.error_string());
return 1;
}
AClientConnection audio_client;
audio_client.handshake();
auto* window = new GWindow;
window->set_title("SoundPlayer");
window->set_rect(300, 300, 300, 200);
auto* widget = new GWidget;
window->set_main_widget(widget);
widget->set_fill_with_background_color(true);
widget->set_layout(make<GBoxLayout>(Orientation::Vertical));
widget->layout()->set_margins({ 2, 2, 2, 2 });
auto* sample_widget = new SampleWidget(widget);
auto* button = new GButton("Quit", widget);
button->set_size_policy(SizePolicy::Fill, SizePolicy::Fixed);
button->set_preferred_size(0, 20);
button->on_click = [&](auto&) {
app.quit();
};
auto next_sample_buffer = loader.get_more_samples();
new CTimer(100, [&] {
if (!next_sample_buffer) {
sample_widget->set_buffer(nullptr);
return;
}
bool enqueued = audio_client.try_enqueue(*next_sample_buffer);
if (!enqueued)
return;
sample_widget->set_buffer(next_sample_buffer);
next_sample_buffer = loader.get_more_samples(16 * KB);
if (!next_sample_buffer) {
dbg() << "Exhausted samples :^)";
}
});
window->show();
return app.exec();
}

View file

@ -85,6 +85,7 @@ cp ../Applications/Piano/Piano mnt/bin/Piano
cp ../Applications/SystemDialog/SystemDialog mnt/bin/SystemDialog
cp ../Applications/ChanViewer/ChanViewer mnt/bin/ChanViewer
cp ../Applications/Calculator/Calculator mnt/bin/Calculator
cp ../Applications/SoundPlayer/SoundPlayer mnt/bin/SoundPlayer
cp ../Demos/HelloWorld/HelloWorld mnt/bin/HelloWorld
cp ../Demos/HelloWorld2/HelloWorld2 mnt/bin/HelloWorld2
cp ../Demos/RetroFetch/RetroFetch mnt/bin/RetroFetch
@ -123,6 +124,7 @@ ln -s SystemDialog mnt/bin/sd
ln -s ChanViewer mnt/bin/cv
ln -s Calculator mnt/bin/calc
ln -s Inspector mnt/bin/ins
ln -s SoundPlayer mnt/bin/sp
echo "done"
# Run local sync script, if it exists

View file

@ -55,6 +55,7 @@ build_targets="$build_targets ../Applications/SystemMonitor"
build_targets="$build_targets ../Applications/Taskbar"
build_targets="$build_targets ../Applications/Terminal"
build_targets="$build_targets ../Applications/TextEditor"
build_targets="$build_targets ../Applications/SoundPlayer"
build_targets="$build_targets ../Demos/Fire"
build_targets="$build_targets ../Demos/HelloWorld"