Compare commits

...

3 commits

Author SHA1 Message Date
snow efea009b02 Add get_volume and set_volume methods
This uses the global volume for the audio/mixer device. This isn't
ideal, but to my understanding follows what the alsa and oss plugins
do as well. Audacious already provides a software volume control in
Settings -> Audio, which despite saying "not recommended," doesn't
seem to have any issues.
2020-08-30 16:53:20 -07:00
snow 276fe1a24d Update TODO 2020-08-30 08:52:47 -07:00
snow 653d5a769c Some code cleanup 2020-08-30 08:46:28 -07:00
2 changed files with 49 additions and 33 deletions

14
TODO
View file

@ -1,9 +1,5 @@
* Figure out how to manage get_volume and set_volume * Determine if audio open/close should happen in open_audio
* Should it be global? Does (audio_info_t)info.play.gain and close_audio
refer to the global mixer or just the track (i'm guessing * Support 24-bit LPCM -> 32-bit
from the manpage that it's global?) * Create a settings panel so users can select their output
* Find out if/how audio(4) supports 24-bit linear PCM device
* Audacious supports two methods-- one is 3-byte, the other
is padded 4-byte. I'm guessing audio(4) doesn't support
both, but who knows
* Clean up the code in terms of formatting/layout

View file

@ -13,7 +13,6 @@
#include <libaudcore/ringbuf.h> #include <libaudcore/ringbuf.h>
#include <libaudcore/runtime.h> #include <libaudcore/runtime.h>
class NetBSDOutput : public OutputPlugin class NetBSDOutput : public OutputPlugin
{ {
public: public:
@ -34,19 +33,16 @@ public:
void close_audio (); void close_audio ();
int write_audio (const void * data, int size); int write_audio (const void * data, int size);
void pause (bool pause);
void period_wait (); void period_wait ();
int get_delay ();
void drain ();
void set_volume(StereoVolume volume); void set_volume(StereoVolume volume);
StereoVolume get_volume(); StereoVolume get_volume();
int get_delay ();
void pause (bool pause);
void flush (); void flush ();
void drain ();
}; };
__attribute__((visibility("default"))) NetBSDOutput aud_plugin_instance; __attribute__((visibility("default"))) NetBSDOutput aud_plugin_instance;
@ -54,7 +50,7 @@ __attribute__((visibility("default"))) NetBSDOutput aud_plugin_instance;
static String audio_path; static String audio_path;
static int audio_fd; static int audio_fd;
static bool audio_paused, audio_prebuffer, audio_flushed; static bool audio_paused, audio_flushed;
static pthread_mutex_t nbout_mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t nbout_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t nbout_cond = PTHREAD_COND_INITIALIZER; static pthread_cond_t nbout_cond = PTHREAD_COND_INITIALIZER;
@ -101,7 +97,7 @@ NetBSDOutput::init ()
audio_fd = open (audio_path, O_WRONLY); audio_fd = open (audio_path, O_WRONLY);
if (audio_fd == -1) { if (audio_fd == -1) {
AUDERR ("Failed to open %s: %s.\n", audio_path, strerror (errno)); AUDERR ("Failed to open %s: %s.\n", (const char *) audio_path, strerror (errno));
return false; return false;
} }
@ -114,16 +110,21 @@ NetBSDOutput::cleanup ()
close (audio_fd); close (audio_fd);
} }
/*
* Converts the format libaudcore provides to something usable
* in audio_info_t, then passes along the information to the
* audio device.
*/
bool bool
NetBSDOutput::open_audio (int format, NetBSDOutput::open_audio (int format,
int rate, int rate,
int chans, int chans,
String & error) String & error)
{ {
// TODO: /* TODO: Use FMT_S24_* or FMT_S24_3* */
audio_info_t info; audio_info_t info;
int props; int props;
// Audacious->NetBSD format table /* Audacious->NetBSD format table */
static const struct fmt_conv fmt_table[] = { static const struct fmt_conv fmt_table[] = {
{FMT_S8, AUDIO_ENCODING_SLINEAR, 8}, {FMT_S8, AUDIO_ENCODING_SLINEAR, 8},
{FMT_U8, AUDIO_ENCODING_ULINEAR, 8}, {FMT_U8, AUDIO_ENCODING_ULINEAR, 8},
@ -141,18 +142,19 @@ NetBSDOutput::open_audio (int format,
if (ioctl (audio_fd, AUDIO_GETPROPS, & props) == -1) { if (ioctl (audio_fd, AUDIO_GETPROPS, & props) == -1) {
error = String (str_printf error = String (str_printf
("Failed to get audio properties on %s: %s.", ("Failed to get audio properties on %s: %s.",
audio_path, strerror (errno))); (const char *) audio_path, strerror (errno)));
return false; return false;
} }
if (props | AUDIO_PROP_PLAYBACK != AUDIO_PROP_PLAYBACK) { if ((props | AUDIO_PROP_PLAYBACK) != AUDIO_PROP_PLAYBACK) {
error = String (str_printf error = String (str_printf
("Device %s does not support playback.", ("Device %s does not support playback.",
audio_path)); (const char *) audio_path));
} }
AUDIO_INITINFO (&info); AUDIO_INITINFO (&info);
/* Loop to find the right format, if it's supported */
for (auto & conv : fmt_table) { for (auto & conv : fmt_table) {
if (conv.aud_format == format) { if (conv.aud_format == format) {
cur_format = conv; cur_format = conv;
@ -165,17 +167,18 @@ NetBSDOutput::open_audio (int format,
return false; return false;
} }
info.play.channels = chans;
info.play.encoding = cur_format.encoding; info.play.encoding = cur_format.encoding;
info.play.precision = cur_format.bits; info.play.precision = cur_format.bits;
/* Channels and sample rate are straightforward, at least */
info.play.channels = chans;
info.play.sample_rate = rate; info.play.sample_rate = rate;
info.mode = AUMODE_PLAY; info.mode = AUMODE_PLAY;
if (ioctl (audio_fd, AUDIO_SETINFO, & info) == -1) { if (ioctl (audio_fd, AUDIO_SETINFO, & info) == -1) {
error = String (str_printf error = String (str_printf
("Failed to set track info on %s: %s.\n", ("Failed to set track info on %s: %s.\n",
audio_path, strerror (errno))); (const char *) audio_path, strerror (errno)));
return false; return false;
} }
@ -185,7 +188,7 @@ NetBSDOutput::open_audio (int format,
void void
NetBSDOutput::close_audio () NetBSDOutput::close_audio ()
{ {
AUDDBG ("close_audio is a stub!\n"); // XXX AUDDBG ("close_audio is a stub!\n"); /* XXX */
} }
int int
@ -235,8 +238,7 @@ NetBSDOutput::period_wait ()
void void
NetBSDOutput::pause (bool pause) NetBSDOutput::pause (bool pause)
{ {
int res, len; int res;
audio_info_t info;
AUDDBG ("Setting pause = %s.\n", pause ? "true" : "false"); AUDDBG ("Setting pause = %s.\n", pause ? "true" : "false");
@ -330,14 +332,32 @@ NetBSDOutput::flush ()
StereoVolume StereoVolume
NetBSDOutput::get_volume () NetBSDOutput::get_volume ()
{ {
// too noisy, even for debug... audio_info_t info;
// AUDDBG ("get_volume: Stub!\n"); int aud_vol;
return {100, 100}; // XXX if (ioctl (audio_fd, AUDIO_GETINFO, & info) != 0) {
AUDERR ("Unable to get volume: %s.\n", strerror (errno));
return { 0, 0 };
}
aud_vol = aud::rescale ((int)info.play.gain - AUDIO_MIN_GAIN,
AUDIO_MAX_GAIN - AUDIO_MIN_GAIN,
100);
return { aud_vol, aud_vol };
} }
void void
NetBSDOutput::set_volume (StereoVolume volume) NetBSDOutput::set_volume (StereoVolume volume)
{ {
AUDDBG ("set_volume: Stub!\n"); // XXX audio_info_t info;
AUDIO_INITINFO (& info);
info.play.gain = aud::rescale (aud::max
(volume.left, volume.right), 100,
AUDIO_MAX_GAIN) + AUDIO_MIN_GAIN;
if (ioctl(audio_fd, AUDIO_SETINFO, & info) != 0) {
AUDERR ("Unable to set volume: %s.\n", strerror (errno));
}
} }