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
7652a298
Commit
7652a298
authored
Aug 06, 2015
by
Max Kellermann
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
client/Response: new Client wrapper class for writing responses
parent
b1480167
Hide whitespace changes
Inline
Side-by-side
Showing
49 changed files
with
1067 additions
and
779 deletions
+1067
-779
Makefile.am
Makefile.am
+1
-0
PlaylistPrint.cxx
src/PlaylistPrint.cxx
+28
-21
PlaylistPrint.hxx
src/PlaylistPrint.hxx
+16
-9
SongPrint.cxx
src/SongPrint.cxx
+47
-40
SongPrint.hxx
src/SongPrint.hxx
+10
-5
Stats.cxx
src/Stats.cxx
+20
-23
Stats.hxx
src/Stats.hxx
+3
-2
TagPrint.cxx
src/TagPrint.cxx
+15
-15
TagPrint.hxx
src/TagPrint.hxx
+6
-5
TimePrint.cxx
src/TimePrint.cxx
+3
-3
TimePrint.hxx
src/TimePrint.hxx
+2
-2
Response.cxx
src/client/Response.cxx
+72
-0
Response.hxx
src/client/Response.hxx
+49
-0
AllCommands.cxx
src/command/AllCommands.cxx
+42
-23
CommandError.cxx
src/command/CommandError.cxx
+25
-30
CommandError.hxx
src/command/CommandError.hxx
+3
-3
DatabaseCommands.cxx
src/command/DatabaseCommands.cxx
+52
-30
FileCommands.cxx
src/command/FileCommands.cxx
+34
-38
MessageCommands.cxx
src/command/MessageCommands.cxx
+18
-16
NeighborCommands.cxx
src/command/NeighborCommands.cxx
+8
-8
OtherCommands.cxx
src/command/OtherCommands.cxx
+65
-52
OutputCommands.cxx
src/command/OutputCommands.cxx
+15
-14
PlayerCommands.cxx
src/command/PlayerCommands.cxx
+102
-85
PlaylistCommands.cxx
src/command/PlaylistCommands.cxx
+48
-27
QueueCommands.cxx
src/command/QueueCommands.cxx
+81
-51
Request.hxx
src/command/Request.hxx
+7
-7
StickerCommands.cxx
src/command/StickerCommands.cxx
+34
-35
StorageCommands.cxx
src/command/StorageCommands.cxx
+40
-36
StorageCommands.hxx
src/command/StorageCommands.hxx
+3
-2
TagCommands.cxx
src/command/TagCommands.cxx
+11
-8
Count.cxx
src/db/Count.cxx
+13
-14
Count.hxx
src/db/Count.hxx
+4
-3
DatabasePrint.cxx
src/db/DatabasePrint.cxx
+52
-45
DatabasePrint.hxx
src/db/DatabasePrint.hxx
+8
-3
DecoderPrint.cxx
src/decoder/DecoderPrint.cxx
+7
-7
DecoderPrint.hxx
src/decoder/DecoderPrint.hxx
+2
-2
ls.cxx
src/ls.cxx
+4
-3
ls.hxx
src/ls.hxx
+2
-2
OutputPrint.cxx
src/output/OutputPrint.cxx
+6
-7
OutputPrint.hxx
src/output/OutputPrint.hxx
+2
-2
Print.cxx
src/playlist/Print.cxx
+12
-9
Print.hxx
src/playlist/Print.hxx
+6
-3
ArgParser.cxx
src/protocol/ArgParser.cxx
+29
-36
ArgParser.hxx
src/protocol/ArgParser.hxx
+11
-11
QueuePrint.cxx
src/queue/QueuePrint.cxx
+18
-18
QueuePrint.hxx
src/queue/QueuePrint.hxx
+7
-6
StickerPrint.cxx
src/sticker/StickerPrint.cxx
+7
-7
StickerPrint.hxx
src/sticker/StickerPrint.hxx
+3
-3
test_protocol.cxx
test/test_protocol.cxx
+14
-8
No files found.
Makefile.am
View file @
7652a298
...
@@ -122,6 +122,7 @@ libmpd_a_SOURCES = \
...
@@ -122,6 +122,7 @@ libmpd_a_SOURCES = \
src/client/ClientMessage.cxx src/client/ClientMessage.hxx
\
src/client/ClientMessage.cxx src/client/ClientMessage.hxx
\
src/client/ClientSubscribe.cxx
\
src/client/ClientSubscribe.cxx
\
src/client/ClientFile.cxx
\
src/client/ClientFile.cxx
\
src/client/Response.cxx src/client/Response.hxx
\
src/Listen.cxx src/Listen.hxx
\
src/Listen.cxx src/Listen.hxx
\
src/LogInit.cxx src/LogInit.hxx
\
src/LogInit.cxx src/LogInit.hxx
\
src/LogBackend.cxx src/LogBackend.hxx
\
src/LogBackend.cxx src/LogBackend.hxx
\
...
...
src/PlaylistPrint.cxx
View file @
7652a298
...
@@ -27,6 +27,7 @@
...
@@ -27,6 +27,7 @@
#include "Instance.hxx"
#include "Instance.hxx"
#include "db/Interface.hxx"
#include "db/Interface.hxx"
#include "client/Client.hxx"
#include "client/Client.hxx"
#include "client/Response.hxx"
#include "input/InputStream.hxx"
#include "input/InputStream.hxx"
#include "DetachedSong.hxx"
#include "DetachedSong.hxx"
#include "fs/Traits.hxx"
#include "fs/Traits.hxx"
...
@@ -37,15 +38,17 @@
...
@@ -37,15 +38,17 @@
#define SONG_TIME "Time: "
#define SONG_TIME "Time: "
void
void
playlist_print_uris
(
Client
&
client
,
const
playlist
&
playlist
)
playlist_print_uris
(
Response
&
r
,
Partition
&
partition
,
const
playlist
&
playlist
)
{
{
const
Queue
&
queue
=
playlist
.
queue
;
const
Queue
&
queue
=
playlist
.
queue
;
queue_print_uris
(
client
,
queue
,
0
,
queue
.
GetLength
());
queue_print_uris
(
r
,
partition
,
queue
,
0
,
queue
.
GetLength
());
}
}
bool
bool
playlist_print_info
(
Client
&
client
,
const
playlist
&
playlist
,
playlist_print_info
(
Response
&
r
,
Partition
&
partition
,
const
playlist
&
playlist
,
unsigned
start
,
unsigned
end
)
unsigned
start
,
unsigned
end
)
{
{
const
Queue
&
queue
=
playlist
.
queue
;
const
Queue
&
queue
=
playlist
.
queue
;
...
@@ -58,12 +61,12 @@ playlist_print_info(Client &client, const playlist &playlist,
...
@@ -58,12 +61,12 @@ playlist_print_info(Client &client, const playlist &playlist,
/* an invalid "start" offset is fatal */
/* an invalid "start" offset is fatal */
return
false
;
return
false
;
queue_print_info
(
client
,
queue
,
start
,
end
);
queue_print_info
(
r
,
partition
,
queue
,
start
,
end
);
return
true
;
return
true
;
}
}
bool
bool
playlist_print_id
(
Client
&
client
,
const
playlist
&
playlist
,
playlist_print_id
(
Response
&
r
,
Partition
&
partition
,
const
playlist
&
playlist
,
unsigned
id
)
unsigned
id
)
{
{
int
position
;
int
position
;
...
@@ -73,50 +76,53 @@ playlist_print_id(Client &client, const playlist &playlist,
...
@@ -73,50 +76,53 @@ playlist_print_id(Client &client, const playlist &playlist,
/* no such song */
/* no such song */
return
false
;
return
false
;
return
playlist_print_info
(
client
,
playlist
,
position
,
position
+
1
);
return
playlist_print_info
(
r
,
partition
,
playlist
,
position
,
position
+
1
);
}
}
bool
bool
playlist_print_current
(
Client
&
client
,
const
playlist
&
playlist
)
playlist_print_current
(
Response
&
r
,
Partition
&
partition
,
const
playlist
&
playlist
)
{
{
int
current_position
=
playlist
.
GetCurrentPosition
();
int
current_position
=
playlist
.
GetCurrentPosition
();
if
(
current_position
<
0
)
if
(
current_position
<
0
)
return
false
;
return
false
;
queue_print_info
(
client
,
playlist
.
queue
,
queue_print_info
(
r
,
partition
,
playlist
.
queue
,
current_position
,
current_position
+
1
);
current_position
,
current_position
+
1
);
return
true
;
return
true
;
}
}
void
void
playlist_print_find
(
Client
&
client
,
const
playlist
&
playlist
,
playlist_print_find
(
Response
&
r
,
Partition
&
partition
,
const
playlist
&
playlist
,
const
SongFilter
&
filter
)
const
SongFilter
&
filter
)
{
{
queue_find
(
client
,
playlist
.
queue
,
filter
);
queue_find
(
r
,
partition
,
playlist
.
queue
,
filter
);
}
}
void
void
playlist_print_changes_info
(
Client
&
client
,
playlist_print_changes_info
(
Response
&
r
,
Partition
&
partition
,
const
playlist
&
playlist
,
const
playlist
&
playlist
,
uint32_t
version
)
uint32_t
version
)
{
{
queue_print_changes_info
(
client
,
playlist
.
queue
,
version
);
queue_print_changes_info
(
r
,
partition
,
playlist
.
queue
,
version
);
}
}
void
void
playlist_print_changes_position
(
Client
&
client
,
playlist_print_changes_position
(
Response
&
r
,
const
playlist
&
playlist
,
const
playlist
&
playlist
,
uint32_t
version
)
uint32_t
version
)
{
{
queue_print_changes_position
(
client
,
playlist
.
queue
,
version
);
queue_print_changes_position
(
r
,
playlist
.
queue
,
version
);
}
}
#ifdef ENABLE_DATABASE
#ifdef ENABLE_DATABASE
static
bool
static
bool
PrintSongDetails
(
Client
&
client
,
const
char
*
uri_utf8
)
PrintSongDetails
(
Response
&
r
,
Partition
&
partition
,
const
char
*
uri_utf8
)
{
{
const
Database
*
db
=
client
.
partition
.
instance
.
database
;
const
Database
*
db
=
partition
.
instance
.
database
;
if
(
db
==
nullptr
)
if
(
db
==
nullptr
)
return
false
;
return
false
;
...
@@ -124,7 +130,7 @@ PrintSongDetails(Client &client, const char *uri_utf8)
...
@@ -124,7 +130,7 @@ PrintSongDetails(Client &client, const char *uri_utf8)
if
(
song
==
nullptr
)
if
(
song
==
nullptr
)
return
false
;
return
false
;
song_print_info
(
client
,
*
song
);
song_print_info
(
r
,
partition
,
*
song
);
db
->
ReturnSong
(
song
);
db
->
ReturnSong
(
song
);
return
true
;
return
true
;
}
}
...
@@ -132,7 +138,8 @@ PrintSongDetails(Client &client, const char *uri_utf8)
...
@@ -132,7 +138,8 @@ PrintSongDetails(Client &client, const char *uri_utf8)
#endif
#endif
bool
bool
spl_print
(
Client
&
client
,
const
char
*
name_utf8
,
bool
detail
,
spl_print
(
Response
&
r
,
Partition
&
partition
,
const
char
*
name_utf8
,
bool
detail
,
Error
&
error
)
Error
&
error
)
{
{
#ifndef ENABLE_DATABASE
#ifndef ENABLE_DATABASE
...
@@ -145,10 +152,10 @@ spl_print(Client &client, const char *name_utf8, bool detail,
...
@@ -145,10 +152,10 @@ spl_print(Client &client, const char *name_utf8, bool detail,
for
(
const
auto
&
uri_utf8
:
contents
)
{
for
(
const
auto
&
uri_utf8
:
contents
)
{
#ifdef ENABLE_DATABASE
#ifdef ENABLE_DATABASE
if
(
!
detail
||
!
PrintSongDetails
(
client
,
uri_utf8
.
c_str
()))
if
(
!
detail
||
!
PrintSongDetails
(
r
,
partition
,
uri_utf8
.
c_str
()))
#endif
#endif
client_printf
(
client
,
SONG_FILE
"%s
\n
"
,
r
.
Format
(
SONG_FILE
"%s
\n
"
,
uri_utf8
.
c_str
());
uri_utf8
.
c_str
());
}
}
return
true
;
return
true
;
...
...
src/PlaylistPrint.hxx
View file @
7652a298
...
@@ -23,15 +23,18 @@
...
@@ -23,15 +23,18 @@
#include <stdint.h>
#include <stdint.h>
struct
playlist
;
struct
playlist
;
struct
Partition
;
class
SongFilter
;
class
SongFilter
;
class
Client
;
class
Client
;
class
Response
;
class
Error
;
class
Error
;
/**
/**
* Sends the whole playlist to the client, song URIs only.
* Sends the whole playlist to the client, song URIs only.
*/
*/
void
void
playlist_print_uris
(
Client
&
client
,
const
playlist
&
playlist
);
playlist_print_uris
(
Response
&
r
,
Partition
&
partition
,
const
playlist
&
playlist
);
/**
/**
* Sends a range of the playlist to the client, including all known
* Sends a range of the playlist to the client, including all known
...
@@ -40,7 +43,8 @@ playlist_print_uris(Client &client, const playlist &playlist);
...
@@ -40,7 +43,8 @@ playlist_print_uris(Client &client, const playlist &playlist);
* This function however fails when the start offset is invalid.
* This function however fails when the start offset is invalid.
*/
*/
bool
bool
playlist_print_info
(
Client
&
client
,
const
playlist
&
playlist
,
playlist_print_info
(
Response
&
r
,
Partition
&
partition
,
const
playlist
&
playlist
,
unsigned
start
,
unsigned
end
);
unsigned
start
,
unsigned
end
);
/**
/**
...
@@ -49,8 +53,8 @@ playlist_print_info(Client &client, const playlist &playlist,
...
@@ -49,8 +53,8 @@ playlist_print_info(Client &client, const playlist &playlist,
* @return true on suite, false if there is no such song
* @return true on suite, false if there is no such song
*/
*/
bool
bool
playlist_print_id
(
Client
&
client
,
const
playlist
&
playlist
,
playlist_print_id
(
Response
&
r
,
Partition
&
partition
,
unsigned
id
);
const
playlist
&
playlist
,
unsigned
id
);
/**
/**
* Sends the current song to the client.
* Sends the current song to the client.
...
@@ -58,20 +62,22 @@ playlist_print_id(Client &client, const playlist &playlist,
...
@@ -58,20 +62,22 @@ playlist_print_id(Client &client, const playlist &playlist,
* @return true on success, false if there is no current song
* @return true on success, false if there is no current song
*/
*/
bool
bool
playlist_print_current
(
Client
&
client
,
const
playlist
&
playlist
);
playlist_print_current
(
Response
&
r
,
Partition
&
partition
,
const
playlist
&
playlist
);
/**
/**
* Find songs in the playlist.
* Find songs in the playlist.
*/
*/
void
void
playlist_print_find
(
Client
&
client
,
const
playlist
&
playlist
,
playlist_print_find
(
Response
&
r
,
Partition
&
partition
,
const
playlist
&
playlist
,
const
SongFilter
&
filter
);
const
SongFilter
&
filter
);
/**
/**
* Print detailed changes since the specified playlist version.
* Print detailed changes since the specified playlist version.
*/
*/
void
void
playlist_print_changes_info
(
Client
&
client
,
playlist_print_changes_info
(
Response
&
r
,
Partition
&
partition
,
const
playlist
&
playlist
,
const
playlist
&
playlist
,
uint32_t
version
);
uint32_t
version
);
...
@@ -79,7 +85,7 @@ playlist_print_changes_info(Client &client,
...
@@ -79,7 +85,7 @@ playlist_print_changes_info(Client &client,
* Print changes since the specified playlist version, position only.
* Print changes since the specified playlist version, position only.
*/
*/
void
void
playlist_print_changes_position
(
Client
&
client
,
playlist_print_changes_position
(
Response
&
r
,
const
playlist
&
playlist
,
const
playlist
&
playlist
,
uint32_t
version
);
uint32_t
version
);
...
@@ -92,7 +98,8 @@ playlist_print_changes_position(Client &client,
...
@@ -92,7 +98,8 @@ playlist_print_changes_position(Client &client,
* @return true on success, false if the playlist does not exist
* @return true on success, false if the playlist does not exist
*/
*/
bool
bool
spl_print
(
Client
&
client
,
const
char
*
name_utf8
,
bool
detail
,
spl_print
(
Response
&
r
,
Partition
&
partition
,
const
char
*
name_utf8
,
bool
detail
,
Error
&
error
);
Error
&
error
);
#endif
#endif
src/SongPrint.cxx
View file @
7652a298
...
@@ -20,18 +20,20 @@
...
@@ -20,18 +20,20 @@
#include "config.h"
#include "config.h"
#include "SongPrint.hxx"
#include "SongPrint.hxx"
#include "db/LightSong.hxx"
#include "db/LightSong.hxx"
#include "Partition.hxx"
#include "Instance.hxx"
#include "storage/StorageInterface.hxx"
#include "storage/StorageInterface.hxx"
#include "DetachedSong.hxx"
#include "DetachedSong.hxx"
#include "TimePrint.hxx"
#include "TimePrint.hxx"
#include "TagPrint.hxx"
#include "TagPrint.hxx"
#include "client/
Client
.hxx"
#include "client/
Response
.hxx"
#include "fs/Traits.hxx"
#include "fs/Traits.hxx"
#include "util/UriUtil.hxx"
#include "util/UriUtil.hxx"
#define SONG_FILE "file: "
#define SONG_FILE "file: "
static
void
static
void
song_print_uri
(
Client
&
client
,
const
char
*
uri
,
bool
base
)
song_print_uri
(
Response
&
r
,
Partition
&
partition
,
const
char
*
uri
,
bool
base
)
{
{
std
::
string
allocated
;
std
::
string
allocated
;
...
@@ -39,12 +41,14 @@ song_print_uri(Client &client, const char *uri, bool base)
...
@@ -39,12 +41,14 @@ song_print_uri(Client &client, const char *uri, bool base)
uri
=
PathTraitsUTF8
::
GetBase
(
uri
);
uri
=
PathTraitsUTF8
::
GetBase
(
uri
);
}
else
{
}
else
{
#ifdef ENABLE_DATABASE
#ifdef ENABLE_DATABASE
const
Storage
*
storage
=
client
.
GetStorage
()
;
const
Storage
*
storage
=
partition
.
instance
.
storage
;
if
(
storage
!=
nullptr
)
{
if
(
storage
!=
nullptr
)
{
const
char
*
suffix
=
storage
->
MapToRelativeUTF8
(
uri
);
const
char
*
suffix
=
storage
->
MapToRelativeUTF8
(
uri
);
if
(
suffix
!=
nullptr
)
if
(
suffix
!=
nullptr
)
uri
=
suffix
;
uri
=
suffix
;
}
}
#else
(
void
)
partition
;
#endif
#endif
allocated
=
uri_remove_auth
(
uri
);
allocated
=
uri_remove_auth
(
uri
);
...
@@ -52,78 +56,81 @@ song_print_uri(Client &client, const char *uri, bool base)
...
@@ -52,78 +56,81 @@ song_print_uri(Client &client, const char *uri, bool base)
uri
=
allocated
.
c_str
();
uri
=
allocated
.
c_str
();
}
}
client_printf
(
client
,
SONG_FILE
"%s
\n
"
,
uri
);
r
.
Format
(
SONG_FILE
"%s
\n
"
,
uri
);
}
}
void
void
song_print_uri
(
Client
&
client
,
const
LightSong
&
song
,
bool
base
)
song_print_uri
(
Response
&
r
,
Partition
&
partition
,
const
LightSong
&
song
,
bool
base
)
{
{
if
(
!
base
&&
song
.
directory
!=
nullptr
)
{
if
(
!
base
&&
song
.
directory
!=
nullptr
)
client_printf
(
client
,
SONG_FILE
"%s/%s
\n
"
,
r
.
Format
(
SONG_FILE
"%s/%s
\n
"
,
song
.
directory
,
song
.
uri
);
song
.
directory
,
song
.
uri
);
else
}
else
song_print_uri
(
r
,
partition
,
song
.
uri
,
base
);
song_print_uri
(
client
,
song
.
uri
,
base
);
}
}
void
void
song_print_uri
(
Client
&
client
,
const
DetachedSong
&
song
,
bool
base
)
song_print_uri
(
Response
&
r
,
Partition
&
partition
,
const
DetachedSong
&
song
,
bool
base
)
{
{
song_print_uri
(
client
,
song
.
GetURI
(),
base
);
song_print_uri
(
r
,
partition
,
song
.
GetURI
(),
base
);
}
}
void
void
song_print_info
(
Client
&
client
,
const
LightSong
&
song
,
bool
base
)
song_print_info
(
Response
&
r
,
Partition
&
partition
,
const
LightSong
&
song
,
bool
base
)
{
{
song_print_uri
(
client
,
song
,
base
);
song_print_uri
(
r
,
partition
,
song
,
base
);
const
unsigned
start_ms
=
song
.
start_time
.
ToMS
();
const
unsigned
start_ms
=
song
.
start_time
.
ToMS
();
const
unsigned
end_ms
=
song
.
end_time
.
ToMS
();
const
unsigned
end_ms
=
song
.
end_time
.
ToMS
();
if
(
end_ms
>
0
)
if
(
end_ms
>
0
)
client_printf
(
client
,
"Range: %u.%03u-%u.%03u
\n
"
,
r
.
Format
(
"Range: %u.%03u-%u.%03u
\n
"
,
start_ms
/
1000
,
start_ms
/
1000
,
start_ms
%
1000
,
start_ms
%
1000
,
end_ms
/
1000
,
end_ms
/
1000
,
end_ms
%
1000
);
end_ms
%
1000
);
else
if
(
start_ms
>
0
)
else
if
(
start_ms
>
0
)
client_printf
(
client
,
"Range: %u.%03u-
\n
"
,
r
.
Format
(
"Range: %u.%03u-
\n
"
,
start_ms
/
1000
,
start_ms
/
1000
,
start_ms
%
1000
);
start_ms
%
1000
);
if
(
song
.
mtime
>
0
)
if
(
song
.
mtime
>
0
)
time_print
(
client
,
"Last-Modified"
,
song
.
mtime
);
time_print
(
r
,
"Last-Modified"
,
song
.
mtime
);
tag_print
(
client
,
*
song
.
tag
);
tag_print
(
r
,
*
song
.
tag
);
}
}
void
void
song_print_info
(
Client
&
client
,
const
DetachedSong
&
song
,
bool
base
)
song_print_info
(
Response
&
r
,
Partition
&
partition
,
const
DetachedSong
&
song
,
bool
base
)
{
{
song_print_uri
(
client
,
song
,
base
);
song_print_uri
(
r
,
partition
,
song
,
base
);
const
unsigned
start_ms
=
song
.
GetStartTime
().
ToMS
();
const
unsigned
start_ms
=
song
.
GetStartTime
().
ToMS
();
const
unsigned
end_ms
=
song
.
GetEndTime
().
ToMS
();
const
unsigned
end_ms
=
song
.
GetEndTime
().
ToMS
();
if
(
end_ms
>
0
)
if
(
end_ms
>
0
)
client_printf
(
client
,
"Range: %u.%03u-%u.%03u
\n
"
,
r
.
Format
(
"Range: %u.%03u-%u.%03u
\n
"
,
start_ms
/
1000
,
start_ms
/
1000
,
start_ms
%
1000
,
start_ms
%
1000
,
end_ms
/
1000
,
end_ms
/
1000
,
end_ms
%
1000
);
end_ms
%
1000
);
else
if
(
start_ms
>
0
)
else
if
(
start_ms
>
0
)
client_printf
(
client
,
"Range: %u.%03u-
\n
"
,
r
.
Format
(
"Range: %u.%03u-
\n
"
,
start_ms
/
1000
,
start_ms
/
1000
,
start_ms
%
1000
);
start_ms
%
1000
);
if
(
song
.
GetLastModified
()
>
0
)
if
(
song
.
GetLastModified
()
>
0
)
time_print
(
client
,
"Last-Modified"
,
song
.
GetLastModified
());
time_print
(
r
,
"Last-Modified"
,
song
.
GetLastModified
());
tag_print_values
(
client
,
song
.
GetTag
());
tag_print_values
(
r
,
song
.
GetTag
());
const
auto
duration
=
song
.
GetDuration
();
const
auto
duration
=
song
.
GetDuration
();
if
(
!
duration
.
IsNegative
())
if
(
!
duration
.
IsNegative
())
client_printf
(
client
,
"Time: %i
\n
"
r
.
Format
(
"Time: %i
\n
"
"duration: %1.3f
\n
"
,
"duration: %1.3f
\n
"
,
duration
.
RoundS
(),
duration
.
RoundS
(),
duration
.
ToDoubleS
());
duration
.
ToDoubleS
());
}
}
src/SongPrint.hxx
View file @
7652a298
...
@@ -22,18 +22,23 @@
...
@@ -22,18 +22,23 @@
struct
LightSong
;
struct
LightSong
;
class
DetachedSong
;
class
DetachedSong
;
class
Client
;
class
Response
;
struct
Partition
;
void
void
song_print_info
(
Client
&
client
,
const
DetachedSong
&
song
,
bool
base
=
false
);
song_print_info
(
Response
&
r
,
Partition
&
partition
,
const
DetachedSong
&
song
,
bool
base
=
false
);
void
void
song_print_info
(
Client
&
client
,
const
LightSong
&
song
,
bool
base
=
false
);
song_print_info
(
Response
&
r
,
Partition
&
partition
,
const
LightSong
&
song
,
bool
base
=
false
);
void
void
song_print_uri
(
Client
&
client
,
const
LightSong
&
song
,
bool
base
=
false
);
song_print_uri
(
Response
&
r
,
Partition
&
partition
,
const
LightSong
&
song
,
bool
base
=
false
);
void
void
song_print_uri
(
Client
&
client
,
const
DetachedSong
&
song
,
bool
base
=
false
);
song_print_uri
(
Response
&
r
,
Partition
&
partition
,
const
DetachedSong
&
song
,
bool
base
=
false
);
#endif
#endif
src/Stats.cxx
View file @
7652a298
...
@@ -20,7 +20,7 @@
...
@@ -20,7 +20,7 @@
#include "config.h"
#include "config.h"
#include "Stats.hxx"
#include "Stats.hxx"
#include "PlayerControl.hxx"
#include "PlayerControl.hxx"
#include "client/
Client
.hxx"
#include "client/
Response
.hxx"
#include "Partition.hxx"
#include "Partition.hxx"
#include "Instance.hxx"
#include "Instance.hxx"
#include "db/Selection.hxx"
#include "db/Selection.hxx"
...
@@ -94,7 +94,7 @@ stats_update(const Database &db)
...
@@ -94,7 +94,7 @@ stats_update(const Database &db)
}
}
static
void
static
void
db_stats_print
(
Client
&
client
,
const
Database
&
db
)
db_stats_print
(
Response
&
r
,
const
Database
&
db
)
{
{
if
(
!
stats_update
(
db
))
if
(
!
stats_update
(
db
))
return
;
return
;
...
@@ -102,41 +102,38 @@ db_stats_print(Client &client, const Database &db)
...
@@ -102,41 +102,38 @@ db_stats_print(Client &client, const Database &db)
unsigned
total_duration_s
=
unsigned
total_duration_s
=
std
::
chrono
::
duration_cast
<
std
::
chrono
::
seconds
>
(
stats
.
total_duration
).
count
();
std
::
chrono
::
duration_cast
<
std
::
chrono
::
seconds
>
(
stats
.
total_duration
).
count
();
client_printf
(
client
,
r
.
Format
(
"artists: %u
\n
"
"artists: %u
\n
"
"albums: %u
\n
"
"albums: %u
\n
"
"songs: %u
\n
"
"songs: %u
\n
"
"db_playtime: %u
\n
"
,
"db_playtime: %u
\n
"
,
stats
.
artist_count
,
stats
.
artist_count
,
stats
.
album_count
,
stats
.
album_count
,
stats
.
song_count
,
stats
.
song_count
,
total_duration_s
);
total_duration_s
);
const
time_t
update_stamp
=
db
.
GetUpdateStamp
();
const
time_t
update_stamp
=
db
.
GetUpdateStamp
();
if
(
update_stamp
>
0
)
if
(
update_stamp
>
0
)
client_printf
(
client
,
r
.
Format
(
"db_update: %lu
\n
"
,
"db_update: %lu
\n
"
,
(
unsigned
long
)
update_stamp
);
(
unsigned
long
)
update_stamp
);
}
}
#endif
#endif
void
void
stats_print
(
Client
&
client
)
stats_print
(
Response
&
r
,
const
Partition
&
partition
)
{
{
client_printf
(
client
,
r
.
Format
(
"uptime: %u
\n
"
"uptime: %u
\n
"
"playtime: %lu
\n
"
,
"playtime: %lu
\n
"
,
#ifdef WIN32
#ifdef WIN32
GetProcessUptimeS
(),
GetProcessUptimeS
(),
#else
#else
MonotonicClockS
()
-
start_time
,
MonotonicClockS
()
-
start_time
,
#endif
#endif
(
unsigned
long
)(
client
.
player_control
.
GetTotalPlayTime
()
+
0.5
));
(
unsigned
long
)(
partition
.
pc
.
GetTotalPlayTime
()
+
0.5
));
#ifdef ENABLE_DATABASE
#ifdef ENABLE_DATABASE
const
Database
*
db
=
client
.
partition
.
instance
.
database
;
const
Database
*
db
=
partition
.
instance
.
database
;
if
(
db
!=
nullptr
)
if
(
db
!=
nullptr
)
db_stats_print
(
client
,
*
db
);
db_stats_print
(
r
,
*
db
);
#endif
#endif
}
}
src/Stats.hxx
View file @
7652a298
...
@@ -20,7 +20,8 @@
...
@@ -20,7 +20,8 @@
#ifndef MPD_STATS_HXX
#ifndef MPD_STATS_HXX
#define MPD_STATS_HXX
#define MPD_STATS_HXX
class
Client
;
class
Response
;
struct
Partition
;
void
void
stats_global_init
();
stats_global_init
();
...
@@ -29,6 +30,6 @@ void
...
@@ -29,6 +30,6 @@ void
stats_invalidate
();
stats_invalidate
();
void
void
stats_print
(
Client
&
client
);
stats_print
(
Response
&
r
,
const
Partition
&
partition
);
#endif
#endif
src/TagPrint.cxx
View file @
7652a298
...
@@ -21,40 +21,40 @@
...
@@ -21,40 +21,40 @@
#include "TagPrint.hxx"
#include "TagPrint.hxx"
#include "tag/Tag.hxx"
#include "tag/Tag.hxx"
#include "tag/TagSettings.h"
#include "tag/TagSettings.h"
#include "client/
Client
.hxx"
#include "client/
Response
.hxx"
void
tag_print_types
(
Client
&
client
)
void
tag_print_types
(
Response
&
r
)
{
{
int
i
;
int
i
;
for
(
i
=
0
;
i
<
TAG_NUM_OF_ITEM_TYPES
;
i
++
)
{
for
(
i
=
0
;
i
<
TAG_NUM_OF_ITEM_TYPES
;
i
++
)
{
if
(
!
ignore_tag_items
[
i
])
if
(
!
ignore_tag_items
[
i
])
client_printf
(
client
,
"tagtype: %s
\n
"
,
r
.
Format
(
"tagtype: %s
\n
"
,
tag_item_names
[
i
]);
tag_item_names
[
i
]);
}
}
}
}
void
void
tag_print
(
Client
&
client
,
TagType
type
,
const
char
*
value
)
tag_print
(
Response
&
r
,
TagType
type
,
const
char
*
value
)
{
{
client_printf
(
client
,
"%s: %s
\n
"
,
tag_item_names
[
type
],
value
);
r
.
Format
(
"%s: %s
\n
"
,
tag_item_names
[
type
],
value
);
}
}
void
void
tag_print_values
(
Client
&
client
,
const
Tag
&
tag
)
tag_print_values
(
Response
&
r
,
const
Tag
&
tag
)
{
{
for
(
const
auto
&
i
:
tag
)
for
(
const
auto
&
i
:
tag
)
client_printf
(
client
,
"%s: %s
\n
"
,
r
.
Format
(
"%s: %s
\n
"
,
tag_item_names
[
i
.
type
],
i
.
value
);
tag_item_names
[
i
.
type
],
i
.
value
);
}
}
void
tag_print
(
Client
&
client
,
const
Tag
&
tag
)
void
tag_print
(
Response
&
r
,
const
Tag
&
tag
)
{
{
if
(
!
tag
.
duration
.
IsNegative
())
if
(
!
tag
.
duration
.
IsNegative
())
client_printf
(
client
,
"Time: %i
\n
"
r
.
Format
(
"Time: %i
\n
"
"duration: %1.3f
\n
"
,
"duration: %1.3f
\n
"
,
tag
.
duration
.
RoundS
(),
tag
.
duration
.
RoundS
(),
tag
.
duration
.
ToDoubleS
());
tag
.
duration
.
ToDoubleS
());
tag_print_values
(
client
,
tag
);
tag_print_values
(
r
,
tag
);
}
}
src/TagPrint.hxx
View file @
7652a298
...
@@ -25,17 +25,18 @@
...
@@ -25,17 +25,18 @@
enum
TagType
:
uint8_t
;
enum
TagType
:
uint8_t
;
struct
Tag
;
struct
Tag
;
class
Client
;
class
Response
;
void
tag_print_types
(
Client
&
client
);
void
tag_print_types
(
Response
&
response
);
void
void
tag_print
(
Client
&
client
,
TagType
type
,
const
char
*
value
);
tag_print
(
Response
&
response
,
TagType
type
,
const
char
*
value
);
void
void
tag_print_values
(
Client
&
client
,
const
Tag
&
tag
);
tag_print_values
(
Response
&
response
,
const
Tag
&
tag
);
void
void
tag_print
(
Client
&
client
,
const
Tag
&
tag
);
tag_print
(
Response
&
response
,
const
Tag
&
tag
);
#endif
#endif
src/TimePrint.cxx
View file @
7652a298
...
@@ -19,10 +19,10 @@
...
@@ -19,10 +19,10 @@
#include "config.h"
#include "config.h"
#include "TimePrint.hxx"
#include "TimePrint.hxx"
#include "client/
Client
.hxx"
#include "client/
Response
.hxx"
void
void
time_print
(
Client
&
client
,
const
char
*
name
,
time_t
t
)
time_print
(
Response
&
r
,
const
char
*
name
,
time_t
t
)
{
{
#ifdef WIN32
#ifdef WIN32
const
struct
tm
*
tm2
=
gmtime
(
&
t
);
const
struct
tm
*
tm2
=
gmtime
(
&
t
);
...
@@ -41,5 +41,5 @@ time_print(Client &client, const char *name, time_t t)
...
@@ -41,5 +41,5 @@ time_print(Client &client, const char *name, time_t t)
"%FT%TZ"
,
"%FT%TZ"
,
#endif
#endif
tm2
);
tm2
);
client_printf
(
client
,
"%s: %s
\n
"
,
name
,
buffer
);
r
.
Format
(
"%s: %s
\n
"
,
name
,
buffer
);
}
}
src/TimePrint.hxx
View file @
7652a298
...
@@ -22,12 +22,12 @@
...
@@ -22,12 +22,12 @@
#include <time.h>
#include <time.h>
class
Client
;
class
Response
;
/**
/**
* Write a line with a time stamp to the client.
* Write a line with a time stamp to the client.
*/
*/
void
void
time_print
(
Client
&
client
,
const
char
*
name
,
time_t
t
);
time_print
(
Response
&
r
,
const
char
*
name
,
time_t
t
);
#endif
#endif
src/client/Response.cxx
0 → 100644
View file @
7652a298
/*
* Copyright (C) 2003-2015 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 "config.h"
#include "Response.hxx"
#include "Client.hxx"
#include "protocol/Result.hxx"
#include "util/FormatString.hxx"
#include <string.h>
bool
Response
::
Write
(
const
void
*
data
,
size_t
length
)
{
return
client
.
Write
(
data
,
length
);
}
bool
Response
::
Write
(
const
char
*
data
)
{
return
Write
(
data
,
strlen
(
data
));
}
bool
Response
::
FormatV
(
const
char
*
fmt
,
va_list
args
)
{
char
*
p
=
FormatNewV
(
fmt
,
args
);
bool
success
=
Write
(
p
);
delete
[]
p
;
return
success
;
}
bool
Response
::
Format
(
const
char
*
fmt
,
...)
{
va_list
args
;
va_start
(
args
,
fmt
);
bool
success
=
FormatV
(
fmt
,
args
);
va_end
(
args
);
return
success
;
}
void
Response
::
Error
(
enum
ack
code
,
const
char
*
msg
)
{
command_error
(
client
,
code
,
"%s"
,
msg
);
}
void
Response
::
FormatError
(
enum
ack
code
,
const
char
*
fmt
,
...)
{
va_list
args
;
va_start
(
args
,
fmt
);
command_error_v
(
client
,
code
,
fmt
,
args
);
va_end
(
args
);
}
src/client/Response.hxx
0 → 100644
View file @
7652a298
/*
* Copyright (C) 2003-2015 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_RESPONSE_HXX
#define MPD_RESPONSE_HXX
#include "check.h"
#include "protocol/Ack.hxx"
#include <stddef.h>
#include <stdarg.h>
class
Client
;
class
Response
{
Client
&
client
;
public
:
explicit
Response
(
Client
&
_client
)
:
client
(
_client
)
{}
Response
(
const
Response
&
)
=
delete
;
Response
&
operator
=
(
const
Response
&
)
=
delete
;
bool
Write
(
const
void
*
data
,
size_t
length
);
bool
Write
(
const
char
*
data
);
bool
FormatV
(
const
char
*
fmt
,
va_list
args
);
bool
Format
(
const
char
*
fmt
,
...);
void
Error
(
enum
ack
code
,
const
char
*
msg
);
void
FormatError
(
enum
ack
code
,
const
char
*
fmt
,
...);
};
#endif
src/command/AllCommands.cxx
View file @
7652a298
...
@@ -36,6 +36,7 @@
...
@@ -36,6 +36,7 @@
#include "protocol/Result.hxx"
#include "protocol/Result.hxx"
#include "Partition.hxx"
#include "Partition.hxx"
#include "client/Client.hxx"
#include "client/Client.hxx"
#include "client/Response.hxx"
#include "util/Macros.hxx"
#include "util/Macros.hxx"
#include "util/Tokenizer.hxx"
#include "util/Tokenizer.hxx"
#include "util/Error.hxx"
#include "util/Error.hxx"
...
@@ -226,38 +227,50 @@ command_available(gcc_unused const Partition &partition,
...
@@ -226,38 +227,50 @@ command_available(gcc_unused const Partition &partition,
return
true
;
return
true
;
}
}
/* don't be fooled, this is the command handler for "commands" command */
static
CommandResult
static
CommandResult
handle_commands
(
Client
&
client
,
gcc_unused
Request
args
)
PrintAvailableCommands
(
Response
&
r
,
const
Partition
&
partition
,
unsigned
permission
)
{
{
const
unsigned
permission
=
client
.
GetPermission
();
for
(
unsigned
i
=
0
;
i
<
num_commands
;
++
i
)
{
for
(
unsigned
i
=
0
;
i
<
num_commands
;
++
i
)
{
const
struct
command
*
cmd
=
&
commands
[
i
];
const
struct
command
*
cmd
=
&
commands
[
i
];
if
(
cmd
->
permission
==
(
permission
&
cmd
->
permission
)
&&
if
(
cmd
->
permission
==
(
permission
&
cmd
->
permission
)
&&
command_available
(
client
.
partition
,
cmd
))
command_available
(
partition
,
cmd
))
client_printf
(
client
,
"command: %s
\n
"
,
cmd
->
cmd
);
r
.
Format
(
"command: %s
\n
"
,
cmd
->
cmd
);
}
}
return
CommandResult
::
OK
;
return
CommandResult
::
OK
;
}
}
static
CommandResult
static
CommandResult
handle_not_commands
(
Client
&
client
,
gcc_unused
Request
args
)
PrintUnavailableCommands
(
Response
&
r
,
unsigned
permission
)
{
{
const
unsigned
permission
=
client
.
GetPermission
();
for
(
unsigned
i
=
0
;
i
<
num_commands
;
++
i
)
{
for
(
unsigned
i
=
0
;
i
<
num_commands
;
++
i
)
{
const
struct
command
*
cmd
=
&
commands
[
i
];
const
struct
command
*
cmd
=
&
commands
[
i
];
if
(
cmd
->
permission
!=
(
permission
&
cmd
->
permission
))
if
(
cmd
->
permission
!=
(
permission
&
cmd
->
permission
))
client_printf
(
client
,
"command: %s
\n
"
,
cmd
->
cmd
);
r
.
Format
(
"command: %s
\n
"
,
cmd
->
cmd
);
}
}
return
CommandResult
::
OK
;
return
CommandResult
::
OK
;
}
}
/* don't be fooled, this is the command handler for "commands" command */
static
CommandResult
handle_commands
(
Client
&
client
,
gcc_unused
Request
args
)
{
Response
r
(
client
);
return
PrintAvailableCommands
(
r
,
client
.
partition
,
client
.
GetPermission
());
}
static
CommandResult
handle_not_commands
(
Client
&
client
,
gcc_unused
Request
args
)
{
Response
r
(
client
);
return
PrintUnavailableCommands
(
r
,
client
.
GetPermission
());
}
void
void
command_init
()
command_init
()
{
{
...
@@ -299,7 +312,8 @@ command_check_request(const struct command *cmd, Client &client,
...
@@ -299,7 +312,8 @@ command_check_request(const struct command *cmd, Client &client,
unsigned
permission
,
Request
args
)
unsigned
permission
,
Request
args
)
{
{
if
(
cmd
->
permission
!=
(
permission
&
cmd
->
permission
))
{
if
(
cmd
->
permission
!=
(
permission
&
cmd
->
permission
))
{
command_error
(
client
,
ACK_ERROR_PERMISSION
,
Response
r
(
client
);
r
.
FormatError
(
ACK_ERROR_PERMISSION
,
"you don't have permission for
\"
%s
\"
"
,
"you don't have permission for
\"
%s
\"
"
,
cmd
->
cmd
);
cmd
->
cmd
);
return
false
;
return
false
;
...
@@ -312,16 +326,19 @@ command_check_request(const struct command *cmd, Client &client,
...
@@ -312,16 +326,19 @@ command_check_request(const struct command *cmd, Client &client,
return
true
;
return
true
;
if
(
min
==
max
&&
unsigned
(
max
)
!=
args
.
size
)
{
if
(
min
==
max
&&
unsigned
(
max
)
!=
args
.
size
)
{
command_error
(
client
,
ACK_ERROR_ARG
,
Response
r
(
client
);
r
.
FormatError
(
ACK_ERROR_ARG
,
"wrong number of arguments for
\"
%s
\"
"
,
"wrong number of arguments for
\"
%s
\"
"
,
cmd
->
cmd
);
cmd
->
cmd
);
return
false
;
return
false
;
}
else
if
(
args
.
size
<
unsigned
(
min
))
{
}
else
if
(
args
.
size
<
unsigned
(
min
))
{
command_error
(
client
,
ACK_ERROR_ARG
,
Response
r
(
client
);
r
.
FormatError
(
ACK_ERROR_ARG
,
"too few arguments for
\"
%s
\"
"
,
cmd
->
cmd
);
"too few arguments for
\"
%s
\"
"
,
cmd
->
cmd
);
return
false
;
return
false
;
}
else
if
(
max
>=
0
&&
args
.
size
>
unsigned
(
max
))
{
}
else
if
(
max
>=
0
&&
args
.
size
>
unsigned
(
max
))
{
command_error
(
client
,
ACK_ERROR_ARG
,
Response
r
(
client
);
r
.
FormatError
(
ACK_ERROR_ARG
,
"too many arguments for
\"
%s
\"
"
,
cmd
->
cmd
);
"too many arguments for
\"
%s
\"
"
,
cmd
->
cmd
);
return
false
;
return
false
;
}
else
}
else
...
@@ -336,7 +353,8 @@ command_checked_lookup(Client &client, unsigned permission,
...
@@ -336,7 +353,8 @@ command_checked_lookup(Client &client, unsigned permission,
const
struct
command
*
cmd
=
command_lookup
(
cmd_name
);
const
struct
command
*
cmd
=
command_lookup
(
cmd_name
);
if
(
cmd
==
nullptr
)
{
if
(
cmd
==
nullptr
)
{
command_error
(
client
,
ACK_ERROR_UNKNOWN
,
Response
r
(
client
);
r
.
FormatError
(
ACK_ERROR_UNKNOWN
,
"unknown command
\"
%s
\"
"
,
cmd_name
);
"unknown command
\"
%s
\"
"
,
cmd_name
);
return
nullptr
;
return
nullptr
;
}
}
...
@@ -357,7 +375,7 @@ command_process(Client &client, unsigned num, char *line)
...
@@ -357,7 +375,7 @@ command_process(Client &client, unsigned num, char *line)
command_list_num
=
num
;
command_list_num
=
num
;
/* get the command name (first word on the line) */
/* get the command name (first word on the line) */
/* we have to set current_command because
command_e
rror()
/* we have to set current_command because
Response::E
rror()
expects it to be set */
expects it to be set */
Tokenizer
tokenizer
(
line
);
Tokenizer
tokenizer
(
line
);
...
@@ -366,12 +384,12 @@ command_process(Client &client, unsigned num, char *line)
...
@@ -366,12 +384,12 @@ command_process(Client &client, unsigned num, char *line)
tokenizer
.
NextWord
(
error
);
tokenizer
.
NextWord
(
error
);
if
(
cmd_name
==
nullptr
)
{
if
(
cmd_name
==
nullptr
)
{
current_command
=
""
;
current_command
=
""
;
Response
r
(
client
);
if
(
tokenizer
.
IsEnd
())
if
(
tokenizer
.
IsEnd
())
command_error
(
client
,
ACK_ERROR_UNKNOWN
,
r
.
FormatError
(
ACK_ERROR_UNKNOWN
,
"No command given"
);
"No command given"
);
else
else
command_error
(
client
,
ACK_ERROR_UNKNOWN
,
r
.
Error
(
ACK_ERROR_UNKNOWN
,
error
.
GetMessage
());
"%s"
,
error
.
GetMessage
());
current_command
=
nullptr
;
current_command
=
nullptr
;
...
@@ -387,8 +405,8 @@ command_process(Client &client, unsigned num, char *line)
...
@@ -387,8 +405,8 @@ command_process(Client &client, unsigned num, char *line)
while
(
true
)
{
while
(
true
)
{
if
(
args
.
size
==
COMMAND_ARGV_MAX
)
{
if
(
args
.
size
==
COMMAND_ARGV_MAX
)
{
command_error
(
client
,
ACK_ERROR_ARG
,
Response
r
(
client
);
"Too many arguments"
);
r
.
Error
(
ACK_ERROR_ARG
,
"Too many arguments"
);
current_command
=
nullptr
;
current_command
=
nullptr
;
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
}
}
...
@@ -398,7 +416,8 @@ command_process(Client &client, unsigned num, char *line)
...
@@ -398,7 +416,8 @@ command_process(Client &client, unsigned num, char *line)
if
(
tokenizer
.
IsEnd
())
if
(
tokenizer
.
IsEnd
())
break
;
break
;
command_error
(
client
,
ACK_ERROR_ARG
,
"%s"
,
error
.
GetMessage
());
Response
r
(
client
);
r
.
Error
(
ACK_ERROR_UNKNOWN
,
error
.
GetMessage
());
current_command
=
nullptr
;
current_command
=
nullptr
;
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
}
}
...
...
src/command/CommandError.cxx
View file @
7652a298
...
@@ -20,7 +20,7 @@
...
@@ -20,7 +20,7 @@
#include "config.h"
#include "config.h"
#include "CommandError.hxx"
#include "CommandError.hxx"
#include "db/DatabaseError.hxx"
#include "db/DatabaseError.hxx"
#include "
protocol/Result
.hxx"
#include "
client/Response
.hxx"
#include "util/Error.hxx"
#include "util/Error.hxx"
#include "Log.hxx"
#include "Log.hxx"
...
@@ -29,57 +29,55 @@
...
@@ -29,57 +29,55 @@
#include <errno.h>
#include <errno.h>
CommandResult
CommandResult
print_playlist_result
(
Client
&
client
,
PlaylistResult
result
)
print_playlist_result
(
Response
&
r
,
PlaylistResult
result
)
{
{
switch
(
result
)
{
switch
(
result
)
{
case
PlaylistResult
:
:
SUCCESS
:
case
PlaylistResult
:
:
SUCCESS
:
return
CommandResult
::
OK
;
return
CommandResult
::
OK
;
case
PlaylistResult
:
:
ERRNO
:
case
PlaylistResult
:
:
ERRNO
:
command_error
(
client
,
ACK_ERROR_SYSTEM
,
"%s"
,
r
.
Error
(
ACK_ERROR_SYSTEM
,
strerror
(
errno
));
strerror
(
errno
));
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
case
PlaylistResult
:
:
DENIED
:
case
PlaylistResult
:
:
DENIED
:
command_error
(
client
,
ACK_ERROR_PERMISSION
,
"Access denied"
);
r
.
Error
(
ACK_ERROR_PERMISSION
,
"Access denied"
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
case
PlaylistResult
:
:
NO_SUCH_SONG
:
case
PlaylistResult
:
:
NO_SUCH_SONG
:
command_error
(
client
,
ACK_ERROR_NO_EXIST
,
"No such song"
);
r
.
Error
(
ACK_ERROR_NO_EXIST
,
"No such song"
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
case
PlaylistResult
:
:
NO_SUCH_LIST
:
case
PlaylistResult
:
:
NO_SUCH_LIST
:
command_error
(
client
,
ACK_ERROR_NO_EXIST
,
"No such playlist"
);
r
.
Error
(
ACK_ERROR_NO_EXIST
,
"No such playlist"
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
case
PlaylistResult
:
:
LIST_EXISTS
:
case
PlaylistResult
:
:
LIST_EXISTS
:
command_error
(
client
,
ACK_ERROR_EXIST
,
r
.
Error
(
ACK_ERROR_EXIST
,
"Playlist already exists"
);
"Playlist already exists"
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
case
PlaylistResult
:
:
BAD_NAME
:
case
PlaylistResult
:
:
BAD_NAME
:
command_error
(
client
,
ACK_ERROR_ARG
,
r
.
Error
(
ACK_ERROR_ARG
,
"playlist name is invalid: "
"playlist name is invalid: "
"playlist names may not contain slashes,"
"playlist names may not contain slashes,"
" newlines or carriage returns"
);
" newlines or carriage returns"
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
case
PlaylistResult
:
:
BAD_RANGE
:
case
PlaylistResult
:
:
BAD_RANGE
:
command_error
(
client
,
ACK_ERROR_ARG
,
"Bad song index"
);
r
.
Error
(
ACK_ERROR_ARG
,
"Bad song index"
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
case
PlaylistResult
:
:
NOT_PLAYING
:
case
PlaylistResult
:
:
NOT_PLAYING
:
command_error
(
client
,
ACK_ERROR_PLAYER_SYNC
,
"Not playing"
);
r
.
Error
(
ACK_ERROR_PLAYER_SYNC
,
"Not playing"
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
case
PlaylistResult
:
:
TOO_LARGE
:
case
PlaylistResult
:
:
TOO_LARGE
:
command_error
(
client
,
ACK_ERROR_PLAYLIST_MAX
,
r
.
Error
(
ACK_ERROR_PLAYLIST_MAX
,
"playlist is at the max size"
);
"playlist is at the max size"
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
case
PlaylistResult
:
:
DISABLED
:
case
PlaylistResult
:
:
DISABLED
:
command_error
(
client
,
ACK_ERROR_UNKNOWN
,
r
.
Error
(
ACK_ERROR_UNKNOWN
,
"stored playlist support is disabled"
);
"stored playlist support is disabled"
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
}
}
...
@@ -88,42 +86,39 @@ print_playlist_result(Client &client, PlaylistResult result)
...
@@ -88,42 +86,39 @@ print_playlist_result(Client &client, PlaylistResult result)
}
}
CommandResult
CommandResult
print_error
(
Client
&
client
,
const
Error
&
error
)
print_error
(
Response
&
r
,
const
Error
&
error
)
{
{
assert
(
error
.
IsDefined
());
assert
(
error
.
IsDefined
());
LogError
(
error
);
LogError
(
error
);
if
(
error
.
IsDomain
(
playlist_domain
))
{
if
(
error
.
IsDomain
(
playlist_domain
))
{
return
print_playlist_result
(
client
,
return
print_playlist_result
(
r
,
PlaylistResult
(
error
.
GetCode
()));
PlaylistResult
(
error
.
GetCode
()));
}
else
if
(
error
.
IsDomain
(
ack_domain
))
{
}
else
if
(
error
.
IsDomain
(
ack_domain
))
{
command_error
(
client
,
(
ack
)
error
.
GetCode
(),
r
.
Error
((
ack
)
error
.
GetCode
(),
error
.
GetMessage
());
"%s"
,
error
.
GetMessage
());
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
#ifdef ENABLE_DATABASE
#ifdef ENABLE_DATABASE
}
else
if
(
error
.
IsDomain
(
db_domain
))
{
}
else
if
(
error
.
IsDomain
(
db_domain
))
{
switch
((
enum
db_error
)
error
.
GetCode
())
{
switch
((
enum
db_error
)
error
.
GetCode
())
{
case
DB_DISABLED
:
case
DB_DISABLED
:
command_error
(
client
,
ACK_ERROR_NO_EXIST
,
"%s"
,
r
.
Error
(
ACK_ERROR_NO_EXIST
,
error
.
GetMessage
());
error
.
GetMessage
());
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
case
DB_NOT_FOUND
:
case
DB_NOT_FOUND
:
command_error
(
client
,
ACK_ERROR_NO_EXIST
,
"Not found"
);
r
.
Error
(
ACK_ERROR_NO_EXIST
,
"Not found"
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
case
DB_CONFLICT
:
case
DB_CONFLICT
:
command_error
(
client
,
ACK_ERROR_ARG
,
"Conflict"
);
r
.
Error
(
ACK_ERROR_ARG
,
"Conflict"
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
}
}
#endif
#endif
}
else
if
(
error
.
IsDomain
(
errno_domain
))
{
}
else
if
(
error
.
IsDomain
(
errno_domain
))
{
command_error
(
client
,
ACK_ERROR_SYSTEM
,
"%s"
,
r
.
Error
(
ACK_ERROR_SYSTEM
,
strerror
(
error
.
GetCode
()));
strerror
(
error
.
GetCode
()));
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
}
}
command_error
(
client
,
ACK_ERROR_UNKNOWN
,
"error"
);
r
.
Error
(
ACK_ERROR_UNKNOWN
,
"error"
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
}
}
src/command/CommandError.hxx
View file @
7652a298
...
@@ -23,16 +23,16 @@
...
@@ -23,16 +23,16 @@
#include "CommandResult.hxx"
#include "CommandResult.hxx"
#include "PlaylistError.hxx"
#include "PlaylistError.hxx"
class
Client
;
class
Response
;
class
Error
;
class
Error
;
CommandResult
CommandResult
print_playlist_result
(
Client
&
client
,
PlaylistResult
result
);
print_playlist_result
(
Response
&
r
,
PlaylistResult
result
);
/**
/**
* Send the #Error to the client.
* Send the #Error to the client.
*/
*/
CommandResult
CommandResult
print_error
(
Client
&
client
,
const
Error
&
error
);
print_error
(
Response
&
r
,
const
Error
&
error
);
#endif
#endif
src/command/DatabaseCommands.cxx
View file @
7652a298
...
@@ -28,11 +28,11 @@
...
@@ -28,11 +28,11 @@
#include "db/Selection.hxx"
#include "db/Selection.hxx"
#include "CommandError.hxx"
#include "CommandError.hxx"
#include "client/Client.hxx"
#include "client/Client.hxx"
#include "client/Response.hxx"
#include "tag/Tag.hxx"
#include "tag/Tag.hxx"
#include "util/ConstBuffer.hxx"
#include "util/ConstBuffer.hxx"
#include "util/Error.hxx"
#include "util/Error.hxx"
#include "SongFilter.hxx"
#include "SongFilter.hxx"
#include "protocol/Result.hxx"
#include "BulkEdit.hxx"
#include "BulkEdit.hxx"
#include <string.h>
#include <string.h>
...
@@ -40,11 +40,13 @@
...
@@ -40,11 +40,13 @@
CommandResult
CommandResult
handle_listfiles_db
(
Client
&
client
,
const
char
*
uri
)
handle_listfiles_db
(
Client
&
client
,
const
char
*
uri
)
{
{
Response
r
(
client
);
const
DatabaseSelection
selection
(
uri
,
false
);
const
DatabaseSelection
selection
(
uri
,
false
);
Error
error
;
Error
error
;
if
(
!
db_selection_print
(
client
,
selection
,
false
,
true
,
error
))
if
(
!
db_selection_print
(
r
,
client
.
partition
,
return
print_error
(
client
,
error
);
selection
,
false
,
true
,
error
))
return
print_error
(
r
,
error
);
return
CommandResult
::
OK
;
return
CommandResult
::
OK
;
}
}
...
@@ -52,14 +54,17 @@ handle_listfiles_db(Client &client, const char *uri)
...
@@ -52,14 +54,17 @@ handle_listfiles_db(Client &client, const char *uri)
CommandResult
CommandResult
handle_lsinfo2
(
Client
&
client
,
Request
args
)
handle_lsinfo2
(
Client
&
client
,
Request
args
)
{
{
Response
r
(
client
);
/* default is root directory */
/* default is root directory */
const
auto
uri
=
args
.
GetOptional
(
0
,
""
);
const
auto
uri
=
args
.
GetOptional
(
0
,
""
);
const
DatabaseSelection
selection
(
uri
,
false
);
const
DatabaseSelection
selection
(
uri
,
false
);
Error
error
;
Error
error
;
if
(
!
db_selection_print
(
client
,
selection
,
true
,
false
,
error
))
if
(
!
db_selection_print
(
r
,
client
.
partition
,
return
print_error
(
client
,
error
);
selection
,
true
,
false
,
error
))
return
print_error
(
r
,
error
);
return
CommandResult
::
OK
;
return
CommandResult
::
OK
;
}
}
...
@@ -67,9 +72,11 @@ handle_lsinfo2(Client &client, Request args)
...
@@ -67,9 +72,11 @@ handle_lsinfo2(Client &client, Request args)
static
CommandResult
static
CommandResult
handle_match
(
Client
&
client
,
Request
args
,
bool
fold_case
)
handle_match
(
Client
&
client
,
Request
args
,
bool
fold_case
)
{
{
Response
r
(
client
);
RangeArg
window
;
RangeArg
window
;
if
(
args
.
size
>=
2
&&
strcmp
(
args
[
args
.
size
-
2
],
"window"
)
==
0
)
{
if
(
args
.
size
>=
2
&&
strcmp
(
args
[
args
.
size
-
2
],
"window"
)
==
0
)
{
if
(
!
args
.
Parse
(
args
.
size
-
1
,
window
,
client
))
if
(
!
args
.
Parse
(
args
.
size
-
1
,
window
,
r
))
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
args
.
pop_back
();
args
.
pop_back
();
...
@@ -79,17 +86,18 @@ handle_match(Client &client, Request args, bool fold_case)
...
@@ -79,17 +86,18 @@ handle_match(Client &client, Request args, bool fold_case)
SongFilter
filter
;
SongFilter
filter
;
if
(
!
filter
.
Parse
(
args
,
fold_case
))
{
if
(
!
filter
.
Parse
(
args
,
fold_case
))
{
command_error
(
client
,
ACK_ERROR_ARG
,
"incorrect arguments"
);
r
.
Error
(
ACK_ERROR_ARG
,
"incorrect arguments"
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
}
}
const
DatabaseSelection
selection
(
""
,
true
,
&
filter
);
const
DatabaseSelection
selection
(
""
,
true
,
&
filter
);
Error
error
;
Error
error
;
return
db_selection_print
(
client
,
selection
,
true
,
false
,
return
db_selection_print
(
r
,
client
.
partition
,
selection
,
true
,
false
,
window
.
start
,
window
.
end
,
error
)
window
.
start
,
window
.
end
,
error
)
?
CommandResult
::
OK
?
CommandResult
::
OK
:
print_error
(
client
,
error
);
:
print_error
(
r
,
error
);
}
}
CommandResult
CommandResult
...
@@ -107,9 +115,11 @@ handle_search(Client &client, Request args)
...
@@ -107,9 +115,11 @@ handle_search(Client &client, Request args)
static
CommandResult
static
CommandResult
handle_match_add
(
Client
&
client
,
Request
args
,
bool
fold_case
)
handle_match_add
(
Client
&
client
,
Request
args
,
bool
fold_case
)
{
{
Response
r
(
client
);
SongFilter
filter
;
SongFilter
filter
;
if
(
!
filter
.
Parse
(
args
,
fold_case
))
{
if
(
!
filter
.
Parse
(
args
,
fold_case
))
{
command_error
(
client
,
ACK_ERROR_ARG
,
"incorrect arguments"
);
r
.
Error
(
ACK_ERROR_ARG
,
"incorrect arguments"
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
}
}
...
@@ -119,7 +129,7 @@ handle_match_add(Client &client, Request args, bool fold_case)
...
@@ -119,7 +129,7 @@ handle_match_add(Client &client, Request args, bool fold_case)
Error
error
;
Error
error
;
return
AddFromDatabase
(
client
.
partition
,
selection
,
error
)
return
AddFromDatabase
(
client
.
partition
,
selection
,
error
)
?
CommandResult
::
OK
?
CommandResult
::
OK
:
print_error
(
client
,
error
);
:
print_error
(
r
,
error
);
}
}
CommandResult
CommandResult
...
@@ -137,34 +147,38 @@ handle_searchadd(Client &client, Request args)
...
@@ -137,34 +147,38 @@ handle_searchadd(Client &client, Request args)
CommandResult
CommandResult
handle_searchaddpl
(
Client
&
client
,
Request
args
)
handle_searchaddpl
(
Client
&
client
,
Request
args
)
{
{
Response
r
(
client
);
const
char
*
playlist
=
args
.
shift
();
const
char
*
playlist
=
args
.
shift
();
SongFilter
filter
;
SongFilter
filter
;
if
(
!
filter
.
Parse
(
args
,
true
))
{
if
(
!
filter
.
Parse
(
args
,
true
))
{
command_error
(
client
,
ACK_ERROR_ARG
,
"incorrect arguments"
);
r
.
Error
(
ACK_ERROR_ARG
,
"incorrect arguments"
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
}
}
Error
error
;
Error
error
;
const
Database
*
db
=
client
.
GetDatabase
(
error
);
const
Database
*
db
=
client
.
GetDatabase
(
error
);
if
(
db
==
nullptr
)
if
(
db
==
nullptr
)
return
print_error
(
client
,
error
);
return
print_error
(
r
,
error
);
return
search_add_to_playlist
(
*
db
,
*
client
.
GetStorage
(),
return
search_add_to_playlist
(
*
db
,
*
client
.
GetStorage
(),
""
,
playlist
,
&
filter
,
error
)
""
,
playlist
,
&
filter
,
error
)
?
CommandResult
::
OK
?
CommandResult
::
OK
:
print_error
(
client
,
error
);
:
print_error
(
r
,
error
);
}
}
CommandResult
CommandResult
handle_count
(
Client
&
client
,
Request
args
)
handle_count
(
Client
&
client
,
Request
args
)
{
{
Response
r
(
client
);
TagType
group
=
TAG_NUM_OF_ITEM_TYPES
;
TagType
group
=
TAG_NUM_OF_ITEM_TYPES
;
if
(
args
.
size
>=
2
&&
strcmp
(
args
[
args
.
size
-
2
],
"group"
)
==
0
)
{
if
(
args
.
size
>=
2
&&
strcmp
(
args
[
args
.
size
-
2
],
"group"
)
==
0
)
{
const
char
*
s
=
args
[
args
.
size
-
1
];
const
char
*
s
=
args
[
args
.
size
-
1
];
group
=
tag_name_parse_i
(
s
);
group
=
tag_name_parse_i
(
s
);
if
(
group
==
TAG_NUM_OF_ITEM_TYPES
)
{
if
(
group
==
TAG_NUM_OF_ITEM_TYPES
)
{
command_error
(
client
,
ACK_ERROR_ARG
,
r
.
FormatError
(
ACK_ERROR_ARG
,
"Unknown tag type: %s"
,
s
);
"Unknown tag type: %s"
,
s
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
}
}
...
@@ -175,38 +189,43 @@ handle_count(Client &client, Request args)
...
@@ -175,38 +189,43 @@ handle_count(Client &client, Request args)
SongFilter
filter
;
SongFilter
filter
;
if
(
!
args
.
IsEmpty
()
&&
!
filter
.
Parse
(
args
,
false
))
{
if
(
!
args
.
IsEmpty
()
&&
!
filter
.
Parse
(
args
,
false
))
{
command_error
(
client
,
ACK_ERROR_ARG
,
"incorrect arguments"
);
r
.
Error
(
ACK_ERROR_ARG
,
"incorrect arguments"
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
}
}
Error
error
;
Error
error
;
return
PrintSongCount
(
client
,
""
,
&
filter
,
group
,
error
)
return
PrintSongCount
(
r
,
client
.
partition
,
""
,
&
filter
,
group
,
error
)
?
CommandResult
::
OK
?
CommandResult
::
OK
:
print_error
(
client
,
error
);
:
print_error
(
r
,
error
);
}
}
CommandResult
CommandResult
handle_listall
(
Client
&
client
,
Request
args
)
handle_listall
(
Client
&
client
,
Request
args
)
{
{
Response
r
(
client
);
/* default is root directory */
/* default is root directory */
const
auto
uri
=
args
.
GetOptional
(
0
,
""
);
const
auto
uri
=
args
.
GetOptional
(
0
,
""
);
Error
error
;
Error
error
;
return
db_selection_print
(
client
,
DatabaseSelection
(
uri
,
true
),
return
db_selection_print
(
r
,
client
.
partition
,
DatabaseSelection
(
uri
,
true
),
false
,
false
,
error
)
false
,
false
,
error
)
?
CommandResult
::
OK
?
CommandResult
::
OK
:
print_error
(
client
,
error
);
:
print_error
(
r
,
error
);
}
}
CommandResult
CommandResult
handle_list
(
Client
&
client
,
Request
args
)
handle_list
(
Client
&
client
,
Request
args
)
{
{
Response
r
(
client
);
const
char
*
tag_name
=
args
.
shift
();
const
char
*
tag_name
=
args
.
shift
();
unsigned
tagType
=
locate_parse_type
(
tag_name
);
unsigned
tagType
=
locate_parse_type
(
tag_name
);
if
(
tagType
>=
TAG_NUM_OF_ITEM_TYPES
&&
if
(
tagType
>=
TAG_NUM_OF_ITEM_TYPES
&&
tagType
!=
LOCATE_TAG_FILE_TYPE
)
{
tagType
!=
LOCATE_TAG_FILE_TYPE
)
{
command_error
(
client
,
ACK_ERROR_ARG
,
r
.
FormatError
(
ACK_ERROR_ARG
,
"Unknown tag type: %s"
,
tag_name
);
"Unknown tag type: %s"
,
tag_name
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
}
}
...
@@ -217,7 +236,7 @@ handle_list(Client &client, Request args)
...
@@ -217,7 +236,7 @@ handle_list(Client &client, Request args)
if
(
args
.
size
==
1
)
{
if
(
args
.
size
==
1
)
{
/* for compatibility with < 0.12.0 */
/* for compatibility with < 0.12.0 */
if
(
tagType
!=
TAG_ALBUM
)
{
if
(
tagType
!=
TAG_ALBUM
)
{
command_error
(
client
,
ACK_ERROR_ARG
,
r
.
FormatError
(
ACK_ERROR_ARG
,
"should be
\"
%s
\"
for 3 arguments"
,
"should be
\"
%s
\"
for 3 arguments"
,
tag_item_names
[
TAG_ALBUM
]);
tag_item_names
[
TAG_ALBUM
]);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
...
@@ -231,7 +250,7 @@ handle_list(Client &client, Request args)
...
@@ -231,7 +250,7 @@ handle_list(Client &client, Request args)
const
char
*
s
=
args
[
args
.
size
-
1
];
const
char
*
s
=
args
[
args
.
size
-
1
];
TagType
gt
=
tag_name_parse_i
(
s
);
TagType
gt
=
tag_name_parse_i
(
s
);
if
(
gt
==
TAG_NUM_OF_ITEM_TYPES
)
{
if
(
gt
==
TAG_NUM_OF_ITEM_TYPES
)
{
command_error
(
client
,
ACK_ERROR_ARG
,
r
.
FormatError
(
ACK_ERROR_ARG
,
"Unknown tag type: %s"
,
s
);
"Unknown tag type: %s"
,
s
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
}
}
...
@@ -246,8 +265,7 @@ handle_list(Client &client, Request args)
...
@@ -246,8 +265,7 @@ handle_list(Client &client, Request args)
filter
=
new
SongFilter
();
filter
=
new
SongFilter
();
if
(
!
filter
->
Parse
(
args
,
false
))
{
if
(
!
filter
->
Parse
(
args
,
false
))
{
delete
filter
;
delete
filter
;
command_error
(
client
,
ACK_ERROR_ARG
,
r
.
Error
(
ACK_ERROR_ARG
,
"not able to parse args"
);
"not able to parse args"
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
}
}
}
}
...
@@ -255,15 +273,16 @@ handle_list(Client &client, Request args)
...
@@ -255,15 +273,16 @@ handle_list(Client &client, Request args)
if
(
tagType
<
TAG_NUM_OF_ITEM_TYPES
&&
if
(
tagType
<
TAG_NUM_OF_ITEM_TYPES
&&
group_mask
&
(
1u
<<
tagType
))
{
group_mask
&
(
1u
<<
tagType
))
{
delete
filter
;
delete
filter
;
command_error
(
client
,
ACK_ERROR_ARG
,
"Conflicting group"
);
r
.
Error
(
ACK_ERROR_ARG
,
"Conflicting group"
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
}
}
Error
error
;
Error
error
;
CommandResult
ret
=
CommandResult
ret
=
PrintUniqueTags
(
client
,
tagType
,
group_mask
,
filter
,
error
)
PrintUniqueTags
(
r
,
client
.
partition
,
tagType
,
group_mask
,
filter
,
error
)
?
CommandResult
::
OK
?
CommandResult
::
OK
:
print_error
(
client
,
error
);
:
print_error
(
r
,
error
);
delete
filter
;
delete
filter
;
...
@@ -273,12 +292,15 @@ handle_list(Client &client, Request args)
...
@@ -273,12 +292,15 @@ handle_list(Client &client, Request args)
CommandResult
CommandResult
handle_listallinfo
(
Client
&
client
,
Request
args
)
handle_listallinfo
(
Client
&
client
,
Request
args
)
{
{
Response
r
(
client
);
/* default is root directory */
/* default is root directory */
const
auto
uri
=
args
.
GetOptional
(
0
,
""
);
const
auto
uri
=
args
.
GetOptional
(
0
,
""
);
Error
error
;
Error
error
;
return
db_selection_print
(
client
,
DatabaseSelection
(
uri
,
true
),
return
db_selection_print
(
r
,
client
.
partition
,
DatabaseSelection
(
uri
,
true
),
true
,
false
,
error
)
true
,
false
,
error
)
?
CommandResult
::
OK
?
CommandResult
::
OK
:
print_error
(
client
,
error
);
:
print_error
(
r
,
error
);
}
}
src/command/FileCommands.cxx
View file @
7652a298
...
@@ -24,8 +24,8 @@
...
@@ -24,8 +24,8 @@
#include "Request.hxx"
#include "Request.hxx"
#include "CommandError.hxx"
#include "CommandError.hxx"
#include "protocol/Ack.hxx"
#include "protocol/Ack.hxx"
#include "protocol/Result.hxx"
#include "client/Client.hxx"
#include "client/Client.hxx"
#include "client/Response.hxx"
#include "util/ConstBuffer.hxx"
#include "util/ConstBuffer.hxx"
#include "util/CharUtil.hxx"
#include "util/CharUtil.hxx"
#include "util/UriUtil.hxx"
#include "util/UriUtil.hxx"
...
@@ -72,21 +72,22 @@ skip_path(Path name_fs)
...
@@ -72,21 +72,22 @@ skip_path(Path name_fs)
CommandResult
CommandResult
handle_listfiles_local
(
Client
&
client
,
const
char
*
path_utf8
)
handle_listfiles_local
(
Client
&
client
,
const
char
*
path_utf8
)
{
{
Response
r
(
client
);
const
auto
path_fs
=
AllocatedPath
::
FromUTF8
(
path_utf8
);
const
auto
path_fs
=
AllocatedPath
::
FromUTF8
(
path_utf8
);
if
(
path_fs
.
IsNull
())
{
if
(
path_fs
.
IsNull
())
{
command_error
(
client
,
ACK_ERROR_NO_EXIST
,
r
.
Error
(
ACK_ERROR_NO_EXIST
,
"unsupported file name"
);
"unsupported file name"
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
}
}
Error
error
;
Error
error
;
if
(
!
client
.
AllowFile
(
path_fs
,
error
))
if
(
!
client
.
AllowFile
(
path_fs
,
error
))
return
print_error
(
client
,
error
);
return
print_error
(
r
,
error
);
DirectoryReader
reader
(
path_fs
);
DirectoryReader
reader
(
path_fs
);
if
(
reader
.
HasFailed
())
{
if
(
reader
.
HasFailed
())
{
error
.
FormatErrno
(
"Failed to open '%s'"
,
path_utf8
);
error
.
FormatErrno
(
"Failed to open '%s'"
,
path_utf8
);
return
print_error
(
client
,
error
);
return
print_error
(
r
,
error
);
}
}
while
(
reader
.
ReadEntry
())
{
while
(
reader
.
ReadEntry
())
{
...
@@ -105,17 +106,16 @@ handle_listfiles_local(Client &client, const char *path_utf8)
...
@@ -105,17 +106,16 @@ handle_listfiles_local(Client &client, const char *path_utf8)
continue
;
continue
;
if
(
fi
.
IsRegular
())
if
(
fi
.
IsRegular
())
client_printf
(
client
,
"file: %s
\n
"
r
.
Format
(
"file: %s
\n
"
"size: %"
PRIu64
"
\n
"
,
"size: %"
PRIu64
"
\n
"
,
name_utf8
.
c_str
(),
name_utf8
.
c_str
(),
fi
.
GetSize
());
fi
.
GetSize
());
else
if
(
fi
.
IsDirectory
())
else
if
(
fi
.
IsDirectory
())
client_printf
(
client
,
"directory: %s
\n
"
,
r
.
Format
(
"directory: %s
\n
"
,
name_utf8
.
c_str
());
name_utf8
.
c_str
());
else
else
continue
;
continue
;
time_print
(
client
,
"Last-Modified"
,
fi
.
GetModificationTime
());
time_print
(
r
,
"Last-Modified"
,
fi
.
GetModificationTime
());
}
}
return
CommandResult
::
OK
;
return
CommandResult
::
OK
;
...
@@ -158,10 +158,10 @@ IsValidValue(const char *p)
...
@@ -158,10 +158,10 @@ IsValidValue(const char *p)
static
void
static
void
print_pair
(
const
char
*
key
,
const
char
*
value
,
void
*
ctx
)
print_pair
(
const
char
*
key
,
const
char
*
value
,
void
*
ctx
)
{
{
Client
&
client
=
*
(
Client
*
)
ctx
;
auto
&
r
=
*
(
Response
*
)
ctx
;
if
(
IsValidName
(
key
)
&&
IsValidValue
(
value
))
if
(
IsValidName
(
key
)
&&
IsValidValue
(
value
))
client_printf
(
client
,
"%s: %s
\n
"
,
key
,
value
);
r
.
Format
(
"%s: %s
\n
"
,
key
,
value
);
}
}
static
constexpr
tag_handler
print_comment_handler
=
{
static
constexpr
tag_handler
print_comment_handler
=
{
...
@@ -171,17 +171,15 @@ static constexpr tag_handler print_comment_handler = {
...
@@ -171,17 +171,15 @@ static constexpr tag_handler print_comment_handler = {
};
};
static
CommandResult
static
CommandResult
read_stream_comments
(
Client
&
client
,
const
char
*
uri
)
read_stream_comments
(
Response
&
r
,
const
char
*
uri
)
{
{
if
(
!
uri_supported_scheme
(
uri
))
{
if
(
!
uri_supported_scheme
(
uri
))
{
command_error
(
client
,
ACK_ERROR_NO_EXIST
,
r
.
Error
(
ACK_ERROR_NO_EXIST
,
"unsupported URI scheme"
);
"unsupported URI scheme"
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
}
}
if
(
!
tag_stream_scan
(
uri
,
print_comment_handler
,
&
client
))
{
if
(
!
tag_stream_scan
(
uri
,
print_comment_handler
,
&
r
))
{
command_error
(
client
,
ACK_ERROR_NO_EXIST
,
r
.
Error
(
ACK_ERROR_NO_EXIST
,
"Failed to load file"
);
"Failed to load file"
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
}
}
...
@@ -190,16 +188,15 @@ read_stream_comments(Client &client, const char *uri)
...
@@ -190,16 +188,15 @@ read_stream_comments(Client &client, const char *uri)
}
}
static
CommandResult
static
CommandResult
read_file_comments
(
Client
&
client
,
const
Path
path_fs
)
read_file_comments
(
Response
&
r
,
const
Path
path_fs
)
{
{
if
(
!
tag_file_scan
(
path_fs
,
print_comment_handler
,
&
client
))
{
if
(
!
tag_file_scan
(
path_fs
,
print_comment_handler
,
&
r
))
{
command_error
(
client
,
ACK_ERROR_NO_EXIST
,
r
.
Error
(
ACK_ERROR_NO_EXIST
,
"Failed to load file"
);
"Failed to load file"
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
}
}
tag_ape_scan2
(
path_fs
,
&
print_comment_handler
,
&
client
);
tag_ape_scan2
(
path_fs
,
&
print_comment_handler
,
&
r
);
tag_id3_scan
(
path_fs
,
&
print_comment_handler
,
&
client
);
tag_id3_scan
(
path_fs
,
&
print_comment_handler
,
&
r
);
return
CommandResult
::
OK
;
return
CommandResult
::
OK
;
...
@@ -219,6 +216,8 @@ translate_uri(const char *uri)
...
@@ -219,6 +216,8 @@ translate_uri(const char *uri)
CommandResult
CommandResult
handle_read_comments
(
Client
&
client
,
Request
args
)
handle_read_comments
(
Client
&
client
,
Request
args
)
{
{
Response
r
(
client
);
assert
(
args
.
size
==
1
);
assert
(
args
.
size
==
1
);
const
char
*
const
uri
=
translate_uri
(
args
.
front
());
const
char
*
const
uri
=
translate_uri
(
args
.
front
());
...
@@ -227,25 +226,23 @@ handle_read_comments(Client &client, Request args)
...
@@ -227,25 +226,23 @@ handle_read_comments(Client &client, Request args)
const
char
*
path_utf8
=
uri
+
7
;
const
char
*
path_utf8
=
uri
+
7
;
AllocatedPath
path_fs
=
AllocatedPath
::
FromUTF8
(
path_utf8
);
AllocatedPath
path_fs
=
AllocatedPath
::
FromUTF8
(
path_utf8
);
if
(
path_fs
.
IsNull
())
{
if
(
path_fs
.
IsNull
())
{
command_error
(
client
,
ACK_ERROR_NO_EXIST
,
r
.
Error
(
ACK_ERROR_NO_EXIST
,
"unsupported file name"
);
"unsupported file name"
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
}
}
Error
error
;
Error
error
;
if
(
!
client
.
AllowFile
(
path_fs
,
error
))
if
(
!
client
.
AllowFile
(
path_fs
,
error
))
return
print_error
(
client
,
error
);
return
print_error
(
r
,
error
);
return
read_file_comments
(
client
,
path_fs
);
return
read_file_comments
(
r
,
path_fs
);
}
else
if
(
uri_has_scheme
(
uri
))
{
}
else
if
(
uri_has_scheme
(
uri
))
{
return
read_stream_comments
(
client
,
uri
);
return
read_stream_comments
(
r
,
uri
);
}
else
if
(
!
PathTraitsUTF8
::
IsAbsolute
(
uri
))
{
}
else
if
(
!
PathTraitsUTF8
::
IsAbsolute
(
uri
))
{
#ifdef ENABLE_DATABASE
#ifdef ENABLE_DATABASE
const
Storage
*
storage
=
client
.
GetStorage
();
const
Storage
*
storage
=
client
.
GetStorage
();
if
(
storage
==
nullptr
)
{
if
(
storage
==
nullptr
)
{
#endif
#endif
command_error
(
client
,
ACK_ERROR_NO_EXIST
,
r
.
Error
(
ACK_ERROR_NO_EXIST
,
"No database"
);
"No database"
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
#ifdef ENABLE_DATABASE
#ifdef ENABLE_DATABASE
}
}
...
@@ -253,21 +250,20 @@ handle_read_comments(Client &client, Request args)
...
@@ -253,21 +250,20 @@ handle_read_comments(Client &client, Request args)
{
{
AllocatedPath
path_fs
=
storage
->
MapFS
(
uri
);
AllocatedPath
path_fs
=
storage
->
MapFS
(
uri
);
if
(
!
path_fs
.
IsNull
())
if
(
!
path_fs
.
IsNull
())
return
read_file_comments
(
client
,
path_fs
);
return
read_file_comments
(
r
,
path_fs
);
}
}
{
{
const
std
::
string
uri2
=
storage
->
MapUTF8
(
uri
);
const
std
::
string
uri2
=
storage
->
MapUTF8
(
uri
);
if
(
uri_has_scheme
(
uri2
.
c_str
()))
if
(
uri_has_scheme
(
uri2
.
c_str
()))
return
read_stream_comments
(
client
,
return
read_stream_comments
(
r
,
uri2
.
c_str
());
uri2
.
c_str
());
}
}
command_error
(
client
,
ACK_ERROR_NO_EXIST
,
"No such file"
);
r
.
Error
(
ACK_ERROR_NO_EXIST
,
"No such file"
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
#endif
#endif
}
else
{
}
else
{
command_error
(
client
,
ACK_ERROR_NO_EXIST
,
"No such file"
);
r
.
Error
(
ACK_ERROR_NO_EXIST
,
"No such file"
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
}
}
}
}
src/command/MessageCommands.cxx
View file @
7652a298
...
@@ -22,9 +22,9 @@
...
@@ -22,9 +22,9 @@
#include "Request.hxx"
#include "Request.hxx"
#include "client/Client.hxx"
#include "client/Client.hxx"
#include "client/ClientList.hxx"
#include "client/ClientList.hxx"
#include "client/Response.hxx"
#include "Instance.hxx"
#include "Instance.hxx"
#include "Partition.hxx"
#include "Partition.hxx"
#include "protocol/Result.hxx"
#include "util/ConstBuffer.hxx"
#include "util/ConstBuffer.hxx"
#include <set>
#include <set>
...
@@ -35,6 +35,8 @@
...
@@ -35,6 +35,8 @@
CommandResult
CommandResult
handle_subscribe
(
Client
&
client
,
Request
args
)
handle_subscribe
(
Client
&
client
,
Request
args
)
{
{
Response
r
(
client
);
assert
(
args
.
size
==
1
);
assert
(
args
.
size
==
1
);
const
char
*
const
channel_name
=
args
[
0
];
const
char
*
const
channel_name
=
args
[
0
];
...
@@ -43,18 +45,15 @@ handle_subscribe(Client &client, Request args)
...
@@ -43,18 +45,15 @@ handle_subscribe(Client &client, Request args)
return
CommandResult
::
OK
;
return
CommandResult
::
OK
;
case
Client
:
:
SubscribeResult
::
INVALID
:
case
Client
:
:
SubscribeResult
::
INVALID
:
command_error
(
client
,
ACK_ERROR_ARG
,
r
.
Error
(
ACK_ERROR_ARG
,
"invalid channel name"
);
"invalid channel name"
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
case
Client
:
:
SubscribeResult
::
ALREADY
:
case
Client
:
:
SubscribeResult
::
ALREADY
:
command_error
(
client
,
ACK_ERROR_EXIST
,
r
.
Error
(
ACK_ERROR_EXIST
,
"already subscribed to this channel"
);
"already subscribed to this channel"
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
case
Client
:
:
SubscribeResult
::
FULL
:
case
Client
:
:
SubscribeResult
::
FULL
:
command_error
(
client
,
ACK_ERROR_EXIST
,
r
.
Error
(
ACK_ERROR_EXIST
,
"subscription list is full"
);
"subscription list is full"
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
}
}
...
@@ -66,14 +65,15 @@ handle_subscribe(Client &client, Request args)
...
@@ -66,14 +65,15 @@ handle_subscribe(Client &client, Request args)
CommandResult
CommandResult
handle_unsubscribe
(
Client
&
client
,
Request
args
)
handle_unsubscribe
(
Client
&
client
,
Request
args
)
{
{
Response
r
(
client
);
assert
(
args
.
size
==
1
);
assert
(
args
.
size
==
1
);
const
char
*
const
channel_name
=
args
[
0
];
const
char
*
const
channel_name
=
args
[
0
];
if
(
client
.
Unsubscribe
(
channel_name
))
if
(
client
.
Unsubscribe
(
channel_name
))
return
CommandResult
::
OK
;
return
CommandResult
::
OK
;
else
{
else
{
command_error
(
client
,
ACK_ERROR_NO_EXIST
,
r
.
Error
(
ACK_ERROR_NO_EXIST
,
"not subscribed to this channel"
);
"not subscribed to this channel"
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
}
}
}
}
...
@@ -88,8 +88,9 @@ handle_channels(Client &client, gcc_unused Request args)
...
@@ -88,8 +88,9 @@ handle_channels(Client &client, gcc_unused Request args)
channels
.
insert
(
c
.
subscriptions
.
begin
(),
channels
.
insert
(
c
.
subscriptions
.
begin
(),
c
.
subscriptions
.
end
());
c
.
subscriptions
.
end
());
Response
r
(
client
);
for
(
const
auto
&
channel
:
channels
)
for
(
const
auto
&
channel
:
channels
)
client_printf
(
client
,
"channel: %s
\n
"
,
channel
.
c_str
());
r
.
Format
(
"channel: %s
\n
"
,
channel
.
c_str
());
return
CommandResult
::
OK
;
return
CommandResult
::
OK
;
}
}
...
@@ -100,11 +101,12 @@ handle_read_messages(Client &client,
...
@@ -100,11 +101,12 @@ handle_read_messages(Client &client,
{
{
assert
(
args
.
IsEmpty
());
assert
(
args
.
IsEmpty
());
Response
r
(
client
);
while
(
!
client
.
messages
.
empty
())
{
while
(
!
client
.
messages
.
empty
())
{
const
ClientMessage
&
msg
=
client
.
messages
.
front
();
const
ClientMessage
&
msg
=
client
.
messages
.
front
();
client_printf
(
client
,
"channel: %s
\n
message: %s
\n
"
,
r
.
Format
(
"channel: %s
\n
message: %s
\n
"
,
msg
.
GetChannel
(),
msg
.
GetMessage
());
msg
.
GetChannel
(),
msg
.
GetMessage
());
client
.
messages
.
pop_front
();
client
.
messages
.
pop_front
();
}
}
...
@@ -119,9 +121,9 @@ handle_send_message(Client &client, Request args)
...
@@ -119,9 +121,9 @@ handle_send_message(Client &client, Request args)
const
char
*
const
channel_name
=
args
[
0
];
const
char
*
const
channel_name
=
args
[
0
];
const
char
*
const
message_text
=
args
[
1
];
const
char
*
const
message_text
=
args
[
1
];
Response
r
(
client
);
if
(
!
client_message_valid_channel_name
(
channel_name
))
{
if
(
!
client_message_valid_channel_name
(
channel_name
))
{
command_error
(
client
,
ACK_ERROR_ARG
,
r
.
Error
(
ACK_ERROR_ARG
,
"invalid channel name"
);
"invalid channel name"
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
}
}
...
@@ -134,8 +136,8 @@ handle_send_message(Client &client, Request args)
...
@@ -134,8 +136,8 @@ handle_send_message(Client &client, Request args)
if
(
sent
)
if
(
sent
)
return
CommandResult
::
OK
;
return
CommandResult
::
OK
;
else
{
else
{
command_error
(
client
,
ACK_ERROR_NO_EXIST
,
r
.
Error
(
ACK_ERROR_NO_EXIST
,
"nobody is subscribed to this channel"
);
"nobody is subscribed to this channel"
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
}
}
}
}
src/command/NeighborCommands.cxx
View file @
7652a298
...
@@ -21,9 +21,9 @@
...
@@ -21,9 +21,9 @@
#include "NeighborCommands.hxx"
#include "NeighborCommands.hxx"
#include "Request.hxx"
#include "Request.hxx"
#include "client/Client.hxx"
#include "client/Client.hxx"
#include "client/Response.hxx"
#include "Instance.hxx"
#include "Instance.hxx"
#include "Partition.hxx"
#include "Partition.hxx"
#include "protocol/Result.hxx"
#include "neighbor/Glue.hxx"
#include "neighbor/Glue.hxx"
#include "neighbor/Info.hxx"
#include "neighbor/Info.hxx"
#include "util/ConstBuffer.hxx"
#include "util/ConstBuffer.hxx"
...
@@ -42,19 +42,19 @@ neighbor_commands_available(const Instance &instance)
...
@@ -42,19 +42,19 @@ neighbor_commands_available(const Instance &instance)
CommandResult
CommandResult
handle_listneighbors
(
Client
&
client
,
gcc_unused
Request
args
)
handle_listneighbors
(
Client
&
client
,
gcc_unused
Request
args
)
{
{
Response
r
(
client
);
const
NeighborGlue
*
const
neighbors
=
const
NeighborGlue
*
const
neighbors
=
client
.
partition
.
instance
.
neighbors
;
client
.
partition
.
instance
.
neighbors
;
if
(
neighbors
==
nullptr
)
{
if
(
neighbors
==
nullptr
)
{
command_error
(
client
,
ACK_ERROR_UNKNOWN
,
r
.
Error
(
ACK_ERROR_UNKNOWN
,
"No neighbor plugin configured"
);
"No neighbor plugin configured"
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
}
}
for
(
const
auto
&
i
:
neighbors
->
GetList
())
for
(
const
auto
&
i
:
neighbors
->
GetList
())
client_printf
(
client
,
r
.
Format
(
"neighbor: %s
\n
"
"neighbor: %s
\n
"
"name: %s
\n
"
,
"name: %s
\n
"
,
i
.
uri
.
c_str
(),
i
.
uri
.
c_str
(),
i
.
display_name
.
c_str
());
i
.
display_name
.
c_str
());
return
CommandResult
::
OK
;
return
CommandResult
::
OK
;
}
}
src/command/OtherCommands.cxx
View file @
7652a298
...
@@ -32,7 +32,6 @@
...
@@ -32,7 +32,6 @@
#include "tag/TagHandler.hxx"
#include "tag/TagHandler.hxx"
#include "TimePrint.hxx"
#include "TimePrint.hxx"
#include "decoder/DecoderPrint.hxx"
#include "decoder/DecoderPrint.hxx"
#include "protocol/Result.hxx"
#include "ls.hxx"
#include "ls.hxx"
#include "mixer/Volume.hxx"
#include "mixer/Volume.hxx"
#include "util/UriUtil.hxx"
#include "util/UriUtil.hxx"
...
@@ -44,6 +43,7 @@
...
@@ -44,6 +43,7 @@
#include "PlaylistFile.hxx"
#include "PlaylistFile.hxx"
#include "db/PlaylistVector.hxx"
#include "db/PlaylistVector.hxx"
#include "client/Client.hxx"
#include "client/Client.hxx"
#include "client/Response.hxx"
#include "Partition.hxx"
#include "Partition.hxx"
#include "Instance.hxx"
#include "Instance.hxx"
#include "Idle.hxx"
#include "Idle.hxx"
...
@@ -58,36 +58,39 @@
...
@@ -58,36 +58,39 @@
#include <string.h>
#include <string.h>
static
void
static
void
print_spl_list
(
Client
&
client
,
const
PlaylistVector
&
list
)
print_spl_list
(
Response
&
r
,
const
PlaylistVector
&
list
)
{
{
for
(
const
auto
&
i
:
list
)
{
for
(
const
auto
&
i
:
list
)
{
client_printf
(
client
,
"playlist: %s
\n
"
,
i
.
name
.
c_str
());
r
.
Format
(
"playlist: %s
\n
"
,
i
.
name
.
c_str
());
if
(
i
.
mtime
>
0
)
if
(
i
.
mtime
>
0
)
time_print
(
client
,
"Last-Modified"
,
i
.
mtime
);
time_print
(
r
,
"Last-Modified"
,
i
.
mtime
);
}
}
}
}
CommandResult
CommandResult
handle_urlhandlers
(
Client
&
client
,
gcc_unused
Request
args
)
handle_urlhandlers
(
Client
&
client
,
gcc_unused
Request
args
)
{
{
Response
r
(
client
);
if
(
client
.
IsLocal
())
if
(
client
.
IsLocal
())
client_puts
(
client
,
"handler: file://
\n
"
);
r
.
Format
(
"handler: file://
\n
"
);
print_supported_uri_schemes
(
client
);
print_supported_uri_schemes
(
r
);
return
CommandResult
::
OK
;
return
CommandResult
::
OK
;
}
}
CommandResult
CommandResult
handle_decoders
(
Client
&
client
,
gcc_unused
Request
args
)
handle_decoders
(
Client
&
client
,
gcc_unused
Request
args
)
{
{
decoder_list_print
(
client
);
Response
r
(
client
);
decoder_list_print
(
r
);
return
CommandResult
::
OK
;
return
CommandResult
::
OK
;
}
}
CommandResult
CommandResult
handle_tagtypes
(
Client
&
client
,
gcc_unused
Request
args
)
handle_tagtypes
(
Client
&
client
,
gcc_unused
Request
args
)
{
{
tag_print_types
(
client
);
Response
r
(
client
);
tag_print_types
(
r
);
return
CommandResult
::
OK
;
return
CommandResult
::
OK
;
}
}
...
@@ -106,14 +109,16 @@ handle_close(gcc_unused Client &client, gcc_unused Request args)
...
@@ -106,14 +109,16 @@ handle_close(gcc_unused Client &client, gcc_unused Request args)
static
void
static
void
print_tag
(
TagType
type
,
const
char
*
value
,
void
*
ctx
)
print_tag
(
TagType
type
,
const
char
*
value
,
void
*
ctx
)
{
{
Client
&
client
=
*
(
Client
*
)
ctx
;
auto
&
r
=
*
(
Response
*
)
ctx
;
tag_print
(
client
,
type
,
value
);
tag_print
(
r
,
type
,
value
);
}
}
CommandResult
CommandResult
handle_listfiles
(
Client
&
client
,
Request
args
)
handle_listfiles
(
Client
&
client
,
Request
args
)
{
{
Response
r
(
client
);
/* default is root directory */
/* default is root directory */
const
auto
uri
=
args
.
GetOptional
(
0
,
""
);
const
auto
uri
=
args
.
GetOptional
(
0
,
""
);
...
@@ -124,7 +129,7 @@ handle_listfiles(Client &client, Request args)
...
@@ -124,7 +129,7 @@ handle_listfiles(Client &client, Request args)
#ifdef ENABLE_DATABASE
#ifdef ENABLE_DATABASE
if
(
uri_has_scheme
(
uri
))
if
(
uri_has_scheme
(
uri
))
/* use storage plugin to list remote directory */
/* use storage plugin to list remote directory */
return
handle_listfiles_storage
(
client
,
uri
);
return
handle_listfiles_storage
(
r
,
uri
);
/* must be a path relative to the configured
/* must be a path relative to the configured
music_directory */
music_directory */
...
@@ -132,14 +137,14 @@ handle_listfiles(Client &client, Request args)
...
@@ -132,14 +137,14 @@ handle_listfiles(Client &client, Request args)
if
(
client
.
partition
.
instance
.
storage
!=
nullptr
)
if
(
client
.
partition
.
instance
.
storage
!=
nullptr
)
/* if we have a storage instance, obtain a list of
/* if we have a storage instance, obtain a list of
files from it */
files from it */
return
handle_listfiles_storage
(
client
,
return
handle_listfiles_storage
(
r
,
*
client
.
partition
.
instance
.
storage
,
*
client
.
partition
.
instance
.
storage
,
uri
);
uri
);
/* fall back to entries from database if we have no storage */
/* fall back to entries from database if we have no storage */
return
handle_listfiles_db
(
client
,
uri
);
return
handle_listfiles_db
(
client
,
uri
);
#else
#else
command_error
(
client
,
ACK_ERROR_NO_EXIST
,
"No database"
);
r
.
Error
(
ACK_ERROR_NO_EXIST
,
"No database"
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
#endif
#endif
}
}
...
@@ -156,42 +161,40 @@ handle_lsinfo(Client &client, Request args)
...
@@ -156,42 +161,40 @@ handle_lsinfo(Client &client, Request args)
/* default is root directory */
/* default is root directory */
const
auto
uri
=
args
.
GetOptional
(
0
,
""
);
const
auto
uri
=
args
.
GetOptional
(
0
,
""
);
Response
r
(
client
);
if
(
memcmp
(
uri
,
"file:///"
,
8
)
==
0
)
{
if
(
memcmp
(
uri
,
"file:///"
,
8
)
==
0
)
{
/* print information about an arbitrary local file */
/* print information about an arbitrary local file */
const
char
*
path_utf8
=
uri
+
7
;
const
char
*
path_utf8
=
uri
+
7
;
const
auto
path_fs
=
AllocatedPath
::
FromUTF8
(
path_utf8
);
const
auto
path_fs
=
AllocatedPath
::
FromUTF8
(
path_utf8
);
if
(
path_fs
.
IsNull
())
{
if
(
path_fs
.
IsNull
())
{
command_error
(
client
,
ACK_ERROR_NO_EXIST
,
r
.
Error
(
ACK_ERROR_NO_EXIST
,
"unsupported file name"
);
"unsupported file name"
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
}
}
Error
error
;
Error
error
;
if
(
!
client
.
AllowFile
(
path_fs
,
error
))
if
(
!
client
.
AllowFile
(
path_fs
,
error
))
return
print_error
(
client
,
error
);
return
print_error
(
r
,
error
);
DetachedSong
song
(
path_utf8
);
DetachedSong
song
(
path_utf8
);
if
(
!
song
.
Update
())
{
if
(
!
song
.
Update
())
{
command_error
(
client
,
ACK_ERROR_NO_EXIST
,
r
.
Error
(
ACK_ERROR_NO_EXIST
,
"No such file"
);
"No such file"
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
}
}
song_print_info
(
client
,
song
);
song_print_info
(
r
,
client
.
partition
,
song
);
return
CommandResult
::
OK
;
return
CommandResult
::
OK
;
}
}
if
(
uri_has_scheme
(
uri
))
{
if
(
uri_has_scheme
(
uri
))
{
if
(
!
uri_supported_scheme
(
uri
))
{
if
(
!
uri_supported_scheme
(
uri
))
{
command_error
(
client
,
ACK_ERROR_NO_EXIST
,
r
.
Error
(
ACK_ERROR_NO_EXIST
,
"unsupported URI scheme"
);
"unsupported URI scheme"
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
}
}
if
(
!
tag_stream_scan
(
uri
,
print_tag_handler
,
&
client
))
{
if
(
!
tag_stream_scan
(
uri
,
print_tag_handler
,
&
r
))
{
command_error
(
client
,
ACK_ERROR_NO_EXIST
,
r
.
Error
(
ACK_ERROR_NO_EXIST
,
"No such file"
);
"No such file"
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
}
}
...
@@ -207,10 +210,10 @@ handle_lsinfo(Client &client, Request args)
...
@@ -207,10 +210,10 @@ handle_lsinfo(Client &client, Request args)
if
(
isRootDirectory
(
uri
))
{
if
(
isRootDirectory
(
uri
))
{
Error
error
;
Error
error
;
const
auto
&
list
=
ListPlaylistFiles
(
error
);
const
auto
&
list
=
ListPlaylistFiles
(
error
);
print_spl_list
(
client
,
list
);
print_spl_list
(
r
,
list
);
}
else
{
}
else
{
#ifndef ENABLE_DATABASE
#ifndef ENABLE_DATABASE
command_error
(
client
,
ACK_ERROR_NO_EXIST
,
"No database"
);
r
.
Error
(
ACK_ERROR_NO_EXIST
,
"No database"
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
#endif
#endif
}
}
...
@@ -224,13 +227,14 @@ static CommandResult
...
@@ -224,13 +227,14 @@ static CommandResult
handle_update
(
Client
&
client
,
UpdateService
&
update
,
handle_update
(
Client
&
client
,
UpdateService
&
update
,
const
char
*
uri_utf8
,
bool
discard
)
const
char
*
uri_utf8
,
bool
discard
)
{
{
Response
r
(
client
);
unsigned
ret
=
update
.
Enqueue
(
uri_utf8
,
discard
);
unsigned
ret
=
update
.
Enqueue
(
uri_utf8
,
discard
);
if
(
ret
>
0
)
{
if
(
ret
>
0
)
{
client_printf
(
client
,
"updating_db: %i
\n
"
,
ret
);
r
.
Format
(
"updating_db: %i
\n
"
,
ret
);
return
CommandResult
::
OK
;
return
CommandResult
::
OK
;
}
else
{
}
else
{
command_error
(
client
,
ACK_ERROR_UPDATE_ALREADY
,
r
.
Error
(
ACK_ERROR_UPDATE_ALREADY
,
"already updating"
);
"already updating"
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
}
}
}
}
...
@@ -239,17 +243,19 @@ static CommandResult
...
@@ -239,17 +243,19 @@ static CommandResult
handle_update
(
Client
&
client
,
Database
&
db
,
handle_update
(
Client
&
client
,
Database
&
db
,
const
char
*
uri_utf8
,
bool
discard
)
const
char
*
uri_utf8
,
bool
discard
)
{
{
Response
r
(
client
);
Error
error
;
Error
error
;
unsigned
id
=
db
.
Update
(
uri_utf8
,
discard
,
error
);
unsigned
id
=
db
.
Update
(
uri_utf8
,
discard
,
error
);
if
(
id
>
0
)
{
if
(
id
>
0
)
{
client_printf
(
client
,
"updating_db: %i
\n
"
,
id
);
r
.
Format
(
"updating_db: %i
\n
"
,
id
);
return
CommandResult
::
OK
;
return
CommandResult
::
OK
;
}
else
if
(
error
.
IsDefined
())
{
}
else
if
(
error
.
IsDefined
())
{
return
print_error
(
client
,
error
);
return
print_error
(
r
,
error
);
}
else
{
}
else
{
/* Database::Update() has returned 0 without setting
/* Database::Update() has returned 0 without setting
the Error: the method is not implemented */
the Error: the method is not implemented */
command_error
(
client
,
ACK_ERROR_NO_EXIST
,
"Not implemented"
);
r
.
Error
(
ACK_ERROR_NO_EXIST
,
"Not implemented"
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
}
}
}
}
...
@@ -259,6 +265,8 @@ handle_update(Client &client, Database &db,
...
@@ -259,6 +265,8 @@ handle_update(Client &client, Database &db,
static
CommandResult
static
CommandResult
handle_update
(
Client
&
client
,
Request
args
,
bool
discard
)
handle_update
(
Client
&
client
,
Request
args
,
bool
discard
)
{
{
Response
r
(
client
);
#ifdef ENABLE_DATABASE
#ifdef ENABLE_DATABASE
const
char
*
path
=
""
;
const
char
*
path
=
""
;
...
@@ -270,8 +278,7 @@ handle_update(Client &client, Request args, bool discard)
...
@@ -270,8 +278,7 @@ handle_update(Client &client, Request args, bool discard)
/* backwards compatibility with MPD 0.15 */
/* backwards compatibility with MPD 0.15 */
path
=
""
;
path
=
""
;
else
if
(
!
uri_safe_local
(
path
))
{
else
if
(
!
uri_safe_local
(
path
))
{
command_error
(
client
,
ACK_ERROR_ARG
,
r
.
Error
(
ACK_ERROR_ARG
,
"Malformed path"
);
"Malformed path"
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
}
}
}
}
...
@@ -288,7 +295,7 @@ handle_update(Client &client, Request args, bool discard)
...
@@ -288,7 +295,7 @@ handle_update(Client &client, Request args, bool discard)
(
void
)
discard
;
(
void
)
discard
;
#endif
#endif
command_error
(
client
,
ACK_ERROR_NO_EXIST
,
"No database"
);
r
.
Error
(
ACK_ERROR_NO_EXIST
,
"No database"
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
}
}
...
@@ -307,13 +314,14 @@ handle_rescan(Client &client, gcc_unused Request args)
...
@@ -307,13 +314,14 @@ handle_rescan(Client &client, gcc_unused Request args)
CommandResult
CommandResult
handle_setvol
(
Client
&
client
,
Request
args
)
handle_setvol
(
Client
&
client
,
Request
args
)
{
{
Response
r
(
client
);
unsigned
level
;
unsigned
level
;
if
(
!
args
.
Parse
(
0
,
level
,
client
,
100
))
if
(
!
args
.
Parse
(
0
,
level
,
r
,
100
))
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
if
(
!
volume_level_change
(
client
.
partition
.
outputs
,
level
))
{
if
(
!
volume_level_change
(
client
.
partition
.
outputs
,
level
))
{
command_error
(
client
,
ACK_ERROR_SYSTEM
,
r
.
Error
(
ACK_ERROR_SYSTEM
,
"problems setting volume"
);
"problems setting volume"
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
}
}
...
@@ -323,13 +331,15 @@ handle_setvol(Client &client, Request args)
...
@@ -323,13 +331,15 @@ handle_setvol(Client &client, Request args)
CommandResult
CommandResult
handle_volume
(
Client
&
client
,
Request
args
)
handle_volume
(
Client
&
client
,
Request
args
)
{
{
Response
r
(
client
);
int
relative
;
int
relative
;
if
(
!
args
.
Parse
(
0
,
relative
,
client
,
-
100
,
100
))
if
(
!
args
.
Parse
(
0
,
relative
,
r
,
-
100
,
100
))
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
const
int
old_volume
=
volume_level_get
(
client
.
partition
.
outputs
);
const
int
old_volume
=
volume_level_get
(
client
.
partition
.
outputs
);
if
(
old_volume
<
0
)
{
if
(
old_volume
<
0
)
{
command_error
(
client
,
ACK_ERROR_SYSTEM
,
"No mixer"
);
r
.
Error
(
ACK_ERROR_SYSTEM
,
"No mixer"
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
}
}
...
@@ -341,8 +351,7 @@ handle_volume(Client &client, Request args)
...
@@ -341,8 +351,7 @@ handle_volume(Client &client, Request args)
if
(
new_volume
!=
old_volume
&&
if
(
new_volume
!=
old_volume
&&
!
volume_level_change
(
client
.
partition
.
outputs
,
new_volume
))
{
!
volume_level_change
(
client
.
partition
.
outputs
,
new_volume
))
{
command_error
(
client
,
ACK_ERROR_SYSTEM
,
r
.
Error
(
ACK_ERROR_SYSTEM
,
"problems setting volume"
);
"problems setting volume"
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
}
}
...
@@ -352,7 +361,8 @@ handle_volume(Client &client, Request args)
...
@@ -352,7 +361,8 @@ handle_volume(Client &client, Request args)
CommandResult
CommandResult
handle_stats
(
Client
&
client
,
gcc_unused
Request
args
)
handle_stats
(
Client
&
client
,
gcc_unused
Request
args
)
{
{
stats_print
(
client
);
Response
r
(
client
);
stats_print
(
r
,
client
.
partition
);
return
CommandResult
::
OK
;
return
CommandResult
::
OK
;
}
}
...
@@ -365,10 +375,11 @@ handle_ping(gcc_unused Client &client, gcc_unused Request args)
...
@@ -365,10 +375,11 @@ handle_ping(gcc_unused Client &client, gcc_unused Request args)
CommandResult
CommandResult
handle_password
(
Client
&
client
,
Request
args
)
handle_password
(
Client
&
client
,
Request
args
)
{
{
unsigned
permission
=
0
;
Response
r
(
client
)
;
unsigned
permission
=
0
;
if
(
getPermissionFromPassword
(
args
.
front
(),
&
permission
)
<
0
)
{
if
(
getPermissionFromPassword
(
args
.
front
(),
&
permission
)
<
0
)
{
command_error
(
client
,
ACK_ERROR_PASSWORD
,
"incorrect password"
);
r
.
Error
(
ACK_ERROR_PASSWORD
,
"incorrect password"
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
}
}
...
@@ -380,9 +391,11 @@ handle_password(Client &client, Request args)
...
@@ -380,9 +391,11 @@ handle_password(Client &client, Request args)
CommandResult
CommandResult
handle_config
(
Client
&
client
,
gcc_unused
Request
args
)
handle_config
(
Client
&
client
,
gcc_unused
Request
args
)
{
{
Response
r
(
client
);
if
(
!
client
.
IsLocal
())
{
if
(
!
client
.
IsLocal
())
{
command_error
(
client
,
ACK_ERROR_PERMISSION
,
r
.
Error
(
ACK_ERROR_PERMISSION
,
"Command only permitted to local clients"
);
"Command only permitted to local clients"
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
}
}
...
@@ -390,7 +403,7 @@ handle_config(Client &client, gcc_unused Request args)
...
@@ -390,7 +403,7 @@ handle_config(Client &client, gcc_unused Request args)
const
Storage
*
storage
=
client
.
GetStorage
();
const
Storage
*
storage
=
client
.
GetStorage
();
if
(
storage
!=
nullptr
)
{
if
(
storage
!=
nullptr
)
{
const
auto
path
=
storage
->
MapUTF8
(
""
);
const
auto
path
=
storage
->
MapUTF8
(
""
);
client_printf
(
client
,
"music_directory: %s
\n
"
,
path
.
c_str
());
r
.
Format
(
"music_directory: %s
\n
"
,
path
.
c_str
());
}
}
#endif
#endif
...
@@ -400,14 +413,14 @@ handle_config(Client &client, gcc_unused Request args)
...
@@ -400,14 +413,14 @@ handle_config(Client &client, gcc_unused Request args)
CommandResult
CommandResult
handle_idle
(
Client
&
client
,
Request
args
)
handle_idle
(
Client
&
client
,
Request
args
)
{
{
unsigned
flags
=
0
;
Response
r
(
client
)
;
unsigned
flags
=
0
;
for
(
const
char
*
i
:
args
)
{
for
(
const
char
*
i
:
args
)
{
unsigned
event
=
idle_parse_name
(
i
);
unsigned
event
=
idle_parse_name
(
i
);
if
(
event
==
0
)
{
if
(
event
==
0
)
{
command_error
(
client
,
ACK_ERROR_ARG
,
r
.
FormatError
(
ACK_ERROR_ARG
,
"Unrecognized idle event: %s"
,
"Unrecognized idle event: %s"
,
i
);
i
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
}
}
...
...
src/command/OutputCommands.cxx
View file @
7652a298
...
@@ -22,23 +22,23 @@
...
@@ -22,23 +22,23 @@
#include "Request.hxx"
#include "Request.hxx"
#include "output/OutputPrint.hxx"
#include "output/OutputPrint.hxx"
#include "output/OutputCommand.hxx"
#include "output/OutputCommand.hxx"
#include "protocol/Result.hxx"
#include "client/Client.hxx"
#include "client/Client.hxx"
#include "client/Response.hxx"
#include "Partition.hxx"
#include "Partition.hxx"
#include "util/ConstBuffer.hxx"
#include "util/ConstBuffer.hxx"
CommandResult
CommandResult
handle_enableoutput
(
Client
&
client
,
Request
args
)
handle_enableoutput
(
Client
&
client
,
Request
args
)
{
{
assert
(
args
.
size
==
1
);
Response
r
(
client
);
assert
(
args
.
size
==
1
);
unsigned
device
;
unsigned
device
;
if
(
!
args
.
Parse
(
0
,
device
,
client
))
if
(
!
args
.
Parse
(
0
,
device
,
r
))
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
if
(
!
audio_output_enable_index
(
client
.
partition
.
outputs
,
device
))
{
if
(
!
audio_output_enable_index
(
client
.
partition
.
outputs
,
device
))
{
command_error
(
client
,
ACK_ERROR_NO_EXIST
,
r
.
Error
(
ACK_ERROR_NO_EXIST
,
"No such audio output"
);
"No such audio output"
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
}
}
...
@@ -48,15 +48,15 @@ handle_enableoutput(Client &client, Request args)
...
@@ -48,15 +48,15 @@ handle_enableoutput(Client &client, Request args)
CommandResult
CommandResult
handle_disableoutput
(
Client
&
client
,
Request
args
)
handle_disableoutput
(
Client
&
client
,
Request
args
)
{
{
assert
(
args
.
size
==
1
);
Response
r
(
client
);
assert
(
args
.
size
==
1
);
unsigned
device
;
unsigned
device
;
if
(
!
args
.
Parse
(
0
,
device
,
client
))
if
(
!
args
.
Parse
(
0
,
device
,
r
))
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
if
(
!
audio_output_disable_index
(
client
.
partition
.
outputs
,
device
))
{
if
(
!
audio_output_disable_index
(
client
.
partition
.
outputs
,
device
))
{
command_error
(
client
,
ACK_ERROR_NO_EXIST
,
r
.
Error
(
ACK_ERROR_NO_EXIST
,
"No such audio output"
);
"No such audio output"
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
}
}
...
@@ -66,15 +66,15 @@ handle_disableoutput(Client &client, Request args)
...
@@ -66,15 +66,15 @@ handle_disableoutput(Client &client, Request args)
CommandResult
CommandResult
handle_toggleoutput
(
Client
&
client
,
Request
args
)
handle_toggleoutput
(
Client
&
client
,
Request
args
)
{
{
assert
(
args
.
size
==
1
);
Response
r
(
client
);
assert
(
args
.
size
==
1
);
unsigned
device
;
unsigned
device
;
if
(
!
args
.
Parse
(
0
,
device
,
client
))
if
(
!
args
.
Parse
(
0
,
device
,
r
))
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
if
(
!
audio_output_toggle_index
(
client
.
partition
.
outputs
,
device
))
{
if
(
!
audio_output_toggle_index
(
client
.
partition
.
outputs
,
device
))
{
command_error
(
client
,
ACK_ERROR_NO_EXIST
,
r
.
Error
(
ACK_ERROR_NO_EXIST
,
"No such audio output"
);
"No such audio output"
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
}
}
...
@@ -86,7 +86,8 @@ handle_devices(Client &client, gcc_unused Request args)
...
@@ -86,7 +86,8 @@ handle_devices(Client &client, gcc_unused Request args)
{
{
assert
(
args
.
IsEmpty
());
assert
(
args
.
IsEmpty
());
printAudioDevices
(
client
,
client
.
partition
.
outputs
);
Response
r
(
client
);
printAudioDevices
(
r
,
client
.
partition
.
outputs
);
return
CommandResult
::
OK
;
return
CommandResult
::
OK
;
}
}
src/command/PlayerCommands.cxx
View file @
7652a298
...
@@ -24,10 +24,10 @@
...
@@ -24,10 +24,10 @@
#include "queue/Playlist.hxx"
#include "queue/Playlist.hxx"
#include "PlaylistPrint.hxx"
#include "PlaylistPrint.hxx"
#include "client/Client.hxx"
#include "client/Client.hxx"
#include "client/Response.hxx"
#include "mixer/Volume.hxx"
#include "mixer/Volume.hxx"
#include "Partition.hxx"
#include "Partition.hxx"
#include "Instance.hxx"
#include "Instance.hxx"
#include "protocol/Result.hxx"
#include "AudioFormat.hxx"
#include "AudioFormat.hxx"
#include "ReplayGainConfig.hxx"
#include "ReplayGainConfig.hxx"
#include "util/ConstBuffer.hxx"
#include "util/ConstBuffer.hxx"
...
@@ -59,23 +59,27 @@
...
@@ -59,23 +59,27 @@
CommandResult
CommandResult
handle_play
(
Client
&
client
,
Request
args
)
handle_play
(
Client
&
client
,
Request
args
)
{
{
Response
r
(
client
);
int
song
=
-
1
;
int
song
=
-
1
;
if
(
!
args
.
ParseOptional
(
0
,
song
,
client
))
if
(
!
args
.
ParseOptional
(
0
,
song
,
r
))
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
PlaylistResult
result
=
client
.
partition
.
PlayPosition
(
song
);
PlaylistResult
result
=
client
.
partition
.
PlayPosition
(
song
);
return
print_playlist_result
(
client
,
result
);
return
print_playlist_result
(
r
,
result
);
}
}
CommandResult
CommandResult
handle_playid
(
Client
&
client
,
Request
args
)
handle_playid
(
Client
&
client
,
Request
args
)
{
{
Response
r
(
client
);
int
id
=
-
1
;
int
id
=
-
1
;
if
(
!
args
.
ParseOptional
(
0
,
id
,
client
))
if
(
!
args
.
ParseOptional
(
0
,
id
,
r
))
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
PlaylistResult
result
=
client
.
partition
.
PlayId
(
id
);
PlaylistResult
result
=
client
.
partition
.
PlayId
(
id
);
return
print_playlist_result
(
client
,
result
);
return
print_playlist_result
(
r
,
result
);
}
}
CommandResult
CommandResult
...
@@ -88,16 +92,19 @@ handle_stop(Client &client, gcc_unused Request args)
...
@@ -88,16 +92,19 @@ handle_stop(Client &client, gcc_unused Request args)
CommandResult
CommandResult
handle_currentsong
(
Client
&
client
,
gcc_unused
Request
args
)
handle_currentsong
(
Client
&
client
,
gcc_unused
Request
args
)
{
{
playlist_print_current
(
client
,
client
.
playlist
);
Response
r
(
client
);
playlist_print_current
(
r
,
client
.
partition
,
client
.
playlist
);
return
CommandResult
::
OK
;
return
CommandResult
::
OK
;
}
}
CommandResult
CommandResult
handle_pause
(
Client
&
client
,
Request
args
)
handle_pause
(
Client
&
client
,
Request
args
)
{
{
Response
r
(
client
);
if
(
!
args
.
IsEmpty
())
{
if
(
!
args
.
IsEmpty
())
{
bool
pause_flag
;
bool
pause_flag
;
if
(
!
args
.
Parse
(
0
,
pause_flag
,
client
))
if
(
!
args
.
Parse
(
0
,
pause_flag
,
r
))
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
client
.
player_control
.
SetPause
(
pause_flag
);
client
.
player_control
.
SetPause
(
pause_flag
);
...
@@ -127,68 +134,64 @@ handle_status(Client &client, gcc_unused Request args)
...
@@ -127,68 +134,64 @@ handle_status(Client &client, gcc_unused Request args)
break
;
break
;
}
}
Response
r
(
client
);
const
playlist
&
playlist
=
client
.
playlist
;
const
playlist
&
playlist
=
client
.
playlist
;
client_printf
(
client
,
r
.
Format
(
"volume: %i
\n
"
"volume: %i
\n
"
COMMAND_STATUS_REPEAT
": %i
\n
"
COMMAND_STATUS_REPEAT
": %i
\n
"
COMMAND_STATUS_RANDOM
": %i
\n
"
COMMAND_STATUS_RANDOM
": %i
\n
"
COMMAND_STATUS_SINGLE
": %i
\n
"
COMMAND_STATUS_SINGLE
": %i
\n
"
COMMAND_STATUS_CONSUME
": %i
\n
"
COMMAND_STATUS_CONSUME
": %i
\n
"
COMMAND_STATUS_PLAYLIST
": %li
\n
"
COMMAND_STATUS_PLAYLIST
": %li
\n
"
COMMAND_STATUS_PLAYLIST_LENGTH
": %i
\n
"
COMMAND_STATUS_PLAYLIST_LENGTH
": %i
\n
"
COMMAND_STATUS_MIXRAMPDB
": %f
\n
"
COMMAND_STATUS_MIXRAMPDB
": %f
\n
"
COMMAND_STATUS_STATE
": %s
\n
"
,
COMMAND_STATUS_STATE
": %s
\n
"
,
volume_level_get
(
client
.
partition
.
outputs
),
volume_level_get
(
client
.
partition
.
outputs
),
playlist
.
GetRepeat
(),
playlist
.
GetRepeat
(),
playlist
.
GetRandom
(),
playlist
.
GetRandom
(),
playlist
.
GetSingle
(),
playlist
.
GetSingle
(),
playlist
.
GetConsume
(),
playlist
.
GetConsume
(),
(
unsigned
long
)
playlist
.
GetVersion
(),
(
unsigned
long
)
playlist
.
GetVersion
(),
playlist
.
GetLength
(),
playlist
.
GetLength
(),
client
.
player_control
.
GetMixRampDb
(),
client
.
player_control
.
GetMixRampDb
(),
state
);
state
);
if
(
client
.
player_control
.
GetCrossFade
()
>
0
)
if
(
client
.
player_control
.
GetCrossFade
()
>
0
)
client_printf
(
client
,
r
.
Format
(
COMMAND_STATUS_CROSSFADE
": %i
\n
"
,
COMMAND_STATUS_CROSSFADE
": %i
\n
"
,
int
(
client
.
player_control
.
GetCrossFade
()
+
0.5
));
int
(
client
.
player_control
.
GetCrossFade
()
+
0.5
));
if
(
client
.
player_control
.
GetMixRampDelay
()
>
0
)
if
(
client
.
player_control
.
GetMixRampDelay
()
>
0
)
client_printf
(
client
,
r
.
Format
(
COMMAND_STATUS_MIXRAMPDELAY
": %f
\n
"
,
COMMAND_STATUS_MIXRAMPDELAY
": %f
\n
"
,
client
.
player_control
.
GetMixRampDelay
());
client
.
player_control
.
GetMixRampDelay
());
song
=
playlist
.
GetCurrentPosition
();
song
=
playlist
.
GetCurrentPosition
();
if
(
song
>=
0
)
{
if
(
song
>=
0
)
{
client_printf
(
client
,
r
.
Format
(
COMMAND_STATUS_SONG
": %i
\n
"
COMMAND_STATUS_SONG
": %i
\n
"
COMMAND_STATUS_SONGID
": %u
\n
"
,
COMMAND_STATUS_SONGID
": %u
\n
"
,
song
,
playlist
.
PositionToId
(
song
));
song
,
playlist
.
PositionToId
(
song
));
}
}
if
(
player_status
.
state
!=
PlayerState
::
STOP
)
{
if
(
player_status
.
state
!=
PlayerState
::
STOP
)
{
client_printf
(
client
,
r
.
Format
(
COMMAND_STATUS_TIME
": %i:%i
\n
"
COMMAND_STATUS_TIME
": %i:%i
\n
"
"elapsed: %1.3f
\n
"
"elapsed: %1.3f
\n
"
COMMAND_STATUS_BITRATE
": %u
\n
"
,
COMMAND_STATUS_BITRATE
": %u
\n
"
,
player_status
.
elapsed_time
.
RoundS
(),
player_status
.
elapsed_time
.
RoundS
(),
player_status
.
total_time
.
IsNegative
()
player_status
.
total_time
.
IsNegative
()
?
0u
?
0u
:
unsigned
(
player_status
.
total_time
.
RoundS
()),
:
unsigned
(
player_status
.
total_time
.
RoundS
()),
player_status
.
elapsed_time
.
ToDoubleS
(),
player_status
.
elapsed_time
.
ToDoubleS
(),
player_status
.
bit_rate
);
player_status
.
bit_rate
);
if
(
!
player_status
.
total_time
.
IsNegative
())
if
(
!
player_status
.
total_time
.
IsNegative
())
client_printf
(
client
,
"duration: %1.3f
\n
"
,
r
.
Format
(
"duration: %1.3f
\n
"
,
player_status
.
total_time
.
ToDoubleS
());
player_status
.
total_time
.
ToDoubleS
());
if
(
player_status
.
audio_format
.
IsDefined
())
{
if
(
player_status
.
audio_format
.
IsDefined
())
{
struct
audio_format_string
af_string
;
struct
audio_format_string
af_string
;
client_printf
(
client
,
r
.
Format
(
COMMAND_STATUS_AUDIO
": %s
\n
"
,
COMMAND_STATUS_AUDIO
": %s
\n
"
,
audio_format_to_string
(
player_status
.
audio_format
,
audio_format_to_string
(
player_status
.
audio_format
,
&
af_string
));
&
af_string
));
}
}
}
}
...
@@ -198,25 +201,21 @@ handle_status(Client &client, gcc_unused Request args)
...
@@ -198,25 +201,21 @@ handle_status(Client &client, gcc_unused Request args)
?
update_service
->
GetId
()
?
update_service
->
GetId
()
:
0
;
:
0
;
if
(
updateJobId
!=
0
)
{
if
(
updateJobId
!=
0
)
{
client_printf
(
client
,
r
.
Format
(
COMMAND_STATUS_UPDATING_DB
": %i
\n
"
,
COMMAND_STATUS_UPDATING_DB
": %i
\n
"
,
updateJobId
);
updateJobId
);
}
}
#endif
#endif
Error
error
=
client
.
player_control
.
LockGetError
();
Error
error
=
client
.
player_control
.
LockGetError
();
if
(
error
.
IsDefined
())
if
(
error
.
IsDefined
())
client_printf
(
client
,
r
.
Format
(
COMMAND_STATUS_ERROR
": %s
\n
"
,
COMMAND_STATUS_ERROR
": %s
\n
"
,
error
.
GetMessage
());
error
.
GetMessage
());
song
=
playlist
.
GetNextPosition
();
song
=
playlist
.
GetNextPosition
();
if
(
song
>=
0
)
{
if
(
song
>=
0
)
client_printf
(
client
,
r
.
Format
(
COMMAND_STATUS_NEXTSONG
": %i
\n
"
COMMAND_STATUS_NEXTSONG
": %i
\n
"
COMMAND_STATUS_NEXTSONGID
": %u
\n
"
,
COMMAND_STATUS_NEXTSONGID
": %u
\n
"
,
song
,
playlist
.
PositionToId
(
song
));
song
,
playlist
.
PositionToId
(
song
));
}
return
CommandResult
::
OK
;
return
CommandResult
::
OK
;
}
}
...
@@ -247,8 +246,10 @@ handle_previous(Client &client, gcc_unused Request args)
...
@@ -247,8 +246,10 @@ handle_previous(Client &client, gcc_unused Request args)
CommandResult
CommandResult
handle_repeat
(
Client
&
client
,
Request
args
)
handle_repeat
(
Client
&
client
,
Request
args
)
{
{
Response
r
(
client
);
bool
status
;
bool
status
;
if
(
!
args
.
Parse
(
0
,
status
,
client
))
if
(
!
args
.
Parse
(
0
,
status
,
r
))
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
client
.
partition
.
SetRepeat
(
status
);
client
.
partition
.
SetRepeat
(
status
);
...
@@ -258,8 +259,10 @@ handle_repeat(Client &client, Request args)
...
@@ -258,8 +259,10 @@ handle_repeat(Client &client, Request args)
CommandResult
CommandResult
handle_single
(
Client
&
client
,
Request
args
)
handle_single
(
Client
&
client
,
Request
args
)
{
{
Response
r
(
client
);
bool
status
;
bool
status
;
if
(
!
args
.
Parse
(
0
,
status
,
client
))
if
(
!
args
.
Parse
(
0
,
status
,
r
))
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
client
.
partition
.
SetSingle
(
status
);
client
.
partition
.
SetSingle
(
status
);
...
@@ -269,8 +272,10 @@ handle_single(Client &client, Request args)
...
@@ -269,8 +272,10 @@ handle_single(Client &client, Request args)
CommandResult
CommandResult
handle_consume
(
Client
&
client
,
Request
args
)
handle_consume
(
Client
&
client
,
Request
args
)
{
{
Response
r
(
client
);
bool
status
;
bool
status
;
if
(
!
args
.
Parse
(
0
,
status
,
client
))
if
(
!
args
.
Parse
(
0
,
status
,
r
))
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
client
.
partition
.
SetConsume
(
status
);
client
.
partition
.
SetConsume
(
status
);
...
@@ -280,8 +285,10 @@ handle_consume(Client &client, Request args)
...
@@ -280,8 +285,10 @@ handle_consume(Client &client, Request args)
CommandResult
CommandResult
handle_random
(
Client
&
client
,
Request
args
)
handle_random
(
Client
&
client
,
Request
args
)
{
{
Response
r
(
client
);
bool
status
;
bool
status
;
if
(
!
args
.
Parse
(
0
,
status
,
client
))
if
(
!
args
.
Parse
(
0
,
status
,
r
))
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
client
.
partition
.
SetRandom
(
status
);
client
.
partition
.
SetRandom
(
status
);
...
@@ -299,53 +306,58 @@ handle_clearerror(gcc_unused Client &client, gcc_unused Request args)
...
@@ -299,53 +306,58 @@ handle_clearerror(gcc_unused Client &client, gcc_unused Request args)
CommandResult
CommandResult
handle_seek
(
Client
&
client
,
Request
args
)
handle_seek
(
Client
&
client
,
Request
args
)
{
{
Response
r
(
client
);
unsigned
song
;
unsigned
song
;
SongTime
seek_time
;
SongTime
seek_time
;
if
(
!
args
.
Parse
(
0
,
song
,
r
)
||
!
args
.
Parse
(
1
,
seek_time
,
r
))
if
(
!
args
.
Parse
(
0
,
song
,
client
))
return
CommandResult
::
ERROR
;
if
(
!
args
.
Parse
(
1
,
seek_time
,
client
))
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
PlaylistResult
result
=
PlaylistResult
result
=
client
.
partition
.
SeekSongPosition
(
song
,
seek_time
);
client
.
partition
.
SeekSongPosition
(
song
,
seek_time
);
return
print_playlist_result
(
client
,
result
);
return
print_playlist_result
(
r
,
result
);
}
}
CommandResult
CommandResult
handle_seekid
(
Client
&
client
,
Request
args
)
handle_seekid
(
Client
&
client
,
Request
args
)
{
{
Response
r
(
client
);
unsigned
id
;
unsigned
id
;
SongTime
seek_time
;
SongTime
seek_time
;
if
(
!
args
.
Parse
(
0
,
id
,
client
))
if
(
!
args
.
Parse
(
0
,
id
,
r
))
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
if
(
!
args
.
Parse
(
1
,
seek_time
,
client
))
if
(
!
args
.
Parse
(
1
,
seek_time
,
r
))
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
PlaylistResult
result
=
PlaylistResult
result
=
client
.
partition
.
SeekSongId
(
id
,
seek_time
);
client
.
partition
.
SeekSongId
(
id
,
seek_time
);
return
print_playlist_result
(
client
,
result
);
return
print_playlist_result
(
r
,
result
);
}
}
CommandResult
CommandResult
handle_seekcur
(
Client
&
client
,
Request
args
)
handle_seekcur
(
Client
&
client
,
Request
args
)
{
{
Response
r
(
client
);
const
char
*
p
=
args
.
front
();
const
char
*
p
=
args
.
front
();
bool
relative
=
*
p
==
'+'
||
*
p
==
'-'
;
bool
relative
=
*
p
==
'+'
||
*
p
==
'-'
;
SignedSongTime
seek_time
;
SignedSongTime
seek_time
;
if
(
!
ParseCommandArg
(
client
,
seek_time
,
p
))
if
(
!
ParseCommandArg
(
r
,
seek_time
,
p
))
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
PlaylistResult
result
=
PlaylistResult
result
=
client
.
partition
.
SeekCurrent
(
seek_time
,
relative
);
client
.
partition
.
SeekCurrent
(
seek_time
,
relative
);
return
print_playlist_result
(
client
,
result
);
return
print_playlist_result
(
r
,
result
);
}
}
CommandResult
CommandResult
handle_crossfade
(
Client
&
client
,
Request
args
)
handle_crossfade
(
Client
&
client
,
Request
args
)
{
{
Response
r
(
client
);
unsigned
xfade_time
;
unsigned
xfade_time
;
if
(
!
args
.
Parse
(
0
,
xfade_time
,
client
))
if
(
!
args
.
Parse
(
0
,
xfade_time
,
r
))
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
client
.
player_control
.
SetCrossFade
(
xfade_time
);
client
.
player_control
.
SetCrossFade
(
xfade_time
);
...
@@ -355,8 +367,10 @@ handle_crossfade(Client &client, Request args)
...
@@ -355,8 +367,10 @@ handle_crossfade(Client &client, Request args)
CommandResult
CommandResult
handle_mixrampdb
(
Client
&
client
,
Request
args
)
handle_mixrampdb
(
Client
&
client
,
Request
args
)
{
{
Response
r
(
client
);
float
db
;
float
db
;
if
(
!
args
.
Parse
(
0
,
db
,
client
))
if
(
!
args
.
Parse
(
0
,
db
,
r
))
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
client
.
player_control
.
SetMixRampDb
(
db
);
client
.
player_control
.
SetMixRampDb
(
db
);
...
@@ -366,8 +380,10 @@ handle_mixrampdb(Client &client, Request args)
...
@@ -366,8 +380,10 @@ handle_mixrampdb(Client &client, Request args)
CommandResult
CommandResult
handle_mixrampdelay
(
Client
&
client
,
Request
args
)
handle_mixrampdelay
(
Client
&
client
,
Request
args
)
{
{
Response
r
(
client
);
float
delay_secs
;
float
delay_secs
;
if
(
!
args
.
Parse
(
0
,
delay_secs
,
client
))
if
(
!
args
.
Parse
(
0
,
delay_secs
,
r
))
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
client
.
player_control
.
SetMixRampDelay
(
delay_secs
);
client
.
player_control
.
SetMixRampDelay
(
delay_secs
);
...
@@ -378,9 +394,10 @@ handle_mixrampdelay(Client &client, Request args)
...
@@ -378,9 +394,10 @@ handle_mixrampdelay(Client &client, Request args)
CommandResult
CommandResult
handle_replay_gain_mode
(
Client
&
client
,
Request
args
)
handle_replay_gain_mode
(
Client
&
client
,
Request
args
)
{
{
Response
r
(
client
);
if
(
!
replay_gain_set_mode_string
(
args
.
front
()))
{
if
(
!
replay_gain_set_mode_string
(
args
.
front
()))
{
command_error
(
client
,
ACK_ERROR_ARG
,
r
.
Error
(
ACK_ERROR_ARG
,
"Unrecognized replay gain mode"
);
"Unrecognized replay gain mode"
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
}
}
...
@@ -391,7 +408,7 @@ handle_replay_gain_mode(Client &client, Request args)
...
@@ -391,7 +408,7 @@ handle_replay_gain_mode(Client &client, Request args)
CommandResult
CommandResult
handle_replay_gain_status
(
Client
&
client
,
gcc_unused
Request
args
)
handle_replay_gain_status
(
Client
&
client
,
gcc_unused
Request
args
)
{
{
client_printf
(
client
,
"replay_gain_mode: %s
\n
"
,
Response
r
(
client
);
replay_gain_get_mode_string
());
r
.
Format
(
"replay_gain_mode: %s
\n
"
,
replay_gain_get_mode_string
());
return
CommandResult
::
OK
;
return
CommandResult
::
OK
;
}
}
src/command/PlaylistCommands.cxx
View file @
7652a298
...
@@ -33,7 +33,7 @@
...
@@ -33,7 +33,7 @@
#include "queue/Playlist.hxx"
#include "queue/Playlist.hxx"
#include "TimePrint.hxx"
#include "TimePrint.hxx"
#include "client/Client.hxx"
#include "client/Client.hxx"
#include "
protocol/Result
.hxx"
#include "
client/Response
.hxx"
#include "ls.hxx"
#include "ls.hxx"
#include "Mapper.hxx"
#include "Mapper.hxx"
#include "fs/AllocatedPath.hxx"
#include "fs/AllocatedPath.hxx"
...
@@ -48,30 +48,33 @@ playlist_commands_available()
...
@@ -48,30 +48,33 @@ playlist_commands_available()
}
}
static
void
static
void
print_spl_list
(
Client
&
client
,
const
PlaylistVector
&
list
)
print_spl_list
(
Response
&
r
,
const
PlaylistVector
&
list
)
{
{
for
(
const
auto
&
i
:
list
)
{
for
(
const
auto
&
i
:
list
)
{
client_printf
(
client
,
"playlist: %s
\n
"
,
i
.
name
.
c_str
());
r
.
Format
(
"playlist: %s
\n
"
,
i
.
name
.
c_str
());
if
(
i
.
mtime
>
0
)
if
(
i
.
mtime
>
0
)
time_print
(
client
,
"Last-Modified"
,
i
.
mtime
);
time_print
(
r
,
"Last-Modified"
,
i
.
mtime
);
}
}
}
}
CommandResult
CommandResult
handle_save
(
Client
&
client
,
Request
args
)
handle_save
(
Client
&
client
,
Request
args
)
{
{
Response
r
(
client
);
Error
error
;
Error
error
;
return
spl_save_playlist
(
args
.
front
(),
client
.
playlist
,
error
)
return
spl_save_playlist
(
args
.
front
(),
client
.
playlist
,
error
)
?
CommandResult
::
OK
?
CommandResult
::
OK
:
print_error
(
client
,
error
);
:
print_error
(
r
,
error
);
}
}
CommandResult
CommandResult
handle_load
(
Client
&
client
,
Request
args
)
handle_load
(
Client
&
client
,
Request
args
)
{
{
Response
r
(
client
);
RangeArg
range
=
RangeArg
::
All
();
RangeArg
range
=
RangeArg
::
All
();
if
(
!
args
.
ParseOptional
(
1
,
range
,
client
))
if
(
!
args
.
ParseOptional
(
1
,
range
,
r
))
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
const
ScopeBulkEdit
bulk_edit
(
client
.
partition
);
const
ScopeBulkEdit
bulk_edit
(
client
.
partition
);
...
@@ -82,7 +85,7 @@ handle_load(Client &client, Request args)
...
@@ -82,7 +85,7 @@ handle_load(Client &client, Request args)
range
.
start
,
range
.
end
,
range
.
start
,
range
.
end
,
client
.
playlist
,
client
.
playlist
,
client
.
player_control
,
loader
,
error
))
client
.
player_control
,
loader
,
error
))
return
print_error
(
client
,
error
);
return
print_error
(
r
,
error
);
return
CommandResult
::
OK
;
return
CommandResult
::
OK
;
}
}
...
@@ -90,97 +93,114 @@ handle_load(Client &client, Request args)
...
@@ -90,97 +93,114 @@ handle_load(Client &client, Request args)
CommandResult
CommandResult
handle_listplaylist
(
Client
&
client
,
Request
args
)
handle_listplaylist
(
Client
&
client
,
Request
args
)
{
{
Response
r
(
client
);
const
char
*
const
name
=
args
.
front
();
const
char
*
const
name
=
args
.
front
();
if
(
playlist_file_print
(
client
,
name
,
false
))
if
(
playlist_file_print
(
r
,
client
.
partition
,
SongLoader
(
client
),
name
,
false
))
return
CommandResult
::
OK
;
return
CommandResult
::
OK
;
Error
error
;
Error
error
;
return
spl_print
(
client
,
name
,
false
,
error
)
return
spl_print
(
r
,
client
.
partition
,
name
,
false
,
error
)
?
CommandResult
::
OK
?
CommandResult
::
OK
:
print_error
(
client
,
error
);
:
print_error
(
r
,
error
);
}
}
CommandResult
CommandResult
handle_listplaylistinfo
(
Client
&
client
,
Request
args
)
handle_listplaylistinfo
(
Client
&
client
,
Request
args
)
{
{
Response
r
(
client
);
const
char
*
const
name
=
args
.
front
();
const
char
*
const
name
=
args
.
front
();
if
(
playlist_file_print
(
client
,
name
,
true
))
if
(
playlist_file_print
(
r
,
client
.
partition
,
SongLoader
(
client
),
name
,
true
))
return
CommandResult
::
OK
;
return
CommandResult
::
OK
;
Error
error
;
Error
error
;
return
spl_print
(
client
,
name
,
true
,
error
)
return
spl_print
(
r
,
client
.
partition
,
name
,
true
,
error
)
?
CommandResult
::
OK
?
CommandResult
::
OK
:
print_error
(
client
,
error
);
:
print_error
(
r
,
error
);
}
}
CommandResult
CommandResult
handle_rm
(
Client
&
client
,
Request
args
)
handle_rm
(
Client
&
client
,
Request
args
)
{
{
Response
r
(
client
);
const
char
*
const
name
=
args
.
front
();
const
char
*
const
name
=
args
.
front
();
Error
error
;
Error
error
;
return
spl_delete
(
name
,
error
)
return
spl_delete
(
name
,
error
)
?
CommandResult
::
OK
?
CommandResult
::
OK
:
print_error
(
client
,
error
);
:
print_error
(
r
,
error
);
}
}
CommandResult
CommandResult
handle_rename
(
Client
&
client
,
Request
args
)
handle_rename
(
Client
&
client
,
Request
args
)
{
{
Response
r
(
client
);
const
char
*
const
old_name
=
args
[
0
];
const
char
*
const
old_name
=
args
[
0
];
const
char
*
const
new_name
=
args
[
1
];
const
char
*
const
new_name
=
args
[
1
];
Error
error
;
Error
error
;
return
spl_rename
(
old_name
,
new_name
,
error
)
return
spl_rename
(
old_name
,
new_name
,
error
)
?
CommandResult
::
OK
?
CommandResult
::
OK
:
print_error
(
client
,
error
);
:
print_error
(
r
,
error
);
}
}
CommandResult
CommandResult
handle_playlistdelete
(
Client
&
client
,
Request
args
)
handle_playlistdelete
(
Client
&
client
,
Request
args
)
{
{
Response
r
(
client
);
const
char
*
const
name
=
args
[
0
];
const
char
*
const
name
=
args
[
0
];
unsigned
from
;
unsigned
from
;
if
(
!
args
.
Parse
(
1
,
from
,
client
))
if
(
!
args
.
Parse
(
1
,
from
,
r
))
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
Error
error
;
Error
error
;
return
spl_remove_index
(
name
,
from
,
error
)
return
spl_remove_index
(
name
,
from
,
error
)
?
CommandResult
::
OK
?
CommandResult
::
OK
:
print_error
(
client
,
error
);
:
print_error
(
r
,
error
);
}
}
CommandResult
CommandResult
handle_playlistmove
(
Client
&
client
,
Request
args
)
handle_playlistmove
(
Client
&
client
,
Request
args
)
{
{
Response
r
(
client
);
const
char
*
const
name
=
args
.
front
();
const
char
*
const
name
=
args
.
front
();
unsigned
from
,
to
;
unsigned
from
,
to
;
if
(
!
args
.
Parse
(
1
,
from
,
client
)
||
if
(
!
args
.
Parse
(
1
,
from
,
r
)
||
!
args
.
Parse
(
2
,
to
,
r
))
!
args
.
Parse
(
2
,
to
,
client
))
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
Error
error
;
Error
error
;
return
spl_move_index
(
name
,
from
,
to
,
error
)
return
spl_move_index
(
name
,
from
,
to
,
error
)
?
CommandResult
::
OK
?
CommandResult
::
OK
:
print_error
(
client
,
error
);
:
print_error
(
r
,
error
);
}
}
CommandResult
CommandResult
handle_playlistclear
(
Client
&
client
,
Request
args
)
handle_playlistclear
(
Client
&
client
,
Request
args
)
{
{
Response
r
(
client
);
const
char
*
const
name
=
args
.
front
();
const
char
*
const
name
=
args
.
front
();
Error
error
;
Error
error
;
return
spl_clear
(
name
,
error
)
return
spl_clear
(
name
,
error
)
?
CommandResult
::
OK
?
CommandResult
::
OK
:
print_error
(
client
,
error
);
:
print_error
(
r
,
error
);
}
}
CommandResult
CommandResult
handle_playlistadd
(
Client
&
client
,
Request
args
)
handle_playlistadd
(
Client
&
client
,
Request
args
)
{
{
Response
r
(
client
);
const
char
*
const
playlist
=
args
[
0
];
const
char
*
const
playlist
=
args
[
0
];
const
char
*
const
uri
=
args
[
1
];
const
char
*
const
uri
=
args
[
1
];
...
@@ -193,7 +213,7 @@ handle_playlistadd(Client &client, Request args)
...
@@ -193,7 +213,7 @@ handle_playlistadd(Client &client, Request args)
#ifdef ENABLE_DATABASE
#ifdef ENABLE_DATABASE
const
Database
*
db
=
client
.
GetDatabase
(
error
);
const
Database
*
db
=
client
.
GetDatabase
(
error
);
if
(
db
==
nullptr
)
if
(
db
==
nullptr
)
return
print_error
(
client
,
error
);
return
print_error
(
r
,
error
);
success
=
search_add_to_playlist
(
*
db
,
*
client
.
GetStorage
(),
success
=
search_add_to_playlist
(
*
db
,
*
client
.
GetStorage
(),
uri
,
playlist
,
nullptr
,
uri
,
playlist
,
nullptr
,
...
@@ -204,22 +224,23 @@ handle_playlistadd(Client &client, Request args)
...
@@ -204,22 +224,23 @@ handle_playlistadd(Client &client, Request args)
}
}
if
(
!
success
&&
!
error
.
IsDefined
())
{
if
(
!
success
&&
!
error
.
IsDefined
())
{
command_error
(
client
,
ACK_ERROR_NO_EXIST
,
r
.
Error
(
ACK_ERROR_NO_EXIST
,
"directory or file not found"
);
"directory or file not found"
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
}
}
return
success
?
CommandResult
::
OK
:
print_error
(
client
,
error
);
return
success
?
CommandResult
::
OK
:
print_error
(
r
,
error
);
}
}
CommandResult
CommandResult
handle_listplaylists
(
Client
&
client
,
gcc_unused
Request
args
)
handle_listplaylists
(
Client
&
client
,
gcc_unused
Request
args
)
{
{
Response
r
(
client
);
Error
error
;
Error
error
;
const
auto
list
=
ListPlaylistFiles
(
error
);
const
auto
list
=
ListPlaylistFiles
(
error
);
if
(
list
.
empty
()
&&
error
.
IsDefined
())
if
(
list
.
empty
()
&&
error
.
IsDefined
())
return
print_error
(
client
,
error
);
return
print_error
(
r
,
error
);
print_spl_list
(
client
,
list
);
print_spl_list
(
r
,
list
);
return
CommandResult
::
OK
;
return
CommandResult
::
OK
;
}
}
src/command/QueueCommands.cxx
View file @
7652a298
...
@@ -28,9 +28,9 @@
...
@@ -28,9 +28,9 @@
#include "queue/Playlist.hxx"
#include "queue/Playlist.hxx"
#include "PlaylistPrint.hxx"
#include "PlaylistPrint.hxx"
#include "client/Client.hxx"
#include "client/Client.hxx"
#include "client/Response.hxx"
#include "Partition.hxx"
#include "Partition.hxx"
#include "BulkEdit.hxx"
#include "BulkEdit.hxx"
#include "protocol/Result.hxx"
#include "ls.hxx"
#include "ls.hxx"
#include "util/ConstBuffer.hxx"
#include "util/ConstBuffer.hxx"
#include "util/UriUtil.hxx"
#include "util/UriUtil.hxx"
...
@@ -56,6 +56,8 @@ translate_uri(const char *uri)
...
@@ -56,6 +56,8 @@ translate_uri(const char *uri)
CommandResult
CommandResult
handle_add
(
Client
&
client
,
Request
args
)
handle_add
(
Client
&
client
,
Request
args
)
{
{
Response
r
(
client
);
const
char
*
uri
=
args
.
front
();
const
char
*
uri
=
args
.
front
();
if
(
memcmp
(
uri
,
"/"
,
2
)
==
0
)
if
(
memcmp
(
uri
,
"/"
,
2
)
==
0
)
/* this URI is malformed, but some clients are buggy
/* this URI is malformed, but some clients are buggy
...
@@ -72,7 +74,7 @@ handle_add(Client &client, Request args)
...
@@ -72,7 +74,7 @@ handle_add(Client &client, Request args)
Error
error
;
Error
error
;
unsigned
id
=
client
.
partition
.
AppendURI
(
loader
,
uri
,
error
);
unsigned
id
=
client
.
partition
.
AppendURI
(
loader
,
uri
,
error
);
if
(
id
==
0
)
if
(
id
==
0
)
return
print_error
(
client
,
error
);
return
print_error
(
r
,
error
);
return
CommandResult
::
OK
;
return
CommandResult
::
OK
;
}
}
...
@@ -84,9 +86,9 @@ handle_add(Client &client, Request args)
...
@@ -84,9 +86,9 @@ handle_add(Client &client, Request args)
Error
error
;
Error
error
;
return
AddFromDatabase
(
client
.
partition
,
selection
,
error
)
return
AddFromDatabase
(
client
.
partition
,
selection
,
error
)
?
CommandResult
::
OK
?
CommandResult
::
OK
:
print_error
(
client
,
error
);
:
print_error
(
r
,
error
);
#else
#else
command_error
(
client
,
ACK_ERROR_NO_EXIST
,
"No database"
);
r
.
Error
(
ACK_ERROR_NO_EXIST
,
"No database"
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
#endif
#endif
}
}
...
@@ -94,29 +96,31 @@ handle_add(Client &client, Request args)
...
@@ -94,29 +96,31 @@ handle_add(Client &client, Request args)
CommandResult
CommandResult
handle_addid
(
Client
&
client
,
Request
args
)
handle_addid
(
Client
&
client
,
Request
args
)
{
{
Response
r
(
client
);
const
char
*
const
uri
=
translate_uri
(
args
.
front
());
const
char
*
const
uri
=
translate_uri
(
args
.
front
());
const
SongLoader
loader
(
client
);
const
SongLoader
loader
(
client
);
Error
error
;
Error
error
;
unsigned
added_id
=
client
.
partition
.
AppendURI
(
loader
,
uri
,
error
);
unsigned
added_id
=
client
.
partition
.
AppendURI
(
loader
,
uri
,
error
);
if
(
added_id
==
0
)
if
(
added_id
==
0
)
return
print_error
(
client
,
error
);
return
print_error
(
r
,
error
);
if
(
args
.
size
==
2
)
{
if
(
args
.
size
==
2
)
{
unsigned
to
;
unsigned
to
;
if
(
!
args
.
Parse
(
1
,
to
,
client
))
if
(
!
args
.
Parse
(
1
,
to
,
r
))
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
PlaylistResult
result
=
client
.
partition
.
MoveId
(
added_id
,
to
);
PlaylistResult
result
=
client
.
partition
.
MoveId
(
added_id
,
to
);
if
(
result
!=
PlaylistResult
::
SUCCESS
)
{
if
(
result
!=
PlaylistResult
::
SUCCESS
)
{
CommandResult
ret
=
CommandResult
ret
=
print_playlist_result
(
client
,
result
);
print_playlist_result
(
r
,
result
);
client
.
partition
.
DeleteId
(
added_id
);
client
.
partition
.
DeleteId
(
added_id
);
return
ret
;
return
ret
;
}
}
}
}
client_printf
(
client
,
"Id: %u
\n
"
,
added_id
);
r
.
Format
(
"Id: %u
\n
"
,
added_id
);
return
CommandResult
::
OK
;
return
CommandResult
::
OK
;
}
}
...
@@ -154,13 +158,15 @@ parse_time_range(const char *p, SongTime &start_r, SongTime &end_r)
...
@@ -154,13 +158,15 @@ parse_time_range(const char *p, SongTime &start_r, SongTime &end_r)
CommandResult
CommandResult
handle_rangeid
(
Client
&
client
,
Request
args
)
handle_rangeid
(
Client
&
client
,
Request
args
)
{
{
Response
r
(
client
);
unsigned
id
;
unsigned
id
;
if
(
!
args
.
Parse
(
0
,
id
,
client
))
if
(
!
args
.
Parse
(
0
,
id
,
r
))
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
SongTime
start
,
end
;
SongTime
start
,
end
;
if
(
!
parse_time_range
(
args
[
1
],
start
,
end
))
{
if
(
!
parse_time_range
(
args
[
1
],
start
,
end
))
{
command_error
(
client
,
ACK_ERROR_ARG
,
"Bad range"
);
r
.
Error
(
ACK_ERROR_ARG
,
"Bad range"
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
}
}
...
@@ -168,7 +174,7 @@ handle_rangeid(Client &client, Request args)
...
@@ -168,7 +174,7 @@ handle_rangeid(Client &client, Request args)
if
(
!
client
.
partition
.
playlist
.
SetSongIdRange
(
client
.
partition
.
pc
,
if
(
!
client
.
partition
.
playlist
.
SetSongIdRange
(
client
.
partition
.
pc
,
id
,
start
,
end
,
id
,
start
,
end
,
error
))
error
))
return
print_error
(
client
,
error
);
return
print_error
(
r
,
error
);
return
CommandResult
::
OK
;
return
CommandResult
::
OK
;
}
}
...
@@ -176,37 +182,44 @@ handle_rangeid(Client &client, Request args)
...
@@ -176,37 +182,44 @@ handle_rangeid(Client &client, Request args)
CommandResult
CommandResult
handle_delete
(
Client
&
client
,
Request
args
)
handle_delete
(
Client
&
client
,
Request
args
)
{
{
Response
r
(
client
);
RangeArg
range
;
RangeArg
range
;
if
(
!
args
.
Parse
(
0
,
range
,
client
))
if
(
!
args
.
Parse
(
0
,
range
,
r
))
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
auto
result
=
client
.
partition
.
DeleteRange
(
range
.
start
,
range
.
end
);
auto
result
=
client
.
partition
.
DeleteRange
(
range
.
start
,
range
.
end
);
return
print_playlist_result
(
client
,
result
);
return
print_playlist_result
(
r
,
result
);
}
}
CommandResult
CommandResult
handle_deleteid
(
Client
&
client
,
Request
args
)
handle_deleteid
(
Client
&
client
,
Request
args
)
{
{
Response
r
(
client
);
unsigned
id
;
unsigned
id
;
if
(
!
args
.
Parse
(
0
,
id
,
client
))
if
(
!
args
.
Parse
(
0
,
id
,
r
))
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
PlaylistResult
result
=
client
.
partition
.
DeleteId
(
id
);
PlaylistResult
result
=
client
.
partition
.
DeleteId
(
id
);
return
print_playlist_result
(
client
,
result
);
return
print_playlist_result
(
r
,
result
);
}
}
CommandResult
CommandResult
handle_playlist
(
Client
&
client
,
gcc_unused
Request
args
)
handle_playlist
(
Client
&
client
,
gcc_unused
Request
args
)
{
{
playlist_print_uris
(
client
,
client
.
playlist
);
Response
r
(
client
);
playlist_print_uris
(
r
,
client
.
partition
,
client
.
playlist
);
return
CommandResult
::
OK
;
return
CommandResult
::
OK
;
}
}
CommandResult
CommandResult
handle_shuffle
(
gcc_unused
Client
&
client
,
Request
args
)
handle_shuffle
(
gcc_unused
Client
&
client
,
Request
args
)
{
{
Response
r
(
client
);
RangeArg
range
=
RangeArg
::
All
();
RangeArg
range
=
RangeArg
::
All
();
if
(
!
args
.
ParseOptional
(
0
,
range
,
client
))
if
(
!
args
.
ParseOptional
(
0
,
range
,
r
))
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
client
.
partition
.
Shuffle
(
range
.
start
,
range
.
end
);
client
.
partition
.
Shuffle
(
range
.
start
,
range
.
end
);
...
@@ -223,37 +236,42 @@ handle_clear(gcc_unused Client &client, gcc_unused Request args)
...
@@ -223,37 +236,42 @@ handle_clear(gcc_unused Client &client, gcc_unused Request args)
CommandResult
CommandResult
handle_plchanges
(
Client
&
client
,
Request
args
)
handle_plchanges
(
Client
&
client
,
Request
args
)
{
{
uint32_t
version
;
Response
r
(
client
)
;
if
(
!
check_uint32
(
client
,
&
version
,
args
.
front
()))
uint32_t
version
;
if
(
!
ParseCommandArg32
(
r
,
version
,
args
.
front
()))
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
playlist_print_changes_info
(
client
,
client
.
playlist
,
version
);
playlist_print_changes_info
(
r
,
client
.
partition
,
client
.
playlist
,
version
);
return
CommandResult
::
OK
;
return
CommandResult
::
OK
;
}
}
CommandResult
CommandResult
handle_plchangesposid
(
Client
&
client
,
Request
args
)
handle_plchangesposid
(
Client
&
client
,
Request
args
)
{
{
uint32_t
version
;
Response
r
(
client
)
;
if
(
!
check_uint32
(
client
,
&
version
,
args
.
front
()))
uint32_t
version
;
if
(
!
ParseCommandArg32
(
r
,
version
,
args
.
front
()))
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
playlist_print_changes_position
(
client
,
client
.
playlist
,
version
);
playlist_print_changes_position
(
r
,
client
.
playlist
,
version
);
return
CommandResult
::
OK
;
return
CommandResult
::
OK
;
}
}
CommandResult
CommandResult
handle_playlistinfo
(
Client
&
client
,
Request
args
)
handle_playlistinfo
(
Client
&
client
,
Request
args
)
{
{
Response
r
(
client
);
RangeArg
range
=
RangeArg
::
All
();
RangeArg
range
=
RangeArg
::
All
();
if
(
!
args
.
ParseOptional
(
0
,
range
,
client
))
if
(
!
args
.
ParseOptional
(
0
,
range
,
r
))
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
if
(
!
playlist_print_info
(
client
,
client
.
playlist
,
if
(
!
playlist_print_info
(
r
,
client
.
partition
,
client
.
playlist
,
range
.
start
,
range
.
end
))
range
.
start
,
range
.
end
))
return
print_playlist_result
(
client
,
return
print_playlist_result
(
r
,
PlaylistResult
::
BAD_RANGE
);
PlaylistResult
::
BAD_RANGE
);
return
CommandResult
::
OK
;
return
CommandResult
::
OK
;
...
@@ -262,17 +280,19 @@ handle_playlistinfo(Client &client, Request args)
...
@@ -262,17 +280,19 @@ handle_playlistinfo(Client &client, Request args)
CommandResult
CommandResult
handle_playlistid
(
Client
&
client
,
Request
args
)
handle_playlistid
(
Client
&
client
,
Request
args
)
{
{
Response
r
(
client
);
if
(
!
args
.
IsEmpty
())
{
if
(
!
args
.
IsEmpty
())
{
unsigned
id
;
unsigned
id
;
if
(
!
args
.
Parse
(
0
,
id
,
client
))
if
(
!
args
.
Parse
(
0
,
id
,
r
))
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
bool
ret
=
playlist_print_id
(
client
,
client
.
playlist
,
id
);
bool
ret
=
playlist_print_id
(
r
,
client
.
partition
,
client
.
playlist
,
id
);
if
(
!
ret
)
if
(
!
ret
)
return
print_playlist_result
(
client
,
return
print_playlist_result
(
r
,
PlaylistResult
::
NO_SUCH_SONG
);
PlaylistResult
::
NO_SUCH_SONG
);
}
else
{
}
else
{
playlist_print_info
(
client
,
client
.
playlist
,
playlist_print_info
(
r
,
client
.
partition
,
client
.
playlist
,
0
,
std
::
numeric_limits
<
unsigned
>::
max
());
0
,
std
::
numeric_limits
<
unsigned
>::
max
());
}
}
...
@@ -283,13 +303,15 @@ static CommandResult
...
@@ -283,13 +303,15 @@ static CommandResult
handle_playlist_match
(
Client
&
client
,
Request
args
,
handle_playlist_match
(
Client
&
client
,
Request
args
,
bool
fold_case
)
bool
fold_case
)
{
{
Response
r
(
client
);
SongFilter
filter
;
SongFilter
filter
;
if
(
!
filter
.
Parse
(
args
,
fold_case
))
{
if
(
!
filter
.
Parse
(
args
,
fold_case
))
{
command_error
(
client
,
ACK_ERROR_ARG
,
"incorrect arguments"
);
r
.
Error
(
ACK_ERROR_ARG
,
"incorrect arguments"
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
}
}
playlist_print_find
(
client
,
client
.
playlist
,
filter
);
playlist_print_find
(
r
,
client
.
partition
,
client
.
playlist
,
filter
);
return
CommandResult
::
OK
;
return
CommandResult
::
OK
;
}
}
...
@@ -308,13 +330,15 @@ handle_playlistsearch(Client &client, Request args)
...
@@ -308,13 +330,15 @@ handle_playlistsearch(Client &client, Request args)
CommandResult
CommandResult
handle_prio
(
Client
&
client
,
Request
args
)
handle_prio
(
Client
&
client
,
Request
args
)
{
{
Response
r
(
client
);
unsigned
priority
;
unsigned
priority
;
if
(
!
args
.
ParseShift
(
0
,
priority
,
client
,
0xff
))
if
(
!
args
.
ParseShift
(
0
,
priority
,
r
,
0xff
))
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
for
(
const
char
*
i
:
args
)
{
for
(
const
char
*
i
:
args
)
{
RangeArg
range
;
RangeArg
range
;
if
(
!
ParseCommandArg
(
client
,
range
,
i
))
if
(
!
ParseCommandArg
(
r
,
range
,
i
))
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
PlaylistResult
result
=
PlaylistResult
result
=
...
@@ -322,7 +346,7 @@ handle_prio(Client &client, Request args)
...
@@ -322,7 +346,7 @@ handle_prio(Client &client, Request args)
range
.
end
,
range
.
end
,
priority
);
priority
);
if
(
result
!=
PlaylistResult
::
SUCCESS
)
if
(
result
!=
PlaylistResult
::
SUCCESS
)
return
print_playlist_result
(
client
,
result
);
return
print_playlist_result
(
r
,
result
);
}
}
return
CommandResult
::
OK
;
return
CommandResult
::
OK
;
...
@@ -331,19 +355,21 @@ handle_prio(Client &client, Request args)
...
@@ -331,19 +355,21 @@ handle_prio(Client &client, Request args)
CommandResult
CommandResult
handle_prioid
(
Client
&
client
,
Request
args
)
handle_prioid
(
Client
&
client
,
Request
args
)
{
{
Response
r
(
client
);
unsigned
priority
;
unsigned
priority
;
if
(
!
args
.
ParseShift
(
0
,
priority
,
client
,
0xff
))
if
(
!
args
.
ParseShift
(
0
,
priority
,
r
,
0xff
))
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
for
(
const
char
*
i
:
args
)
{
for
(
const
char
*
i
:
args
)
{
unsigned
song_id
;
unsigned
song_id
;
if
(
!
ParseCommandArg
(
client
,
song_id
,
i
))
if
(
!
ParseCommandArg
(
r
,
song_id
,
i
))
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
PlaylistResult
result
=
PlaylistResult
result
=
client
.
partition
.
SetPriorityId
(
song_id
,
priority
);
client
.
partition
.
SetPriorityId
(
song_id
,
priority
);
if
(
result
!=
PlaylistResult
::
SUCCESS
)
if
(
result
!=
PlaylistResult
::
SUCCESS
)
return
print_playlist_result
(
client
,
result
);
return
print_playlist_result
(
r
,
result
);
}
}
return
CommandResult
::
OK
;
return
CommandResult
::
OK
;
...
@@ -352,52 +378,56 @@ handle_prioid(Client &client, Request args)
...
@@ -352,52 +378,56 @@ handle_prioid(Client &client, Request args)
CommandResult
CommandResult
handle_move
(
Client
&
client
,
Request
args
)
handle_move
(
Client
&
client
,
Request
args
)
{
{
Response
r
(
client
);
RangeArg
range
;
RangeArg
range
;
int
to
;
int
to
;
if
(
!
args
.
Parse
(
0
,
range
,
client
)
||
if
(
!
args
.
Parse
(
0
,
range
,
r
)
||
!
args
.
Parse
(
1
,
to
,
r
))
!
args
.
Parse
(
1
,
to
,
client
))
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
PlaylistResult
result
=
PlaylistResult
result
=
client
.
partition
.
MoveRange
(
range
.
start
,
range
.
end
,
to
);
client
.
partition
.
MoveRange
(
range
.
start
,
range
.
end
,
to
);
return
print_playlist_result
(
client
,
result
);
return
print_playlist_result
(
r
,
result
);
}
}
CommandResult
CommandResult
handle_moveid
(
Client
&
client
,
Request
args
)
handle_moveid
(
Client
&
client
,
Request
args
)
{
{
Response
r
(
client
);
unsigned
id
;
unsigned
id
;
int
to
;
int
to
;
if
(
!
args
.
Parse
(
0
,
id
,
client
)
||
if
(
!
args
.
Parse
(
0
,
id
,
r
)
||
!
args
.
Parse
(
1
,
to
,
r
))
!
args
.
Parse
(
1
,
to
,
client
))
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
PlaylistResult
result
=
client
.
partition
.
MoveId
(
id
,
to
);
PlaylistResult
result
=
client
.
partition
.
MoveId
(
id
,
to
);
return
print_playlist_result
(
client
,
result
);
return
print_playlist_result
(
r
,
result
);
}
}
CommandResult
CommandResult
handle_swap
(
Client
&
client
,
Request
args
)
handle_swap
(
Client
&
client
,
Request
args
)
{
{
Response
r
(
client
);
unsigned
song1
,
song2
;
unsigned
song1
,
song2
;
if
(
!
args
.
Parse
(
0
,
song1
,
client
)
||
if
(
!
args
.
Parse
(
0
,
song1
,
r
)
||
!
args
.
Parse
(
1
,
song2
,
r
))
!
args
.
Parse
(
1
,
song2
,
client
))
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
PlaylistResult
result
=
PlaylistResult
result
=
client
.
partition
.
SwapPositions
(
song1
,
song2
);
client
.
partition
.
SwapPositions
(
song1
,
song2
);
return
print_playlist_result
(
client
,
result
);
return
print_playlist_result
(
r
,
result
);
}
}
CommandResult
CommandResult
handle_swapid
(
Client
&
client
,
Request
args
)
handle_swapid
(
Client
&
client
,
Request
args
)
{
{
Response
r
(
client
);
unsigned
id1
,
id2
;
unsigned
id1
,
id2
;
if
(
!
args
.
Parse
(
0
,
id1
,
client
)
||
if
(
!
args
.
Parse
(
0
,
id1
,
r
)
||
!
args
.
Parse
(
1
,
id2
,
r
))
!
args
.
Parse
(
1
,
id2
,
client
))
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
PlaylistResult
result
=
client
.
partition
.
SwapIds
(
id1
,
id2
);
PlaylistResult
result
=
client
.
partition
.
SwapIds
(
id1
,
id2
);
return
print_playlist_result
(
client
,
result
);
return
print_playlist_result
(
r
,
result
);
}
}
src/command/Request.hxx
View file @
7652a298
...
@@ -28,7 +28,7 @@
...
@@ -28,7 +28,7 @@
#include <assert.h>
#include <assert.h>
class
Client
;
class
Response
;
class
Request
:
public
ConstBuffer
<
const
char
*>
{
class
Request
:
public
ConstBuffer
<
const
char
*>
{
typedef
ConstBuffer
<
const
char
*>
Base
;
typedef
ConstBuffer
<
const
char
*>
Base
;
...
@@ -45,26 +45,26 @@ public:
...
@@ -45,26 +45,26 @@ public:
}
}
template
<
typename
T
,
typename
...
Args
>
template
<
typename
T
,
typename
...
Args
>
bool
Parse
(
unsigned
idx
,
T
&
value_r
,
Client
&
client
,
bool
Parse
(
unsigned
idx
,
T
&
value_r
,
Response
&
r
,
Args
&&
...
args
)
{
Args
&&
...
args
)
{
assert
(
idx
<
size
);
assert
(
idx
<
size
);
return
ParseCommandArg
(
client
,
value_r
,
data
[
idx
],
return
ParseCommandArg
(
r
,
value_r
,
data
[
idx
],
std
::
forward
<
Args
>
(
args
)...);
std
::
forward
<
Args
>
(
args
)...);
}
}
template
<
typename
T
,
typename
...
Args
>
template
<
typename
T
,
typename
...
Args
>
bool
ParseOptional
(
unsigned
idx
,
T
&
value_r
,
Client
&
client
,
bool
ParseOptional
(
unsigned
idx
,
T
&
value_r
,
Response
&
r
,
Args
&&
...
args
)
{
Args
&&
...
args
)
{
return
idx
>=
size
||
return
idx
>=
size
||
Parse
(
idx
,
value_r
,
client
,
Parse
(
idx
,
value_r
,
r
,
std
::
forward
<
Args
>
(
args
)...);
std
::
forward
<
Args
>
(
args
)...);
}
}
template
<
typename
T
,
typename
...
Args
>
template
<
typename
T
,
typename
...
Args
>
bool
ParseShift
(
unsigned
idx
,
T
&
value_r
,
Client
&
client
,
bool
ParseShift
(
unsigned
idx
,
T
&
value_r
,
Response
&
r
,
Args
&&
...
args
)
{
Args
&&
...
args
)
{
bool
success
=
Parse
(
idx
,
value_r
,
client
,
bool
success
=
Parse
(
idx
,
value_r
,
r
,
std
::
forward
<
Args
>
(
args
)...);
std
::
forward
<
Args
>
(
args
)...);
shift
();
shift
();
return
success
;
return
success
;
...
...
src/command/StickerCommands.cxx
View file @
7652a298
...
@@ -27,8 +27,8 @@
...
@@ -27,8 +27,8 @@
#include "sticker/StickerPrint.hxx"
#include "sticker/StickerPrint.hxx"
#include "sticker/StickerDatabase.hxx"
#include "sticker/StickerDatabase.hxx"
#include "CommandError.hxx"
#include "CommandError.hxx"
#include "protocol/Result.hxx"
#include "client/Client.hxx"
#include "client/Client.hxx"
#include "client/Response.hxx"
#include "Partition.hxx"
#include "Partition.hxx"
#include "Instance.hxx"
#include "Instance.hxx"
#include "util/Error.hxx"
#include "util/Error.hxx"
...
@@ -37,7 +37,8 @@
...
@@ -37,7 +37,8 @@
#include <string.h>
#include <string.h>
struct
sticker_song_find_data
{
struct
sticker_song_find_data
{
Client
&
client
;
Response
&
r
;
Partition
&
partition
;
const
char
*
name
;
const
char
*
name
;
};
};
...
@@ -48,17 +49,17 @@ sticker_song_find_print_cb(const LightSong &song, const char *value,
...
@@ -48,17 +49,17 @@ sticker_song_find_print_cb(const LightSong &song, const char *value,
struct
sticker_song_find_data
*
data
=
struct
sticker_song_find_data
*
data
=
(
struct
sticker_song_find_data
*
)
user_data
;
(
struct
sticker_song_find_data
*
)
user_data
;
song_print_uri
(
data
->
client
,
song
);
song_print_uri
(
data
->
r
,
data
->
partition
,
song
);
sticker_print_value
(
data
->
client
,
data
->
name
,
value
);
sticker_print_value
(
data
->
r
,
data
->
name
,
value
);
}
}
static
CommandResult
static
CommandResult
handle_sticker_song
(
Client
&
client
,
Request
args
)
handle_sticker_song
(
Response
&
r
,
Partition
&
partition
,
Request
args
)
{
{
Error
error
;
Error
error
;
const
Database
*
db
=
client
.
GetDatabase
(
error
);
const
Database
*
db
=
partition
.
GetDatabase
(
error
);
if
(
db
==
nullptr
)
if
(
db
==
nullptr
)
return
print_error
(
client
,
error
);
return
print_error
(
r
,
error
);
const
char
*
const
cmd
=
args
.
front
();
const
char
*
const
cmd
=
args
.
front
();
...
@@ -66,53 +67,52 @@ handle_sticker_song(Client &client, Request args)
...
@@ -66,53 +67,52 @@ handle_sticker_song(Client &client, Request args)
if
(
args
.
size
==
4
&&
strcmp
(
cmd
,
"get"
)
==
0
)
{
if
(
args
.
size
==
4
&&
strcmp
(
cmd
,
"get"
)
==
0
)
{
const
LightSong
*
song
=
db
->
GetSong
(
args
[
2
],
error
);
const
LightSong
*
song
=
db
->
GetSong
(
args
[
2
],
error
);
if
(
song
==
nullptr
)
if
(
song
==
nullptr
)
return
print_error
(
client
,
error
);
return
print_error
(
r
,
error
);
const
auto
value
=
sticker_song_get_value
(
*
song
,
args
[
3
],
const
auto
value
=
sticker_song_get_value
(
*
song
,
args
[
3
],
error
);
error
);
db
->
ReturnSong
(
song
);
db
->
ReturnSong
(
song
);
if
(
value
.
empty
())
{
if
(
value
.
empty
())
{
if
(
error
.
IsDefined
())
if
(
error
.
IsDefined
())
return
print_error
(
client
,
error
);
return
print_error
(
r
,
error
);
command_error
(
client
,
ACK_ERROR_NO_EXIST
,
r
.
Error
(
ACK_ERROR_NO_EXIST
,
"no such sticker"
);
"no such sticker"
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
}
}
sticker_print_value
(
client
,
args
[
3
],
value
.
c_str
());
sticker_print_value
(
r
,
args
[
3
],
value
.
c_str
());
return
CommandResult
::
OK
;
return
CommandResult
::
OK
;
/* list song song_id */
/* list song song_id */
}
else
if
(
args
.
size
==
3
&&
strcmp
(
cmd
,
"list"
)
==
0
)
{
}
else
if
(
args
.
size
==
3
&&
strcmp
(
cmd
,
"list"
)
==
0
)
{
const
LightSong
*
song
=
db
->
GetSong
(
args
[
2
],
error
);
const
LightSong
*
song
=
db
->
GetSong
(
args
[
2
],
error
);
if
(
song
==
nullptr
)
if
(
song
==
nullptr
)
return
print_error
(
client
,
error
);
return
print_error
(
r
,
error
);
Sticker
*
sticker
=
sticker_song_get
(
*
song
,
error
);
Sticker
*
sticker
=
sticker_song_get
(
*
song
,
error
);
db
->
ReturnSong
(
song
);
db
->
ReturnSong
(
song
);
if
(
sticker
)
{
if
(
sticker
)
{
sticker_print
(
client
,
*
sticker
);
sticker_print
(
r
,
*
sticker
);
sticker_free
(
sticker
);
sticker_free
(
sticker
);
}
else
if
(
error
.
IsDefined
())
}
else
if
(
error
.
IsDefined
())
return
print_error
(
client
,
error
);
return
print_error
(
r
,
error
);
return
CommandResult
::
OK
;
return
CommandResult
::
OK
;
/* set song song_id id key */
/* set song song_id id key */
}
else
if
(
args
.
size
==
5
&&
strcmp
(
cmd
,
"set"
)
==
0
)
{
}
else
if
(
args
.
size
==
5
&&
strcmp
(
cmd
,
"set"
)
==
0
)
{
const
LightSong
*
song
=
db
->
GetSong
(
args
[
2
],
error
);
const
LightSong
*
song
=
db
->
GetSong
(
args
[
2
],
error
);
if
(
song
==
nullptr
)
if
(
song
==
nullptr
)
return
print_error
(
client
,
error
);
return
print_error
(
r
,
error
);
bool
ret
=
sticker_song_set_value
(
*
song
,
args
[
3
],
args
[
4
],
bool
ret
=
sticker_song_set_value
(
*
song
,
args
[
3
],
args
[
4
],
error
);
error
);
db
->
ReturnSong
(
song
);
db
->
ReturnSong
(
song
);
if
(
!
ret
)
{
if
(
!
ret
)
{
if
(
error
.
IsDefined
())
if
(
error
.
IsDefined
())
return
print_error
(
client
,
error
);
return
print_error
(
r
,
error
);
command_error
(
client
,
ACK_ERROR_SYSTEM
,
r
.
Error
(
ACK_ERROR_SYSTEM
,
"failed to set sticker value"
);
"failed to set sticker value"
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
}
}
...
@@ -122,7 +122,7 @@ handle_sticker_song(Client &client, Request args)
...
@@ -122,7 +122,7 @@ handle_sticker_song(Client &client, Request args)
strcmp
(
cmd
,
"delete"
)
==
0
)
{
strcmp
(
cmd
,
"delete"
)
==
0
)
{
const
LightSong
*
song
=
db
->
GetSong
(
args
[
2
],
error
);
const
LightSong
*
song
=
db
->
GetSong
(
args
[
2
],
error
);
if
(
song
==
nullptr
)
if
(
song
==
nullptr
)
return
print_error
(
client
,
error
);
return
print_error
(
r
,
error
);
bool
ret
=
args
.
size
==
3
bool
ret
=
args
.
size
==
3
?
sticker_song_delete
(
*
song
,
error
)
?
sticker_song_delete
(
*
song
,
error
)
...
@@ -130,10 +130,9 @@ handle_sticker_song(Client &client, Request args)
...
@@ -130,10 +130,9 @@ handle_sticker_song(Client &client, Request args)
db
->
ReturnSong
(
song
);
db
->
ReturnSong
(
song
);
if
(
!
ret
)
{
if
(
!
ret
)
{
if
(
error
.
IsDefined
())
if
(
error
.
IsDefined
())
return
print_error
(
client
,
error
);
return
print_error
(
r
,
error
);
command_error
(
client
,
ACK_ERROR_SYSTEM
,
r
.
Error
(
ACK_ERROR_SYSTEM
,
"no such sticker"
);
"no such sticker"
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
}
}
...
@@ -161,14 +160,14 @@ handle_sticker_song(Client &client, Request args)
...
@@ -161,14 +160,14 @@ handle_sticker_song(Client &client, Request args)
else
if
(
strcmp
(
op_s
,
">"
)
==
0
)
else
if
(
strcmp
(
op_s
,
">"
)
==
0
)
op
=
StickerOperator
::
GREATER_THAN
;
op
=
StickerOperator
::
GREATER_THAN
;
else
{
else
{
command_error
(
client
,
ACK_ERROR_ARG
,
r
.
Error
(
ACK_ERROR_ARG
,
"bad operator"
);
"bad operator"
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
}
}
}
}
struct
sticker_song_find_data
data
=
{
struct
sticker_song_find_data
data
=
{
client
,
r
,
partition
,
args
[
3
],
args
[
3
],
};
};
...
@@ -177,16 +176,16 @@ handle_sticker_song(Client &client, Request args)
...
@@ -177,16 +176,16 @@ handle_sticker_song(Client &client, Request args)
sticker_song_find_print_cb
,
&
data
,
sticker_song_find_print_cb
,
&
data
,
error
))
{
error
))
{
if
(
error
.
IsDefined
())
if
(
error
.
IsDefined
())
return
print_error
(
client
,
error
);
return
print_error
(
r
,
error
);
command_error
(
client
,
ACK_ERROR_SYSTEM
,
r
.
Error
(
ACK_ERROR_SYSTEM
,
"failed to set search sticker database"
);
"failed to set search sticker database"
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
}
}
return
CommandResult
::
OK
;
return
CommandResult
::
OK
;
}
else
{
}
else
{
command_error
(
client
,
ACK_ERROR_ARG
,
"bad request"
);
r
.
Error
(
ACK_ERROR_ARG
,
"bad request"
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
}
}
}
}
...
@@ -194,19 +193,19 @@ handle_sticker_song(Client &client, Request args)
...
@@ -194,19 +193,19 @@ handle_sticker_song(Client &client, Request args)
CommandResult
CommandResult
handle_sticker
(
Client
&
client
,
Request
args
)
handle_sticker
(
Client
&
client
,
Request
args
)
{
{
Response
r
(
client
);
assert
(
args
.
size
>=
3
);
assert
(
args
.
size
>=
3
);
if
(
!
sticker_enabled
())
{
if
(
!
sticker_enabled
())
{
command_error
(
client
,
ACK_ERROR_UNKNOWN
,
r
.
Error
(
ACK_ERROR_UNKNOWN
,
"sticker database is disabled"
);
"sticker database is disabled"
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
}
}
if
(
strcmp
(
args
[
1
],
"song"
)
==
0
)
if
(
strcmp
(
args
[
1
],
"song"
)
==
0
)
return
handle_sticker_song
(
client
,
args
);
return
handle_sticker_song
(
r
,
client
.
partition
,
args
);
else
{
else
{
command_error
(
client
,
ACK_ERROR_ARG
,
r
.
Error
(
ACK_ERROR_ARG
,
"unknown sticker domain"
);
"unknown sticker domain"
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
}
}
}
}
src/command/StorageCommands.cxx
View file @
7652a298
...
@@ -23,12 +23,12 @@
...
@@ -23,12 +23,12 @@
#include "StorageCommands.hxx"
#include "StorageCommands.hxx"
#include "Request.hxx"
#include "Request.hxx"
#include "CommandError.hxx"
#include "CommandError.hxx"
#include "protocol/Result.hxx"
#include "util/UriUtil.hxx"
#include "util/UriUtil.hxx"
#include "util/Error.hxx"
#include "util/Error.hxx"
#include "util/ConstBuffer.hxx"
#include "util/ConstBuffer.hxx"
#include "fs/Traits.hxx"
#include "fs/Traits.hxx"
#include "client/Client.hxx"
#include "client/Client.hxx"
#include "client/Response.hxx"
#include "Partition.hxx"
#include "Partition.hxx"
#include "Instance.hxx"
#include "Instance.hxx"
#include "storage/Registry.hxx"
#include "storage/Registry.hxx"
...
@@ -57,7 +57,7 @@ skip_path(const char *name_utf8)
...
@@ -57,7 +57,7 @@ skip_path(const char *name_utf8)
#endif
#endif
static
bool
static
bool
handle_listfiles_storage
(
Client
&
client
,
StorageDirectoryReader
&
reader
,
handle_listfiles_storage
(
Response
&
r
,
StorageDirectoryReader
&
reader
,
Error
&
error
)
Error
&
error
)
{
{
const
char
*
name_utf8
;
const
char
*
name_utf8
;
...
@@ -75,19 +75,19 @@ handle_listfiles_storage(Client &client, StorageDirectoryReader &reader,
...
@@ -75,19 +75,19 @@ handle_listfiles_storage(Client &client, StorageDirectoryReader &reader,
continue
;
continue
;
case
StorageFileInfo
:
:
Type
::
REGULAR
:
case
StorageFileInfo
:
:
Type
::
REGULAR
:
client_printf
(
client
,
"file: %s
\n
"
r
.
Format
(
"file: %s
\n
"
"size: %"
PRIu64
"
\n
"
,
"size: %"
PRIu64
"
\n
"
,
name_utf8
,
name_utf8
,
info
.
size
);
info
.
size
);
break
;
break
;
case
StorageFileInfo
:
:
Type
::
DIRECTORY
:
case
StorageFileInfo
:
:
Type
::
DIRECTORY
:
client_printf
(
client
,
"directory: %s
\n
"
,
name_utf8
);
r
.
Format
(
"directory: %s
\n
"
,
name_utf8
);
break
;
break
;
}
}
if
(
info
.
mtime
!=
0
)
if
(
info
.
mtime
!=
0
)
time_print
(
client
,
"Last-Modified"
,
info
.
mtime
);
time_print
(
r
,
"Last-Modified"
,
info
.
mtime
);
}
}
return
true
;
return
true
;
...
@@ -98,52 +98,51 @@ handle_listfiles_storage(Client &client, StorageDirectoryReader &reader,
...
@@ -98,52 +98,51 @@ handle_listfiles_storage(Client &client, StorageDirectoryReader &reader,
#endif
#endif
static
bool
static
bool
handle_listfiles_storage
(
Client
&
client
,
Storage
&
storage
,
const
char
*
uri
,
handle_listfiles_storage
(
Response
&
r
,
Storage
&
storage
,
const
char
*
uri
,
Error
&
error
)
Error
&
error
)
{
{
auto
reader
=
storage
.
OpenDirectory
(
uri
,
error
);
auto
reader
=
storage
.
OpenDirectory
(
uri
,
error
);
if
(
reader
==
nullptr
)
if
(
reader
==
nullptr
)
return
false
;
return
false
;
bool
success
=
handle_listfiles_storage
(
client
,
*
reader
,
error
);
bool
success
=
handle_listfiles_storage
(
r
,
*
reader
,
error
);
delete
reader
;
delete
reader
;
return
success
;
return
success
;
}
}
CommandResult
CommandResult
handle_listfiles_storage
(
Client
&
client
,
Storage
&
storage
,
const
char
*
uri
)
handle_listfiles_storage
(
Response
&
r
,
Storage
&
storage
,
const
char
*
uri
)
{
{
Error
error
;
Error
error
;
if
(
!
handle_listfiles_storage
(
client
,
storage
,
uri
,
error
))
if
(
!
handle_listfiles_storage
(
r
,
storage
,
uri
,
error
))
return
print_error
(
client
,
error
);
return
print_error
(
r
,
error
);
return
CommandResult
::
OK
;
return
CommandResult
::
OK
;
}
}
CommandResult
CommandResult
handle_listfiles_storage
(
Client
&
client
,
const
char
*
uri
)
handle_listfiles_storage
(
Response
&
r
,
const
char
*
uri
)
{
{
Error
error
;
Error
error
;
Storage
*
storage
=
CreateStorageURI
(
io_thread_get
(),
uri
,
error
);
Storage
*
storage
=
CreateStorageURI
(
io_thread_get
(),
uri
,
error
);
if
(
storage
==
nullptr
)
{
if
(
storage
==
nullptr
)
{
if
(
error
.
IsDefined
())
if
(
error
.
IsDefined
())
return
print_error
(
client
,
error
);
return
print_error
(
r
,
error
);
command_error
(
client
,
ACK_ERROR_ARG
,
r
.
Error
(
ACK_ERROR_ARG
,
"Unrecognized storage URI"
);
"Unrecognized storage URI"
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
}
}
bool
success
=
handle_listfiles_storage
(
client
,
*
storage
,
""
,
error
);
bool
success
=
handle_listfiles_storage
(
r
,
*
storage
,
""
,
error
);
delete
storage
;
delete
storage
;
if
(
!
success
)
if
(
!
success
)
return
print_error
(
client
,
error
);
return
print_error
(
r
,
error
);
return
CommandResult
::
OK
;
return
CommandResult
::
OK
;
}
}
static
void
static
void
print_storage_uri
(
Client
&
client
,
const
Storage
&
storage
)
print_storage_uri
(
Client
&
client
,
Response
&
r
,
const
Storage
&
storage
)
{
{
std
::
string
uri
=
storage
.
MapUTF8
(
""
);
std
::
string
uri
=
storage
.
MapUTF8
(
""
);
if
(
uri
.
empty
())
if
(
uri
.
empty
())
...
@@ -165,24 +164,26 @@ print_storage_uri(Client &client, const Storage &storage)
...
@@ -165,24 +164,26 @@ print_storage_uri(Client &client, const Storage &storage)
uri
=
std
::
move
(
allocated
);
uri
=
std
::
move
(
allocated
);
}
}
client_printf
(
client
,
"storage: %s
\n
"
,
uri
.
c_str
());
r
.
Format
(
"storage: %s
\n
"
,
uri
.
c_str
());
}
}
CommandResult
CommandResult
handle_listmounts
(
Client
&
client
,
gcc_unused
Request
args
)
handle_listmounts
(
Client
&
client
,
gcc_unused
Request
args
)
{
{
Response
r
(
client
);
Storage
*
_composite
=
client
.
partition
.
instance
.
storage
;
Storage
*
_composite
=
client
.
partition
.
instance
.
storage
;
if
(
_composite
==
nullptr
)
{
if
(
_composite
==
nullptr
)
{
command_error
(
client
,
ACK_ERROR_NO_EXIST
,
"No database"
);
r
.
Error
(
ACK_ERROR_NO_EXIST
,
"No database"
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
}
}
CompositeStorage
&
composite
=
*
(
CompositeStorage
*
)
_composite
;
CompositeStorage
&
composite
=
*
(
CompositeStorage
*
)
_composite
;
const
auto
visitor
=
[
&
client
](
const
char
*
mount_uri
,
const
auto
visitor
=
[
&
client
,
&
r
](
const
char
*
mount_uri
,
const
Storage
&
storage
){
const
Storage
&
storage
){
client_printf
(
client
,
"mount: %s
\n
"
,
mount_uri
);
r
.
Format
(
"mount: %s
\n
"
,
mount_uri
);
print_storage_uri
(
client
,
storage
);
print_storage_uri
(
client
,
r
,
storage
);
};
};
composite
.
VisitMounts
(
visitor
);
composite
.
VisitMounts
(
visitor
);
...
@@ -193,9 +194,11 @@ handle_listmounts(Client &client, gcc_unused Request args)
...
@@ -193,9 +194,11 @@ handle_listmounts(Client &client, gcc_unused Request args)
CommandResult
CommandResult
handle_mount
(
Client
&
client
,
Request
args
)
handle_mount
(
Client
&
client
,
Request
args
)
{
{
Response
r
(
client
);
Storage
*
_composite
=
client
.
partition
.
instance
.
storage
;
Storage
*
_composite
=
client
.
partition
.
instance
.
storage
;
if
(
_composite
==
nullptr
)
{
if
(
_composite
==
nullptr
)
{
command_error
(
client
,
ACK_ERROR_NO_EXIST
,
"No database"
);
r
.
Error
(
ACK_ERROR_NO_EXIST
,
"No database"
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
}
}
...
@@ -205,7 +208,7 @@ handle_mount(Client &client, Request args)
...
@@ -205,7 +208,7 @@ handle_mount(Client &client, Request args)
const
char
*
const
remote_uri
=
args
[
1
];
const
char
*
const
remote_uri
=
args
[
1
];
if
(
*
local_uri
==
0
)
{
if
(
*
local_uri
==
0
)
{
command_error
(
client
,
ACK_ERROR_ARG
,
"Bad mount point"
);
r
.
Error
(
ACK_ERROR_ARG
,
"Bad mount point"
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
}
}
...
@@ -215,7 +218,7 @@ handle_mount(Client &client, Request args)
...
@@ -215,7 +218,7 @@ handle_mount(Client &client, Request args)
UpdateQueue::Erase() really gets called for every
UpdateQueue::Erase() really gets called for every
unmount, and no Directory disappears recursively
unmount, and no Directory disappears recursively
during database update */
during database update */
command_error
(
client
,
ACK_ERROR_ARG
,
"Bad mount point"
);
r
.
Error
(
ACK_ERROR_ARG
,
"Bad mount point"
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
}
}
...
@@ -224,10 +227,9 @@ handle_mount(Client &client, Request args)
...
@@ -224,10 +227,9 @@ handle_mount(Client &client, Request args)
error
);
error
);
if
(
storage
==
nullptr
)
{
if
(
storage
==
nullptr
)
{
if
(
error
.
IsDefined
())
if
(
error
.
IsDefined
())
return
print_error
(
client
,
error
);
return
print_error
(
r
,
error
);
command_error
(
client
,
ACK_ERROR_ARG
,
r
.
Error
(
ACK_ERROR_ARG
,
"Unrecognized storage URI"
);
"Unrecognized storage URI"
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
}
}
...
@@ -241,7 +243,7 @@ handle_mount(Client &client, Request args)
...
@@ -241,7 +243,7 @@ handle_mount(Client &client, Request args)
if
(
!
db
.
Mount
(
local_uri
,
remote_uri
,
error
))
{
if
(
!
db
.
Mount
(
local_uri
,
remote_uri
,
error
))
{
composite
.
Unmount
(
local_uri
);
composite
.
Unmount
(
local_uri
);
return
print_error
(
client
,
error
);
return
print_error
(
r
,
error
);
}
}
// TODO: call Instance::OnDatabaseModified()?
// TODO: call Instance::OnDatabaseModified()?
...
@@ -256,9 +258,11 @@ handle_mount(Client &client, Request args)
...
@@ -256,9 +258,11 @@ handle_mount(Client &client, Request args)
CommandResult
CommandResult
handle_unmount
(
Client
&
client
,
Request
args
)
handle_unmount
(
Client
&
client
,
Request
args
)
{
{
Response
r
(
client
);
Storage
*
_composite
=
client
.
partition
.
instance
.
storage
;
Storage
*
_composite
=
client
.
partition
.
instance
.
storage
;
if
(
_composite
==
nullptr
)
{
if
(
_composite
==
nullptr
)
{
command_error
(
client
,
ACK_ERROR_NO_EXIST
,
"No database"
);
r
.
Error
(
ACK_ERROR_NO_EXIST
,
"No database"
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
}
}
...
@@ -267,7 +271,7 @@ handle_unmount(Client &client, Request args)
...
@@ -267,7 +271,7 @@ handle_unmount(Client &client, Request args)
const
char
*
const
local_uri
=
args
.
front
();
const
char
*
const
local_uri
=
args
.
front
();
if
(
*
local_uri
==
0
)
{
if
(
*
local_uri
==
0
)
{
command_error
(
client
,
ACK_ERROR_ARG
,
"Bad mount point"
);
r
.
Error
(
ACK_ERROR_ARG
,
"Bad mount point"
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
}
}
...
@@ -289,7 +293,7 @@ handle_unmount(Client &client, Request args)
...
@@ -289,7 +293,7 @@ handle_unmount(Client &client, Request args)
#endif
#endif
if
(
!
composite
.
Unmount
(
local_uri
))
{
if
(
!
composite
.
Unmount
(
local_uri
))
{
command_error
(
client
,
ACK_ERROR_ARG
,
"Not a mount point"
);
r
.
Error
(
ACK_ERROR_ARG
,
"Not a mount point"
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
}
}
...
...
src/command/StorageCommands.hxx
View file @
7652a298
...
@@ -25,12 +25,13 @@
...
@@ -25,12 +25,13 @@
class
Client
;
class
Client
;
class
Storage
;
class
Storage
;
class
Request
;
class
Request
;
class
Response
;
CommandResult
CommandResult
handle_listfiles_storage
(
Client
&
client
,
Storage
&
storage
,
const
char
*
uri
);
handle_listfiles_storage
(
Response
&
r
,
Storage
&
storage
,
const
char
*
uri
);
CommandResult
CommandResult
handle_listfiles_storage
(
Client
&
client
,
const
char
*
uri
);
handle_listfiles_storage
(
Response
&
r
,
const
char
*
uri
);
CommandResult
CommandResult
handle_listmounts
(
Client
&
client
,
Request
args
);
handle_listmounts
(
Client
&
client
,
Request
args
);
...
...
src/command/TagCommands.cxx
View file @
7652a298
...
@@ -22,7 +22,7 @@
...
@@ -22,7 +22,7 @@
#include "Request.hxx"
#include "Request.hxx"
#include "CommandError.hxx"
#include "CommandError.hxx"
#include "client/Client.hxx"
#include "client/Client.hxx"
#include "
protocol/Result
.hxx"
#include "
client/Response
.hxx"
#include "tag/Tag.hxx"
#include "tag/Tag.hxx"
#include "Partition.hxx"
#include "Partition.hxx"
#include "util/ConstBuffer.hxx"
#include "util/ConstBuffer.hxx"
...
@@ -30,15 +30,16 @@
...
@@ -30,15 +30,16 @@
CommandResult
CommandResult
handle_addtagid
(
Client
&
client
,
Request
args
)
handle_addtagid
(
Client
&
client
,
Request
args
)
{
{
Response
r
(
client
);
unsigned
song_id
;
unsigned
song_id
;
if
(
!
args
.
Parse
(
0
,
song_id
,
client
))
if
(
!
args
.
Parse
(
0
,
song_id
,
r
))
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
const
char
*
const
tag_name
=
args
[
1
];
const
char
*
const
tag_name
=
args
[
1
];
const
TagType
tag_type
=
tag_name_parse_i
(
tag_name
);
const
TagType
tag_type
=
tag_name_parse_i
(
tag_name
);
if
(
tag_type
==
TAG_NUM_OF_ITEM_TYPES
)
{
if
(
tag_type
==
TAG_NUM_OF_ITEM_TYPES
)
{
command_error
(
client
,
ACK_ERROR_ARG
,
r
.
FormatError
(
ACK_ERROR_ARG
,
"Unknown tag type: %s"
,
tag_name
);
"Unknown tag type: %s"
,
tag_name
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
}
}
...
@@ -47,7 +48,7 @@ handle_addtagid(Client &client, Request args)
...
@@ -47,7 +48,7 @@ handle_addtagid(Client &client, Request args)
Error
error
;
Error
error
;
if
(
!
client
.
partition
.
playlist
.
AddSongIdTag
(
song_id
,
tag_type
,
value
,
if
(
!
client
.
partition
.
playlist
.
AddSongIdTag
(
song_id
,
tag_type
,
value
,
error
))
error
))
return
print_error
(
client
,
error
);
return
print_error
(
r
,
error
);
return
CommandResult
::
OK
;
return
CommandResult
::
OK
;
}
}
...
@@ -55,8 +56,10 @@ handle_addtagid(Client &client, Request args)
...
@@ -55,8 +56,10 @@ handle_addtagid(Client &client, Request args)
CommandResult
CommandResult
handle_cleartagid
(
Client
&
client
,
Request
args
)
handle_cleartagid
(
Client
&
client
,
Request
args
)
{
{
Response
r
(
client
);
unsigned
song_id
;
unsigned
song_id
;
if
(
!
args
.
Parse
(
0
,
song_id
,
client
))
if
(
!
args
.
Parse
(
0
,
song_id
,
r
))
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
TagType
tag_type
=
TAG_NUM_OF_ITEM_TYPES
;
TagType
tag_type
=
TAG_NUM_OF_ITEM_TYPES
;
...
@@ -64,7 +67,7 @@ handle_cleartagid(Client &client, Request args)
...
@@ -64,7 +67,7 @@ handle_cleartagid(Client &client, Request args)
const
char
*
const
tag_name
=
args
[
1
];
const
char
*
const
tag_name
=
args
[
1
];
tag_type
=
tag_name_parse_i
(
tag_name
);
tag_type
=
tag_name_parse_i
(
tag_name
);
if
(
tag_type
==
TAG_NUM_OF_ITEM_TYPES
)
{
if
(
tag_type
==
TAG_NUM_OF_ITEM_TYPES
)
{
command_error
(
client
,
ACK_ERROR_ARG
,
r
.
FormatError
(
ACK_ERROR_ARG
,
"Unknown tag type: %s"
,
tag_name
);
"Unknown tag type: %s"
,
tag_name
);
return
CommandResult
::
ERROR
;
return
CommandResult
::
ERROR
;
}
}
...
@@ -73,7 +76,7 @@ handle_cleartagid(Client &client, Request args)
...
@@ -73,7 +76,7 @@ handle_cleartagid(Client &client, Request args)
Error
error
;
Error
error
;
if
(
!
client
.
partition
.
playlist
.
ClearSongIdTag
(
song_id
,
tag_type
,
if
(
!
client
.
partition
.
playlist
.
ClearSongIdTag
(
song_id
,
tag_type
,
error
))
error
))
return
print_error
(
client
,
error
);
return
print_error
(
r
,
error
);
return
CommandResult
::
OK
;
return
CommandResult
::
OK
;
}
}
src/db/Count.cxx
View file @
7652a298
...
@@ -21,7 +21,8 @@
...
@@ -21,7 +21,8 @@
#include "Count.hxx"
#include "Count.hxx"
#include "Selection.hxx"
#include "Selection.hxx"
#include "Interface.hxx"
#include "Interface.hxx"
#include "client/Client.hxx"
#include "Partition.hxx"
#include "client/Response.hxx"
#include "LightSong.hxx"
#include "LightSong.hxx"
#include "tag/Tag.hxx"
#include "tag/Tag.hxx"
...
@@ -40,26 +41,24 @@ class TagCountMap : public std::map<std::string, SearchStats> {
...
@@ -40,26 +41,24 @@ class TagCountMap : public std::map<std::string, SearchStats> {
};
};
static
void
static
void
PrintSearchStats
(
Client
&
client
,
const
SearchStats
&
stats
)
PrintSearchStats
(
Response
&
r
,
const
SearchStats
&
stats
)
{
{
unsigned
total_duration_s
=
unsigned
total_duration_s
=
std
::
chrono
::
duration_cast
<
std
::
chrono
::
seconds
>
(
stats
.
total_duration
).
count
();
std
::
chrono
::
duration_cast
<
std
::
chrono
::
seconds
>
(
stats
.
total_duration
).
count
();
client_printf
(
client
,
r
.
Format
(
"songs: %u
\n
"
"songs: %u
\n
"
"playtime: %u
\n
"
,
"playtime: %u
\n
"
,
stats
.
n_songs
,
total_duration_s
);
stats
.
n_songs
,
total_duration_s
);
}
}
static
void
static
void
Print
(
Client
&
client
,
TagType
group
,
const
TagCountMap
&
m
)
Print
(
Response
&
r
,
TagType
group
,
const
TagCountMap
&
m
)
{
{
assert
(
unsigned
(
group
)
<
TAG_NUM_OF_ITEM_TYPES
);
assert
(
unsigned
(
group
)
<
TAG_NUM_OF_ITEM_TYPES
);
for
(
const
auto
&
i
:
m
)
{
for
(
const
auto
&
i
:
m
)
{
client_printf
(
client
,
"%s: %s
\n
"
,
r
.
Format
(
"%s: %s
\n
"
,
tag_item_names
[
group
],
i
.
first
.
c_str
());
tag_item_names
[
group
],
i
.
first
.
c_str
());
PrintSearchStats
(
r
,
i
.
second
);
PrintSearchStats
(
client
,
i
.
second
);
}
}
}
}
...
@@ -109,12 +108,12 @@ GroupCountVisitor(TagCountMap &map, TagType group, const LightSong &song)
...
@@ -109,12 +108,12 @@ GroupCountVisitor(TagCountMap &map, TagType group, const LightSong &song)
}
}
bool
bool
PrintSongCount
(
Client
&
client
,
const
char
*
name
,
PrintSongCount
(
Response
&
r
,
const
Partition
&
partition
,
const
char
*
name
,
const
SongFilter
*
filter
,
const
SongFilter
*
filter
,
TagType
group
,
TagType
group
,
Error
&
error
)
Error
&
error
)
{
{
const
Database
*
db
=
client
.
GetDatabase
(
error
);
const
Database
*
db
=
partition
.
GetDatabase
(
error
);
if
(
db
==
nullptr
)
if
(
db
==
nullptr
)
return
false
;
return
false
;
...
@@ -131,7 +130,7 @@ PrintSongCount(Client &client, const char *name,
...
@@ -131,7 +130,7 @@ PrintSongCount(Client &client, const char *name,
if
(
!
db
->
Visit
(
selection
,
f
,
error
))
if
(
!
db
->
Visit
(
selection
,
f
,
error
))
return
false
;
return
false
;
PrintSearchStats
(
client
,
stats
);
PrintSearchStats
(
r
,
stats
);
}
else
{
}
else
{
/* group by the specified tag: store counts in a
/* group by the specified tag: store counts in a
std::map */
std::map */
...
@@ -144,7 +143,7 @@ PrintSongCount(Client &client, const char *name,
...
@@ -144,7 +143,7 @@ PrintSongCount(Client &client, const char *name,
if
(
!
db
->
Visit
(
selection
,
f
,
error
))
if
(
!
db
->
Visit
(
selection
,
f
,
error
))
return
false
;
return
false
;
Print
(
client
,
group
,
map
);
Print
(
r
,
group
,
map
);
}
}
return
true
;
return
true
;
...
...
src/db/Count.hxx
View file @
7652a298
...
@@ -25,13 +25,14 @@
...
@@ -25,13 +25,14 @@
#include <stdint.h>
#include <stdint.h>
enum
TagType
:
uint8_t
;
enum
TagType
:
uint8_t
;
class
Client
;
struct
Partition
;
class
Response
;
class
SongFilter
;
class
SongFilter
;
class
Error
;
class
Error
;
gcc_nonnull
(
2
)
gcc_nonnull
(
3
)
bool
bool
PrintSongCount
(
Client
&
client
,
const
char
*
name
,
PrintSongCount
(
Response
&
r
,
const
Partition
&
partition
,
const
char
*
name
,
const
SongFilter
*
filter
,
const
SongFilter
*
filter
,
TagType
group
,
TagType
group
,
Error
&
error
);
Error
&
error
);
...
...
src/db/DatabasePrint.cxx
View file @
7652a298
...
@@ -24,6 +24,8 @@
...
@@ -24,6 +24,8 @@
#include "SongPrint.hxx"
#include "SongPrint.hxx"
#include "TimePrint.hxx"
#include "TimePrint.hxx"
#include "client/Client.hxx"
#include "client/Client.hxx"
#include "client/Response.hxx"
#include "Partition.hxx"
#include "tag/Tag.hxx"
#include "tag/Tag.hxx"
#include "LightSong.hxx"
#include "LightSong.hxx"
#include "LightDirectory.hxx"
#include "LightDirectory.hxx"
...
@@ -42,116 +44,119 @@ ApplyBaseFlag(const char *uri, bool base)
...
@@ -42,116 +44,119 @@ ApplyBaseFlag(const char *uri, bool base)
}
}
static
void
static
void
PrintDirectoryURI
(
Client
&
client
,
bool
base
,
const
LightDirectory
&
directory
)
PrintDirectoryURI
(
Response
&
r
,
bool
base
,
const
LightDirectory
&
directory
)
{
{
client_printf
(
client
,
"directory: %s
\n
"
,
r
.
Format
(
"directory: %s
\n
"
,
ApplyBaseFlag
(
directory
.
GetPath
(),
base
));
ApplyBaseFlag
(
directory
.
GetPath
(),
base
));
}
}
static
bool
static
bool
PrintDirectoryBrief
(
Client
&
client
,
bool
base
,
const
LightDirectory
&
directory
)
PrintDirectoryBrief
(
Response
&
r
,
bool
base
,
const
LightDirectory
&
directory
)
{
{
if
(
!
directory
.
IsRoot
())
if
(
!
directory
.
IsRoot
())
PrintDirectoryURI
(
client
,
base
,
directory
);
PrintDirectoryURI
(
r
,
base
,
directory
);
return
true
;
return
true
;
}
}
static
bool
static
bool
PrintDirectoryFull
(
Client
&
client
,
bool
base
,
const
LightDirectory
&
directory
)
PrintDirectoryFull
(
Response
&
r
,
bool
base
,
const
LightDirectory
&
directory
)
{
{
if
(
!
directory
.
IsRoot
())
{
if
(
!
directory
.
IsRoot
())
{
PrintDirectoryURI
(
client
,
base
,
directory
);
PrintDirectoryURI
(
r
,
base
,
directory
);
if
(
directory
.
mtime
>
0
)
if
(
directory
.
mtime
>
0
)
time_print
(
client
,
"Last-Modified"
,
directory
.
mtime
);
time_print
(
r
,
"Last-Modified"
,
directory
.
mtime
);
}
}
return
true
;
return
true
;
}
}
static
void
static
void
print_playlist_in_directory
(
Client
&
client
,
bool
base
,
print_playlist_in_directory
(
Response
&
r
,
bool
base
,
const
char
*
directory
,
const
char
*
directory
,
const
char
*
name_utf8
)
const
char
*
name_utf8
)
{
{
if
(
base
||
directory
==
nullptr
)
if
(
base
||
directory
==
nullptr
)
client_printf
(
client
,
"playlist: %s
\n
"
,
r
.
Format
(
"playlist: %s
\n
"
,
ApplyBaseFlag
(
name_utf8
,
base
));
ApplyBaseFlag
(
name_utf8
,
base
));
else
else
client_printf
(
client
,
"playlist: %s/%s
\n
"
,
r
.
Format
(
"playlist: %s/%s
\n
"
,
directory
,
name_utf8
);
directory
,
name_utf8
);
}
}
static
void
static
void
print_playlist_in_directory
(
Client
&
client
,
bool
base
,
print_playlist_in_directory
(
Response
&
r
,
bool
base
,
const
LightDirectory
*
directory
,
const
LightDirectory
*
directory
,
const
char
*
name_utf8
)
const
char
*
name_utf8
)
{
{
if
(
base
||
directory
==
nullptr
||
directory
->
IsRoot
())
if
(
base
||
directory
==
nullptr
||
directory
->
IsRoot
())
client_printf
(
client
,
"playlist: %s
\n
"
,
name_utf8
);
r
.
Format
(
"playlist: %s
\n
"
,
name_utf8
);
else
else
client_printf
(
client
,
"playlist: %s/%s
\n
"
,
r
.
Format
(
"playlist: %s/%s
\n
"
,
directory
->
GetPath
(),
name_utf8
);
directory
->
GetPath
(),
name_utf8
);
}
}
static
bool
static
bool
PrintSongBrief
(
Client
&
client
,
bool
base
,
const
LightSong
&
song
)
PrintSongBrief
(
Response
&
r
,
Partition
&
partition
,
bool
base
,
const
LightSong
&
song
)
{
{
song_print_uri
(
client
,
song
,
base
);
song_print_uri
(
r
,
partition
,
song
,
base
);
if
(
song
.
tag
->
has_playlist
)
if
(
song
.
tag
->
has_playlist
)
/* this song file has an embedded CUE sheet */
/* this song file has an embedded CUE sheet */
print_playlist_in_directory
(
client
,
base
,
print_playlist_in_directory
(
r
,
base
,
song
.
directory
,
song
.
uri
);
song
.
directory
,
song
.
uri
);
return
true
;
return
true
;
}
}
static
bool
static
bool
PrintSongFull
(
Client
&
client
,
bool
base
,
const
LightSong
&
song
)
PrintSongFull
(
Response
&
r
,
Partition
&
partition
,
bool
base
,
const
LightSong
&
song
)
{
{
song_print_info
(
client
,
song
,
base
);
song_print_info
(
r
,
partition
,
song
,
base
);
if
(
song
.
tag
->
has_playlist
)
if
(
song
.
tag
->
has_playlist
)
/* this song file has an embedded CUE sheet */
/* this song file has an embedded CUE sheet */
print_playlist_in_directory
(
client
,
base
,
print_playlist_in_directory
(
r
,
base
,
song
.
directory
,
song
.
uri
);
song
.
directory
,
song
.
uri
);
return
true
;
return
true
;
}
}
static
bool
static
bool
PrintPlaylistBrief
(
Client
&
client
,
bool
base
,
PrintPlaylistBrief
(
Response
&
r
,
bool
base
,
const
PlaylistInfo
&
playlist
,
const
PlaylistInfo
&
playlist
,
const
LightDirectory
&
directory
)
const
LightDirectory
&
directory
)
{
{
print_playlist_in_directory
(
client
,
base
,
print_playlist_in_directory
(
r
,
base
,
&
directory
,
playlist
.
name
.
c_str
());
&
directory
,
playlist
.
name
.
c_str
());
return
true
;
return
true
;
}
}
static
bool
static
bool
PrintPlaylistFull
(
Client
&
client
,
bool
base
,
PrintPlaylistFull
(
Response
&
r
,
bool
base
,
const
PlaylistInfo
&
playlist
,
const
PlaylistInfo
&
playlist
,
const
LightDirectory
&
directory
)
const
LightDirectory
&
directory
)
{
{
print_playlist_in_directory
(
client
,
base
,
print_playlist_in_directory
(
r
,
base
,
&
directory
,
playlist
.
name
.
c_str
());
&
directory
,
playlist
.
name
.
c_str
());
if
(
playlist
.
mtime
>
0
)
if
(
playlist
.
mtime
>
0
)
time_print
(
client
,
"Last-Modified"
,
playlist
.
mtime
);
time_print
(
r
,
"Last-Modified"
,
playlist
.
mtime
);
return
true
;
return
true
;
}
}
bool
bool
db_selection_print
(
Client
&
client
,
const
DatabaseSelection
&
selection
,
db_selection_print
(
Response
&
r
,
Partition
&
partition
,
const
DatabaseSelection
&
selection
,
bool
full
,
bool
base
,
bool
full
,
bool
base
,
unsigned
window_start
,
unsigned
window_end
,
unsigned
window_start
,
unsigned
window_end
,
Error
&
error
)
Error
&
error
)
{
{
const
Database
*
db
=
client
.
GetDatabase
(
error
);
const
Database
*
db
=
partition
.
GetDatabase
(
error
);
if
(
db
==
nullptr
)
if
(
db
==
nullptr
)
return
false
;
return
false
;
...
@@ -160,13 +165,13 @@ db_selection_print(Client &client, const DatabaseSelection &selection,
...
@@ -160,13 +165,13 @@ db_selection_print(Client &client, const DatabaseSelection &selection,
using
namespace
std
::
placeholders
;
using
namespace
std
::
placeholders
;
const
auto
d
=
selection
.
filter
==
nullptr
const
auto
d
=
selection
.
filter
==
nullptr
?
std
::
bind
(
full
?
PrintDirectoryFull
:
PrintDirectoryBrief
,
?
std
::
bind
(
full
?
PrintDirectoryFull
:
PrintDirectoryBrief
,
std
::
ref
(
client
),
base
,
_1
)
std
::
ref
(
r
),
base
,
_1
)
:
VisitDirectory
();
:
VisitDirectory
();
VisitSong
s
=
std
::
bind
(
full
?
PrintSongFull
:
PrintSongBrief
,
VisitSong
s
=
std
::
bind
(
full
?
PrintSongFull
:
PrintSongBrief
,
std
::
ref
(
client
),
base
,
_1
);
std
::
ref
(
r
),
std
::
ref
(
partition
),
base
,
_1
);
const
auto
p
=
selection
.
filter
==
nullptr
const
auto
p
=
selection
.
filter
==
nullptr
?
std
::
bind
(
full
?
PrintPlaylistFull
:
PrintPlaylistBrief
,
?
std
::
bind
(
full
?
PrintPlaylistFull
:
PrintPlaylistBrief
,
std
::
ref
(
client
),
base
,
_1
,
_2
)
std
::
ref
(
r
),
base
,
_1
,
_2
)
:
VisitPlaylist
();
:
VisitPlaylist
();
if
(
window_start
>
0
||
if
(
window_start
>
0
||
...
@@ -182,45 +187,47 @@ db_selection_print(Client &client, const DatabaseSelection &selection,
...
@@ -182,45 +187,47 @@ db_selection_print(Client &client, const DatabaseSelection &selection,
}
}
bool
bool
db_selection_print
(
Client
&
client
,
const
DatabaseSelection
&
selection
,
db_selection_print
(
Response
&
r
,
Partition
&
partition
,
const
DatabaseSelection
&
selection
,
bool
full
,
bool
base
,
bool
full
,
bool
base
,
Error
&
error
)
Error
&
error
)
{
{
return
db_selection_print
(
client
,
selection
,
full
,
base
,
return
db_selection_print
(
r
,
partition
,
selection
,
full
,
base
,
0
,
std
::
numeric_limits
<
int
>::
max
(),
0
,
std
::
numeric_limits
<
int
>::
max
(),
error
);
error
);
}
}
static
bool
static
bool
PrintSongURIVisitor
(
Client
&
client
,
const
LightSong
&
song
)
PrintSongURIVisitor
(
Response
&
r
,
Partition
&
partition
,
const
LightSong
&
song
)
{
{
song_print_uri
(
client
,
song
);
song_print_uri
(
r
,
partition
,
song
);
return
true
;
return
true
;
}
}
static
bool
static
bool
PrintUniqueTag
(
Client
&
client
,
TagType
tag_type
,
PrintUniqueTag
(
Response
&
r
,
TagType
tag_type
,
const
Tag
&
tag
)
const
Tag
&
tag
)
{
{
const
char
*
value
=
tag
.
GetValue
(
tag_type
);
const
char
*
value
=
tag
.
GetValue
(
tag_type
);
assert
(
value
!=
nullptr
);
assert
(
value
!=
nullptr
);
client_printf
(
client
,
"%s: %s
\n
"
,
tag_item_names
[
tag_type
],
value
);
r
.
Format
(
"%s: %s
\n
"
,
tag_item_names
[
tag_type
],
value
);
for
(
const
auto
&
item
:
tag
)
for
(
const
auto
&
item
:
tag
)
if
(
item
.
type
!=
tag_type
)
if
(
item
.
type
!=
tag_type
)
client_printf
(
client
,
"%s: %s
\n
"
,
r
.
Format
(
"%s: %s
\n
"
,
tag_item_names
[
item
.
type
],
item
.
value
);
tag_item_names
[
item
.
type
],
item
.
value
);
return
true
;
return
true
;
}
}
bool
bool
PrintUniqueTags
(
Client
&
client
,
unsigned
type
,
uint32_t
group_mask
,
PrintUniqueTags
(
Response
&
r
,
Partition
&
partition
,
unsigned
type
,
uint32_t
group_mask
,
const
SongFilter
*
filter
,
const
SongFilter
*
filter
,
Error
&
error
)
Error
&
error
)
{
{
const
Database
*
db
=
client
.
GetDatabase
(
error
);
const
Database
*
db
=
partition
.
GetDatabase
(
error
);
if
(
db
==
nullptr
)
if
(
db
==
nullptr
)
return
false
;
return
false
;
...
@@ -229,13 +236,13 @@ PrintUniqueTags(Client &client, unsigned type, uint32_t group_mask,
...
@@ -229,13 +236,13 @@ PrintUniqueTags(Client &client, unsigned type, uint32_t group_mask,
if
(
type
==
LOCATE_TAG_FILE_TYPE
)
{
if
(
type
==
LOCATE_TAG_FILE_TYPE
)
{
using
namespace
std
::
placeholders
;
using
namespace
std
::
placeholders
;
const
auto
f
=
std
::
bind
(
PrintSongURIVisitor
,
const
auto
f
=
std
::
bind
(
PrintSongURIVisitor
,
std
::
ref
(
client
),
_1
);
std
::
ref
(
r
),
std
::
ref
(
partition
),
_1
);
return
db
->
Visit
(
selection
,
f
,
error
);
return
db
->
Visit
(
selection
,
f
,
error
);
}
else
{
}
else
{
assert
(
type
<
TAG_NUM_OF_ITEM_TYPES
);
assert
(
type
<
TAG_NUM_OF_ITEM_TYPES
);
using
namespace
std
::
placeholders
;
using
namespace
std
::
placeholders
;
const
auto
f
=
std
::
bind
(
PrintUniqueTag
,
std
::
ref
(
client
),
const
auto
f
=
std
::
bind
(
PrintUniqueTag
,
std
::
ref
(
r
),
(
TagType
)
type
,
_1
);
(
TagType
)
type
,
_1
);
return
db
->
VisitUniqueTags
(
selection
,
(
TagType
)
type
,
return
db
->
VisitUniqueTags
(
selection
,
(
TagType
)
type
,
group_mask
,
group_mask
,
...
...
src/db/DatabasePrint.hxx
View file @
7652a298
...
@@ -26,7 +26,9 @@
...
@@ -26,7 +26,9 @@
class
SongFilter
;
class
SongFilter
;
struct
DatabaseSelection
;
struct
DatabaseSelection
;
struct
Partition
;
class
Client
;
class
Client
;
class
Response
;
class
Error
;
class
Error
;
/**
/**
...
@@ -34,17 +36,20 @@ class Error;
...
@@ -34,17 +36,20 @@ class Error;
* @param base print only base name of songs/directories?
* @param base print only base name of songs/directories?
*/
*/
bool
bool
db_selection_print
(
Client
&
client
,
const
DatabaseSelection
&
selection
,
db_selection_print
(
Response
&
r
,
Partition
&
partition
,
const
DatabaseSelection
&
selection
,
bool
full
,
bool
base
,
Error
&
error
);
bool
full
,
bool
base
,
Error
&
error
);
bool
bool
db_selection_print
(
Client
&
client
,
const
DatabaseSelection
&
selection
,
db_selection_print
(
Response
&
r
,
Partition
&
partition
,
const
DatabaseSelection
&
selection
,
bool
full
,
bool
base
,
bool
full
,
bool
base
,
unsigned
window_start
,
unsigned
window_end
,
unsigned
window_start
,
unsigned
window_end
,
Error
&
error
);
Error
&
error
);
bool
bool
PrintUniqueTags
(
Client
&
client
,
unsigned
type
,
uint32_t
group_mask
,
PrintUniqueTags
(
Response
&
r
,
Partition
&
partition
,
unsigned
type
,
uint32_t
group_mask
,
const
SongFilter
*
filter
,
const
SongFilter
*
filter
,
Error
&
error
);
Error
&
error
);
...
...
src/decoder/DecoderPrint.cxx
View file @
7652a298
...
@@ -21,35 +21,35 @@
...
@@ -21,35 +21,35 @@
#include "DecoderPrint.hxx"
#include "DecoderPrint.hxx"
#include "DecoderList.hxx"
#include "DecoderList.hxx"
#include "DecoderPlugin.hxx"
#include "DecoderPlugin.hxx"
#include "client/
Client
.hxx"
#include "client/
Response
.hxx"
#include <functional>
#include <functional>
#include <assert.h>
#include <assert.h>
static
void
static
void
decoder_plugin_print
(
Client
&
client
,
decoder_plugin_print
(
Response
&
r
,
const
DecoderPlugin
&
plugin
)
const
DecoderPlugin
&
plugin
)
{
{
const
char
*
const
*
p
;
const
char
*
const
*
p
;
assert
(
plugin
.
name
!=
nullptr
);
assert
(
plugin
.
name
!=
nullptr
);
client_printf
(
client
,
"plugin: %s
\n
"
,
plugin
.
name
);
r
.
Format
(
"plugin: %s
\n
"
,
plugin
.
name
);
if
(
plugin
.
suffixes
!=
nullptr
)
if
(
plugin
.
suffixes
!=
nullptr
)
for
(
p
=
plugin
.
suffixes
;
*
p
!=
nullptr
;
++
p
)
for
(
p
=
plugin
.
suffixes
;
*
p
!=
nullptr
;
++
p
)
client_printf
(
client
,
"suffix: %s
\n
"
,
*
p
);
r
.
Format
(
"suffix: %s
\n
"
,
*
p
);
if
(
plugin
.
mime_types
!=
nullptr
)
if
(
plugin
.
mime_types
!=
nullptr
)
for
(
p
=
plugin
.
mime_types
;
*
p
!=
nullptr
;
++
p
)
for
(
p
=
plugin
.
mime_types
;
*
p
!=
nullptr
;
++
p
)
client_printf
(
client
,
"mime_type: %s
\n
"
,
*
p
);
r
.
Format
(
"mime_type: %s
\n
"
,
*
p
);
}
}
void
void
decoder_list_print
(
Client
&
client
)
decoder_list_print
(
Response
&
r
)
{
{
using
namespace
std
::
placeholders
;
using
namespace
std
::
placeholders
;
const
auto
f
=
std
::
bind
(
decoder_plugin_print
,
std
::
ref
(
client
),
_1
);
const
auto
f
=
std
::
bind
(
decoder_plugin_print
,
std
::
ref
(
r
),
_1
);
decoder_plugins_for_each_enabled
(
f
);
decoder_plugins_for_each_enabled
(
f
);
}
}
src/decoder/DecoderPrint.hxx
View file @
7652a298
...
@@ -20,9 +20,9 @@
...
@@ -20,9 +20,9 @@
#ifndef MPD_DECODER_PRINT_HXX
#ifndef MPD_DECODER_PRINT_HXX
#define MPD_DECODER_PRINT_HXX
#define MPD_DECODER_PRINT_HXX
class
Client
;
class
Response
;
void
void
decoder_list_print
(
Client
&
client
);
decoder_list_print
(
Response
&
r
);
#endif
#endif
src/ls.cxx
View file @
7652a298
...
@@ -19,9 +19,9 @@
...
@@ -19,9 +19,9 @@
#include "config.h"
#include "config.h"
#include "ls.hxx"
#include "ls.hxx"
#include "client/Response.hxx"
#include "util/StringUtil.hxx"
#include "util/StringUtil.hxx"
#include "util/UriUtil.hxx"
#include "util/UriUtil.hxx"
#include "client/Client.hxx"
#include <assert.h>
#include <assert.h>
...
@@ -78,12 +78,13 @@ void print_supported_uri_schemes_to_fp(FILE *fp)
...
@@ -78,12 +78,13 @@ void print_supported_uri_schemes_to_fp(FILE *fp)
fprintf
(
fp
,
"
\n
"
);
fprintf
(
fp
,
"
\n
"
);
}
}
void
print_supported_uri_schemes
(
Client
&
client
)
void
print_supported_uri_schemes
(
Response
&
r
)
{
{
const
char
*
const
*
prefixes
=
remoteUrlPrefixes
;
const
char
*
const
*
prefixes
=
remoteUrlPrefixes
;
while
(
*
prefixes
)
{
while
(
*
prefixes
)
{
client_printf
(
client
,
"handler: %s
\n
"
,
*
prefixes
);
r
.
Format
(
"handler: %s
\n
"
,
*
prefixes
);
prefixes
++
;
prefixes
++
;
}
}
}
}
...
...
src/ls.hxx
View file @
7652a298
...
@@ -24,7 +24,7 @@
...
@@ -24,7 +24,7 @@
#include <stdio.h>
#include <stdio.h>
class
Client
;
class
Response
;
/**
/**
* Checks whether the scheme of the specified URI is supported by MPD.
* Checks whether the scheme of the specified URI is supported by MPD.
...
@@ -38,7 +38,7 @@ bool uri_supported_scheme(const char *url);
...
@@ -38,7 +38,7 @@ bool uri_supported_scheme(const char *url);
* Send a list of supported URI schemes to the client. This is the
* Send a list of supported URI schemes to the client. This is the
* response to the "urlhandlers" command.
* response to the "urlhandlers" command.
*/
*/
void
print_supported_uri_schemes
(
Client
&
client
);
void
print_supported_uri_schemes
(
Response
&
r
);
/**
/**
* Send a list of supported URI schemes to a file pointer.
* Send a list of supported URI schemes to a file pointer.
...
...
src/output/OutputPrint.cxx
View file @
7652a298
...
@@ -26,18 +26,17 @@
...
@@ -26,18 +26,17 @@
#include "OutputPrint.hxx"
#include "OutputPrint.hxx"
#include "MultipleOutputs.hxx"
#include "MultipleOutputs.hxx"
#include "Internal.hxx"
#include "Internal.hxx"
#include "client/
Client
.hxx"
#include "client/
Response
.hxx"
void
void
printAudioDevices
(
Client
&
client
,
const
MultipleOutputs
&
outputs
)
printAudioDevices
(
Response
&
r
,
const
MultipleOutputs
&
outputs
)
{
{
for
(
unsigned
i
=
0
,
n
=
outputs
.
Size
();
i
!=
n
;
++
i
)
{
for
(
unsigned
i
=
0
,
n
=
outputs
.
Size
();
i
!=
n
;
++
i
)
{
const
AudioOutput
&
ao
=
outputs
.
Get
(
i
);
const
AudioOutput
&
ao
=
outputs
.
Get
(
i
);
client_printf
(
client
,
r
.
Format
(
"outputid: %i
\n
"
"outputid: %i
\n
"
"outputname: %s
\n
"
"outputname: %s
\n
"
"outputenabled: %i
\n
"
,
"outputenabled: %i
\n
"
,
i
,
ao
.
name
,
ao
.
enabled
);
i
,
ao
.
name
,
ao
.
enabled
);
}
}
}
}
src/output/OutputPrint.hxx
View file @
7652a298
...
@@ -25,10 +25,10 @@
...
@@ -25,10 +25,10 @@
#ifndef MPD_OUTPUT_PRINT_HXX
#ifndef MPD_OUTPUT_PRINT_HXX
#define MPD_OUTPUT_PRINT_HXX
#define MPD_OUTPUT_PRINT_HXX
class
Client
;
class
Response
;
class
MultipleOutputs
;
class
MultipleOutputs
;
void
void
printAudioDevices
(
Client
&
client
,
const
MultipleOutputs
&
outputs
);
printAudioDevices
(
Response
&
r
,
const
MultipleOutputs
&
outputs
);
#endif
#endif
src/playlist/Print.cxx
View file @
7652a298
...
@@ -28,48 +28,51 @@
...
@@ -28,48 +28,51 @@
#include "fs/Traits.hxx"
#include "fs/Traits.hxx"
#include "thread/Mutex.hxx"
#include "thread/Mutex.hxx"
#include "thread/Cond.hxx"
#include "thread/Cond.hxx"
#include "client/Client.hxx"
#include "Partition.hxx"
#include "Instance.hxx"
static
void
static
void
playlist_provider_print
(
Client
&
client
,
const
char
*
uri
,
playlist_provider_print
(
Response
&
r
,
Partition
&
partition
,
const
SongLoader
&
loader
,
const
char
*
uri
,
SongEnumerator
&
e
,
bool
detail
)
SongEnumerator
&
e
,
bool
detail
)
{
{
const
std
::
string
base_uri
=
uri
!=
nullptr
const
std
::
string
base_uri
=
uri
!=
nullptr
?
PathTraitsUTF8
::
GetParent
(
uri
)
?
PathTraitsUTF8
::
GetParent
(
uri
)
:
std
::
string
(
"."
);
:
std
::
string
(
"."
);
const
SongLoader
loader
(
client
);
DetachedSong
*
song
;
DetachedSong
*
song
;
while
((
song
=
e
.
NextSong
())
!=
nullptr
)
{
while
((
song
=
e
.
NextSong
())
!=
nullptr
)
{
if
(
playlist_check_translate_song
(
*
song
,
base_uri
.
c_str
(),
if
(
playlist_check_translate_song
(
*
song
,
base_uri
.
c_str
(),
loader
)
&&
loader
)
&&
detail
)
detail
)
song_print_info
(
client
,
*
song
);
song_print_info
(
r
,
partition
,
*
song
);
else
else
/* fallback if no detail was requested or no
/* fallback if no detail was requested or no
detail was available */
detail was available */
song_print_uri
(
client
,
*
song
);
song_print_uri
(
r
,
partition
,
*
song
);
delete
song
;
delete
song
;
}
}
}
}
bool
bool
playlist_file_print
(
Client
&
client
,
const
char
*
uri
,
bool
detail
)
playlist_file_print
(
Response
&
r
,
Partition
&
partition
,
const
SongLoader
&
loader
,
const
char
*
uri
,
bool
detail
)
{
{
Mutex
mutex
;
Mutex
mutex
;
Cond
cond
;
Cond
cond
;
SongEnumerator
*
playlist
=
playlist_open_any
(
uri
,
SongEnumerator
*
playlist
=
playlist_open_any
(
uri
,
#ifdef ENABLE_DATABASE
#ifdef ENABLE_DATABASE
client
.
GetStorage
()
,
partition
.
instance
.
storage
,
#endif
#endif
mutex
,
cond
);
mutex
,
cond
);
if
(
playlist
==
nullptr
)
if
(
playlist
==
nullptr
)
return
false
;
return
false
;
playlist_provider_print
(
client
,
uri
,
*
playlist
,
detail
);
playlist_provider_print
(
r
,
partition
,
loader
,
uri
,
*
playlist
,
detail
);
delete
playlist
;
delete
playlist
;
return
true
;
return
true
;
}
}
src/playlist/Print.hxx
View file @
7652a298
...
@@ -20,17 +20,20 @@
...
@@ -20,17 +20,20 @@
#ifndef MPD_PLAYLIST__PRINT_HXX
#ifndef MPD_PLAYLIST__PRINT_HXX
#define MPD_PLAYLIST__PRINT_HXX
#define MPD_PLAYLIST__PRINT_HXX
class
Client
;
class
Response
;
class
SongLoader
;
struct
Partition
;
/**
/**
* Send the playlist file to the client.
* Send the playlist file to the client.
*
*
* @param client the client which requested the playlist
* @param uri the URI of the playlist file in UTF-8 encoding
* @param uri the URI of the playlist file in UTF-8 encoding
* @param detail true if all details should be printed
* @param detail true if all details should be printed
* @return true on success, false if the playlist does not exist
* @return true on success, false if the playlist does not exist
*/
*/
bool
bool
playlist_file_print
(
Client
&
client
,
const
char
*
uri
,
bool
detail
);
playlist_file_print
(
Response
&
r
,
Partition
&
partition
,
const
SongLoader
&
loader
,
const
char
*
uri
,
bool
detail
);
#endif
#endif
src/protocol/ArgParser.cxx
View file @
7652a298
...
@@ -19,27 +19,26 @@
...
@@ -19,27 +19,26 @@
#include "config.h"
#include "config.h"
#include "ArgParser.hxx"
#include "ArgParser.hxx"
#include "Result.hxx"
#include "Chrono.hxx"
#include "Chrono.hxx"
#include "client/Response.hxx"
#include <stdlib.h>
#include <stdlib.h>
bool
bool
check_uint32
(
Client
&
client
,
uint32_t
*
dst
,
const
char
*
s
)
ParseCommandArg32
(
Response
&
r
,
uint32_t
&
value_r
,
const
char
*
s
)
{
{
char
*
test
;
char
*
test
;
*
dst
=
strtoul
(
s
,
&
test
,
10
);
value_r
=
strtoul
(
s
,
&
test
,
10
);
if
(
test
==
s
||
*
test
!=
'\0'
)
{
if
(
test
==
s
||
*
test
!=
'\0'
)
{
command_error
(
client
,
ACK_ERROR_ARG
,
r
.
FormatError
(
ACK_ERROR_ARG
,
"Integer expected: %s"
,
s
);
"Integer expected: %s"
,
s
);
return
false
;
return
false
;
}
}
return
true
;
return
true
;
}
}
bool
bool
ParseCommandArg
(
Client
&
client
,
int
&
value_r
,
const
char
*
s
,
ParseCommandArg
(
Response
&
r
,
int
&
value_r
,
const
char
*
s
,
int
min_value
,
int
max_value
)
int
min_value
,
int
max_value
)
{
{
char
*
test
;
char
*
test
;
...
@@ -47,14 +46,12 @@ ParseCommandArg(Client &client, int &value_r, const char *s,
...
@@ -47,14 +46,12 @@ ParseCommandArg(Client &client, int &value_r, const char *s,
value
=
strtol
(
s
,
&
test
,
10
);
value
=
strtol
(
s
,
&
test
,
10
);
if
(
test
==
s
||
*
test
!=
'\0'
)
{
if
(
test
==
s
||
*
test
!=
'\0'
)
{
command_error
(
client
,
ACK_ERROR_ARG
,
r
.
FormatError
(
ACK_ERROR_ARG
,
"Integer expected: %s"
,
s
);
"Integer expected: %s"
,
s
);
return
false
;
return
false
;
}
}
if
(
value
<
min_value
||
value
>
max_value
)
{
if
(
value
<
min_value
||
value
>
max_value
)
{
command_error
(
client
,
ACK_ERROR_ARG
,
r
.
FormatError
(
ACK_ERROR_ARG
,
"Number too large: %s"
,
s
);
"Number too large: %s"
,
s
);
return
false
;
return
false
;
}
}
...
@@ -63,22 +60,22 @@ ParseCommandArg(Client &client, int &value_r, const char *s,
...
@@ -63,22 +60,22 @@ ParseCommandArg(Client &client, int &value_r, const char *s,
}
}
bool
bool
ParseCommandArg
(
Client
&
client
,
int
&
value_r
,
const
char
*
s
)
ParseCommandArg
(
Response
&
r
,
int
&
value_r
,
const
char
*
s
)
{
{
return
ParseCommandArg
(
client
,
value_r
,
s
,
return
ParseCommandArg
(
r
,
value_r
,
s
,
std
::
numeric_limits
<
int
>::
min
(),
std
::
numeric_limits
<
int
>::
min
(),
std
::
numeric_limits
<
int
>::
max
());
std
::
numeric_limits
<
int
>::
max
());
}
}
bool
bool
ParseCommandArg
(
Client
&
client
,
RangeArg
&
value_r
,
const
char
*
s
)
ParseCommandArg
(
Response
&
r
,
RangeArg
&
value_r
,
const
char
*
s
)
{
{
char
*
test
,
*
test2
;
char
*
test
,
*
test2
;
long
value
;
long
value
;
value
=
strtol
(
s
,
&
test
,
10
);
value
=
strtol
(
s
,
&
test
,
10
);
if
(
test
==
s
||
(
*
test
!=
'\0'
&&
*
test
!=
':'
))
{
if
(
test
==
s
||
(
*
test
!=
'\0'
&&
*
test
!=
':'
))
{
command_error
(
client
,
ACK_ERROR_ARG
,
r
.
FormatError
(
ACK_ERROR_ARG
,
"Integer or range expected: %s"
,
s
);
"Integer or range expected: %s"
,
s
);
return
false
;
return
false
;
}
}
...
@@ -92,14 +89,12 @@ ParseCommandArg(Client &client, RangeArg &value_r, const char *s)
...
@@ -92,14 +89,12 @@ ParseCommandArg(Client &client, RangeArg &value_r, const char *s)
}
}
if
(
value
<
0
)
{
if
(
value
<
0
)
{
command_error
(
client
,
ACK_ERROR_ARG
,
r
.
FormatError
(
ACK_ERROR_ARG
,
"Number is negative: %s"
,
s
);
"Number is negative: %s"
,
s
);
return
false
;
return
false
;
}
}
if
(
unsigned
(
value
)
>
std
::
numeric_limits
<
unsigned
>::
max
())
{
if
(
unsigned
(
value
)
>
std
::
numeric_limits
<
unsigned
>::
max
())
{
command_error
(
client
,
ACK_ERROR_ARG
,
r
.
FormatError
(
ACK_ERROR_ARG
,
"Number too large: %s"
,
s
);
"Number too large: %s"
,
s
);
return
false
;
return
false
;
}
}
...
@@ -108,7 +103,7 @@ ParseCommandArg(Client &client, RangeArg &value_r, const char *s)
...
@@ -108,7 +103,7 @@ ParseCommandArg(Client &client, RangeArg &value_r, const char *s)
if
(
*
test
==
':'
)
{
if
(
*
test
==
':'
)
{
value
=
strtol
(
++
test
,
&
test2
,
10
);
value
=
strtol
(
++
test
,
&
test2
,
10
);
if
(
*
test2
!=
'\0'
)
{
if
(
*
test2
!=
'\0'
)
{
command_error
(
client
,
ACK_ERROR_ARG
,
r
.
FormatError
(
ACK_ERROR_ARG
,
"Integer or range expected: %s"
,
s
);
"Integer or range expected: %s"
,
s
);
return
false
;
return
false
;
}
}
...
@@ -117,13 +112,13 @@ ParseCommandArg(Client &client, RangeArg &value_r, const char *s)
...
@@ -117,13 +112,13 @@ ParseCommandArg(Client &client, RangeArg &value_r, const char *s)
value
=
std
::
numeric_limits
<
int
>::
max
();
value
=
std
::
numeric_limits
<
int
>::
max
();
if
(
value
<
0
)
{
if
(
value
<
0
)
{
command_error
(
client
,
ACK_ERROR_ARG
,
r
.
FormatError
(
ACK_ERROR_ARG
,
"Number is negative: %s"
,
s
);
"Number is negative: %s"
,
s
);
return
false
;
return
false
;
}
}
if
(
unsigned
(
value
)
>
std
::
numeric_limits
<
unsigned
>::
max
())
{
if
(
unsigned
(
value
)
>
std
::
numeric_limits
<
unsigned
>::
max
())
{
command_error
(
client
,
ACK_ERROR_ARG
,
r
.
FormatError
(
ACK_ERROR_ARG
,
"Number too large: %s"
,
s
);
"Number too large: %s"
,
s
);
return
false
;
return
false
;
}
}
...
@@ -137,7 +132,7 @@ ParseCommandArg(Client &client, RangeArg &value_r, const char *s)
...
@@ -137,7 +132,7 @@ ParseCommandArg(Client &client, RangeArg &value_r, const char *s)
}
}
bool
bool
ParseCommandArg
(
Client
&
client
,
unsigned
&
value_r
,
const
char
*
s
,
ParseCommandArg
(
Response
&
r
,
unsigned
&
value_r
,
const
char
*
s
,
unsigned
max_value
)
unsigned
max_value
)
{
{
unsigned
long
value
;
unsigned
long
value
;
...
@@ -145,13 +140,12 @@ ParseCommandArg(Client &client, unsigned &value_r, const char *s,
...
@@ -145,13 +140,12 @@ ParseCommandArg(Client &client, unsigned &value_r, const char *s,
value
=
strtoul
(
s
,
&
endptr
,
10
);
value
=
strtoul
(
s
,
&
endptr
,
10
);
if
(
endptr
==
s
||
*
endptr
!=
0
)
{
if
(
endptr
==
s
||
*
endptr
!=
0
)
{
command_error
(
client
,
ACK_ERROR_ARG
,
r
.
FormatError
(
ACK_ERROR_ARG
,
"Integer expected: %s"
,
s
);
"Integer expected: %s"
,
s
);
return
false
;
return
false
;
}
}
if
(
value
>
max_value
)
{
if
(
value
>
max_value
)
{
command_error
(
client
,
ACK_ERROR_ARG
,
r
.
FormatError
(
ACK_ERROR_ARG
,
"Number too large: %s"
,
s
);
"Number too large: %s"
,
s
);
return
false
;
return
false
;
}
}
...
@@ -161,21 +155,21 @@ ParseCommandArg(Client &client, unsigned &value_r, const char *s,
...
@@ -161,21 +155,21 @@ ParseCommandArg(Client &client, unsigned &value_r, const char *s,
}
}
bool
bool
ParseCommandArg
(
Client
&
client
,
unsigned
&
value_r
,
const
char
*
s
)
ParseCommandArg
(
Response
&
r
,
unsigned
&
value_r
,
const
char
*
s
)
{
{
return
ParseCommandArg
(
client
,
value_r
,
s
,
return
ParseCommandArg
(
r
,
value_r
,
s
,
std
::
numeric_limits
<
unsigned
>::
max
());
std
::
numeric_limits
<
unsigned
>::
max
());
}
}
bool
bool
ParseCommandArg
(
Client
&
client
,
bool
&
value_r
,
const
char
*
s
)
ParseCommandArg
(
Response
&
r
,
bool
&
value_r
,
const
char
*
s
)
{
{
long
value
;
long
value
;
char
*
endptr
;
char
*
endptr
;
value
=
strtol
(
s
,
&
endptr
,
10
);
value
=
strtol
(
s
,
&
endptr
,
10
);
if
(
endptr
==
s
||
*
endptr
!=
0
||
(
value
!=
0
&&
value
!=
1
))
{
if
(
endptr
==
s
||
*
endptr
!=
0
||
(
value
!=
0
&&
value
!=
1
))
{
command_error
(
client
,
ACK_ERROR_ARG
,
r
.
FormatError
(
ACK_ERROR_ARG
,
"Boolean (0/1) expected: %s"
,
s
);
"Boolean (0/1) expected: %s"
,
s
);
return
false
;
return
false
;
}
}
...
@@ -185,15 +179,14 @@ ParseCommandArg(Client &client, bool &value_r, const char *s)
...
@@ -185,15 +179,14 @@ ParseCommandArg(Client &client, bool &value_r, const char *s)
}
}
bool
bool
ParseCommandArg
(
Client
&
client
,
float
&
value_r
,
const
char
*
s
)
ParseCommandArg
(
Response
&
r
,
float
&
value_r
,
const
char
*
s
)
{
{
float
value
;
float
value
;
char
*
endptr
;
char
*
endptr
;
value
=
strtof
(
s
,
&
endptr
);
value
=
strtof
(
s
,
&
endptr
);
if
(
endptr
==
s
||
*
endptr
!=
0
)
{
if
(
endptr
==
s
||
*
endptr
!=
0
)
{
command_error
(
client
,
ACK_ERROR_ARG
,
r
.
FormatError
(
ACK_ERROR_ARG
,
"Float expected: %s"
,
s
);
"Float expected: %s"
,
s
);
return
false
;
return
false
;
}
}
...
@@ -202,10 +195,10 @@ ParseCommandArg(Client &client, float &value_r, const char *s)
...
@@ -202,10 +195,10 @@ ParseCommandArg(Client &client, float &value_r, const char *s)
}
}
bool
bool
ParseCommandArg
(
Client
&
client
,
SongTime
&
value_r
,
const
char
*
s
)
ParseCommandArg
(
Response
&
r
,
SongTime
&
value_r
,
const
char
*
s
)
{
{
float
value
;
float
value
;
bool
success
=
ParseCommandArg
(
client
,
value
,
s
)
&&
value
>=
0
;
bool
success
=
ParseCommandArg
(
r
,
value
,
s
)
&&
value
>=
0
;
if
(
success
)
if
(
success
)
value_r
=
SongTime
::
FromS
(
value
);
value_r
=
SongTime
::
FromS
(
value
);
...
@@ -213,10 +206,10 @@ ParseCommandArg(Client &client, SongTime &value_r, const char *s)
...
@@ -213,10 +206,10 @@ ParseCommandArg(Client &client, SongTime &value_r, const char *s)
}
}
bool
bool
ParseCommandArg
(
Client
&
client
,
SignedSongTime
&
value_r
,
const
char
*
s
)
ParseCommandArg
(
Response
&
r
,
SignedSongTime
&
value_r
,
const
char
*
s
)
{
{
float
value
;
float
value
;
bool
success
=
ParseCommandArg
(
client
,
value
,
s
);
bool
success
=
ParseCommandArg
(
r
,
value
,
s
);
if
(
success
)
if
(
success
)
value_r
=
SignedSongTime
::
FromS
(
value
);
value_r
=
SignedSongTime
::
FromS
(
value
);
...
...
src/protocol/ArgParser.hxx
View file @
7652a298
...
@@ -26,19 +26,19 @@
...
@@ -26,19 +26,19 @@
#include <stdint.h>
#include <stdint.h>
class
Client
;
class
Response
;
class
SongTime
;
class
SongTime
;
class
SignedSongTime
;
class
SignedSongTime
;
bool
bool
check_uint32
(
Client
&
client
,
uint32_t
*
dst
,
const
char
*
s
);
ParseCommandArg32
(
Response
&
r
,
uint32_t
&
value_r
,
const
char
*
s
);
bool
bool
ParseCommandArg
(
Client
&
client
,
int
&
value_r
,
const
char
*
s
,
ParseCommandArg
(
Response
&
r
,
int
&
value_r
,
const
char
*
s
,
int
min_value
,
int
max_value
);
int
min_value
,
int
max_value
);
bool
bool
ParseCommandArg
(
Client
&
client
,
int
&
value_r
,
const
char
*
s
);
ParseCommandArg
(
Response
&
r
,
int
&
value_r
,
const
char
*
s
);
struct
RangeArg
{
struct
RangeArg
{
unsigned
start
,
end
;
unsigned
start
,
end
;
...
@@ -54,25 +54,25 @@ struct RangeArg {
...
@@ -54,25 +54,25 @@ struct RangeArg {
};
};
bool
bool
ParseCommandArg
(
Client
&
client
,
RangeArg
&
value_r
,
const
char
*
s
);
ParseCommandArg
(
Response
&
r
,
RangeArg
&
value_r
,
const
char
*
s
);
bool
bool
ParseCommandArg
(
Client
&
client
,
unsigned
&
value_r
,
const
char
*
s
,
ParseCommandArg
(
Response
&
r
,
unsigned
&
value_r
,
const
char
*
s
,
unsigned
max_value
);
unsigned
max_value
);
bool
bool
ParseCommandArg
(
Client
&
client
,
unsigned
&
value_r
,
const
char
*
s
);
ParseCommandArg
(
Response
&
r
,
unsigned
&
value_r
,
const
char
*
s
);
bool
bool
ParseCommandArg
(
Client
&
client
,
bool
&
value_r
,
const
char
*
s
);
ParseCommandArg
(
Response
&
r
,
bool
&
value_r
,
const
char
*
s
);
bool
bool
ParseCommandArg
(
Client
&
client
,
float
&
value_r
,
const
char
*
s
);
ParseCommandArg
(
Response
&
r
,
float
&
value_r
,
const
char
*
s
);
bool
bool
ParseCommandArg
(
Client
&
client
,
SongTime
&
value_r
,
const
char
*
s
);
ParseCommandArg
(
Response
&
r
,
SongTime
&
value_r
,
const
char
*
s
);
bool
bool
ParseCommandArg
(
Client
&
client
,
SignedSongTime
&
value_r
,
const
char
*
s
);
ParseCommandArg
(
Response
&
r
,
SignedSongTime
&
value_r
,
const
char
*
s
);
#endif
#endif
src/queue/QueuePrint.cxx
View file @
7652a298
...
@@ -22,7 +22,7 @@
...
@@ -22,7 +22,7 @@
#include "Queue.hxx"
#include "Queue.hxx"
#include "SongFilter.hxx"
#include "SongFilter.hxx"
#include "SongPrint.hxx"
#include "SongPrint.hxx"
#include "client/
Client
.hxx"
#include "client/
Response
.hxx"
/**
/**
* Send detailed information about a range of songs in the queue to a
* Send detailed information about a range of songs in the queue to a
...
@@ -33,70 +33,70 @@
...
@@ -33,70 +33,70 @@
* @param end the index of the last song (excluding)
* @param end the index of the last song (excluding)
*/
*/
static
void
static
void
queue_print_song_info
(
Client
&
client
,
const
Queue
&
queue
,
queue_print_song_info
(
Response
&
r
,
Partition
&
partition
,
const
Queue
&
queue
,
unsigned
position
)
unsigned
position
)
{
{
song_print_info
(
client
,
queue
.
Get
(
position
));
song_print_info
(
r
,
partition
,
queue
.
Get
(
position
));
client_printf
(
client
,
"Pos: %u
\n
Id: %u
\n
"
,
r
.
Format
(
"Pos: %u
\n
Id: %u
\n
"
,
position
,
queue
.
PositionToId
(
position
));
position
,
queue
.
PositionToId
(
position
));
uint8_t
priority
=
queue
.
GetPriorityAtPosition
(
position
);
uint8_t
priority
=
queue
.
GetPriorityAtPosition
(
position
);
if
(
priority
!=
0
)
if
(
priority
!=
0
)
client_printf
(
client
,
"Prio: %u
\n
"
,
priority
);
r
.
Format
(
"Prio: %u
\n
"
,
priority
);
}
}
void
void
queue_print_info
(
Client
&
client
,
const
Queue
&
queue
,
queue_print_info
(
Response
&
r
,
Partition
&
partition
,
const
Queue
&
queue
,
unsigned
start
,
unsigned
end
)
unsigned
start
,
unsigned
end
)
{
{
assert
(
start
<=
end
);
assert
(
start
<=
end
);
assert
(
end
<=
queue
.
GetLength
());
assert
(
end
<=
queue
.
GetLength
());
for
(
unsigned
i
=
start
;
i
<
end
;
++
i
)
for
(
unsigned
i
=
start
;
i
<
end
;
++
i
)
queue_print_song_info
(
client
,
queue
,
i
);
queue_print_song_info
(
r
,
partition
,
queue
,
i
);
}
}
void
void
queue_print_uris
(
Client
&
client
,
const
Queue
&
queue
,
queue_print_uris
(
Response
&
r
,
Partition
&
partition
,
const
Queue
&
queue
,
unsigned
start
,
unsigned
end
)
unsigned
start
,
unsigned
end
)
{
{
assert
(
start
<=
end
);
assert
(
start
<=
end
);
assert
(
end
<=
queue
.
GetLength
());
assert
(
end
<=
queue
.
GetLength
());
for
(
unsigned
i
=
start
;
i
<
end
;
++
i
)
{
for
(
unsigned
i
=
start
;
i
<
end
;
++
i
)
{
client_printf
(
client
,
"%i:"
,
i
);
r
.
Format
(
"%i:"
,
i
);
song_print_uri
(
client
,
queue
.
Get
(
i
));
song_print_uri
(
r
,
partition
,
queue
.
Get
(
i
));
}
}
}
}
void
void
queue_print_changes_info
(
Client
&
client
,
const
Queue
&
queue
,
queue_print_changes_info
(
Response
&
r
,
Partition
&
partition
,
const
Queue
&
queue
,
uint32_t
version
)
uint32_t
version
)
{
{
for
(
unsigned
i
=
0
;
i
<
queue
.
GetLength
();
i
++
)
{
for
(
unsigned
i
=
0
;
i
<
queue
.
GetLength
();
i
++
)
{
if
(
queue
.
IsNewerAtPosition
(
i
,
version
))
if
(
queue
.
IsNewerAtPosition
(
i
,
version
))
queue_print_song_info
(
client
,
queue
,
i
);
queue_print_song_info
(
r
,
partition
,
queue
,
i
);
}
}
}
}
void
void
queue_print_changes_position
(
Client
&
client
,
const
Queue
&
queue
,
queue_print_changes_position
(
Response
&
r
,
const
Queue
&
queue
,
uint32_t
version
)
uint32_t
version
)
{
{
for
(
unsigned
i
=
0
;
i
<
queue
.
GetLength
();
i
++
)
for
(
unsigned
i
=
0
;
i
<
queue
.
GetLength
();
i
++
)
if
(
queue
.
IsNewerAtPosition
(
i
,
version
))
if
(
queue
.
IsNewerAtPosition
(
i
,
version
))
client_printf
(
client
,
"cpos: %i
\n
Id: %i
\n
"
,
r
.
Format
(
"cpos: %i
\n
Id: %i
\n
"
,
i
,
queue
.
PositionToId
(
i
));
i
,
queue
.
PositionToId
(
i
));
}
}
void
void
queue_find
(
Client
&
client
,
const
Queue
&
queue
,
queue_find
(
Response
&
r
,
Partition
&
partition
,
const
Queue
&
queue
,
const
SongFilter
&
filter
)
const
SongFilter
&
filter
)
{
{
for
(
unsigned
i
=
0
;
i
<
queue
.
GetLength
();
i
++
)
{
for
(
unsigned
i
=
0
;
i
<
queue
.
GetLength
();
i
++
)
{
const
DetachedSong
&
song
=
queue
.
Get
(
i
);
const
DetachedSong
&
song
=
queue
.
Get
(
i
);
if
(
filter
.
Match
(
song
))
if
(
filter
.
Match
(
song
))
queue_print_song_info
(
client
,
queue
,
i
);
queue_print_song_info
(
r
,
partition
,
queue
,
i
);
}
}
}
}
src/queue/QueuePrint.hxx
View file @
7652a298
...
@@ -28,27 +28,28 @@
...
@@ -28,27 +28,28 @@
#include <stdint.h>
#include <stdint.h>
struct
Queue
;
struct
Queue
;
struct
Partition
;
class
SongFilter
;
class
SongFilter
;
class
Client
;
class
Response
;
void
void
queue_print_info
(
Client
&
client
,
const
Queue
&
queue
,
queue_print_info
(
Response
&
r
,
Partition
&
partition
,
const
Queue
&
queue
,
unsigned
start
,
unsigned
end
);
unsigned
start
,
unsigned
end
);
void
void
queue_print_uris
(
Client
&
client
,
const
Queue
&
queue
,
queue_print_uris
(
Response
&
r
,
Partition
&
partition
,
const
Queue
&
queue
,
unsigned
start
,
unsigned
end
);
unsigned
start
,
unsigned
end
);
void
void
queue_print_changes_info
(
Client
&
client
,
const
Queue
&
queue
,
queue_print_changes_info
(
Response
&
r
,
Partition
&
partition
,
const
Queue
&
queue
,
uint32_t
version
);
uint32_t
version
);
void
void
queue_print_changes_position
(
Client
&
client
,
const
Queue
&
queue
,
queue_print_changes_position
(
Response
&
r
,
const
Queue
&
queue
,
uint32_t
version
);
uint32_t
version
);
void
void
queue_find
(
Client
&
client
,
const
Queue
&
queue
,
queue_find
(
Response
&
response
,
Partition
&
partition
,
const
Queue
&
queue
,
const
SongFilter
&
filter
);
const
SongFilter
&
filter
);
#endif
#endif
src/sticker/StickerPrint.cxx
View file @
7652a298
...
@@ -20,25 +20,25 @@
...
@@ -20,25 +20,25 @@
#include "config.h"
#include "config.h"
#include "StickerPrint.hxx"
#include "StickerPrint.hxx"
#include "StickerDatabase.hxx"
#include "StickerDatabase.hxx"
#include "client/
Client
.hxx"
#include "client/
Response
.hxx"
void
void
sticker_print_value
(
Client
&
client
,
sticker_print_value
(
Response
&
r
,
const
char
*
name
,
const
char
*
value
)
const
char
*
name
,
const
char
*
value
)
{
{
client_printf
(
client
,
"sticker: %s=%s
\n
"
,
name
,
value
);
r
.
Format
(
"sticker: %s=%s
\n
"
,
name
,
value
);
}
}
static
void
static
void
print_sticker_cb
(
const
char
*
name
,
const
char
*
value
,
void
*
data
)
print_sticker_cb
(
const
char
*
name
,
const
char
*
value
,
void
*
data
)
{
{
Client
&
client
=
*
(
Client
*
)
data
;
auto
&
r
=
*
(
Response
*
)
data
;
sticker_print_value
(
client
,
name
,
value
);
sticker_print_value
(
r
,
name
,
value
);
}
}
void
void
sticker_print
(
Client
&
client
,
const
Sticker
&
sticker
)
sticker_print
(
Response
&
r
,
const
Sticker
&
sticker
)
{
{
sticker_foreach
(
sticker
,
print_sticker_cb
,
&
client
);
sticker_foreach
(
sticker
,
print_sticker_cb
,
&
r
);
}
}
src/sticker/StickerPrint.hxx
View file @
7652a298
...
@@ -21,18 +21,18 @@
...
@@ -21,18 +21,18 @@
#define MPD_STICKER_PRINT_HXX
#define MPD_STICKER_PRINT_HXX
struct
Sticker
;
struct
Sticker
;
class
Client
;
class
Response
;
/**
/**
* Sends one sticker value to the client.
* Sends one sticker value to the client.
*/
*/
void
void
sticker_print_value
(
Client
&
client
,
const
char
*
name
,
const
char
*
value
);
sticker_print_value
(
Response
&
r
,
const
char
*
name
,
const
char
*
value
);
/**
/**
* Sends all sticker values to the client.
* Sends all sticker values to the client.
*/
*/
void
void
sticker_print
(
Client
&
client
,
const
Sticker
&
sticker
);
sticker_print
(
Response
&
r
,
const
Sticker
&
sticker
);
#endif
#endif
test/test_protocol.cxx
View file @
7652a298
#include "config.h"
#include "config.h"
#include "protocol/ArgParser.hxx"
#include "protocol/ArgParser.hxx"
#include "
protocol/Result
.hxx"
#include "
client/Response
.hxx"
#include "Compiler.h"
#include "Compiler.h"
#include <cppunit/TestFixture.h>
#include <cppunit/TestFixture.h>
...
@@ -13,10 +13,15 @@
...
@@ -13,10 +13,15 @@
static
enum
ack
last_error
=
ack
(
-
1
);
static
enum
ack
last_error
=
ack
(
-
1
);
void
void
command_error
(
gcc_unused
Client
&
client
,
enum
ack
error
,
Response
::
Error
(
enum
ack
code
,
gcc_unused
const
char
*
msg
)
gcc_unused
const
char
*
fmt
,
...)
{
{
last_error
=
error
;
last_error
=
code
;
}
void
Response
::
FormatError
(
enum
ack
code
,
gcc_unused
const
char
*
fmt
,
...)
{
last_error
=
code
;
}
}
class
ArgParserTest
:
public
CppUnit
::
TestFixture
{
class
ArgParserTest
:
public
CppUnit
::
TestFixture
{
...
@@ -32,22 +37,23 @@ void
...
@@ -32,22 +37,23 @@ void
ArgParserTest
::
TestRange
()
ArgParserTest
::
TestRange
()
{
{
Client
&
client
=
*
(
Client
*
)
nullptr
;
Client
&
client
=
*
(
Client
*
)
nullptr
;
Response
r
(
client
);
RangeArg
range
;
RangeArg
range
;
CPPUNIT_ASSERT
(
ParseCommandArg
(
client
,
range
,
"1"
));
CPPUNIT_ASSERT
(
ParseCommandArg
(
r
,
range
,
"1"
));
CPPUNIT_ASSERT_EQUAL
(
1u
,
range
.
start
);
CPPUNIT_ASSERT_EQUAL
(
1u
,
range
.
start
);
CPPUNIT_ASSERT_EQUAL
(
2u
,
range
.
end
);
CPPUNIT_ASSERT_EQUAL
(
2u
,
range
.
end
);
CPPUNIT_ASSERT
(
ParseCommandArg
(
client
,
range
,
"1:5"
));
CPPUNIT_ASSERT
(
ParseCommandArg
(
r
,
range
,
"1:5"
));
CPPUNIT_ASSERT_EQUAL
(
1u
,
range
.
start
);
CPPUNIT_ASSERT_EQUAL
(
1u
,
range
.
start
);
CPPUNIT_ASSERT_EQUAL
(
5u
,
range
.
end
);
CPPUNIT_ASSERT_EQUAL
(
5u
,
range
.
end
);
CPPUNIT_ASSERT
(
ParseCommandArg
(
client
,
range
,
"1:"
));
CPPUNIT_ASSERT
(
ParseCommandArg
(
r
,
range
,
"1:"
));
CPPUNIT_ASSERT_EQUAL
(
1u
,
range
.
start
);
CPPUNIT_ASSERT_EQUAL
(
1u
,
range
.
start
);
CPPUNIT_ASSERT
(
range
.
end
>=
999999u
);
CPPUNIT_ASSERT
(
range
.
end
>=
999999u
);
CPPUNIT_ASSERT
(
!
ParseCommandArg
(
client
,
range
,
"-2"
));
CPPUNIT_ASSERT
(
!
ParseCommandArg
(
r
,
range
,
"-2"
));
CPPUNIT_ASSERT_EQUAL
(
ACK_ERROR_ARG
,
last_error
);
CPPUNIT_ASSERT_EQUAL
(
ACK_ERROR_ARG
,
last_error
);
}
}
...
...
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