Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
M
mpd
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Иван Мажукин
mpd
Commits
1628d801
Commit
1628d801
authored
Feb 05, 2018
by
Patryk Hachuła
Committed by
Max Kellermann
Feb 25, 2018
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
playlist/Queue: add one-shot to single mode
parent
1fb35824
Show whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
183 additions
and
21 deletions
+183
-21
Makefile.am
Makefile.am
+1
-0
NEWS
NEWS
+2
-0
protocol.xml
doc/protocol.xml
+2
-2
Partition.cxx
src/Partition.cxx
+15
-0
Partition.hxx
src/Partition.hxx
+10
-1
SingleMode.cxx
src/SingleMode.cxx
+58
-0
SingleMode.hxx
src/SingleMode.hxx
+46
-0
PlayerCommands.cxx
src/command/PlayerCommands.cxx
+7
-6
Listener.hxx
src/player/Listener.hxx
+5
-0
Thread.cxx
src/player/Thread.cxx
+1
-0
Playlist.cxx
src/queue/Playlist.cxx
+18
-5
Playlist.hxx
src/queue/Playlist.hxx
+9
-2
PlaylistState.cxx
src/queue/PlaylistState.cxx
+6
-3
Queue.cxx
src/queue/Queue.cxx
+1
-1
Queue.hxx
src/queue/Queue.hxx
+2
-1
No files found.
Makefile.am
View file @
1628d801
...
...
@@ -947,6 +947,7 @@ endif
libbasic_a_SOURCES
=
\
src/ReplayGainConfig.hxx
\
src/ReplayGainMode.cxx src/ReplayGainMode.hxx
\
src/SingleMode.cxx src/SingleMode.hxx
\
src/ReplayGainInfo.cxx src/ReplayGainInfo.hxx
# configuration library
...
...
NEWS
View file @
1628d801
...
...
@@ -5,6 +5,8 @@ ver 0.21 (not yet released)
- "outputs" prints the plugin name
- "outputset" sets runtime attributes
- close connection when client sends HTTP request
* player
- "one-shot" single mode
* input
- qobuz: new plugin to play Qobuz streams
- tidal: new plugin to play Tidal streams
...
...
doc/protocol.xml
View file @
1628d801
...
...
@@ -464,8 +464,8 @@
<listitem>
<para>
<varname>
single
</varname>
:
<footnote
id=
"since_0_15"
><simpara>
Introduced with
<application>
MPD
</application>
0.15
</simpara></footnote>
<returnvalue>
0
or 1
</returnvalue>
<footnote
id=
"since_0_15"
><simpara>
Introduced with
<application>
MPD
</application>
0.15
(oneshot introduced with 0.20)
</simpara></footnote>
<returnvalue>
0
, 1, or oneshot
</returnvalue>
</para>
</listitem>
<listitem>
...
...
src/Partition.cxx
View file @
1628d801
...
...
@@ -110,6 +110,12 @@ Partition::SyncWithPlayer()
}
void
Partition
::
BorderPause
()
{
playlist
.
BorderPause
(
pc
);
}
void
Partition
::
OnQueueModified
()
{
EmitIdle
(
IDLE_PLAYLIST
);
...
...
@@ -140,6 +146,12 @@ Partition::OnPlayerTagModified() noexcept
}
void
Partition
::
OnBorderPause
()
noexcept
{
EmitGlobalEvent
(
BORDER_PAUSE
);
}
void
Partition
::
OnMixerVolumeChanged
(
gcc_unused
Mixer
&
mixer
,
gcc_unused
int
volume
)
{
InvalidateHardwareVolume
();
...
...
@@ -156,4 +168,7 @@ Partition::OnGlobalEvent(unsigned mask)
if
((
mask
&
TAG_MODIFIED
)
!=
0
)
TagModified
();
if
((
mask
&
BORDER_PAUSE
)
!=
0
)
BorderPause
();
}
src/Partition.hxx
View file @
1628d801
...
...
@@ -28,6 +28,7 @@
#include "player/Control.hxx"
#include "player/Listener.hxx"
#include "ReplayGainMode.hxx"
#include "SingleMode.hxx"
#include "Chrono.hxx"
#include "Compiler.h"
...
...
@@ -46,6 +47,7 @@ class ClientListener;
struct
Partition
final
:
QueueListener
,
PlayerListener
,
MixerListener
{
static
constexpr
unsigned
TAG_MODIFIED
=
0x1
;
static
constexpr
unsigned
SYNC_WITH_PLAYER
=
0x2
;
static
constexpr
unsigned
BORDER_PAUSE
=
0x4
;
Instance
&
instance
;
...
...
@@ -184,7 +186,7 @@ struct Partition final : QueueListener, PlayerListener, MixerListener {
playlist
.
SetRandom
(
pc
,
new_value
);
}
void
SetSingle
(
bool
new_value
)
{
void
SetSingle
(
SingleMode
new_value
)
{
playlist
.
SetSingle
(
pc
,
new_value
);
}
...
...
@@ -237,6 +239,12 @@ struct Partition final : QueueListener, PlayerListener, MixerListener {
*/
void
SyncWithPlayer
();
/**
* Border pause has just been enabled. Change single mode to off
* if it was one-shot.
*/
void
BorderPause
();
private
:
/* virtual methods from class QueueListener */
void
OnQueueModified
()
override
;
...
...
@@ -246,6 +254,7 @@ private:
/* virtual methods from class PlayerListener */
void
OnPlayerSync
()
noexcept
override
;
void
OnPlayerTagModified
()
noexcept
override
;
void
OnBorderPause
()
noexcept
override
;
/* virtual methods from class MixerListener */
void
OnMixerVolumeChanged
(
Mixer
&
mixer
,
int
volume
)
override
;
...
...
src/SingleMode.cxx
0 → 100644
View file @
1628d801
/*
* Copyright 2003-2017 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "SingleMode.hxx"
#include <stdexcept>
#include <assert.h>
#include <string.h>
const
char
*
SingleToString
(
SingleMode
mode
)
noexcept
{
switch
(
mode
)
{
case
SingleMode
:
:
OFF
:
return
"0"
;
case
SingleMode
:
:
ON
:
return
"1"
;
case
SingleMode
:
:
ONE_SHOT
:
return
"oneshot"
;
}
assert
(
false
);
gcc_unreachable
();
}
SingleMode
SingleFromString
(
const
char
*
s
)
{
assert
(
s
!=
nullptr
);
if
(
strcmp
(
s
,
"0"
)
==
0
)
return
SingleMode
::
OFF
;
else
if
(
strcmp
(
s
,
"1"
)
==
0
)
return
SingleMode
::
ON
;
else
if
(
strcmp
(
s
,
"oneshot"
)
==
0
)
return
SingleMode
::
ONE_SHOT
;
else
throw
std
::
invalid_argument
(
"Unrecognized single mode, expected 0, 1, or oneshot"
);
}
src/SingleMode.hxx
0 → 100644
View file @
1628d801
/*
* Copyright 2003-2017 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef MPD_SINGLE_MODE_HXX
#define MPD_SINGLE_MODE_HXX
#include "Compiler.h"
#include <stdint.h>
enum
class
SingleMode
:
uint8_t
{
OFF
,
ON
,
ONE_SHOT
,
};
/**
* Return the string representation of a #SingleMode.
*/
gcc_pure
const
char
*
SingleToString
(
SingleMode
mode
)
noexcept
;
/**
* Parse a string to a #SingleMode. Throws std::invalid_argument on error.
*/
SingleMode
SingleFromString
(
const
char
*
s
);
#endif
src/command/PlayerCommands.cxx
View file @
1628d801
...
...
@@ -23,6 +23,7 @@
#include "CommandError.hxx"
#include "queue/Playlist.hxx"
#include "PlaylistPrint.hxx"
#include "SingleMode.hxx"
#include "client/Client.hxx"
#include "client/Response.hxx"
#include "mixer/Volume.hxx"
...
...
@@ -134,7 +135,7 @@ handle_status(Client &client, gcc_unused Request args, Response &r)
r
.
Format
(
COMMAND_STATUS_REPEAT
": %i
\n
"
COMMAND_STATUS_RANDOM
": %i
\n
"
COMMAND_STATUS_SINGLE
": %
i
\n
"
COMMAND_STATUS_SINGLE
": %
s
\n
"
COMMAND_STATUS_CONSUME
": %i
\n
"
COMMAND_STATUS_PLAYLIST
": %li
\n
"
COMMAND_STATUS_PLAYLIST_LENGTH
": %i
\n
"
...
...
@@ -142,7 +143,7 @@ handle_status(Client &client, gcc_unused Request args, Response &r)
COMMAND_STATUS_STATE
": %s
\n
"
,
playlist
.
GetRepeat
(),
playlist
.
GetRandom
(),
playlist
.
GetSingle
(
),
SingleToString
(
playlist
.
GetSingle
()
),
playlist
.
GetConsume
(),
(
unsigned
long
)
playlist
.
GetVersion
(),
playlist
.
GetLength
(),
...
...
@@ -218,8 +219,8 @@ handle_next(Client &client, gcc_unused Request args, gcc_unused Response &r)
/* single mode is not considered when this is user who
* wants to change song. */
const
bool
single
=
playlist
.
queue
.
single
;
playlist
.
queue
.
single
=
false
;
const
SingleMode
single
=
playlist
.
queue
.
single
;
playlist
.
queue
.
single
=
SingleMode
::
OFF
;
AtScopeExit
(
&
playlist
,
single
)
{
playlist
.
queue
.
single
=
single
;
...
...
@@ -248,8 +249,8 @@ handle_repeat(Client &client, Request args, gcc_unused Response &r)
CommandResult
handle_single
(
Client
&
client
,
Request
args
,
gcc_unused
Response
&
r
)
{
bool
status
=
args
.
ParseBool
(
0
);
client
.
GetPartition
().
SetSingle
(
status
);
auto
new_mode
=
SingleFromString
(
args
.
front
()
);
client
.
GetPartition
().
SetSingle
(
new_mode
);
return
CommandResult
::
OK
;
}
...
...
src/player/Listener.hxx
View file @
1628d801
...
...
@@ -31,6 +31,11 @@ public:
* The current song's tag has changed.
*/
virtual
void
OnPlayerTagModified
()
noexcept
=
0
;
/**
* Playback went into border pause.
*/
virtual
void
OnBorderPause
()
noexcept
=
0
;
};
#endif
src/player/Thread.cxx
View file @
1628d801
...
...
@@ -930,6 +930,7 @@ Player::SongBorder() noexcept
const
bool
border_pause
=
pc
.
ApplyBorderPause
();
if
(
border_pause
)
{
paused
=
true
;
pc
.
listener
.
OnBorderPause
();
idle_add
(
IDLE_PLAYER
);
}
}
...
...
src/queue/Playlist.cxx
View file @
1628d801
...
...
@@ -23,6 +23,7 @@
#include "PlaylistError.hxx"
#include "player/Control.hxx"
#include "DetachedSong.hxx"
#include "SingleMode.hxx"
#include "Log.hxx"
#include <assert.h>
...
...
@@ -136,7 +137,7 @@ playlist::UpdateQueuedSong(PlayerControl &pc, const DetachedSong *prev)
?
queue
.
GetNextOrder
(
current
)
:
0
;
if
(
next_order
==
0
&&
queue
.
random
&&
!
queue
.
single
)
{
if
(
next_order
==
0
&&
queue
.
random
&&
queue
.
single
==
SingleMode
::
OFF
)
{
/* shuffle the song order again, so we get a different
order each time the playlist is played
completely */
...
...
@@ -257,7 +258,7 @@ playlist::SetRepeat(PlayerControl &pc, bool status)
queue
.
repeat
=
status
;
pc
.
LockSetBorderPause
(
queue
.
single
&&
!
queue
.
repeat
);
pc
.
LockSetBorderPause
(
queue
.
single
!=
SingleMode
::
OFF
&&
!
queue
.
repeat
);
/* if the last song is currently being played, the "next song"
might change when repeat mode is toggled */
...
...
@@ -277,14 +278,15 @@ playlist_order(playlist &playlist)
}
void
playlist
::
SetSingle
(
PlayerControl
&
pc
,
bool
status
)
playlist
::
SetSingle
(
PlayerControl
&
pc
,
SingleMode
status
)
{
if
(
status
==
queue
.
single
)
return
;
queue
.
single
=
status
;
pc
.
LockSetBorderPause
(
queue
.
single
&&
!
queue
.
repeat
);
pc
.
LockSetBorderPause
(
queue
.
single
!=
SingleMode
::
OFF
&&
!
queue
.
repeat
);
/* if the last song is currently being played, the "next song"
might change when single mode is toggled */
...
...
@@ -353,7 +355,7 @@ playlist::GetNextPosition() const noexcept
if
(
current
<
0
)
return
-
1
;
if
(
queue
.
single
&&
queue
.
repeat
)
if
(
queue
.
single
!=
SingleMode
::
OFF
&&
queue
.
repeat
)
return
queue
.
OrderToPosition
(
current
);
else
if
(
queue
.
IsValidOrder
(
current
+
1
))
return
queue
.
OrderToPosition
(
current
+
1
);
...
...
@@ -362,3 +364,14 @@ playlist::GetNextPosition() const noexcept
return
-
1
;
}
void
playlist
::
BorderPause
(
PlayerControl
&
pc
)
{
if
(
queue
.
single
==
SingleMode
::
ONE_SHOT
)
{
queue
.
single
=
SingleMode
::
OFF
;
pc
.
LockSetBorderPause
(
false
);
listener
.
OnQueueOptionsChanged
();
}
}
src/queue/Playlist.hxx
View file @
1628d801
...
...
@@ -20,6 +20,7 @@
#ifndef MPD_PLAYLIST_HXX
#define MPD_PLAYLIST_HXX
#include "SingleMode.hxx"
#include "queue/Queue.hxx"
enum
TagType
:
uint8_t
;
...
...
@@ -133,6 +134,12 @@ struct playlist {
*/
void
SyncWithPlayer
(
PlayerControl
&
pc
);
/**
* This is the "BORDER_PAUSE" event handler. It is invoked by
* the player thread whenever playback goes into border pause.
*/
void
BorderPause
(
PlayerControl
&
pc
);
protected
:
/**
* Called by all editing methods after a modification.
...
...
@@ -347,11 +354,11 @@ public:
void
SetRandom
(
PlayerControl
&
pc
,
bool
new_value
);
bool
GetSingle
()
const
{
SingleMode
GetSingle
()
const
{
return
queue
.
single
;
}
void
SetSingle
(
PlayerControl
&
pc
,
bool
new_value
);
void
SetSingle
(
PlayerControl
&
pc
,
SingleMode
new_value
);
bool
GetConsume
()
const
{
return
queue
.
consume
;
...
...
src/queue/PlaylistState.cxx
View file @
1628d801
...
...
@@ -26,6 +26,7 @@
#include "PlaylistState.hxx"
#include "PlaylistError.hxx"
#include "Playlist.hxx"
#include "SingleMode.hxx"
#include "queue/QueueSave.hxx"
#include "fs/io/TextFile.hxx"
#include "fs/io/BufferedOutputStream.hxx"
...
...
@@ -88,7 +89,8 @@ playlist_state_save(BufferedOutputStream &os, const struct playlist &playlist,
os
.
Format
(
PLAYLIST_STATE_FILE_RANDOM
"%i
\n
"
,
playlist
.
queue
.
random
);
os
.
Format
(
PLAYLIST_STATE_FILE_REPEAT
"%i
\n
"
,
playlist
.
queue
.
repeat
);
os
.
Format
(
PLAYLIST_STATE_FILE_SINGLE
"%i
\n
"
,
playlist
.
queue
.
single
);
os
.
Format
(
PLAYLIST_STATE_FILE_SINGLE
"%i
\n
"
,
(
int
)
playlist
.
queue
.
single
);
os
.
Format
(
PLAYLIST_STATE_FILE_CONSUME
"%i
\n
"
,
playlist
.
queue
.
consume
);
os
.
Format
(
PLAYLIST_STATE_FILE_CROSSFADE
"%i
\n
"
,
(
int
)
pc
.
GetCrossFade
());
...
...
@@ -153,7 +155,7 @@ playlist_state_restore(const char *line, TextFile &file,
}
else
if
((
p
=
StringAfterPrefix
(
line
,
PLAYLIST_STATE_FILE_REPEAT
)))
{
playlist
.
SetRepeat
(
pc
,
StringIsEqual
(
p
,
"1"
));
}
else
if
((
p
=
StringAfterPrefix
(
line
,
PLAYLIST_STATE_FILE_SINGLE
)))
{
playlist
.
SetSingle
(
pc
,
S
tringIsEqual
(
p
,
"1"
));
playlist
.
SetSingle
(
pc
,
S
ingleFromString
(
p
));
}
else
if
((
p
=
StringAfterPrefix
(
line
,
PLAYLIST_STATE_FILE_CONSUME
)))
{
playlist
.
SetConsume
(
StringIsEqual
(
p
,
"1"
));
}
else
if
((
p
=
StringAfterPrefix
(
line
,
PLAYLIST_STATE_FILE_CROSSFADE
)))
{
...
...
@@ -233,9 +235,10 @@ playlist_state_get_hash(const playlist &playlist,
:
0
)
^
((
int
)
pc
.
GetCrossFade
()
<<
20
)
^
(
unsigned
(
player_status
.
state
)
<<
24
)
^
/* note that this takes 2 bits */
((
int
)
playlist
.
queue
.
single
<<
25
)
^
(
playlist
.
queue
.
random
<<
27
)
^
(
playlist
.
queue
.
repeat
<<
28
)
^
(
playlist
.
queue
.
single
<<
29
)
^
(
playlist
.
queue
.
consume
<<
30
)
^
(
playlist
.
queue
.
random
<<
31
);
}
src/queue/Queue.cxx
View file @
1628d801
...
...
@@ -42,7 +42,7 @@ Queue::GetNextOrder(unsigned _order) const noexcept
{
assert
(
_order
<
length
);
if
(
single
&&
repeat
&&
!
consume
)
if
(
single
!=
SingleMode
::
OFF
&&
repeat
&&
!
consume
)
return
_order
;
else
if
(
_order
+
1
<
length
)
return
_order
+
1
;
...
...
src/queue/Queue.hxx
View file @
1628d801
...
...
@@ -22,6 +22,7 @@
#include "Compiler.h"
#include "IdTable.hxx"
#include "SingleMode.hxx"
#include "util/LazyRandomEngine.hxx"
#include <algorithm>
...
...
@@ -92,7 +93,7 @@ struct Queue {
bool
repeat
=
false
;
/** play only current song. */
bool
single
=
false
;
SingleMode
single
=
SingleMode
::
OFF
;
/** remove each played files. */
bool
consume
=
false
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment