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
e7d32722
Commit
e7d32722
authored
Sep 09, 2016
by
Max Kellermann
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
mixer: migrate to C++ exceptions
parent
ae1eb9cc
Hide whitespace changes
Inline
Side-by-side
Showing
21 changed files
with
273 additions
and
342 deletions
+273
-342
ReplayGainFilterPlugin.cxx
src/filter/plugins/ReplayGainFilterPlugin.cxx
+5
-3
MixerAll.cxx
src/mixer/MixerAll.cxx
+17
-15
MixerControl.cxx
src/mixer/MixerControl.cxx
+29
-25
MixerControl.hxx
src/mixer/MixerControl.hxx
+18
-8
MixerInternal.hxx
src/mixer/MixerInternal.hxx
+10
-7
MixerPlugin.hxx
src/mixer/MixerPlugin.hxx
+4
-6
AlsaMixerPlugin.cxx
src/mixer/plugins/AlsaMixerPlugin.cxx
+48
-74
NullMixerPlugin.cxx
src/mixer/plugins/NullMixerPlugin.cxx
+4
-7
OssMixerPlugin.cxx
src/mixer/plugins/OssMixerPlugin.cxx
+40
-63
PulseMixerPlugin.cxx
src/mixer/plugins/PulseMixerPlugin.cxx
+17
-23
RoarMixerPlugin.cxx
src/mixer/plugins/RoarMixerPlugin.cxx
+8
-10
SoftwareMixerPlugin.cxx
src/mixer/plugins/SoftwareMixerPlugin.cxx
+6
-10
WinmmMixerPlugin.cxx
src/mixer/plugins/WinmmMixerPlugin.cxx
+14
-24
Init.cxx
src/output/Init.cxx
+12
-14
OutputControl.cxx
src/output/OutputControl.cxx
+7
-4
PulseOutputPlugin.cxx
src/output/plugins/PulseOutputPlugin.cxx
+12
-17
PulseOutputPlugin.hxx
src/output/plugins/PulseOutputPlugin.hxx
+2
-3
RoarOutputPlugin.cxx
src/output/plugins/RoarOutputPlugin.cxx
+9
-8
RoarOutputPlugin.hxx
src/output/plugins/RoarOutputPlugin.hxx
+1
-1
read_mixer.cxx
test/read_mixer.cxx
+8
-17
run_filter.cxx
test/run_filter.cxx
+2
-3
No files found.
src/filter/plugins/ReplayGainFilterPlugin.cxx
View file @
e7d32722
...
@@ -158,9 +158,11 @@ ReplayGainFilter::Update()
...
@@ -158,9 +158,11 @@ ReplayGainFilter::Update()
if
(
_volume
>
100
)
if
(
_volume
>
100
)
_volume
=
100
;
_volume
=
100
;
Error
error
;
try
{
if
(
!
mixer_set_volume
(
mixer
,
_volume
,
error
))
mixer_set_volume
(
mixer
,
_volume
);
LogError
(
error
,
"Failed to update hardware mixer"
);
}
catch
(
const
std
::
runtime_error
&
e
)
{
LogError
(
e
,
"Failed to update hardware mixer"
);
}
}
else
}
else
pv
.
SetVolume
(
volume
);
pv
.
SetVolume
(
volume
);
}
}
...
...
src/mixer/MixerAll.cxx
View file @
e7d32722
...
@@ -24,9 +24,10 @@
...
@@ -24,9 +24,10 @@
#include "MixerList.hxx"
#include "MixerList.hxx"
#include "output/Internal.hxx"
#include "output/Internal.hxx"
#include "pcm/Volume.hxx"
#include "pcm/Volume.hxx"
#include "util/Error.hxx"
#include "Log.hxx"
#include "Log.hxx"
#include <stdexcept>
#include <assert.h>
#include <assert.h>
static
int
static
int
...
@@ -39,14 +40,14 @@ output_mixer_get_volume(const AudioOutput &ao)
...
@@ -39,14 +40,14 @@ output_mixer_get_volume(const AudioOutput &ao)
if
(
mixer
==
nullptr
)
if
(
mixer
==
nullptr
)
return
-
1
;
return
-
1
;
Error
error
;
try
{
int
volume
=
mixer_get_volume
(
mixer
,
erro
r
);
return
mixer_get_volume
(
mixe
r
);
if
(
volume
<
0
&&
error
.
IsDefined
())
}
catch
(
const
std
::
runtime_error
&
e
)
{
FormatError
(
e
rror
,
FormatError
(
e
,
"Failed to read mixer for '%s'"
,
"Failed to read mixer for '%s'"
,
ao
.
name
);
ao
.
name
);
return
-
1
;
return
volume
;
}
}
}
int
int
...
@@ -81,14 +82,15 @@ output_mixer_set_volume(AudioOutput &ao, unsigned volume)
...
@@ -81,14 +82,15 @@ output_mixer_set_volume(AudioOutput &ao, unsigned volume)
if
(
mixer
==
nullptr
)
if
(
mixer
==
nullptr
)
return
false
;
return
false
;
Error
error
;
try
{
bool
success
=
mixer_set_volume
(
mixer
,
volume
,
error
);
mixer_set_volume
(
mixer
,
volume
);
if
(
!
success
&&
error
.
IsDefined
())
return
true
;
FormatError
(
error
,
}
catch
(
const
std
::
runtime_error
&
e
)
{
FormatError
(
e
,
"Failed to set mixer for '%s'"
,
"Failed to set mixer for '%s'"
,
ao
.
name
);
ao
.
name
);
return
false
;
return
success
;
}
}
}
bool
bool
...
@@ -114,7 +116,7 @@ output_mixer_get_software_volume(const AudioOutput &ao)
...
@@ -114,7 +116,7 @@ output_mixer_get_software_volume(const AudioOutput &ao)
if
(
mixer
==
nullptr
||
!
mixer
->
IsPlugin
(
software_mixer_plugin
))
if
(
mixer
==
nullptr
||
!
mixer
->
IsPlugin
(
software_mixer_plugin
))
return
-
1
;
return
-
1
;
return
mixer_get_volume
(
mixer
,
IgnoreError
()
);
return
mixer_get_volume
(
mixer
);
}
}
int
int
...
@@ -148,6 +150,6 @@ MultipleOutputs::SetSoftwareVolume(unsigned volume)
...
@@ -148,6 +150,6 @@ MultipleOutputs::SetSoftwareVolume(unsigned volume)
if
(
mixer
!=
nullptr
&&
if
(
mixer
!=
nullptr
&&
(
&
mixer
->
plugin
==
&
software_mixer_plugin
||
(
&
mixer
->
plugin
==
&
software_mixer_plugin
||
&
mixer
->
plugin
==
&
null_mixer_plugin
))
&
mixer
->
plugin
==
&
null_mixer_plugin
))
mixer_set_volume
(
mixer
,
volume
,
IgnoreError
()
);
mixer_set_volume
(
mixer
,
volume
);
}
}
}
}
src/mixer/MixerControl.cxx
View file @
e7d32722
...
@@ -20,7 +20,6 @@
...
@@ -20,7 +20,6 @@
#include "config.h"
#include "config.h"
#include "MixerControl.hxx"
#include "MixerControl.hxx"
#include "MixerInternal.hxx"
#include "MixerInternal.hxx"
#include "util/Error.hxx"
#include <assert.h>
#include <assert.h>
...
@@ -28,10 +27,9 @@ Mixer *
...
@@ -28,10 +27,9 @@ Mixer *
mixer_new
(
EventLoop
&
event_loop
,
mixer_new
(
EventLoop
&
event_loop
,
const
MixerPlugin
&
plugin
,
AudioOutput
&
ao
,
const
MixerPlugin
&
plugin
,
AudioOutput
&
ao
,
MixerListener
&
listener
,
MixerListener
&
listener
,
const
ConfigBlock
&
block
,
const
ConfigBlock
&
block
)
Error
&
error
)
{
{
Mixer
*
mixer
=
plugin
.
init
(
event_loop
,
ao
,
listener
,
block
,
error
);
Mixer
*
mixer
=
plugin
.
init
(
event_loop
,
ao
,
listener
,
block
);
assert
(
mixer
==
nullptr
||
mixer
->
IsPlugin
(
plugin
));
assert
(
mixer
==
nullptr
||
mixer
->
IsPlugin
(
plugin
));
...
@@ -50,20 +48,24 @@ mixer_free(Mixer *mixer)
...
@@ -50,20 +48,24 @@ mixer_free(Mixer *mixer)
delete
mixer
;
delete
mixer
;
}
}
bool
void
mixer_open
(
Mixer
*
mixer
,
Error
&
error
)
mixer_open
(
Mixer
*
mixer
)
{
{
bool
success
;
assert
(
mixer
!=
nullptr
);
assert
(
mixer
!=
nullptr
);
const
ScopeLock
protect
(
mixer
->
mutex
);
const
ScopeLock
protect
(
mixer
->
mutex
);
success
=
mixer
->
open
||
(
mixer
->
open
=
mixer
->
Open
(
error
));
if
(
mixer
->
open
)
return
;
mixer
->
failed
=
!
success
;
try
{
return
success
;
mixer
->
Open
();
mixer
->
open
=
true
;
mixer
->
failed
=
false
;
}
catch
(...)
{
mixer
->
failed
=
true
;
throw
;
}
}
}
static
void
static
void
...
@@ -109,39 +111,41 @@ mixer_failed(Mixer *mixer)
...
@@ -109,39 +111,41 @@ mixer_failed(Mixer *mixer)
}
}
int
int
mixer_get_volume
(
Mixer
*
mixer
,
Error
&
error
)
mixer_get_volume
(
Mixer
*
mixer
)
{
{
int
volume
;
int
volume
;
assert
(
mixer
!=
nullptr
);
assert
(
mixer
!=
nullptr
);
if
(
mixer
->
plugin
.
global
&&
!
mixer
->
failed
&&
if
(
mixer
->
plugin
.
global
&&
!
mixer
->
failed
)
!
mixer_open
(
mixer
,
error
))
mixer_open
(
mixer
);
return
-
1
;
const
ScopeLock
protect
(
mixer
->
mutex
);
const
ScopeLock
protect
(
mixer
->
mutex
);
if
(
mixer
->
open
)
{
if
(
mixer
->
open
)
{
volume
=
mixer
->
GetVolume
(
error
);
try
{
if
(
volume
<
0
&&
error
.
IsDefined
())
volume
=
mixer
->
GetVolume
();
}
catch
(...)
{
mixer_failed
(
mixer
);
mixer_failed
(
mixer
);
throw
;
}
}
else
}
else
volume
=
-
1
;
volume
=
-
1
;
return
volume
;
return
volume
;
}
}
bool
void
mixer_set_volume
(
Mixer
*
mixer
,
unsigned
volume
,
Error
&
error
)
mixer_set_volume
(
Mixer
*
mixer
,
unsigned
volume
)
{
{
assert
(
mixer
!=
nullptr
);
assert
(
mixer
!=
nullptr
);
assert
(
volume
<=
100
);
assert
(
volume
<=
100
);
if
(
mixer
->
plugin
.
global
&&
!
mixer
->
failed
&&
if
(
mixer
->
plugin
.
global
&&
!
mixer
->
failed
)
!
mixer_open
(
mixer
,
error
))
mixer_open
(
mixer
);
return
false
;
const
ScopeLock
protect
(
mixer
->
mutex
);
const
ScopeLock
protect
(
mixer
->
mutex
);
return
mixer
->
open
&&
mixer
->
SetVolume
(
volume
,
error
);
if
(
mixer
->
open
)
mixer
->
SetVolume
(
volume
);
}
}
src/mixer/MixerControl.hxx
View file @
e7d32722
...
@@ -25,7 +25,6 @@
...
@@ -25,7 +25,6 @@
#ifndef MPD_MIXER_CONTROL_HXX
#ifndef MPD_MIXER_CONTROL_HXX
#define MPD_MIXER_CONTROL_HXX
#define MPD_MIXER_CONTROL_HXX
class
Error
;
class
Mixer
;
class
Mixer
;
class
EventLoop
;
class
EventLoop
;
struct
AudioOutput
;
struct
AudioOutput
;
...
@@ -33,17 +32,22 @@ struct MixerPlugin;
...
@@ -33,17 +32,22 @@ struct MixerPlugin;
class
MixerListener
;
class
MixerListener
;
struct
ConfigBlock
;
struct
ConfigBlock
;
/**
* Throws std::runtime_error on error.
*/
Mixer
*
Mixer
*
mixer_new
(
EventLoop
&
event_loop
,
const
MixerPlugin
&
plugin
,
AudioOutput
&
ao
,
mixer_new
(
EventLoop
&
event_loop
,
const
MixerPlugin
&
plugin
,
AudioOutput
&
ao
,
MixerListener
&
listener
,
MixerListener
&
listener
,
const
ConfigBlock
&
block
,
const
ConfigBlock
&
block
);
Error
&
error
);
void
void
mixer_free
(
Mixer
*
mixer
);
mixer_free
(
Mixer
*
mixer
);
bool
/**
mixer_open
(
Mixer
*
mixer
,
Error
&
error
);
* Throws std::runtime_error on error.
*/
void
mixer_open
(
Mixer
*
mixer
);
void
void
mixer_close
(
Mixer
*
mixer
);
mixer_close
(
Mixer
*
mixer
);
...
@@ -55,10 +59,16 @@ mixer_close(Mixer *mixer);
...
@@ -55,10 +59,16 @@ mixer_close(Mixer *mixer);
void
void
mixer_auto_close
(
Mixer
*
mixer
);
mixer_auto_close
(
Mixer
*
mixer
);
/**
* Throws std::runtime_error on error.
*/
int
int
mixer_get_volume
(
Mixer
*
mixer
,
Error
&
error
);
mixer_get_volume
(
Mixer
*
mixer
);
bool
/**
mixer_set_volume
(
Mixer
*
mixer
,
unsigned
volume
,
Error
&
error
);
* Throws std::runtime_error on error.
*/
void
mixer_set_volume
(
Mixer
*
mixer
,
unsigned
volume
);
#endif
#endif
src/mixer/MixerInternal.hxx
View file @
e7d32722
...
@@ -67,9 +67,9 @@ public:
...
@@ -67,9 +67,9 @@ public:
/**
/**
* Open mixer device
* Open mixer device
*
*
*
@return true on success, false on error
*
Throws std::runtime_error on error.
*/
*/
virtual
bool
Open
(
Error
&
error
)
=
0
;
virtual
void
Open
(
)
=
0
;
/**
/**
* Close mixer device
* Close mixer device
...
@@ -79,19 +79,22 @@ public:
...
@@ -79,19 +79,22 @@ public:
/**
/**
* Reads the current volume.
* Reads the current volume.
*
*
* Throws std::runtime_error on error.
*
* @return the current volume (0..100 including) or -1 if
* @return the current volume (0..100 including) or -1 if
* unavailable
or on error (error set, mixer will be closed)
* unavailable
*/
*/
gcc_pure
gcc_pure
virtual
int
GetVolume
(
Error
&
error
)
=
0
;
virtual
int
GetVolume
()
=
0
;
/**
/**
* Sets the volume.
* Sets the volume.
*
*
* @param volume the new volume (0..100 including) @return
* Throws std::runtime_error on error.
* true on success, false on error
*
* @param volume the new volume (0..100 including)
*/
*/
virtual
bool
SetVolume
(
unsigned
volume
,
Error
&
error
)
=
0
;
virtual
void
SetVolume
(
unsigned
volume
)
=
0
;
};
};
#endif
#endif
src/mixer/MixerPlugin.hxx
View file @
e7d32722
...
@@ -32,22 +32,20 @@ struct AudioOutput;
...
@@ -32,22 +32,20 @@ struct AudioOutput;
class
Mixer
;
class
Mixer
;
class
MixerListener
;
class
MixerListener
;
class
EventLoop
;
class
EventLoop
;
class
Error
;
struct
MixerPlugin
{
struct
MixerPlugin
{
/**
/**
* Alocates and configures a mixer device.
* Alocates and configures a mixer device.
*
*
* Throws std::runtime_error on error.
*
* @param ao the associated AudioOutput
* @param ao the associated AudioOutput
* @param param the configuration section
* @param param the configuration section
* @param error_r location to store the error occurring, or
* @return a mixer object
* nullptr to ignore errors
* @return a mixer object, or nullptr on error
*/
*/
Mixer
*
(
*
init
)(
EventLoop
&
event_loop
,
AudioOutput
&
ao
,
Mixer
*
(
*
init
)(
EventLoop
&
event_loop
,
AudioOutput
&
ao
,
MixerListener
&
listener
,
MixerListener
&
listener
,
const
ConfigBlock
&
block
,
const
ConfigBlock
&
block
);
Error
&
error
);
/**
/**
* If true, then the mixer is automatically opened, even if
* If true, then the mixer is automatically opened, even if
...
...
src/mixer/plugins/AlsaMixerPlugin.cxx
View file @
e7d32722
...
@@ -26,8 +26,8 @@
...
@@ -26,8 +26,8 @@
#include "util/ASCII.hxx"
#include "util/ASCII.hxx"
#include "util/ReusableArray.hxx"
#include "util/ReusableArray.hxx"
#include "util/Clamp.hxx"
#include "util/Clamp.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include "util/Domain.hxx"
#include "util/RuntimeError.hxx"
#include "Log.hxx"
#include "Log.hxx"
#include <algorithm>
#include <algorithm>
...
@@ -82,13 +82,13 @@ public:
...
@@ -82,13 +82,13 @@ public:
virtual
~
AlsaMixer
();
virtual
~
AlsaMixer
();
void
Configure
(
const
ConfigBlock
&
block
);
void
Configure
(
const
ConfigBlock
&
block
);
bool
Setup
(
Error
&
error
);
void
Setup
(
);
/* virtual methods from class Mixer */
/* virtual methods from class Mixer */
v
irtual
bool
Open
(
Error
&
error
)
override
;
v
oid
Open
(
)
override
;
v
irtual
v
oid
Close
()
override
;
void
Close
()
override
;
virtual
int
GetVolume
(
Error
&
error
)
override
;
int
GetVolume
(
)
override
;
v
irtual
bool
SetVolume
(
unsigned
volume
,
Error
&
error
)
override
;
v
oid
SetVolume
(
unsigned
volume
)
override
;
};
};
static
constexpr
Domain
alsa_mixer_domain
(
"alsa_mixer"
);
static
constexpr
Domain
alsa_mixer_domain
(
"alsa_mixer"
);
...
@@ -148,8 +148,11 @@ alsa_mixer_elem_callback(snd_mixer_elem_t *elem, unsigned mask)
...
@@ -148,8 +148,11 @@ alsa_mixer_elem_callback(snd_mixer_elem_t *elem, unsigned mask)
snd_mixer_elem_get_callback_private
(
elem
);
snd_mixer_elem_get_callback_private
(
elem
);
if
(
mask
&
SND_CTL_EVENT_MASK_VALUE
)
{
if
(
mask
&
SND_CTL_EVENT_MASK_VALUE
)
{
int
volume
=
mixer
.
GetVolume
(
IgnoreError
());
try
{
mixer
.
listener
.
OnMixerVolumeChanged
(
mixer
,
volume
);
int
volume
=
mixer
.
GetVolume
();
mixer
.
listener
.
OnMixerVolumeChanged
(
mixer
,
volume
);
}
catch
(
const
std
::
runtime_error
&
)
{
}
}
}
return
0
;
return
0
;
...
@@ -174,8 +177,7 @@ AlsaMixer::Configure(const ConfigBlock &block)
...
@@ -174,8 +177,7 @@ AlsaMixer::Configure(const ConfigBlock &block)
static
Mixer
*
static
Mixer
*
alsa_mixer_init
(
EventLoop
&
event_loop
,
gcc_unused
AudioOutput
&
ao
,
alsa_mixer_init
(
EventLoop
&
event_loop
,
gcc_unused
AudioOutput
&
ao
,
MixerListener
&
listener
,
MixerListener
&
listener
,
const
ConfigBlock
&
block
,
const
ConfigBlock
&
block
)
gcc_unused
Error
&
error
)
{
{
AlsaMixer
*
am
=
new
AlsaMixer
(
event_loop
,
listener
);
AlsaMixer
*
am
=
new
AlsaMixer
(
event_loop
,
listener
);
am
->
Configure
(
block
);
am
->
Configure
(
block
);
...
@@ -205,39 +207,26 @@ alsa_mixer_lookup_elem(snd_mixer_t *handle, const char *name, unsigned idx)
...
@@ -205,39 +207,26 @@ alsa_mixer_lookup_elem(snd_mixer_t *handle, const char *name, unsigned idx)
return
nullptr
;
return
nullptr
;
}
}
inline
bool
inline
void
AlsaMixer
::
Setup
(
Error
&
error
)
AlsaMixer
::
Setup
()
{
{
int
err
;
int
err
;
if
((
err
=
snd_mixer_attach
(
handle
,
device
))
<
0
)
{
if
((
err
=
snd_mixer_attach
(
handle
,
device
))
<
0
)
error
.
Format
(
alsa_mixer_domain
,
err
,
throw
FormatRuntimeError
(
"failed to attach to %s: %s"
,
"failed to attach to %s: %s"
,
device
,
snd_strerror
(
err
));
device
,
snd_strerror
(
err
));
return
false
;
}
if
((
err
=
snd_mixer_selem_register
(
handle
,
nullptr
,
if
((
err
=
snd_mixer_selem_register
(
handle
,
nullptr
,
nullptr
))
<
0
)
nullptr
))
<
0
)
{
throw
FormatRuntimeError
(
"snd_mixer_selem_register() failed: %s"
,
error
.
Format
(
alsa_mixer_domain
,
err
,
snd_strerror
(
err
));
"snd_mixer_selem_register() failed: %s"
,
snd_strerror
(
err
));
return
false
;
}
if
((
err
=
snd_mixer_load
(
handle
))
<
0
)
{
if
((
err
=
snd_mixer_load
(
handle
))
<
0
)
error
.
Format
(
alsa_mixer_domain
,
err
,
throw
FormatRuntimeError
(
"snd_mixer_load() failed: %s
\n
"
,
"snd_mixer_load() failed: %s
\n
"
,
snd_strerror
(
err
));
snd_strerror
(
err
));
return
false
;
}
elem
=
alsa_mixer_lookup_elem
(
handle
,
control
,
index
);
elem
=
alsa_mixer_lookup_elem
(
handle
,
control
,
index
);
if
(
elem
==
nullptr
)
{
if
(
elem
==
nullptr
)
error
.
Format
(
alsa_mixer_domain
,
0
,
throw
FormatRuntimeError
(
"no such mixer control: %s"
,
control
);
"no such mixer control: %s"
,
control
);
return
false
;
}
snd_mixer_selem_get_playback_volume_range
(
elem
,
&
volume_min
,
snd_mixer_selem_get_playback_volume_range
(
elem
,
&
volume_min
,
&
volume_max
);
&
volume_max
);
...
@@ -246,33 +235,29 @@ AlsaMixer::Setup(Error &error)
...
@@ -246,33 +235,29 @@ AlsaMixer::Setup(Error &error)
snd_mixer_elem_set_callback
(
elem
,
alsa_mixer_elem_callback
);
snd_mixer_elem_set_callback
(
elem
,
alsa_mixer_elem_callback
);
monitor
=
new
AlsaMixerMonitor
(
event_loop
,
handle
);
monitor
=
new
AlsaMixerMonitor
(
event_loop
,
handle
);
return
true
;
}
}
inline
bool
void
AlsaMixer
::
Open
(
Error
&
error
)
AlsaMixer
::
Open
()
{
{
int
err
;
int
err
;
volume_set
=
-
1
;
volume_set
=
-
1
;
err
=
snd_mixer_open
(
&
handle
,
0
);
err
=
snd_mixer_open
(
&
handle
,
0
);
if
(
err
<
0
)
{
if
(
err
<
0
)
error
.
Format
(
alsa_mixer_domain
,
err
,
throw
FormatRuntimeError
(
"snd_mixer_open() failed: %s"
,
"snd_mixer_open() failed: %s"
,
snd_strerror
(
err
));
snd_strerror
(
err
));
return
false
;
}
if
(
!
Setup
(
error
))
{
try
{
Setup
();
}
catch
(...)
{
snd_mixer_close
(
handle
);
snd_mixer_close
(
handle
);
return
false
;
throw
;
}
}
return
true
;
}
}
inline
void
void
AlsaMixer
::
Close
()
AlsaMixer
::
Close
()
{
{
assert
(
handle
!=
nullptr
);
assert
(
handle
!=
nullptr
);
...
@@ -283,8 +268,8 @@ AlsaMixer::Close()
...
@@ -283,8 +268,8 @@ AlsaMixer::Close()
snd_mixer_close
(
handle
);
snd_mixer_close
(
handle
);
}
}
in
line
in
t
int
AlsaMixer
::
GetVolume
(
Error
&
error
)
AlsaMixer
::
GetVolume
()
{
{
int
err
;
int
err
;
int
ret
;
int
ret
;
...
@@ -293,22 +278,16 @@ AlsaMixer::GetVolume(Error &error)
...
@@ -293,22 +278,16 @@ AlsaMixer::GetVolume(Error &error)
assert
(
handle
!=
nullptr
);
assert
(
handle
!=
nullptr
);
err
=
snd_mixer_handle_events
(
handle
);
err
=
snd_mixer_handle_events
(
handle
);
if
(
err
<
0
)
{
if
(
err
<
0
)
error
.
Format
(
alsa_mixer_domain
,
err
,
throw
FormatRuntimeError
(
"snd_mixer_handle_events() failed: %s"
,
"snd_mixer_handle_events() failed: %s"
,
snd_strerror
(
err
));
snd_strerror
(
err
));
return
false
;
}
err
=
snd_mixer_selem_get_playback_volume
(
elem
,
err
=
snd_mixer_selem_get_playback_volume
(
elem
,
SND_MIXER_SCHN_FRONT_LEFT
,
SND_MIXER_SCHN_FRONT_LEFT
,
&
level
);
&
level
);
if
(
err
<
0
)
{
if
(
err
<
0
)
error
.
Format
(
alsa_mixer_domain
,
err
,
throw
FormatRuntimeError
(
"failed to read ALSA volume: %s"
,
"failed to read ALSA volume: %s"
,
snd_strerror
(
err
));
snd_strerror
(
err
));
return
false
;
}
ret
=
((
volume_set
/
100.0
)
*
(
volume_max
-
volume_min
)
ret
=
((
volume_set
/
100.0
)
*
(
volume_max
-
volume_min
)
+
volume_min
)
+
0.5
;
+
volume_min
)
+
0.5
;
...
@@ -322,8 +301,8 @@ AlsaMixer::GetVolume(Error &error)
...
@@ -322,8 +301,8 @@ AlsaMixer::GetVolume(Error &error)
return
ret
;
return
ret
;
}
}
inline
bool
void
AlsaMixer
::
SetVolume
(
unsigned
volume
,
Error
&
error
)
AlsaMixer
::
SetVolume
(
unsigned
volume
)
{
{
float
vol
;
float
vol
;
long
level
;
long
level
;
...
@@ -340,14 +319,9 @@ AlsaMixer::SetVolume(unsigned volume, Error &error)
...
@@ -340,14 +319,9 @@ AlsaMixer::SetVolume(unsigned volume, Error &error)
level
=
Clamp
(
level
,
volume_min
,
volume_max
);
level
=
Clamp
(
level
,
volume_min
,
volume_max
);
err
=
snd_mixer_selem_set_playback_volume_all
(
elem
,
level
);
err
=
snd_mixer_selem_set_playback_volume_all
(
elem
,
level
);
if
(
err
<
0
)
{
if
(
err
<
0
)
error
.
Format
(
alsa_mixer_domain
,
err
,
throw
FormatRuntimeError
(
"failed to set ALSA volume: %s"
,
"failed to set ALSA volume: %s"
,
snd_strerror
(
err
));
snd_strerror
(
err
));
return
false
;
}
return
true
;
}
}
const
MixerPlugin
alsa_mixer_plugin
=
{
const
MixerPlugin
alsa_mixer_plugin
=
{
...
...
src/mixer/plugins/NullMixerPlugin.cxx
View file @
e7d32722
...
@@ -34,20 +34,18 @@ public:
...
@@ -34,20 +34,18 @@ public:
}
}
/* virtual methods from class Mixer */
/* virtual methods from class Mixer */
bool
Open
(
gcc_unused
Error
&
error
)
override
{
void
Open
()
override
{
return
true
;
}
}
void
Close
()
override
{
void
Close
()
override
{
}
}
int
GetVolume
(
gcc_unused
Error
&
error
)
override
{
int
GetVolume
()
override
{
return
volume
;
return
volume
;
}
}
bool
SetVolume
(
unsigned
_volume
,
gcc_unused
Error
&
error
)
override
{
void
SetVolume
(
unsigned
_volume
)
override
{
volume
=
_volume
;
volume
=
_volume
;
return
true
;
}
}
};
};
...
@@ -55,8 +53,7 @@ static Mixer *
...
@@ -55,8 +53,7 @@ static Mixer *
null_mixer_init
(
gcc_unused
EventLoop
&
event_loop
,
null_mixer_init
(
gcc_unused
EventLoop
&
event_loop
,
gcc_unused
AudioOutput
&
ao
,
gcc_unused
AudioOutput
&
ao
,
MixerListener
&
listener
,
MixerListener
&
listener
,
gcc_unused
const
ConfigBlock
&
block
,
gcc_unused
const
ConfigBlock
&
block
)
gcc_unused
Error
&
error
)
{
{
return
new
NullMixer
(
listener
);
return
new
NullMixer
(
listener
);
}
}
...
...
src/mixer/plugins/OssMixerPlugin.cxx
View file @
e7d32722
...
@@ -21,9 +21,10 @@
...
@@ -21,9 +21,10 @@
#include "mixer/MixerInternal.hxx"
#include "mixer/MixerInternal.hxx"
#include "config/Block.hxx"
#include "config/Block.hxx"
#include "system/fd_util.h"
#include "system/fd_util.h"
#include "system/Error.hxx"
#include "util/ASCII.hxx"
#include "util/ASCII.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include "util/Domain.hxx"
#include "util/RuntimeError.hxx"
#include "Log.hxx"
#include "Log.hxx"
#include <assert.h>
#include <assert.h>
...
@@ -49,16 +50,18 @@ class OssMixer final : public Mixer {
...
@@ -49,16 +50,18 @@ class OssMixer final : public Mixer {
int
volume_control
;
int
volume_control
;
public
:
public
:
OssMixer
(
MixerListener
&
_listener
)
OssMixer
(
MixerListener
&
_listener
,
const
ConfigBlock
&
block
)
:
Mixer
(
oss_mixer_plugin
,
_listener
)
{}
:
Mixer
(
oss_mixer_plugin
,
_listener
)
{
Configure
(
block
);
}
bool
Configure
(
const
ConfigBlock
&
block
,
Error
&
error
);
void
Configure
(
const
ConfigBlock
&
block
);
/* virtual methods from class Mixer */
/* virtual methods from class Mixer */
v
irtual
bool
Open
(
Error
&
error
)
override
;
v
oid
Open
(
)
override
;
v
irtual
v
oid
Close
()
override
;
void
Close
()
override
;
virtual
int
GetVolume
(
Error
&
error
)
override
;
int
GetVolume
(
)
override
;
v
irtual
bool
SetVolume
(
unsigned
volume
,
Error
&
error
)
override
;
v
oid
SetVolume
(
unsigned
volume
)
override
;
};
};
static
constexpr
Domain
oss_mixer_domain
(
"oss_mixer"
);
static
constexpr
Domain
oss_mixer_domain
(
"oss_mixer"
);
...
@@ -78,39 +81,27 @@ oss_find_mixer(const char *name)
...
@@ -78,39 +81,27 @@ oss_find_mixer(const char *name)
return
-
1
;
return
-
1
;
}
}
inline
bool
inline
void
OssMixer
::
Configure
(
const
ConfigBlock
&
block
,
Error
&
error
)
OssMixer
::
Configure
(
const
ConfigBlock
&
block
)
{
{
device
=
block
.
GetBlockValue
(
"mixer_device"
,
VOLUME_MIXER_OSS_DEFAULT
);
device
=
block
.
GetBlockValue
(
"mixer_device"
,
VOLUME_MIXER_OSS_DEFAULT
);
control
=
block
.
GetBlockValue
(
"mixer_control"
);
control
=
block
.
GetBlockValue
(
"mixer_control"
);
if
(
control
!=
NULL
)
{
if
(
control
!=
NULL
)
{
volume_control
=
oss_find_mixer
(
control
);
volume_control
=
oss_find_mixer
(
control
);
if
(
volume_control
<
0
)
{
if
(
volume_control
<
0
)
error
.
Format
(
oss_mixer_domain
,
0
,
throw
FormatRuntimeError
(
"no such mixer control: %s"
,
"no such mixer control: %s"
,
control
);
control
);
return
false
;
}
}
else
}
else
volume_control
=
SOUND_MIXER_PCM
;
volume_control
=
SOUND_MIXER_PCM
;
return
true
;
}
}
static
Mixer
*
static
Mixer
*
oss_mixer_init
(
gcc_unused
EventLoop
&
event_loop
,
gcc_unused
AudioOutput
&
ao
,
oss_mixer_init
(
gcc_unused
EventLoop
&
event_loop
,
gcc_unused
AudioOutput
&
ao
,
MixerListener
&
listener
,
MixerListener
&
listener
,
const
ConfigBlock
&
block
,
const
ConfigBlock
&
block
)
Error
&
error
)
{
{
OssMixer
*
om
=
new
OssMixer
(
listener
);
return
new
OssMixer
(
listener
,
block
);
if
(
!
om
->
Configure
(
block
,
error
))
{
delete
om
;
return
nullptr
;
}
return
om
;
}
}
void
void
...
@@ -121,38 +112,32 @@ OssMixer::Close()
...
@@ -121,38 +112,32 @@ OssMixer::Close()
close
(
device_fd
);
close
(
device_fd
);
}
}
bool
void
OssMixer
::
Open
(
Error
&
error
)
OssMixer
::
Open
()
{
{
device_fd
=
open_cloexec
(
device
,
O_RDONLY
,
0
);
device_fd
=
open_cloexec
(
device
,
O_RDONLY
,
0
);
if
(
device_fd
<
0
)
{
if
(
device_fd
<
0
)
error
.
FormatErrno
(
"failed to open %s"
,
device
);
throw
FormatErrno
(
"failed to open %s"
,
device
);
return
false
;
}
if
(
control
)
{
try
{
int
devmask
=
0
;
if
(
control
)
{
int
devmask
=
0
;
if
(
ioctl
(
device_fd
,
SOUND_MIXER_READ_DEVMASK
,
&
devmask
)
<
0
)
{
if
(
ioctl
(
device_fd
,
SOUND_MIXER_READ_DEVMASK
,
&
devmask
)
<
0
)
error
.
SetErrno
(
"READ_DEVMASK failed"
);
throw
MakeErrno
(
"READ_DEVMASK failed"
);
Close
();
return
false
;
}
if
(((
1
<<
volume_control
)
&
devmask
)
==
0
)
{
if
(((
1
<<
volume_control
)
&
devmask
)
==
0
)
error
.
Format
(
oss_mixer_domain
,
0
,
throw
FormatErrno
(
"mixer control
\"
%s
\"
not usable"
,
"mixer control
\"
%s
\"
not usable"
,
control
);
control
);
Close
();
return
false
;
}
}
}
catch
(...)
{
Close
();
throw
;
}
}
return
true
;
}
}
int
int
OssMixer
::
GetVolume
(
Error
&
error
)
OssMixer
::
GetVolume
()
{
{
int
left
,
right
,
level
;
int
left
,
right
,
level
;
int
ret
;
int
ret
;
...
@@ -160,10 +145,8 @@ OssMixer::GetVolume(Error &error)
...
@@ -160,10 +145,8 @@ OssMixer::GetVolume(Error &error)
assert
(
device_fd
>=
0
);
assert
(
device_fd
>=
0
);
ret
=
ioctl
(
device_fd
,
MIXER_READ
(
volume_control
),
&
level
);
ret
=
ioctl
(
device_fd
,
MIXER_READ
(
volume_control
),
&
level
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
error
.
SetErrno
(
"failed to read OSS volume"
);
throw
MakeErrno
(
"failed to read OSS volume"
);
return
false
;
}
left
=
level
&
0xff
;
left
=
level
&
0xff
;
right
=
(
level
&
0xff00
)
>>
8
;
right
=
(
level
&
0xff00
)
>>
8
;
...
@@ -177,24 +160,18 @@ OssMixer::GetVolume(Error &error)
...
@@ -177,24 +160,18 @@ OssMixer::GetVolume(Error &error)
return
left
;
return
left
;
}
}
bool
void
OssMixer
::
SetVolume
(
unsigned
volume
,
Error
&
error
)
OssMixer
::
SetVolume
(
unsigned
volume
)
{
{
int
level
;
int
level
;
int
ret
;
assert
(
device_fd
>=
0
);
assert
(
device_fd
>=
0
);
assert
(
volume
<=
100
);
assert
(
volume
<=
100
);
level
=
(
volume
<<
8
)
+
volume
;
level
=
(
volume
<<
8
)
+
volume
;
ret
=
ioctl
(
device_fd
,
MIXER_WRITE
(
volume_control
),
&
level
);
if
(
ioctl
(
device_fd
,
MIXER_WRITE
(
volume_control
),
&
level
)
<
0
)
if
(
ret
<
0
)
{
throw
MakeErrno
(
"failed to set OSS volume"
);
error
.
SetErrno
(
"failed to set OSS volume"
);
return
false
;
}
return
true
;
}
}
const
MixerPlugin
oss_mixer_plugin
=
{
const
MixerPlugin
oss_mixer_plugin
=
{
...
...
src/mixer/plugins/PulseMixerPlugin.cxx
View file @
e7d32722
...
@@ -25,13 +25,14 @@
...
@@ -25,13 +25,14 @@
#include "mixer/MixerInternal.hxx"
#include "mixer/MixerInternal.hxx"
#include "mixer/Listener.hxx"
#include "mixer/Listener.hxx"
#include "output/plugins/PulseOutputPlugin.hxx"
#include "output/plugins/PulseOutputPlugin.hxx"
#include "util/Error.hxx"
#include <pulse/context.h>
#include <pulse/context.h>
#include <pulse/introspect.h>
#include <pulse/introspect.h>
#include <pulse/stream.h>
#include <pulse/stream.h>
#include <pulse/subscribe.h>
#include <pulse/subscribe.h>
#include <stdexcept>
#include <assert.h>
#include <assert.h>
class
PulseMixer
final
:
public
Mixer
{
class
PulseMixer
final
:
public
Mixer
{
...
@@ -52,18 +53,17 @@ public:
...
@@ -52,18 +53,17 @@ public:
void
Offline
();
void
Offline
();
void
VolumeCallback
(
const
pa_sink_input_info
*
i
,
int
eol
);
void
VolumeCallback
(
const
pa_sink_input_info
*
i
,
int
eol
);
void
Update
(
pa_context
*
context
,
pa_stream
*
stream
);
void
Update
(
pa_context
*
context
,
pa_stream
*
stream
);
int
GetVolumeInternal
(
Error
&
error
);
int
GetVolumeInternal
();
/* virtual methods from class Mixer */
/* virtual methods from class Mixer */
bool
Open
(
gcc_unused
Error
&
error
)
override
{
void
Open
()
override
{
return
true
;
}
}
void
Close
()
override
{
void
Close
()
override
{
}
}
int
GetVolume
(
Error
&
error
)
override
;
int
GetVolume
()
override
;
bool
SetVolume
(
unsigned
volume
,
Error
&
error
)
override
;
void
SetVolume
(
unsigned
volume
)
override
;
};
};
void
void
...
@@ -91,7 +91,7 @@ PulseMixer::VolumeCallback(const pa_sink_input_info *i, int eol)
...
@@ -91,7 +91,7 @@ PulseMixer::VolumeCallback(const pa_sink_input_info *i, int eol)
online
=
true
;
online
=
true
;
volume
=
i
->
volume
;
volume
=
i
->
volume
;
listener
.
OnMixerVolumeChanged
(
*
this
,
GetVolumeInternal
(
IgnoreError
()
));
listener
.
OnMixerVolumeChanged
(
*
this
,
GetVolumeInternal
());
}
}
/**
/**
...
@@ -163,8 +163,7 @@ pulse_mixer_on_change(PulseMixer &pm,
...
@@ -163,8 +163,7 @@ pulse_mixer_on_change(PulseMixer &pm,
static
Mixer
*
static
Mixer
*
pulse_mixer_init
(
gcc_unused
EventLoop
&
event_loop
,
AudioOutput
&
ao
,
pulse_mixer_init
(
gcc_unused
EventLoop
&
event_loop
,
AudioOutput
&
ao
,
MixerListener
&
listener
,
MixerListener
&
listener
,
gcc_unused
const
ConfigBlock
&
block
,
gcc_unused
const
ConfigBlock
&
block
)
gcc_unused
Error
&
error
)
{
{
PulseOutput
&
po
=
(
PulseOutput
&
)
ao
;
PulseOutput
&
po
=
(
PulseOutput
&
)
ao
;
PulseMixer
*
pm
=
new
PulseMixer
(
po
,
listener
);
PulseMixer
*
pm
=
new
PulseMixer
(
po
,
listener
);
...
@@ -180,42 +179,37 @@ PulseMixer::~PulseMixer()
...
@@ -180,42 +179,37 @@ PulseMixer::~PulseMixer()
}
}
int
int
PulseMixer
::
GetVolume
(
gcc_unused
Error
&
error
)
PulseMixer
::
GetVolume
()
{
{
Pulse
::
LockGuard
lock
(
pulse_output_get_mainloop
(
output
));
Pulse
::
LockGuard
lock
(
pulse_output_get_mainloop
(
output
));
return
GetVolumeInternal
(
error
);
return
GetVolumeInternal
();
}
}
/**
/**
* Pulse mainloop lock must be held by caller
* Pulse mainloop lock must be held by caller
*/
*/
int
int
PulseMixer
::
GetVolumeInternal
(
gcc_unused
Error
&
error
)
PulseMixer
::
GetVolumeInternal
()
{
{
return
online
?
return
online
?
(
int
)((
100
*
(
pa_cvolume_avg
(
&
volume
)
+
1
))
/
PA_VOLUME_NORM
)
(
int
)((
100
*
(
pa_cvolume_avg
(
&
volume
)
+
1
))
/
PA_VOLUME_NORM
)
:
-
1
;
:
-
1
;
}
}
bool
void
PulseMixer
::
SetVolume
(
unsigned
new_volume
,
Error
&
error
)
PulseMixer
::
SetVolume
(
unsigned
new_volume
)
{
{
Pulse
::
LockGuard
lock
(
pulse_output_get_mainloop
(
output
));
Pulse
::
LockGuard
lock
(
pulse_output_get_mainloop
(
output
));
if
(
!
online
)
{
if
(
!
online
)
error
.
Set
(
pulse_domain
,
"disconnected"
);
throw
std
::
runtime_error
(
"disconnected"
);
return
false
;
}
struct
pa_cvolume
cvolume
;
struct
pa_cvolume
cvolume
;
pa_cvolume_set
(
&
cvolume
,
volume
.
channels
,
pa_cvolume_set
(
&
cvolume
,
volume
.
channels
,
(
new_volume
*
PA_VOLUME_NORM
+
50
)
/
100
);
(
new_volume
*
PA_VOLUME_NORM
+
50
)
/
100
);
bool
success
=
pulse_output_set_volume
(
output
,
&
cvolume
,
error
);
pulse_output_set_volume
(
output
,
&
cvolume
);
if
(
success
)
volume
=
cvolume
;
volume
=
cvolume
;
return
success
;
}
}
const
MixerPlugin
pulse_mixer_plugin
=
{
const
MixerPlugin
pulse_mixer_plugin
=
{
...
...
src/mixer/plugins/RoarMixerPlugin.cxx
View file @
e7d32722
...
@@ -34,36 +34,34 @@ public:
...
@@ -34,36 +34,34 @@ public:
self
(
_output
)
{}
self
(
_output
)
{}
/* virtual methods from class Mixer */
/* virtual methods from class Mixer */
virtual
bool
Open
(
gcc_unused
Error
&
error
)
override
{
void
Open
()
override
{
return
true
;
}
}
virtual
void
Close
()
override
{
virtual
void
Close
()
override
{
}
}
virtual
int
GetVolume
(
Error
&
error
)
override
;
int
GetVolume
(
)
override
;
v
irtual
bool
SetVolume
(
unsigned
volume
,
Error
&
error
)
override
;
v
oid
SetVolume
(
unsigned
volume
)
override
;
};
};
static
Mixer
*
static
Mixer
*
roar_mixer_init
(
gcc_unused
EventLoop
&
event_loop
,
AudioOutput
&
ao
,
roar_mixer_init
(
gcc_unused
EventLoop
&
event_loop
,
AudioOutput
&
ao
,
MixerListener
&
listener
,
MixerListener
&
listener
,
gcc_unused
const
ConfigBlock
&
block
,
gcc_unused
const
ConfigBlock
&
block
)
gcc_unused
Error
&
error
)
{
{
return
new
RoarMixer
((
RoarOutput
&
)
ao
,
listener
);
return
new
RoarMixer
((
RoarOutput
&
)
ao
,
listener
);
}
}
int
int
RoarMixer
::
GetVolume
(
gcc_unused
Error
&
error
)
RoarMixer
::
GetVolume
()
{
{
return
roar_output_get_volume
(
self
);
return
roar_output_get_volume
(
self
);
}
}
bool
void
RoarMixer
::
SetVolume
(
unsigned
volume
,
gcc_unused
Error
&
error
)
RoarMixer
::
SetVolume
(
unsigned
volume
)
{
{
r
eturn
r
oar_output_set_volume
(
self
,
volume
);
roar_output_set_volume
(
self
,
volume
);
}
}
const
MixerPlugin
roar_mixer_plugin
=
{
const
MixerPlugin
roar_mixer_plugin
=
{
...
...
src/mixer/plugins/SoftwareMixerPlugin.cxx
View file @
e7d32722
...
@@ -26,7 +26,6 @@
...
@@ -26,7 +26,6 @@
#include "filter/plugins/VolumeFilterPlugin.hxx"
#include "filter/plugins/VolumeFilterPlugin.hxx"
#include "pcm/Volume.hxx"
#include "pcm/Volume.hxx"
#include "config/Block.hxx"
#include "config/Block.hxx"
#include "util/Error.hxx"
#include <assert.h>
#include <assert.h>
#include <math.h>
#include <math.h>
...
@@ -48,26 +47,24 @@ public:
...
@@ -48,26 +47,24 @@ public:
void
SetFilter
(
Filter
*
_filter
);
void
SetFilter
(
Filter
*
_filter
);
/* virtual methods from class Mixer */
/* virtual methods from class Mixer */
virtual
bool
Open
(
gcc_unused
Error
&
error
)
override
{
void
Open
()
override
{
return
true
;
}
}
virtual
void
Close
()
override
{
virtual
void
Close
()
override
{
}
}
virtual
int
GetVolume
(
gcc_unused
Error
&
error
)
override
{
int
GetVolume
(
)
override
{
return
volume
;
return
volume
;
}
}
v
irtual
bool
SetVolume
(
unsigned
volume
,
Error
&
error
)
override
;
v
oid
SetVolume
(
unsigned
volume
)
override
;
};
};
static
Mixer
*
static
Mixer
*
software_mixer_init
(
gcc_unused
EventLoop
&
event_loop
,
software_mixer_init
(
gcc_unused
EventLoop
&
event_loop
,
gcc_unused
AudioOutput
&
ao
,
gcc_unused
AudioOutput
&
ao
,
MixerListener
&
listener
,
MixerListener
&
listener
,
gcc_unused
const
ConfigBlock
&
block
,
gcc_unused
const
ConfigBlock
&
block
)
gcc_unused
Error
&
error
)
{
{
return
new
SoftwareMixer
(
listener
);
return
new
SoftwareMixer
(
listener
);
}
}
...
@@ -87,8 +84,8 @@ PercentVolumeToSoftwareVolume(unsigned volume)
...
@@ -87,8 +84,8 @@ PercentVolumeToSoftwareVolume(unsigned volume)
return
0
;
return
0
;
}
}
bool
void
SoftwareMixer
::
SetVolume
(
unsigned
new_volume
,
gcc_unused
Error
&
error
)
SoftwareMixer
::
SetVolume
(
unsigned
new_volume
)
{
{
assert
(
new_volume
<=
100
);
assert
(
new_volume
<=
100
);
...
@@ -96,7 +93,6 @@ SoftwareMixer::SetVolume(unsigned new_volume, gcc_unused Error &error)
...
@@ -96,7 +93,6 @@ SoftwareMixer::SetVolume(unsigned new_volume, gcc_unused Error &error)
if
(
filter
!=
nullptr
)
if
(
filter
!=
nullptr
)
volume_filter_set
(
filter
,
PercentVolumeToSoftwareVolume
(
new_volume
));
volume_filter_set
(
filter
,
PercentVolumeToSoftwareVolume
(
new_volume
));
return
true
;
}
}
const
MixerPlugin
software_mixer_plugin
=
{
const
MixerPlugin
software_mixer_plugin
=
{
...
...
src/mixer/plugins/WinmmMixerPlugin.cxx
View file @
e7d32722
...
@@ -21,11 +21,11 @@
...
@@ -21,11 +21,11 @@
#include "mixer/MixerInternal.hxx"
#include "mixer/MixerInternal.hxx"
#include "output/OutputAPI.hxx"
#include "output/OutputAPI.hxx"
#include "output/plugins/WinmmOutputPlugin.hxx"
#include "output/plugins/WinmmOutputPlugin.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include <mmsystem.h>
#include <mmsystem.h>
#include <stdexcept>
#include <assert.h>
#include <assert.h>
#include <math.h>
#include <math.h>
#include <windows.h>
#include <windows.h>
...
@@ -40,19 +40,16 @@ public:
...
@@ -40,19 +40,16 @@ public:
}
}
/* virtual methods from class Mixer */
/* virtual methods from class Mixer */
virtual
bool
Open
(
gcc_unused
Error
&
error
)
override
{
void
Open
()
override
{
return
true
;
}
}
v
irtual
v
oid
Close
()
override
{
void
Close
()
override
{
}
}
virtual
int
GetVolume
(
Error
&
error
)
override
;
int
GetVolume
(
)
override
;
v
irtual
bool
SetVolume
(
unsigned
volume
,
Error
&
error
)
override
;
v
oid
SetVolume
(
unsigned
volume
)
override
;
};
};
static
constexpr
Domain
winmm_mixer_domain
(
"winmm_mixer"
);
static
inline
int
static
inline
int
winmm_volume_decode
(
DWORD
volume
)
winmm_volume_decode
(
DWORD
volume
)
{
{
...
@@ -69,40 +66,33 @@ winmm_volume_encode(int volume)
...
@@ -69,40 +66,33 @@ winmm_volume_encode(int volume)
static
Mixer
*
static
Mixer
*
winmm_mixer_init
(
gcc_unused
EventLoop
&
event_loop
,
AudioOutput
&
ao
,
winmm_mixer_init
(
gcc_unused
EventLoop
&
event_loop
,
AudioOutput
&
ao
,
MixerListener
&
listener
,
MixerListener
&
listener
,
gcc_unused
const
ConfigBlock
&
block
,
gcc_unused
const
ConfigBlock
&
block
)
gcc_unused
Error
&
error
)
{
{
return
new
WinmmMixer
((
WinmmOutput
&
)
ao
,
listener
);
return
new
WinmmMixer
((
WinmmOutput
&
)
ao
,
listener
);
}
}
int
int
WinmmMixer
::
GetVolume
(
Error
&
error
)
WinmmMixer
::
GetVolume
()
{
{
DWORD
volume
;
DWORD
volume
;
HWAVEOUT
handle
=
winmm_output_get_handle
(
output
);
HWAVEOUT
handle
=
winmm_output_get_handle
(
output
);
MMRESULT
result
=
waveOutGetVolume
(
handle
,
&
volume
);
MMRESULT
result
=
waveOutGetVolume
(
handle
,
&
volume
);
if
(
result
!=
MMSYSERR_NOERROR
)
{
if
(
result
!=
MMSYSERR_NOERROR
)
error
.
Set
(
winmm_mixer_domain
,
"Failed to get winmm volume"
);
throw
std
::
runtime_error
(
"Failed to get winmm volume"
);
return
-
1
;
}
return
winmm_volume_decode
(
volume
);
return
winmm_volume_decode
(
volume
);
}
}
bool
void
WinmmMixer
::
SetVolume
(
unsigned
volume
,
Error
&
error
)
WinmmMixer
::
SetVolume
(
unsigned
volume
)
{
{
DWORD
value
=
winmm_volume_encode
(
volume
);
DWORD
value
=
winmm_volume_encode
(
volume
);
HWAVEOUT
handle
=
winmm_output_get_handle
(
output
);
HWAVEOUT
handle
=
winmm_output_get_handle
(
output
);
MMRESULT
result
=
waveOutSetVolume
(
handle
,
value
);
MMRESULT
result
=
waveOutSetVolume
(
handle
,
value
);
if
(
result
!=
MMSYSERR_NOERROR
)
{
if
(
result
!=
MMSYSERR_NOERROR
)
error
.
Set
(
winmm_mixer_domain
,
"Failed to set winmm volume"
);
throw
std
::
runtime_error
(
"Failed to set winmm volume"
);
return
false
;
}
return
true
;
}
}
const
MixerPlugin
winmm_mixer_plugin
=
{
const
MixerPlugin
winmm_mixer_plugin
=
{
...
...
src/output/Init.cxx
View file @
e7d32722
...
@@ -115,8 +115,7 @@ audio_output_load_mixer(EventLoop &event_loop, AudioOutput &ao,
...
@@ -115,8 +115,7 @@ audio_output_load_mixer(EventLoop &event_loop, AudioOutput &ao,
const
ConfigBlock
&
block
,
const
ConfigBlock
&
block
,
const
MixerPlugin
*
plugin
,
const
MixerPlugin
*
plugin
,
PreparedFilter
&
filter_chain
,
PreparedFilter
&
filter_chain
,
MixerListener
&
listener
,
MixerListener
&
listener
)
Error
&
error
)
{
{
Mixer
*
mixer
;
Mixer
*
mixer
;
...
@@ -127,20 +126,19 @@ audio_output_load_mixer(EventLoop &event_loop, AudioOutput &ao,
...
@@ -127,20 +126,19 @@ audio_output_load_mixer(EventLoop &event_loop, AudioOutput &ao,
case
MixerType
:
:
NULL_
:
case
MixerType
:
:
NULL_
:
return
mixer_new
(
event_loop
,
null_mixer_plugin
,
ao
,
listener
,
return
mixer_new
(
event_loop
,
null_mixer_plugin
,
ao
,
listener
,
block
,
error
);
block
);
case
MixerType
:
:
HARDWARE
:
case
MixerType
:
:
HARDWARE
:
if
(
plugin
==
nullptr
)
if
(
plugin
==
nullptr
)
return
nullptr
;
return
nullptr
;
return
mixer_new
(
event_loop
,
*
plugin
,
ao
,
listener
,
return
mixer_new
(
event_loop
,
*
plugin
,
ao
,
listener
,
block
,
error
);
block
);
case
MixerType
:
:
SOFTWARE
:
case
MixerType
:
:
SOFTWARE
:
mixer
=
mixer_new
(
event_loop
,
software_mixer_plugin
,
ao
,
mixer
=
mixer_new
(
event_loop
,
software_mixer_plugin
,
ao
,
listener
,
listener
,
ConfigBlock
(),
ConfigBlock
());
IgnoreError
());
assert
(
mixer
!=
nullptr
);
assert
(
mixer
!=
nullptr
);
filter_chain_append
(
filter_chain
,
"software_mixer"
,
filter_chain_append
(
filter_chain
,
"software_mixer"
,
...
@@ -246,16 +244,16 @@ audio_output_setup(EventLoop &event_loop, AudioOutput &ao,
...
@@ -246,16 +244,16 @@ audio_output_setup(EventLoop &event_loop, AudioOutput &ao,
/* set up the mixer */
/* set up the mixer */
Error
mixer_error
;
try
{
ao
.
mixer
=
audio_output_load_mixer
(
event_loop
,
ao
,
block
,
ao
.
mixer
=
audio_output_load_mixer
(
event_loop
,
ao
,
block
,
ao
.
plugin
.
mixer_plugin
,
ao
.
plugin
.
mixer_plugin
,
*
ao
.
prepared_filter
,
*
ao
.
prepared_filter
,
mixer_listener
,
mixer_listener
);
mixer_error
);
}
catch
(
const
std
::
runtime_error
&
e
)
{
if
(
ao
.
mixer
==
nullptr
&&
mixer_error
.
IsDefined
())
FormatError
(
e
,
FormatError
(
mixer_error
,
"Failed to initialize hardware mixer for '%s'"
,
"Failed to initialize hardware mixer for '%s'"
,
ao
.
name
);
ao
.
name
);
}
/* use the hardware mixer for replay gain? */
/* use the hardware mixer for replay gain? */
...
...
src/output/OutputControl.cxx
View file @
e7d32722
...
@@ -27,6 +27,8 @@
...
@@ -27,6 +27,8 @@
#include "util/Error.hxx"
#include "util/Error.hxx"
#include "Log.hxx"
#include "Log.hxx"
#include <stdexcept>
#include <assert.h>
#include <assert.h>
/** after a failure, wait this number of seconds before
/** after a failure, wait this number of seconds before
...
@@ -145,10 +147,11 @@ AudioOutput::Open(const AudioFormat audio_format, const MusicPipe &mp)
...
@@ -145,10 +147,11 @@ AudioOutput::Open(const AudioFormat audio_format, const MusicPipe &mp)
const
bool
open2
=
open
;
const
bool
open2
=
open
;
if
(
open2
&&
mixer
!=
nullptr
)
{
if
(
open2
&&
mixer
!=
nullptr
)
{
Error
error
;
try
{
if
(
!
mixer_open
(
mixer
,
error
))
mixer_open
(
mixer
);
FormatWarning
(
output_domain
,
}
catch
(
const
std
::
runtime_error
&
e
)
{
"Failed to open mixer for '%s'"
,
name
);
FormatError
(
e
,
"Failed to open mixer for '%s'"
,
name
);
}
}
}
return
open2
;
return
open2
;
...
...
src/output/plugins/PulseOutputPlugin.cxx
View file @
e7d32722
...
@@ -37,6 +37,8 @@
...
@@ -37,6 +37,8 @@
#include <pulse/subscribe.h>
#include <pulse/subscribe.h>
#include <pulse/version.h>
#include <pulse/version.h>
#include <stdexcept>
#include <assert.h>
#include <assert.h>
#include <stddef.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdlib.h>
...
@@ -74,7 +76,7 @@ public:
...
@@ -74,7 +76,7 @@ public:
mixer
=
nullptr
;
mixer
=
nullptr
;
}
}
bool
SetVolume
(
const
pa_cvolume
&
volume
,
Error
&
error
);
void
SetVolume
(
const
pa_cvolume
&
volume
);
struct
pa_threaded_mainloop
*
GetMainloop
()
{
struct
pa_threaded_mainloop
*
GetMainloop
()
{
return
mainloop
;
return
mainloop
;
...
@@ -217,34 +219,27 @@ pulse_output_clear_mixer(PulseOutput &po, PulseMixer &pm)
...
@@ -217,34 +219,27 @@ pulse_output_clear_mixer(PulseOutput &po, PulseMixer &pm)
po
.
ClearMixer
(
pm
);
po
.
ClearMixer
(
pm
);
}
}
inline
bool
inline
void
PulseOutput
::
SetVolume
(
const
pa_cvolume
&
volume
,
Error
&
error
)
PulseOutput
::
SetVolume
(
const
pa_cvolume
&
volume
)
{
{
if
(
context
==
nullptr
||
stream
==
nullptr
||
if
(
context
==
nullptr
||
stream
==
nullptr
||
pa_stream_get_state
(
stream
)
!=
PA_STREAM_READY
)
{
pa_stream_get_state
(
stream
)
!=
PA_STREAM_READY
)
error
.
Set
(
pulse_domain
,
"disconnected"
);
throw
std
::
runtime_error
(
"disconnected"
);
return
false
;
}
pa_operation
*
o
=
pa_operation
*
o
=
pa_context_set_sink_input_volume
(
context
,
pa_context_set_sink_input_volume
(
context
,
pa_stream_get_index
(
stream
),
pa_stream_get_index
(
stream
),
&
volume
,
nullptr
,
nullptr
);
&
volume
,
nullptr
,
nullptr
);
if
(
o
==
nullptr
)
{
if
(
o
==
nullptr
)
SetPulseError
(
error
,
context
,
throw
std
::
runtime_error
(
"failed to set PulseAudio volume"
);
"failed to set PulseAudio volume"
);
return
false
;
}
pa_operation_unref
(
o
);
pa_operation_unref
(
o
);
return
true
;
}
}
bool
void
pulse_output_set_volume
(
PulseOutput
&
po
,
const
pa_cvolume
*
volume
,
pulse_output_set_volume
(
PulseOutput
&
po
,
const
pa_cvolume
*
volume
)
Error
&
error
)
{
{
return
po
.
SetVolume
(
*
volume
,
error
);
return
po
.
SetVolume
(
*
volume
);
}
}
/**
/**
...
...
src/output/plugins/PulseOutputPlugin.hxx
View file @
e7d32722
...
@@ -36,8 +36,7 @@ pulse_output_set_mixer(PulseOutput &po, PulseMixer &pm);
...
@@ -36,8 +36,7 @@ pulse_output_set_mixer(PulseOutput &po, PulseMixer &pm);
void
void
pulse_output_clear_mixer
(
PulseOutput
&
po
,
PulseMixer
&
pm
);
pulse_output_clear_mixer
(
PulseOutput
&
po
,
PulseMixer
&
pm
);
bool
void
pulse_output_set_volume
(
PulseOutput
&
po
,
pulse_output_set_volume
(
PulseOutput
&
po
,
const
pa_cvolume
*
volume
);
const
pa_cvolume
*
volume
,
Error
&
error
);
#endif
#endif
src/output/plugins/RoarOutputPlugin.cxx
View file @
e7d32722
...
@@ -29,6 +29,7 @@
...
@@ -29,6 +29,7 @@
#include "Log.hxx"
#include "Log.hxx"
#include <string>
#include <string>
#include <stdexcept>
/* libroar/services.h declares roar_service_stream::new - work around
/* libroar/services.h declares roar_service_stream::new - work around
this C++ problem */
this C++ problem */
...
@@ -74,7 +75,7 @@ public:
...
@@ -74,7 +75,7 @@ public:
void
Cancel
();
void
Cancel
();
int
GetVolume
()
const
;
int
GetVolume
()
const
;
bool
SetVolume
(
unsigned
volume
);
void
SetVolume
(
unsigned
volume
);
};
};
static
constexpr
Domain
roar_output_domain
(
"roar_output"
);
static
constexpr
Domain
roar_output_domain
(
"roar_output"
);
...
@@ -90,7 +91,7 @@ RoarOutput::GetVolume() const
...
@@ -90,7 +91,7 @@ RoarOutput::GetVolume() const
float
l
,
r
;
float
l
,
r
;
int
error
;
int
error
;
if
(
roar_vs_volume_get
(
vss
,
&
l
,
&
r
,
&
error
)
<
0
)
if
(
roar_vs_volume_get
(
vss
,
&
l
,
&
r
,
&
error
)
<
0
)
return
-
1
;
throw
std
::
runtime_error
(
roar_vs_strerr
(
error
))
;
return
(
l
+
r
)
*
50
;
return
(
l
+
r
)
*
50
;
}
}
...
@@ -101,26 +102,26 @@ roar_output_get_volume(RoarOutput &roar)
...
@@ -101,26 +102,26 @@ roar_output_get_volume(RoarOutput &roar)
return
roar
.
GetVolume
();
return
roar
.
GetVolume
();
}
}
bool
inline
void
RoarOutput
::
SetVolume
(
unsigned
volume
)
RoarOutput
::
SetVolume
(
unsigned
volume
)
{
{
assert
(
volume
<=
100
);
assert
(
volume
<=
100
);
const
ScopeLock
protect
(
mutex
);
const
ScopeLock
protect
(
mutex
);
if
(
vss
==
nullptr
||
!
alive
)
if
(
vss
==
nullptr
||
!
alive
)
return
false
;
throw
std
::
runtime_error
(
"closed"
)
;
int
error
;
int
error
;
float
level
=
volume
/
100.0
;
float
level
=
volume
/
100.0
;
roar_vs_volume_mono
(
vss
,
level
,
&
error
);
if
(
roar_vs_volume_mono
(
vss
,
level
,
&
error
)
<
0
)
return
true
;
throw
std
::
runtime_error
(
roar_vs_strerr
(
error
))
;
}
}
bool
void
roar_output_set_volume
(
RoarOutput
&
roar
,
unsigned
volume
)
roar_output_set_volume
(
RoarOutput
&
roar
,
unsigned
volume
)
{
{
r
eturn
r
oar
.
SetVolume
(
volume
);
roar
.
SetVolume
(
volume
);
}
}
inline
void
inline
void
...
...
src/output/plugins/RoarOutputPlugin.hxx
View file @
e7d32722
...
@@ -27,7 +27,7 @@ extern const struct AudioOutputPlugin roar_output_plugin;
...
@@ -27,7 +27,7 @@ extern const struct AudioOutputPlugin roar_output_plugin;
int
int
roar_output_get_volume
(
RoarOutput
&
roar
);
roar_output_get_volume
(
RoarOutput
&
roar
);
bool
void
roar_output_set_volume
(
RoarOutput
&
roar
,
unsigned
volume
);
roar_output_set_volume
(
RoarOutput
&
roar
,
unsigned
volume
);
#endif
#endif
test/read_mixer.cxx
View file @
e7d32722
...
@@ -41,7 +41,7 @@ filter_plugin_by_name(gcc_unused const char *name)
...
@@ -41,7 +41,7 @@ filter_plugin_by_name(gcc_unused const char *name)
}
}
int
main
(
int
argc
,
gcc_unused
char
**
argv
)
int
main
(
int
argc
,
gcc_unused
char
**
argv
)
{
try
{
int
volume
;
int
volume
;
if
(
argc
!=
2
)
{
if
(
argc
!=
2
)
{
...
@@ -51,36 +51,27 @@ int main(int argc, gcc_unused char **argv)
...
@@ -51,36 +51,27 @@ int main(int argc, gcc_unused char **argv)
EventLoop
event_loop
;
EventLoop
event_loop
;
Error
error
;
Mixer
*
mixer
=
mixer_new
(
event_loop
,
alsa_mixer_plugin
,
Mixer
*
mixer
=
mixer_new
(
event_loop
,
alsa_mixer_plugin
,
*
(
AudioOutput
*
)
nullptr
,
*
(
AudioOutput
*
)
nullptr
,
*
(
MixerListener
*
)
nullptr
,
*
(
MixerListener
*
)
nullptr
,
ConfigBlock
(),
error
);
ConfigBlock
());
if
(
mixer
==
NULL
)
{
LogError
(
error
,
"mixer_new() failed"
);
return
EXIT_FAILURE
;
}
if
(
!
mixer_open
(
mixer
,
error
))
{
mixer_open
(
mixer
);
mixer_free
(
mixer
);
LogError
(
error
,
"failed to open the mixer"
);
return
EXIT_FAILURE
;
}
volume
=
mixer_get_volume
(
mixer
,
error
);
volume
=
mixer_get_volume
(
mixer
);
mixer_close
(
mixer
);
mixer_close
(
mixer
);
mixer_free
(
mixer
);
mixer_free
(
mixer
);
assert
(
volume
>=
-
1
&&
volume
<=
100
);
assert
(
volume
>=
-
1
&&
volume
<=
100
);
if
(
volume
<
0
)
{
if
(
volume
<
0
)
{
if
(
error
.
IsDefined
())
{
fprintf
(
stderr
,
"failed to read volume
\n
"
);
LogError
(
error
,
"failed to read volume"
);
}
else
fprintf
(
stderr
,
"failed to read volume
\n
"
);
return
EXIT_FAILURE
;
return
EXIT_FAILURE
;
}
}
printf
(
"%d
\n
"
,
volume
);
printf
(
"%d
\n
"
,
volume
);
return
0
;
return
0
;
}
catch
(
const
std
::
exception
&
e
)
{
LogError
(
e
);
return
EXIT_FAILURE
;
}
}
test/run_filter.cxx
View file @
e7d32722
...
@@ -41,11 +41,10 @@
...
@@ -41,11 +41,10 @@
#include <errno.h>
#include <errno.h>
#include <unistd.h>
#include <unistd.h>
bool
void
mixer_set_volume
(
gcc_unused
Mixer
*
mixer
,
mixer_set_volume
(
gcc_unused
Mixer
*
mixer
,
gcc_unused
unsigned
volume
,
gcc_unused
Error
&
error
)
gcc_unused
unsigned
volume
)
{
{
return
true
;
}
}
static
PreparedFilter
*
static
PreparedFilter
*
...
...
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