Skip to content

Commit

Permalink
qtaudio: Add Qt 6 support
Browse files Browse the repository at this point in the history
QtAudio is a Qt namespace now so we need to use another plugin name.
  • Loading branch information
radioactiveman committed Sep 14, 2024
1 parent 9616097 commit 82c6289
Show file tree
Hide file tree
Showing 6 changed files with 70 additions and 38 deletions.
1 change: 1 addition & 0 deletions .github/actions/install-dependencies/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ runs:
mingw-w64-ucrt-x86_64-opusfile
mingw-w64-ucrt-x86_64-pkg-config
mingw-w64-ucrt-x86_64-qt6-base
mingw-w64-ucrt-x86_64-qt6-multimedia
mingw-w64-ucrt-x86_64-qt6-svg
mingw-w64-ucrt-x86_64-SDL2
mingw-w64-ucrt-x86_64-wavpack
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ ubuntu_packages='gettext libadplug-dev libasound2-dev libavformat-dev
libsndio-dev libsoxr-dev libvorbis-dev libwavpack-dev libxml2-dev'

ubuntu_qt5_packages='libqt5svg5-dev libqt5x11extras5-dev qtbase5-dev qtmultimedia5-dev'
ubuntu_qt6_packages='qt6-base-dev qt6-svg-dev'
ubuntu_qt6_packages='qt6-base-dev qt6-multimedia-dev qt6-svg-dev'

macos_packages='adplug faad2 ffmpeg libbs2b libcue libmms libmodplug libnotify
libopenmpt libsamplerate libsoxr neon opusfile sdl2 wavpack'
Expand Down
8 changes: 1 addition & 7 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -117,12 +117,6 @@ check_allowed () {
if test $plugin_allowed = no -a $2 = yes ; then
AC_MSG_ERROR([--enable-$1 cannot be used without --enable-qt])
fi
if test $plugin_allowed = yes -a $1 = qtaudio ; then
plugin_allowed=$USE_QT5
if test $plugin_allowed = no -a $2 = yes ; then
AC_MSG_ERROR([--enable-$1 cannot be used without --enable-qt5])
fi
fi
if test $plugin_allowed = yes -a $1 = ampache ; then
plugin_allowed=$have_neon
if test $plugin_allowed = no -a $2 = yes ; then
Expand Down Expand Up @@ -887,7 +881,7 @@ fi
if test "x$USE_QT" = "xyes" ; then
echo " Qt Support"
echo " ----------"
echo " Qt Multimedia output (Qt 5 only): $have_qtaudio"
echo " Qt Multimedia output: $have_qtaudio"
echo " Qt Interface: yes"
echo " Winamp Classic Interface: yes"
echo " Album Art: yes"
Expand Down
6 changes: 3 additions & 3 deletions src/qtaudio/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ include ../../extra.mk
plugindir := ${plugindir}/${OUTPUT_PLUGIN_DIR}

LD = ${CXX}
CPPFLAGS += -I../.. ${QTMULTIMEDIA_CFLAGS}
CXXFLAGS += ${GLIB_CFLAGS} ${PLUGIN_CFLAGS}
LIBS += -lm ${GLIB_LIBS} ${QTMULTIMEDIA_LIBS}
CPPFLAGS += -I../.. ${QT_CFLAGS} ${QTMULTIMEDIA_CFLAGS}
CXXFLAGS += ${PLUGIN_CFLAGS}
LIBS += -lm ${QT_LIBS} ${QTMULTIMEDIA_LIBS}
7 changes: 1 addition & 6 deletions src/qtaudio/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,6 @@ if get_option('qt5')
qt_multimedia_dep = dependency('qt5', version: qt_req, required: false, modules: ['Multimedia'])
else
qt_multimedia_dep = dependency('qt6', version: qt_req, required: false, modules: ['Multimedia'])

if qt_multimedia_dep.found()
warning('The Qt Multimedia output plugin is not yet compatible with Qt 6.')
qt_multimedia_dep = dependency('', required: false)
endif
endif

have_qtaudio = qt_multimedia_dep.found()
Expand All @@ -15,7 +10,7 @@ have_qtaudio = qt_multimedia_dep.found()
if have_qtaudio
shared_module('qtaudio',
'qtaudio.cc',
dependencies: [audacious_dep, qt_multimedia_dep],
dependencies: [audacious_dep, qt_dep, qt_multimedia_dep],
name_prefix: '',
install: true,
install_dir: output_plugin_dir
Expand Down
84 changes: 63 additions & 21 deletions src/qtaudio/qtaudio.cc
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,19 @@
#include <libaudcore/plugin.h>
#include <libaudcore/runtime.h>

#include <QtGlobal>
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
#include <QAudioDevice>
#include <QAudioFormat>
#include <QAudioSink>
#include <QMediaDevices>
#else
#include <QAudioOutput>
#endif

#define VOLUME_RANGE 40 /* decibels */

class QtAudio : public OutputPlugin
class QtAudioOutput : public OutputPlugin
{
public:
static const char about[];
Expand All @@ -46,7 +54,7 @@ class QtAudio : public OutputPlugin
about
};

constexpr QtAudio () : OutputPlugin (info, 1) {}
constexpr QtAudioOutput () : OutputPlugin (info, 1) {}

bool init ();

Expand All @@ -66,15 +74,15 @@ class QtAudio : public OutputPlugin
void flush ();
};

EXPORT QtAudio aud_plugin_instance;
EXPORT QtAudioOutput aud_plugin_instance;

const char QtAudio::about[] =
const char QtAudioOutput::about[] =
N_("QtMultimedia Audio Output Plugin for Audacious\n"
"Copyright 2014 William Pitcock\n\n"
"Based on SDL Output Plugin for Audacious\n"
"Copyright 2010 John Lindgren");

const char * const QtAudio::defaults[] = {
const char * const QtAudioOutput::defaults[] = {
"vol_left", "100",
"vol_right", "100",
nullptr};
Expand All @@ -89,18 +97,36 @@ static bool paused;
static int last_buffered, delay_estimate;
static timeval last_system_time;

#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
static QAudioSink * output_instance = nullptr;
#else
static QAudioOutput * output_instance = nullptr;
#endif
static QIODevice * buffer_instance = nullptr;

struct FormatDescriptionMap {
int aud_format;

#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
enum QAudioFormat::SampleFormat sample_format;
#else
unsigned int sample_size;
enum QAudioFormat::SampleType sample_type;
enum QAudioFormat::Endian endian;
enum QAudioFormat::Endian endian;
#endif
};

static constexpr FormatDescriptionMap FormatMap[] = {
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
{FMT_S16_LE, QAudioFormat::Int16},
{FMT_S16_BE, QAudioFormat::Int16},
{FMT_U16_LE, QAudioFormat::Int16},
{FMT_U16_BE, QAudioFormat::Int16},
{FMT_S32_LE, QAudioFormat::Int32},
{FMT_S32_BE, QAudioFormat::Int32},
{FMT_U32_LE, QAudioFormat::Int32},
{FMT_U32_BE, QAudioFormat::Int32},
{FMT_FLOAT, QAudioFormat::Float},
#else
{FMT_S16_LE, 16, QAudioFormat::SignedInt, QAudioFormat::LittleEndian},
{FMT_S16_BE, 16, QAudioFormat::SignedInt, QAudioFormat::BigEndian},
{FMT_U16_LE, 16, QAudioFormat::UnSignedInt, QAudioFormat::LittleEndian},
Expand All @@ -110,20 +136,21 @@ static constexpr FormatDescriptionMap FormatMap[] = {
{FMT_U32_LE, 32, QAudioFormat::UnSignedInt, QAudioFormat::LittleEndian},
{FMT_U32_BE, 32, QAudioFormat::UnSignedInt, QAudioFormat::BigEndian},
{FMT_FLOAT, 32, QAudioFormat::Float, QAudioFormat::LittleEndian},
#endif
};

bool QtAudio::init ()
bool QtAudioOutput::init ()
{
aud_config_set_defaults ("qtaudio", defaults);
return true;
}

StereoVolume QtAudio::get_volume ()
StereoVolume QtAudioOutput::get_volume ()
{
return {aud_get_int ("qtaudio", "vol_left"), aud_get_int ("qtaudio", "vol_right")};
}

void QtAudio::set_volume (StereoVolume v)
void QtAudioOutput::set_volume (StereoVolume v)
{
int vol_max = aud::max (v.left, v.right);

Expand All @@ -138,7 +165,7 @@ void QtAudio::set_volume (StereoVolume v)
}
}

bool QtAudio::open_audio (int format, int rate, int chan, String & error)
bool QtAudioOutput::open_audio (int format, int rate, int chan, String & error)
{
const FormatDescriptionMap * m = nullptr;

Expand Down Expand Up @@ -174,19 +201,30 @@ bool QtAudio::open_audio (int format, int rate, int chan, String & error)
QAudioFormat fmt;
fmt.setSampleRate (rate);
fmt.setChannelCount (chan);

#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
/* How do we need to handle signed/unsigned formats and endianess? */
fmt.setSampleFormat (m->sample_format);
QAudioDevice info = QMediaDevices::defaultAudioOutput ();
#else
fmt.setSampleSize (m->sample_size);
fmt.setCodec ("audio/pcm");
fmt.setByteOrder (m->endian);
fmt.setSampleType (m->sample_type);

QAudioDeviceInfo info (QAudioDeviceInfo::defaultOutputDevice ());
#endif

if (! info.isFormatSupported (fmt))
{
error = String ("QtAudio error: Format not supported by backend.");
return false;
}

output_instance = new QAudioOutput (fmt, nullptr);
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
output_instance = new QAudioSink (info, fmt);
#else
output_instance = new QAudioOutput (fmt);
#endif
output_instance->setBufferSize (buffer_size);
buffer_instance = output_instance->start ();

Expand All @@ -195,7 +233,7 @@ bool QtAudio::open_audio (int format, int rate, int chan, String & error)
return true;
}

void QtAudio::close_audio ()
void QtAudioOutput::close_audio ()
{
AUDDBG ("Closing audio.\n");

Expand All @@ -205,29 +243,33 @@ void QtAudio::close_audio ()
output_instance = nullptr;
}

void QtAudio::period_wait ()
void QtAudioOutput::period_wait ()
{
pthread_mutex_lock (& mutex);

#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
/* periodSize() is Qt 5 only, how to replace it? */
#else
while (output_instance->bytesFree () < output_instance->periodSize ())
pthread_cond_timedwait (& cond, & mutex, & fifty_ms);
#endif

pthread_mutex_unlock (& mutex);
}

int QtAudio::write_audio (const void * data, int len)
int QtAudioOutput::write_audio (const void * data, int len)
{
pthread_mutex_lock (& mutex);

len = aud::min (len, output_instance->bytesFree ());
len = aud::min<int> (len, output_instance->bytesFree ());
buffer_instance->write ((const char *) data, len);
last_buffered += len;

pthread_mutex_unlock (& mutex);
return len;
}

void QtAudio::drain ()
void QtAudioOutput::drain ()
{
AUDDBG ("Draining.\n");
pthread_mutex_lock (& mutex);
Expand All @@ -238,7 +280,7 @@ void QtAudio::drain ()
pthread_mutex_unlock (& mutex);
}

int QtAudio::get_delay ()
int QtAudioOutput::get_delay ()
{
auto timediff = [] (const timeval & a, const timeval & b) -> int64_t
{ return 1000 * (int64_t) (b.tv_sec - a.tv_sec) + (b.tv_usec - a.tv_usec) / 1000; };
Expand All @@ -265,7 +307,7 @@ int QtAudio::get_delay ()
return delay;
}

void QtAudio::pause (bool pause)
void QtAudioOutput::pause (bool pause)
{
AUDDBG ("%sause.\n", pause ? "P" : "Unp");
pthread_mutex_lock (& mutex);
Expand All @@ -281,7 +323,7 @@ void QtAudio::pause (bool pause)
pthread_mutex_unlock (& mutex);
}

void QtAudio::flush ()
void QtAudioOutput::flush ()
{
AUDDBG ("Seek requested; discarding buffer.\n");
pthread_mutex_lock (& mutex);
Expand Down

0 comments on commit 82c6289

Please sign in to comment.