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
6db77dcf
Commit
6db77dcf
authored
Oct 15, 2013
by
Max Kellermann
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
output/roar: move code into the RoarOutput class
parent
1cde8682
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
137 additions
and
96 deletions
+137
-96
RoarOutputPlugin.cxx
src/output/RoarOutputPlugin.cxx
+136
-95
RoarOutputPlugin.hxx
src/output/RoarOutputPlugin.hxx
+1
-1
No files found.
src/output/RoarOutputPlugin.cxx
View file @
6db77dcf
...
@@ -35,7 +35,7 @@
...
@@ -35,7 +35,7 @@
#include <roaraudio.h>
#include <roaraudio.h>
#undef new
#undef new
struct
RoarOutput
{
class
RoarOutput
{
struct
audio_output
base
;
struct
audio_output
base
;
roar_vs_t
*
vss
;
roar_vs_t
*
vss
;
...
@@ -45,9 +45,10 @@ struct RoarOutput {
...
@@ -45,9 +45,10 @@ struct RoarOutput {
int
role
;
int
role
;
struct
roar_connection
con
;
struct
roar_connection
con
;
struct
roar_audio_info
info
;
struct
roar_audio_info
info
;
Mutex
mutex
;
mutable
Mutex
mutex
;
volatile
bool
alive
;
volatile
bool
alive
;
public
:
RoarOutput
()
RoarOutput
()
:
err
(
ROAR_ERROR_NONE
),
:
err
(
ROAR_ERROR_NONE
),
host
(
nullptr
),
name
(
nullptr
)
{}
host
(
nullptr
),
name
(
nullptr
)
{}
...
@@ -56,19 +57,46 @@ struct RoarOutput {
...
@@ -56,19 +57,46 @@ struct RoarOutput {
g_free
(
host
);
g_free
(
host
);
g_free
(
name
);
g_free
(
name
);
}
}
operator
audio_output
*
()
{
return
&
base
;
}
bool
Initialize
(
const
config_param
&
param
,
Error
&
error
)
{
return
ao_base_init
(
&
base
,
&
roar_output_plugin
,
param
,
error
);
}
void
Deinitialize
()
{
ao_base_finish
(
&
base
);
}
void
Configure
(
const
config_param
&
param
);
bool
Open
(
AudioFormat
&
audio_format
,
Error
&
error
);
void
Close
();
void
SendTag
(
const
Tag
&
tag
);
size_t
Play
(
const
void
*
chunk
,
size_t
size
,
Error
&
error
);
void
Cancel
();
int
GetVolume
()
const
;
bool
SetVolume
(
unsigned
volume
);
};
};
static
constexpr
Domain
roar_output_domain
(
"roar_output"
);
static
constexpr
Domain
roar_output_domain
(
"roar_output"
);
static
int
inline
int
roar_output_get_volume_locked
(
RoarOutput
*
roar
)
RoarOutput
::
GetVolume
()
const
{
{
if
(
roar
->
vss
==
nullptr
||
!
roar
->
alive
)
const
ScopeLock
protect
(
mutex
);
if
(
vss
==
nullptr
||
!
alive
)
return
-
1
;
return
-
1
;
float
l
,
r
;
float
l
,
r
;
int
error
;
int
error
;
if
(
roar_vs_volume_get
(
roar
->
vss
,
&
l
,
&
r
,
&
error
)
<
0
)
if
(
roar_vs_volume_get
(
vss
,
&
l
,
&
r
,
&
error
)
<
0
)
return
-
1
;
return
-
1
;
return
(
l
+
r
)
*
50
;
return
(
l
+
r
)
*
50
;
...
@@ -77,41 +105,40 @@ roar_output_get_volume_locked(RoarOutput *roar)
...
@@ -77,41 +105,40 @@ roar_output_get_volume_locked(RoarOutput *roar)
int
int
roar_output_get_volume
(
RoarOutput
*
roar
)
roar_output_get_volume
(
RoarOutput
*
roar
)
{
{
const
ScopeLock
protect
(
roar
->
mutex
);
return
roar
->
GetVolume
();
return
roar_output_get_volume_locked
(
roar
);
}
}
static
bool
bool
roar_output_set_volume_locked
(
RoarOutput
*
roar
,
unsigned
volume
)
RoarOutput
::
SetVolume
(
unsigned
volume
)
{
{
assert
(
volume
<=
100
);
assert
(
volume
<=
100
);
if
(
roar
->
vss
==
nullptr
||
!
roar
->
alive
)
const
ScopeLock
protect
(
mutex
);
if
(
vss
==
nullptr
||
!
alive
)
return
false
;
return
false
;
int
error
;
int
error
;
float
level
=
volume
/
100.0
;
float
level
=
volume
/
100.0
;
roar_vs_volume_mono
(
roar
->
vss
,
level
,
&
error
);
roar_vs_volume_mono
(
vss
,
level
,
&
error
);
return
true
;
return
true
;
}
}
bool
bool
roar_output_set_volume
(
RoarOutput
*
roar
,
unsigned
volume
)
roar_output_set_volume
(
RoarOutput
*
roar
,
unsigned
volume
)
{
{
const
ScopeLock
protect
(
roar
->
mutex
);
return
roar
->
SetVolume
(
volume
);
return
roar_output_set_volume_locked
(
roar
,
volume
);
}
}
static
void
inline
void
roar_configure
(
RoarOutput
*
self
,
const
config_param
&
param
)
RoarOutput
::
Configure
(
const
config_param
&
param
)
{
{
self
->
host
=
param
.
DupBlockString
(
"server"
,
nullptr
);
host
=
param
.
DupBlockString
(
"server"
,
nullptr
);
self
->
name
=
param
.
DupBlockString
(
"name"
,
"MPD"
);
name
=
param
.
DupBlockString
(
"name"
,
"MPD"
);
const
char
*
role
=
param
.
GetBlockValue
(
"role"
,
"music"
);
const
char
*
_
role
=
param
.
GetBlockValue
(
"role"
,
"music"
);
self
->
role
=
role
!=
nullptr
role
=
_
role
!=
nullptr
?
roar_str2role
(
role
)
?
roar_str2role
(
_
role
)
:
ROAR_ROLE_MUSIC
;
:
ROAR_ROLE_MUSIC
;
}
}
...
@@ -120,13 +147,13 @@ roar_init(const config_param ¶m, Error &error)
...
@@ -120,13 +147,13 @@ roar_init(const config_param ¶m, Error &error)
{
{
RoarOutput
*
self
=
new
RoarOutput
();
RoarOutput
*
self
=
new
RoarOutput
();
if
(
!
ao_base_init
(
&
self
->
base
,
&
roar_output_plugin
,
param
,
error
))
{
if
(
!
self
->
Initialize
(
param
,
error
))
{
delete
self
;
delete
self
;
return
nullptr
;
return
nullptr
;
}
}
roar_configure
(
self
,
param
);
self
->
Configure
(
param
);
return
&
self
->
base
;
return
*
self
;
}
}
static
void
static
void
...
@@ -134,7 +161,7 @@ roar_finish(struct audio_output *ao)
...
@@ -134,7 +161,7 @@ roar_finish(struct audio_output *ao)
{
{
RoarOutput
*
self
=
(
RoarOutput
*
)
ao
;
RoarOutput
*
self
=
(
RoarOutput
*
)
ao
;
ao_base_finish
(
&
self
->
base
);
self
->
Deinitialize
(
);
delete
self
;
delete
self
;
}
}
...
@@ -173,80 +200,90 @@ roar_use_audio_format(struct roar_audio_info *info,
...
@@ -173,80 +200,90 @@ roar_use_audio_format(struct roar_audio_info *info,
}
}
}
}
static
bool
inline
bool
roar_open
(
struct
audio_output
*
ao
,
AudioFormat
&
audio_format
,
Error
&
error
)
RoarOutput
::
Open
(
AudioFormat
&
audio_format
,
Error
&
error
)
{
{
RoarOutput
*
self
=
(
RoarOutput
*
)
ao
;
const
ScopeLock
protect
(
mutex
);
const
ScopeLock
protect
(
self
->
mutex
);
if
(
roar_simple_connect
(
&
(
self
->
con
),
self
->
host
,
self
->
name
)
<
0
)
if
(
roar_simple_connect
(
&
con
,
host
,
name
)
<
0
)
{
{
error
.
Set
(
roar_output_domain
,
error
.
Set
(
roar_output_domain
,
"Failed to connect to Roar server"
);
"Failed to connect to Roar server"
);
return
false
;
return
false
;
}
}
self
->
vss
=
roar_vs_new_from_con
(
&
(
self
->
con
),
&
(
self
->
err
)
);
vss
=
roar_vs_new_from_con
(
&
con
,
&
err
);
if
(
self
->
vss
==
nullptr
||
self
->
err
!=
ROAR_ERROR_NONE
)
if
(
vss
==
nullptr
||
err
!=
ROAR_ERROR_NONE
)
{
{
error
.
Set
(
roar_output_domain
,
"Failed to connect to server"
);
error
.
Set
(
roar_output_domain
,
"Failed to connect to server"
);
return
false
;
return
false
;
}
}
roar_use_audio_format
(
&
self
->
info
,
audio_format
);
roar_use_audio_format
(
&
info
,
audio_format
);
if
(
roar_vs_stream
(
self
->
vss
,
&
(
self
->
info
),
ROAR_DIR_PLAY
,
if
(
roar_vs_stream
(
vss
,
&
info
,
ROAR_DIR_PLAY
,
&
err
)
<
0
)
{
&
(
self
->
err
))
<
0
)
{
error
.
Set
(
roar_output_domain
,
"Failed to start stream"
);
error
.
Set
(
roar_output_domain
,
"Failed to start stream"
);
return
false
;
return
false
;
}
}
roar_vs_role
(
self
->
vss
,
self
->
role
,
&
(
self
->
err
));
self
->
alive
=
true
;
roar_vs_role
(
vss
,
role
,
&
err
);
alive
=
true
;
return
true
;
return
true
;
}
}
static
void
static
bool
roar_
close
(
struct
audio_output
*
ao
)
roar_
open
(
struct
audio_output
*
ao
,
AudioFormat
&
audio_format
,
Error
&
error
)
{
{
RoarOutput
*
self
=
(
RoarOutput
*
)
ao
;
RoarOutput
*
self
=
(
RoarOutput
*
)
ao
;
const
ScopeLock
protect
(
self
->
mutex
);
self
->
alive
=
false
;
return
self
->
Open
(
audio_format
,
error
);
}
inline
void
RoarOutput
::
Close
()
{
const
ScopeLock
protect
(
mutex
);
alive
=
false
;
if
(
self
->
vss
!=
nullptr
)
if
(
vss
!=
nullptr
)
roar_vs_close
(
self
->
vss
,
ROAR_VS_TRUE
,
&
(
self
->
err
)
);
roar_vs_close
(
vss
,
ROAR_VS_TRUE
,
&
err
);
self
->
vss
=
nullptr
;
vss
=
nullptr
;
roar_disconnect
(
&
(
self
->
con
)
);
roar_disconnect
(
&
con
);
}
}
static
void
static
void
roar_c
ancel_locked
(
RoarOutput
*
self
)
roar_c
lose
(
struct
audio_output
*
ao
)
{
{
if
(
self
->
vss
==
nullptr
)
RoarOutput
*
self
=
(
RoarOutput
*
)
ao
;
return
;
self
->
Close
();
}
roar_vs_t
*
vss
=
self
->
vss
;
inline
void
self
->
vss
=
nullptr
;
RoarOutput
::
Cancel
()
roar_vs_close
(
vss
,
ROAR_VS_TRUE
,
&
(
self
->
err
));
{
self
->
alive
=
false
;
const
ScopeLock
protect
(
mutex
)
;
vss
=
roar_vs_new_from_con
(
&
(
self
->
con
),
&
(
self
->
err
));
if
(
vss
==
nullptr
)
if
(
vss
==
nullptr
)
return
;
return
;
if
(
roar_vs_stream
(
vss
,
&
(
self
->
info
),
ROAR_DIR_PLAY
,
roar_vs_t
*
_vss
=
vss
;
&
(
self
->
err
))
<
0
)
{
vss
=
nullptr
;
roar_vs_close
(
vss
,
ROAR_VS_TRUE
,
&
(
self
->
err
));
roar_vs_close
(
_vss
,
ROAR_VS_TRUE
,
&
err
);
alive
=
false
;
_vss
=
roar_vs_new_from_con
(
&
con
,
&
err
);
if
(
_vss
==
nullptr
)
return
;
if
(
roar_vs_stream
(
_vss
,
&
info
,
ROAR_DIR_PLAY
,
&
err
)
<
0
)
{
roar_vs_close
(
_vss
,
ROAR_VS_TRUE
,
&
err
);
LogError
(
roar_output_domain
,
"Failed to start stream"
);
LogError
(
roar_output_domain
,
"Failed to start stream"
);
return
;
return
;
}
}
roar_vs_role
(
vss
,
self
->
role
,
&
(
self
->
err
)
);
roar_vs_role
(
_vss
,
role
,
&
err
);
self
->
vss
=
vss
;
vss
=
_
vss
;
self
->
alive
=
true
;
alive
=
true
;
}
}
static
void
static
void
...
@@ -254,31 +291,32 @@ roar_cancel(struct audio_output *ao)
...
@@ -254,31 +291,32 @@ roar_cancel(struct audio_output *ao)
{
{
RoarOutput
*
self
=
(
RoarOutput
*
)
ao
;
RoarOutput
*
self
=
(
RoarOutput
*
)
ao
;
const
ScopeLock
protect
(
self
->
mutex
);
self
->
Cancel
();
roar_cancel_locked
(
self
);
}
}
static
size_t
inline
size_t
roar_play
(
struct
audio_output
*
ao
,
const
void
*
chunk
,
size_t
size
,
RoarOutput
::
Play
(
const
void
*
chunk
,
size_t
size
,
Error
&
error
)
Error
&
error
)
{
{
RoarOutput
*
self
=
(
RoarOutput
*
)
ao
;
if
(
vss
==
nullptr
)
{
ssize_t
rc
;
if
(
self
->
vss
==
nullptr
)
{
error
.
Set
(
roar_output_domain
,
"Connection is invalid"
);
error
.
Set
(
roar_output_domain
,
"Connection is invalid"
);
return
0
;
return
0
;
}
}
rc
=
roar_vs_write
(
self
->
vss
,
chunk
,
size
,
&
(
self
->
err
));
ssize_t
nbytes
=
roar_vs_write
(
vss
,
chunk
,
size
,
&
err
);
if
(
rc
<=
0
)
if
(
nbytes
<=
0
)
{
{
error
.
Set
(
roar_output_domain
,
"Failed to play data"
);
error
.
Set
(
roar_output_domain
,
"Failed to play data"
);
return
0
;
return
0
;
}
}
return
rc
;
return
nbytes
;
}
static
size_t
roar_play
(
struct
audio_output
*
ao
,
const
void
*
chunk
,
size_t
size
,
Error
&
error
)
{
RoarOutput
*
self
=
(
RoarOutput
*
)
ao
;
return
self
->
Play
(
chunk
,
size
,
error
);
}
}
static
const
char
*
static
const
char
*
...
@@ -326,15 +364,13 @@ roar_tag_convert(enum tag_type type, bool *is_uuid)
...
@@ -326,15 +364,13 @@ roar_tag_convert(enum tag_type type, bool *is_uuid)
}
}
}
}
static
void
inline
void
roar_send_tag
(
struct
audio_output
*
ao
,
const
Tag
*
meta
)
RoarOutput
::
SendTag
(
const
Tag
&
tag
)
{
{
RoarOutput
*
self
=
(
RoarOutput
*
)
ao
;
if
(
vss
==
nullptr
)
if
(
self
->
vss
==
nullptr
)
return
;
return
;
const
ScopeLock
protect
(
self
->
mutex
);
const
ScopeLock
protect
(
mutex
);
size_t
cnt
=
1
;
size_t
cnt
=
1
;
struct
roar_keyval
vals
[
32
];
struct
roar_keyval
vals
[
32
];
...
@@ -343,39 +379,44 @@ roar_send_tag(struct audio_output *ao, const Tag *meta)
...
@@ -343,39 +379,44 @@ roar_send_tag(struct audio_output *ao, const Tag *meta)
char
timebuf
[
16
];
char
timebuf
[
16
];
snprintf
(
timebuf
,
sizeof
(
timebuf
),
"%02d:%02d:%02d"
,
snprintf
(
timebuf
,
sizeof
(
timebuf
),
"%02d:%02d:%02d"
,
meta
->
time
/
3600
,
(
meta
->
time
%
3600
)
/
60
,
meta
->
time
%
60
);
tag
.
time
/
3600
,
(
tag
.
time
%
3600
)
/
60
,
tag
.
time
%
60
);
vals
[
0
].
key
=
g_strdup
(
"LENGTH"
);
vals
[
0
].
key
=
g_strdup
(
"LENGTH"
);
vals
[
0
].
value
=
timebuf
;
vals
[
0
].
value
=
timebuf
;
for
(
unsigned
i
=
0
;
i
<
meta
->
num_items
&&
cnt
<
32
;
i
++
)
for
(
unsigned
i
=
0
;
i
<
tag
.
num_items
&&
cnt
<
32
;
i
++
)
{
{
bool
is_uuid
=
false
;
bool
is_uuid
=
false
;
const
char
*
key
=
roar_tag_convert
(
meta
->
items
[
i
]
->
type
,
&
is_uuid
);
const
char
*
key
=
roar_tag_convert
(
tag
.
items
[
i
]
->
type
,
if
(
key
!=
nullptr
)
&
is_uuid
);
{
if
(
key
!=
nullptr
)
{
if
(
is_uuid
)
if
(
is_uuid
)
{
{
snprintf
(
uuid_buf
[
cnt
],
sizeof
(
uuid_buf
[
0
]),
"{UUID}%s"
,
snprintf
(
uuid_buf
[
cnt
],
sizeof
(
uuid_buf
[
0
]),
"{UUID}%s"
,
meta
->
items
[
i
]
->
value
);
tag
.
items
[
i
]
->
value
);
vals
[
cnt
].
key
=
g_strdup
(
key
);
vals
[
cnt
].
key
=
g_strdup
(
key
);
vals
[
cnt
].
value
=
uuid_buf
[
cnt
];
vals
[
cnt
].
value
=
uuid_buf
[
cnt
];
}
}
else
{
else
{
vals
[
cnt
].
key
=
g_strdup
(
key
);
vals
[
cnt
].
key
=
g_strdup
(
key
);
vals
[
cnt
].
value
=
meta
->
items
[
i
]
->
value
;
vals
[
cnt
].
value
=
tag
.
items
[
i
]
->
value
;
}
}
cnt
++
;
cnt
++
;
}
}
}
}
roar_vs_meta
(
self
->
vss
,
vals
,
cnt
,
&
(
self
->
err
));
roar_vs_meta
(
vss
,
vals
,
cnt
,
&
(
err
));
for
(
unsigned
i
=
0
;
i
<
32
;
i
++
)
for
(
unsigned
i
=
0
;
i
<
32
;
i
++
)
g_free
(
vals
[
i
].
key
);
g_free
(
vals
[
i
].
key
);
}
}
static
void
roar_send_tag
(
struct
audio_output
*
ao
,
const
Tag
*
meta
)
{
RoarOutput
*
self
=
(
RoarOutput
*
)
ao
;
self
->
SendTag
(
*
meta
);
}
const
struct
audio_output_plugin
roar_output_plugin
=
{
const
struct
audio_output_plugin
roar_output_plugin
=
{
"roar"
,
"roar"
,
nullptr
,
nullptr
,
...
...
src/output/RoarOutputPlugin.hxx
View file @
6db77dcf
...
@@ -20,7 +20,7 @@
...
@@ -20,7 +20,7 @@
#ifndef MPD_ROAR_OUTPUT_PLUGIN_H
#ifndef MPD_ROAR_OUTPUT_PLUGIN_H
#define MPD_ROAR_OUTPUT_PLUGIN_H
#define MPD_ROAR_OUTPUT_PLUGIN_H
struct
RoarOutput
;
class
RoarOutput
;
extern
const
struct
audio_output_plugin
roar_output_plugin
;
extern
const
struct
audio_output_plugin
roar_output_plugin
;
...
...
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