Skip to content

Commit e64314f

Browse files
committed
FLTK: implement audio support
1 parent e906289 commit e64314f

File tree

11 files changed

+145
-42
lines changed

11 files changed

+145
-42
lines changed

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[submodule "src/lib/miniaudio"]
2+
path = src/lib/miniaudio
3+
url = https://github.com/dr-soft/miniaudio.git

configure.ac

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,8 @@ function buildFLTK() {
352352
FLTK_CXXFLAGS="${FLTK_CXXFLAGS} -mms-bitfields"
353353
PACKAGE_LIBS="-Wl,-Bstatic ${PACKAGE_LIBS} -lwsock32 -lws2_32 -static-libgcc -static-libstdc++"
354354
AC_DEFINE(_Win32, 1, [Windows build])
355+
AC_DEFINE(_USE_MATH_DEFINES, 1, [for M_PI in math.h])
356+
AC_DEFINE(realpath(F, R), _fullpath(R, F, PATH_MAX), [add missing realpath for system.cpp])
355357
;;
356358

357359
*darwin*)

src/lib/miniaudio

Submodule miniaudio added at 1ca6f80

src/platform/fltk/HelpWidget.cxx

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include <FL/Fl_Slider.H>
2626
#include <FL/Fl_Value_Input.H>
2727
#include <FL/Fl_Window.H>
28+
#include <FL/filename.H>
2829

2930
#define Fl_HELP_WIDGET_RESOURCES
3031
#include "platform/fltk/HelpWidget.h"
@@ -3043,24 +3044,6 @@ Fl_Image *loadImage(const char *imgSrc) {
30433044
return image != 0 ? image : &brokenImage;
30443045
}
30453046

3046-
#if defined(WIN32)
3047-
#include <windows.h>
3048-
#include <FL/Fl_Window.h>
3049-
#include <FL/Fl_win32.h>
3050-
#endif
3051-
30523047
void browseFile(const char *url) {
3053-
#if defined(WIN32)
3054-
ShellExecute(xid(Window::first()), "open", url, 0, 0, SW_SHOWNORMAL);
3055-
#else
3056-
if (fork() == 0) {
3057-
fclose(stderr);
3058-
fclose(stdin);
3059-
fclose(stdout);
3060-
execlp("htmlview", "htmlview", url, NULL);
3061-
execlp("firefox", "firefox", url, NULL);
3062-
execlp("mozilla", "mozilla", url, NULL);
3063-
::exit(0); // in case exec failed
3064-
}
3065-
#endif
3048+
fl_open_uri(url);
30663049
}

src/platform/fltk/MainWindow.cxx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -841,7 +841,7 @@ bool initialise(int argc, char **argv) {
841841
opt_interactive = true;
842842
opt_file_permitted = 1;
843843
os_graphics = 1;
844-
opt_mute_audio = 1;
844+
opt_mute_audio = 0;
845845

846846
int i = 0;
847847
if (Fl::args(argc, argv, i, arg_cb) < argc) {

src/platform/fltk/MainWindow.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ struct MainWindow : public BaseWindow {
108108
bool logPrint();
109109
FILE *openConfig(const char *fileName, const char *flags = "w");
110110
TtyWidget *tty();
111+
void exit(int code) { delete this; ::exit(code); }
111112

112113
CALLBACK_METHOD(close_tab);
113114
CALLBACK_METHOD(close_other_tabs);

src/platform/fltk/Makefile.am

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ sbasici_SOURCES = \
2727
../../ui/image.cpp \
2828
../../ui/strlib.cpp \
2929
../../ui/textedit.cpp \
30+
../../ui/audio.cpp \
3031
display.cxx display.h \
3132
runtime.cxx runtime.h \
3233
HelpWidget.cxx HelpWidget.h \

src/platform/fltk/runtime.cxx

Lines changed: 3 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "lib/maapi.h"
1212
#include "platform/fltk/MainWindow.h"
1313
#include "platform/fltk/runtime.h"
14+
#include "ui/audio.h"
1415
#include <FL/fl_ask.H>
1516
#include <FL/Fl_Menu_Button.H>
1617

@@ -44,10 +45,11 @@ Runtime::Runtime(int w, int h, int defsize) : System() {
4445
_output->construct();
4546
_output->setTextColor(DEFAULT_FOREGROUND, DEFAULT_BACKGROUND);
4647
_output->setFontSize(defsize);
48+
open_audio();
4749
}
4850

4951
Runtime::~Runtime() {
50-
// empty
52+
close_audio();
5153
}
5254

5355
void Runtime::alert(const char *title, const char *message) {
@@ -338,18 +340,6 @@ int osd_devrestore() {
338340
return 1;
339341
}
340342

341-
void osd_beep() {
342-
fl_beep();
343-
}
344-
345-
void osd_sound(int frq, int ms, int vol, int bgplay) {
346-
#if defined(WIN32)
347-
if (!bgplay) {
348-
::Beep(frq, ms);
349-
}
350-
#endif
351-
}
352-
353343
//
354344
// utils
355345
//
@@ -380,11 +370,3 @@ void appLog(const char *format, ...) {
380370
free(buf);
381371
}
382372
}
383-
384-
//
385-
// not implemented
386-
//
387-
void open_audio() {}
388-
void close_audio() {}
389-
void osd_audio(const char *path) {}
390-
void osd_clear_sound_queue() {}

src/platform/fltk/utils.cxx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
//
88

99
#include <config.h>
10-
#include <sys/socket.h>
1110
#include <stdint.h>
1211
#include "lib/str.h"
1312
#include "utils.h"

src/ui/audio.cpp

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
// This file is part of SmallBASIC
2+
//
3+
// Copyright(C) 2001-2019 Chris Warren-Smith.
4+
//
5+
// This program is distributed under the terms of the GPL v2.0 or later
6+
// Download the GNU Public License (GPL) from www.gnu.org
7+
//
8+
9+
#define MINIAUDIO_IMPLEMENTATION
10+
#define DR_WAV_IMPLEMENTATION
11+
//#define DR_MP3_IMPLEMENTATION
12+
13+
#include "config.h"
14+
#include <stdio.h>
15+
#include "common/osd.h"
16+
#include "common/device.h"
17+
#include "ui/strlib.h"
18+
#include "lib/miniaudio/miniaudio.h"
19+
#include "lib/miniaudio/extras/dr_wav.h"
20+
//#include "lib/miniaudio/extras/dr_mp3.h"
21+
22+
#define DEVICE_SAMPLE_RATE 48000
23+
#define DEVICE_CHANNELS 1
24+
#define MILLIS_TO_MICROS(n) (n * 1000)
25+
26+
struct Sound {
27+
Sound(int frequency, int millis, int volume);
28+
~Sound();
29+
30+
ma_sine_wave *_tone;
31+
uint32_t _start;
32+
uint32_t _duration;
33+
};
34+
35+
Sound::Sound(int frequency, int millis, int volume) :
36+
_tone(nullptr),
37+
_start(0),
38+
_duration(millis) {
39+
_tone = (ma_sine_wave *)malloc(sizeof(ma_sine_wave));
40+
ma_sine_wave_init(volume / 100.0, frequency, DEVICE_SAMPLE_RATE, _tone);
41+
}
42+
43+
Sound::~Sound() {
44+
free(_tone);
45+
_tone = nullptr;
46+
}
47+
48+
strlib::Queue<Sound *> queue;
49+
ma_decoder decoder;
50+
ma_device device;
51+
ma_device_config config;
52+
53+
void data_callback(ma_device *device, void *output, const void *input, ma_uint32 frameCount) {
54+
if (device->playback.channels == DEVICE_CHANNELS) {
55+
if (queue.empty()) {
56+
usleep(MILLIS_TO_MICROS(10));
57+
} else {
58+
Sound *sound = queue.front();
59+
if (sound->_start == 0) {
60+
// start new sound
61+
sound->_start = dev_get_millisecond_count();
62+
ma_sine_wave_read_f32(sound->_tone, frameCount, (float*)output);
63+
} else if (dev_get_millisecond_count() - sound->_start > sound->_duration) {
64+
// sound has timed out
65+
queue.pop();
66+
} else {
67+
// continue sound
68+
ma_sine_wave_read_f32(sound->_tone, frameCount, (float*)output);
69+
}
70+
}
71+
}
72+
}
73+
74+
bool open_audio() {
75+
config = ma_device_config_init(ma_device_type_playback);
76+
config.playback.format = ma_format_f32;
77+
config.playback.channels = DEVICE_CHANNELS;
78+
config.sampleRate = DEVICE_SAMPLE_RATE;
79+
config.dataCallback = data_callback;
80+
config.pUserData = nullptr;
81+
return (ma_device_init(nullptr, &config, &device) == MA_SUCCESS);
82+
}
83+
84+
void close_audio() {
85+
ma_device_uninit(&device);
86+
}
87+
88+
void osd_audio(const char *path) {
89+
//if (ma_decoder_init_file_wav(path, nullptr, &decoder) == MA_SUCCESS) {
90+
// ma_device_start(&device);
91+
// } else {
92+
// fprintf(stderr, "failed\n");
93+
// }
94+
}
95+
96+
void osd_clear_sound_queue() {
97+
ma_device_stop(&device);
98+
queue.removeAll();
99+
}
100+
101+
void osd_beep() {
102+
osd_sound(1000, 30, 100, 0);
103+
osd_sound(500, 30, 100, 0);
104+
}
105+
106+
void osd_sound(int frequency, int millis, int volume, int background) {
107+
ma_mutex_lock(&device.lock);
108+
queue.push(new Sound(frequency, millis, volume));
109+
ma_mutex_unlock(&device.lock);
110+
111+
if (!background) {
112+
ma_device_start(&device);
113+
usleep(MILLIS_TO_MICROS(millis));
114+
ma_device_stop(&device);
115+
ma_mutex_lock(&device.lock);
116+
queue.pop();
117+
ma_mutex_unlock(&device.lock);
118+
} else if (queue.size() == 1) {
119+
ma_device_start(&device);
120+
}
121+
}

0 commit comments

Comments
 (0)