Merge branch 'v0.20.x'
This commit is contained in:
commit
44bbf42a9f
2
NEWS
2
NEWS
|
@ -12,6 +12,8 @@ ver 0.21 (not yet released)
|
||||||
ver 0.20.11 (not yet released)
|
ver 0.20.11 (not yet released)
|
||||||
* storage
|
* storage
|
||||||
- curl: support Content-Type application/xml
|
- curl: support Content-Type application/xml
|
||||||
|
* decoder
|
||||||
|
- ffmpeg: more reliable song duration
|
||||||
|
|
||||||
ver 0.20.10 (2017/08/24)
|
ver 0.20.10 (2017/08/24)
|
||||||
* decoder
|
* decoder
|
||||||
|
|
54
doc/user.xml
54
doc/user.xml
|
@ -2991,6 +2991,60 @@ run</programlisting>
|
||||||
</informaltable>
|
</informaltable>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
<section id="opus_encoder">
|
||||||
|
<title><varname>opus</varname></title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Encodes into <ulink
|
||||||
|
url="http://www.opus-codec.org/">Ogg Opus</ulink>.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<informaltable>
|
||||||
|
<tgroup cols="2">
|
||||||
|
<thead>
|
||||||
|
<row>
|
||||||
|
<entry>Setting</entry>
|
||||||
|
<entry>Description</entry>
|
||||||
|
</row>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<row>
|
||||||
|
<entry>
|
||||||
|
<varname>bitrate</varname>
|
||||||
|
</entry>
|
||||||
|
<entry>
|
||||||
|
Sets the data rate in bit per second. The special
|
||||||
|
value "auto" lets <application>libopus</application>
|
||||||
|
choose a rate (which is the default), and "max" uses
|
||||||
|
the maximum possible data rate.
|
||||||
|
</entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry>
|
||||||
|
<varname>complexity</varname>
|
||||||
|
</entry>
|
||||||
|
<entry>
|
||||||
|
Sets the <ulink
|
||||||
|
url="https://wiki.xiph.org/OpusFAQ#What_is_the_complexity_of_Opus.3F">Opus
|
||||||
|
complexity</ulink>.
|
||||||
|
</entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry>
|
||||||
|
<varname>signal</varname>
|
||||||
|
</entry>
|
||||||
|
<entry>
|
||||||
|
Sets the Opus signal type. Valid values are "auto"
|
||||||
|
(the default), "voice" and "music".
|
||||||
|
</entry>
|
||||||
|
</row>
|
||||||
|
</tbody>
|
||||||
|
</tgroup>
|
||||||
|
</informaltable>
|
||||||
|
</section>
|
||||||
|
|
||||||
<section id="vorbis_encoder">
|
<section id="vorbis_encoder">
|
||||||
<title><varname>vorbis</varname></title>
|
<title><varname>vorbis</varname></title>
|
||||||
|
|
||||||
|
|
|
@ -712,7 +712,9 @@ FfmpegDecode(DecoderClient &client, InputStream &input,
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const SignedSongTime total_time =
|
const SignedSongTime total_time =
|
||||||
FromFfmpegTimeChecked(av_stream.duration, av_stream.time_base);
|
av_stream.duration != (int64_t)AV_NOPTS_VALUE
|
||||||
|
? FromFfmpegTimeChecked(av_stream.duration, av_stream.time_base)
|
||||||
|
: FromFfmpegTimeChecked(format_context.duration, AV_TIME_BASE_Q);
|
||||||
|
|
||||||
client.Ready(audio_format, input.IsSeekable(), total_time);
|
client.Ready(audio_format, input.IsSeekable(), total_time);
|
||||||
|
|
||||||
|
@ -842,6 +844,10 @@ FfmpegScanStream(AVFormatContext &format_context,
|
||||||
tag_handler_invoke_duration(handler, handler_ctx,
|
tag_handler_invoke_duration(handler, handler_ctx,
|
||||||
FromFfmpegTime(stream.duration,
|
FromFfmpegTime(stream.duration,
|
||||||
stream.time_base));
|
stream.time_base));
|
||||||
|
else if (format_context.duration != (int64_t)AV_NOPTS_VALUE)
|
||||||
|
tag_handler_invoke_duration(handler, handler_ctx,
|
||||||
|
FromFfmpegTime(format_context.duration,
|
||||||
|
AV_TIME_BASE_Q));
|
||||||
|
|
||||||
FfmpegScanMetadata(format_context, audio_stream, handler, handler_ctx);
|
FfmpegScanMetadata(format_context, audio_stream, handler, handler_ctx);
|
||||||
|
|
||||||
|
|
|
@ -66,16 +66,14 @@ SndioOutput::Create(EventLoop &, const ConfigBlock &block) {
|
||||||
static bool
|
static bool
|
||||||
sndio_test_default_device()
|
sndio_test_default_device()
|
||||||
{
|
{
|
||||||
struct sio_hdl *sio_hdl;
|
auto *hdl = sio_open(SIO_DEVANY, SIO_PLAY, 0);
|
||||||
|
if (!hdl) {
|
||||||
sio_hdl = sio_open(SIO_DEVANY, SIO_PLAY, 0);
|
|
||||||
if (!sio_hdl) {
|
|
||||||
FormatError(sndio_output_domain,
|
FormatError(sndio_output_domain,
|
||||||
"Error opening default sndio device");
|
"Error opening default sndio device");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
sio_close(sio_hdl);
|
sio_close(hdl);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,8 +83,8 @@ SndioOutput::Open(AudioFormat &audio_format)
|
||||||
struct sio_par par;
|
struct sio_par par;
|
||||||
unsigned bits, rate, chans;
|
unsigned bits, rate, chans;
|
||||||
|
|
||||||
sio_hdl = sio_open(device, SIO_PLAY, 0);
|
hdl = sio_open(device, SIO_PLAY, 0);
|
||||||
if (!sio_hdl)
|
if (!hdl)
|
||||||
throw std::runtime_error("Failed to open default sndio device");
|
throw std::runtime_error("Failed to open default sndio device");
|
||||||
|
|
||||||
switch (audio_format.format) {
|
switch (audio_format.format) {
|
||||||
|
@ -116,9 +114,9 @@ SndioOutput::Open(AudioFormat &audio_format)
|
||||||
par.le = SIO_LE_NATIVE;
|
par.le = SIO_LE_NATIVE;
|
||||||
par.appbufsz = rate * buffer_time / 1000;
|
par.appbufsz = rate * buffer_time / 1000;
|
||||||
|
|
||||||
if (!sio_setpar(sio_hdl, &par) ||
|
if (!sio_setpar(hdl, &par) ||
|
||||||
!sio_getpar(sio_hdl, &par)) {
|
!sio_getpar(hdl, &par)) {
|
||||||
sio_close(sio_hdl);
|
sio_close(hdl);
|
||||||
throw std::runtime_error("Failed to set/get audio params");
|
throw std::runtime_error("Failed to set/get audio params");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,21 +126,21 @@ SndioOutput::Open(AudioFormat &audio_format)
|
||||||
par.pchan != chans ||
|
par.pchan != chans ||
|
||||||
par.sig != 1 ||
|
par.sig != 1 ||
|
||||||
par.le != SIO_LE_NATIVE) {
|
par.le != SIO_LE_NATIVE) {
|
||||||
sio_close(sio_hdl);
|
sio_close(hdl);
|
||||||
throw std::runtime_error("Requested audio params cannot be satisfied");
|
throw std::runtime_error("Requested audio params cannot be satisfied");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set volume after opening fresh audio stream which does
|
// Set volume after opening fresh audio stream which does
|
||||||
// know nothing about previous audio streams.
|
// know nothing about previous audio streams.
|
||||||
sio_setvol(sio_hdl, raw_volume);
|
sio_setvol(hdl, raw_volume);
|
||||||
// sio_onvol returns 0 if no volume knob is available.
|
// sio_onvol returns 0 if no volume knob is available.
|
||||||
// This is the case on raw audio devices rather than
|
// This is the case on raw audio devices rather than
|
||||||
// the sndiod audio server.
|
// the sndiod audio server.
|
||||||
if (sio_onvol(sio_hdl, VolumeCallback, this) == 0)
|
if (sio_onvol(hdl, VolumeCallback, this) == 0)
|
||||||
raw_volume = -1;
|
raw_volume = -1;
|
||||||
|
|
||||||
if (!sio_start(sio_hdl)) {
|
if (!sio_start(hdl)) {
|
||||||
sio_close(sio_hdl);
|
sio_close(hdl);
|
||||||
throw std::runtime_error("Failed to start audio device");
|
throw std::runtime_error("Failed to start audio device");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -150,7 +148,7 @@ SndioOutput::Open(AudioFormat &audio_format)
|
||||||
void
|
void
|
||||||
SndioOutput::Close() noexcept
|
SndioOutput::Close() noexcept
|
||||||
{
|
{
|
||||||
sio_close(sio_hdl);
|
sio_close(hdl);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
|
@ -158,15 +156,16 @@ SndioOutput::Play(const void *chunk, size_t size)
|
||||||
{
|
{
|
||||||
size_t n;
|
size_t n;
|
||||||
|
|
||||||
n = sio_write(sio_hdl, chunk, size);
|
n = sio_write(hdl, chunk, size);
|
||||||
if (n == 0 && sio_eof(sio_hdl) != 0)
|
if (n == 0 && sio_eof(hdl) != 0)
|
||||||
throw std::runtime_error("sndio write failed");
|
throw std::runtime_error("sndio write failed");
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
SndioOutput::SetVolume(unsigned int volume) {
|
SndioOutput::SetVolume(unsigned int volume)
|
||||||
sio_setvol(sio_hdl, volume * SIO_MAXVOL / 100);
|
{
|
||||||
|
sio_setvol(hdl, volume * SIO_MAXVOL / 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline unsigned int
|
static inline unsigned int
|
||||||
|
|
|
@ -30,7 +30,7 @@ class SndioOutput final : AudioOutput {
|
||||||
MixerListener *listener = nullptr;
|
MixerListener *listener = nullptr;
|
||||||
const char *const device;
|
const char *const device;
|
||||||
const unsigned buffer_time; /* in ms */
|
const unsigned buffer_time; /* in ms */
|
||||||
struct sio_hdl *sio_hdl;
|
struct sio_hdl *hdl;
|
||||||
int raw_volume;
|
int raw_volume;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
Loading…
Reference in New Issue