release v0.18.13
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJUAxsyAAoJECNuiljG20USmRAP/2J/+kV5TRfqr7acFKh/aqip RAefHTvHpYuAUDOi3WDVSZcmMnaYGKslZhbXhqchbRfR2oMwYhR+5gHIoxOp+EcL 09UF1fJfUnjg6B2zz6tggIWR53Dwxckg4xEaKtI2Wi3Gz+9Q/CiNlpWLJc0ONA5e 9gcz8pNK3oN0Em9c1KXahZKArzGdOGeytfSI3PLE+QnRiEyEDz1+StxIuyl72vr4 ar2EMa9Vdvb7ouNK0g8WqaEOzYyNDXhklIqc+zALQJGThY1xj6OCfQ8JVagJhzwB UDuYfX1FylkN8LhF5pNzH1F0ANMozWcqeZlLLph6vuKkVBD7WUX4X1t82bwUlFDB ppdA5pPkiXsqYnuhHML4GqL7LlI2wsMxUHK7v+A9+9hfGN9HIoFyOSLBjB1pyI93 yi8IPOq2a1BJQfQ2c69693ZS7WPxU6vOFKucKrk9PBlr2900SlvpMzIpZr1PMnGV hoU8eLHOIW86wi5Ea2ycFbFyI1ZoyrKJmzcVJjPjZUT05jDV6bA2Gi1IG6gIhX1q DiBfXUre+GISkLS4r8GcbG1FIXcv7fGjZ6Vols5di8lpYQ5oBu5aw2TEf8zukrHC LzPRa2l6Mhe2OI7a/mmTaEYDINgCL//46hOU5mIbmB0XZS8Jf+D1/HBzqKpeqO7f idENtbelqQdSsR5UU+R0 =c2vC -----END PGP SIGNATURE----- Merge tag 'v0.18.13'
This commit is contained in:
commit
6e04d66a35
8
NEWS
8
NEWS
@ -68,10 +68,16 @@ ver 0.19 (not yet released)
|
|||||||
* install systemd unit for socket activation
|
* install systemd unit for socket activation
|
||||||
* Android port
|
* Android port
|
||||||
|
|
||||||
ver 0.18.13 (not yet released)
|
ver 0.18.13 (2014/08/31)
|
||||||
|
* protocol
|
||||||
|
- don't change song on "seekcur" in random mode
|
||||||
|
|
||||||
* decoder
|
* decoder
|
||||||
- dsdiff, dsf: fix endless loop on malformed file
|
- dsdiff, dsf: fix endless loop on malformed file
|
||||||
- ffmpeg: support ffmpeg/libav version 11
|
- ffmpeg: support ffmpeg/libav version 11
|
||||||
|
- gme: fix song duration
|
||||||
|
* output
|
||||||
|
- alsa: fix endless loop at end of file in dsd_usb mode
|
||||||
* fix state file saver
|
* fix state file saver
|
||||||
* fix build failure on Darwin
|
* fix build failure on Darwin
|
||||||
|
|
||||||
|
@ -576,7 +576,12 @@
|
|||||||
</listitem>
|
</listitem>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
<varname>songs</varname>: number of albums
|
<varname>albums</varname>: number of albums
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<varname>songs</varname>: number of songs
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
<listitem>
|
<listitem>
|
||||||
|
@ -825,6 +825,7 @@ alsa_play(AudioOutput *ao, const void *chunk, size_t size,
|
|||||||
{
|
{
|
||||||
AlsaOutput *ad = (AlsaOutput *)ao;
|
AlsaOutput *ad = (AlsaOutput *)ao;
|
||||||
|
|
||||||
|
assert(size > 0);
|
||||||
assert(size % ad->in_frame_size == 0);
|
assert(size % ad->in_frame_size == 0);
|
||||||
|
|
||||||
if (ad->must_prepare) {
|
if (ad->must_prepare) {
|
||||||
@ -838,12 +839,22 @@ alsa_play(AudioOutput *ao, const void *chunk, size_t size,
|
|||||||
}
|
}
|
||||||
|
|
||||||
const auto e = ad->pcm_export->Export({chunk, size});
|
const auto e = ad->pcm_export->Export({chunk, size});
|
||||||
|
if (e.size == 0)
|
||||||
|
/* the DoP (DSD over PCM) filter converts two frames
|
||||||
|
at a time and ignores the last odd frame; if there
|
||||||
|
was only one frame (e.g. the last frame in the
|
||||||
|
file), the result is empty; to avoid an endless
|
||||||
|
loop, bail out here, and pretend the one frame has
|
||||||
|
been played */
|
||||||
|
return size;
|
||||||
|
|
||||||
chunk = e.data;
|
chunk = e.data;
|
||||||
size = e.size;
|
size = e.size;
|
||||||
|
|
||||||
assert(size % ad->out_frame_size == 0);
|
assert(size % ad->out_frame_size == 0);
|
||||||
|
|
||||||
size /= ad->out_frame_size;
|
size /= ad->out_frame_size;
|
||||||
|
assert(size > 0);
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
snd_pcm_sframes_t ret = ad->writei(ad->pcm, chunk, size);
|
snd_pcm_sframes_t ret = ad->writei(ad->pcm, chunk, size);
|
||||||
|
@ -724,6 +724,8 @@ oss_output_play(AudioOutput *ao, const void *chunk, size_t size,
|
|||||||
OssOutput *od = (OssOutput *)ao;
|
OssOutput *od = (OssOutput *)ao;
|
||||||
ssize_t ret;
|
ssize_t ret;
|
||||||
|
|
||||||
|
assert(size > 0);
|
||||||
|
|
||||||
/* reopen the device since it was closed by dropBufferedAudio */
|
/* reopen the device since it was closed by dropBufferedAudio */
|
||||||
if (od->fd < 0 && !oss_reopen(od, error))
|
if (od->fd < 0 && !oss_reopen(od, error))
|
||||||
return 0;
|
return 0;
|
||||||
@ -734,6 +736,8 @@ oss_output_play(AudioOutput *ao, const void *chunk, size_t size,
|
|||||||
size = e.size;
|
size = e.size;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
assert(size > 0);
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
ret = write(od->fd, chunk, size);
|
ret = write(od->fd, chunk, size);
|
||||||
if (ret > 0) {
|
if (ret > 0) {
|
||||||
|
@ -251,6 +251,10 @@ public:
|
|||||||
|
|
||||||
void PlayPrevious(PlayerControl &pc);
|
void PlayPrevious(PlayerControl &pc);
|
||||||
|
|
||||||
|
PlaylistResult SeekSongOrder(PlayerControl &pc,
|
||||||
|
unsigned song_order,
|
||||||
|
SongTime seek_time);
|
||||||
|
|
||||||
PlaylistResult SeekSongPosition(PlayerControl &pc,
|
PlaylistResult SeekSongPosition(PlayerControl &pc,
|
||||||
unsigned song_position,
|
unsigned song_position,
|
||||||
SongTime seek_time);
|
SongTime seek_time);
|
||||||
|
@ -190,18 +190,12 @@ playlist::PlayPrevious(PlayerControl &pc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
PlaylistResult
|
PlaylistResult
|
||||||
playlist::SeekSongPosition(PlayerControl &pc,
|
playlist::SeekSongOrder(PlayerControl &pc, unsigned i, SongTime seek_time)
|
||||||
unsigned song, SongTime seek_time)
|
|
||||||
{
|
{
|
||||||
if (!queue.IsValidPosition(song))
|
assert(queue.IsValidOrder(i));
|
||||||
return PlaylistResult::BAD_RANGE;
|
|
||||||
|
|
||||||
const DetachedSong *queued_song = GetQueuedSong();
|
const DetachedSong *queued_song = GetQueuedSong();
|
||||||
|
|
||||||
unsigned i = queue.random
|
|
||||||
? queue.PositionToOrder(song)
|
|
||||||
: song;
|
|
||||||
|
|
||||||
pc.ClearError();
|
pc.ClearError();
|
||||||
stop_on_error = true;
|
stop_on_error = true;
|
||||||
error_count = 0;
|
error_count = 0;
|
||||||
@ -228,6 +222,20 @@ playlist::SeekSongPosition(PlayerControl &pc,
|
|||||||
return PlaylistResult::SUCCESS;
|
return PlaylistResult::SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PlaylistResult
|
||||||
|
playlist::SeekSongPosition(PlayerControl &pc, unsigned song,
|
||||||
|
SongTime seek_time)
|
||||||
|
{
|
||||||
|
if (!queue.IsValidPosition(song))
|
||||||
|
return PlaylistResult::BAD_RANGE;
|
||||||
|
|
||||||
|
unsigned i = queue.random
|
||||||
|
? queue.PositionToOrder(song)
|
||||||
|
: song;
|
||||||
|
|
||||||
|
return SeekSongOrder(pc, i, seek_time);
|
||||||
|
}
|
||||||
|
|
||||||
PlaylistResult
|
PlaylistResult
|
||||||
playlist::SeekSongId(PlayerControl &pc, unsigned id, SongTime seek_time)
|
playlist::SeekSongId(PlayerControl &pc, unsigned id, SongTime seek_time)
|
||||||
{
|
{
|
||||||
@ -257,5 +265,8 @@ playlist::SeekCurrent(PlayerControl &pc,
|
|||||||
seek_time = SignedSongTime::zero();
|
seek_time = SignedSongTime::zero();
|
||||||
}
|
}
|
||||||
|
|
||||||
return SeekSongPosition(pc, current, SongTime(seek_time));
|
if (seek_time.IsNegative())
|
||||||
|
seek_time = SignedSongTime::zero();
|
||||||
|
|
||||||
|
return SeekSongOrder(pc, current, SongTime(seek_time));
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user