Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
vlc-gpu
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
videolan
vlc-gpu
Commits
ce90ea7f
Commit
ce90ea7f
authored
Jul 18, 2011
by
Rémi Denis-Courmont
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
PulseAudio: use the helpers
parent
8ed55bbf
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
38 additions
and
96 deletions
+38
-96
modules/audio_output/Modules.am
modules/audio_output/Modules.am
+2
-1
modules/audio_output/pulse.c
modules/audio_output/pulse.c
+36
-95
No files found.
modules/audio_output/Modules.am
View file @
ce90ea7f
...
@@ -34,7 +34,8 @@ endif
...
@@ -34,7 +34,8 @@ endif
libpulse_plugin_la_SOURCES = pulse.c
libpulse_plugin_la_SOURCES = pulse.c
libpulse_plugin_la_CFLAGS = $(AM_CFLAGS) $(PULSE_CFLAGS)
libpulse_plugin_la_CFLAGS = $(AM_CFLAGS) $(PULSE_CFLAGS)
libpulse_plugin_la_LIBADD = $(AM_LIBADD) $(PULSE_LIBS)
libpulse_plugin_la_LIBADD = $(AM_LIBADD) $(PULSE_LIBS) \
../../src/libvlcpulse.la
libpulse_plugin_la_DEPENDENCIES =
libpulse_plugin_la_DEPENDENCIES =
if HAVE_PULSE
if HAVE_PULSE
libvlc_LTLIBRARIES += libpulse_plugin.la
libvlc_LTLIBRARIES += libpulse_plugin.la
...
...
modules/audio_output/pulse.c
View file @
ce90ea7f
...
@@ -32,6 +32,7 @@
...
@@ -32,6 +32,7 @@
#include <vlc_cpu.h>
#include <vlc_cpu.h>
#include <pulse/pulseaudio.h>
#include <pulse/pulseaudio.h>
#include <vlc_pulse.h>
static
int
Open
(
vlc_object_t
*
);
static
int
Open
(
vlc_object_t
*
);
static
void
Close
(
vlc_object_t
*
);
static
void
Close
(
vlc_object_t
*
);
...
@@ -47,7 +48,6 @@ vlc_module_begin ()
...
@@ -47,7 +48,6 @@ vlc_module_begin ()
vlc_module_end
()
vlc_module_end
()
/* TODO:
/* TODO:
* - single static mainloop
* - pause input on policy event
* - pause input on policy event
* - resample to compensate for long term drift
* - resample to compensate for long term drift
* - select music or video stream property correctly (?)
* - select music or video stream property correctly (?)
...
@@ -57,7 +57,7 @@ vlc_module_end ()
...
@@ -57,7 +57,7 @@ vlc_module_end ()
/* NOTE:
/* NOTE:
* Be careful what you do when the PulseAudio mainloop is held, which is to say
* Be careful what you do when the PulseAudio mainloop is held, which is to say
* within PulseAudio callbacks, or after
pa_threaded_mainloop
_lock().
* within PulseAudio callbacks, or after
vlc_pa
_lock().
* In particular, a VLC variable callback cannot be triggered nor deleted with
* In particular, a VLC variable callback cannot be triggered nor deleted with
* the PulseAudio mainloop lock held, if the callback acquires the lock. */
* the PulseAudio mainloop lock held, if the callback acquires the lock. */
...
@@ -65,43 +65,10 @@ struct aout_sys_t
...
@@ -65,43 +65,10 @@ struct aout_sys_t
{
{
pa_stream
*
stream
;
/**< PulseAudio playback stream object */
pa_stream
*
stream
;
/**< PulseAudio playback stream object */
pa_context
*
context
;
/**< PulseAudio connection context */
pa_context
*
context
;
/**< PulseAudio connection context */
pa_threaded_mainloop
*
mainloop
;
/**< PulseAudio event loop */
pa_volume_t
base_volume
;
/**< 0dB reference volume */
pa_volume_t
base_volume
;
/**< 0dB reference volume */
pa_cvolume
cvolume
;
/**< actual sink input volume */
pa_cvolume
cvolume
;
/**< actual sink input volume */
};
};
/*** Context helpers ***/
static
void
context_state_cb
(
pa_context
*
c
,
void
*
userdata
)
{
pa_threaded_mainloop
*
mainloop
=
userdata
;
switch
(
pa_context_get_state
(
c
))
{
case
PA_CONTEXT_READY
:
case
PA_CONTEXT_FAILED
:
case
PA_CONTEXT_TERMINATED
:
pa_threaded_mainloop_signal
(
mainloop
,
0
);
default:
break
;
}
}
static
bool
context_wait
(
pa_threaded_mainloop
*
mainloop
,
pa_context
*
context
)
{
pa_context_state_t
state
;
while
((
state
=
pa_context_get_state
(
context
))
!=
PA_CONTEXT_READY
)
{
if
(
state
==
PA_CONTEXT_FAILED
||
state
==
PA_CONTEXT_TERMINATED
)
return
-
1
;
pa_threaded_mainloop_wait
(
mainloop
);
}
return
0
;
}
static
void
error
(
aout_instance_t
*
aout
,
const
char
*
msg
,
pa_context
*
context
)
{
msg_Err
(
aout
,
"%s: %s"
,
msg
,
pa_strerror
(
pa_context_errno
(
context
)));
}
/*** Sink ***/
/*** Sink ***/
static
void
sink_list_cb
(
pa_context
*
c
,
const
pa_sink_info
*
i
,
int
eol
,
static
void
sink_list_cb
(
pa_context
*
c
,
const
pa_sink_info
*
i
,
int
eol
,
void
*
userdata
)
void
*
userdata
)
...
@@ -145,16 +112,15 @@ static void sink_info_cb(pa_context *c, const pa_sink_info *i, int eol,
...
@@ -145,16 +112,15 @@ static void sink_info_cb(pa_context *c, const pa_sink_info *i, int eol,
/*** Stream helpers ***/
/*** Stream helpers ***/
static
void
stream_state_cb
(
pa_stream
*
s
,
void
*
userdata
)
static
void
stream_state_cb
(
pa_stream
*
s
,
void
*
userdata
)
{
{
pa_threaded_mainloop
*
mainloop
=
userdata
;
switch
(
pa_stream_get_state
(
s
))
{
switch
(
pa_stream_get_state
(
s
))
{
case
PA_STREAM_READY
:
case
PA_STREAM_READY
:
case
PA_STREAM_FAILED
:
case
PA_STREAM_FAILED
:
case
PA_STREAM_TERMINATED
:
case
PA_STREAM_TERMINATED
:
pa_threaded_mainloop_signal
(
mainloop
,
0
);
vlc_pa_signal
(
0
);
default:
default:
break
;
break
;
}
}
(
void
)
userdata
;
}
}
static
void
stream_moved_cb
(
pa_stream
*
s
,
void
*
userdata
)
static
void
stream_moved_cb
(
pa_stream
*
s
,
void
*
userdata
)
...
@@ -211,14 +177,14 @@ static void stream_underflow_cb(pa_stream *s, void *userdata)
...
@@ -211,14 +177,14 @@ static void stream_underflow_cb(pa_stream *s, void *userdata)
pa_operation_unref
(
op
);
pa_operation_unref
(
op
);
}
}
static
int
stream_wait
(
pa_
threaded_mainloop
*
mainloop
,
pa_
stream
*
stream
)
static
int
stream_wait
(
pa_stream
*
stream
)
{
{
pa_stream_state_t
state
;
pa_stream_state_t
state
;
while
((
state
=
pa_stream_get_state
(
stream
))
!=
PA_STREAM_READY
)
{
while
((
state
=
pa_stream_get_state
(
stream
))
!=
PA_STREAM_READY
)
{
if
(
state
==
PA_STREAM_FAILED
||
state
==
PA_STREAM_TERMINATED
)
if
(
state
==
PA_STREAM_FAILED
||
state
==
PA_STREAM_TERMINATED
)
return
-
1
;
return
-
1
;
pa_threaded_mainloop_wait
(
mainloop
);
vlc_pa_wait
(
);
}
}
return
0
;
return
0
;
}
}
...
@@ -271,7 +237,7 @@ static void Play(aout_instance_t *aout)
...
@@ -271,7 +237,7 @@ static void Play(aout_instance_t *aout)
* output FIFO lock while the PulseAudio threaded main loop lock is held
* output FIFO lock while the PulseAudio threaded main loop lock is held
* (including from PulseAudio stream callbacks). Otherwise lock inversion
* (including from PulseAudio stream callbacks). Otherwise lock inversion
* will take place, and sooner or later a deadlock. */
* will take place, and sooner or later a deadlock. */
pa_threaded_mainloop_lock
(
sys
->
mainloop
);
vlc_pa_lock
(
);
if
(
pa_stream_is_corked
(
s
)
>
0
)
{
if
(
pa_stream_is_corked
(
s
)
>
0
)
{
/* Start or resume the stream. Zeroes are prepended to sync.
/* Start or resume the stream. Zeroes are prepended to sync.
...
@@ -323,11 +289,11 @@ static void Play(aout_instance_t *aout)
...
@@ -323,11 +289,11 @@ static void Play(aout_instance_t *aout)
#endif
#endif
if
(
pa_stream_write
(
s
,
ptr
,
len
,
data_free
,
0
,
PA_SEEK_RELATIVE
)
<
0
)
{
if
(
pa_stream_write
(
s
,
ptr
,
len
,
data_free
,
0
,
PA_SEEK_RELATIVE
)
<
0
)
{
error
(
aout
,
"cannot write"
,
sys
->
context
);
vlc_pa_
error
(
aout
,
"cannot write"
,
sys
->
context
);
block_Release
(
block
);
block_Release
(
block
);
}
}
pa_threaded_mainloop_unlock
(
sys
->
mainloop
);
vlc_pa_unlock
(
);
}
}
/**
/**
...
@@ -341,20 +307,19 @@ static void Pause(aout_instance_t *aout, bool b_paused, mtime_t i_date)
...
@@ -341,20 +307,19 @@ static void Pause(aout_instance_t *aout, bool b_paused, mtime_t i_date)
if
(
!
b_paused
)
if
(
!
b_paused
)
return
;
/* nothing to do - yet */
return
;
/* nothing to do - yet */
pa_threaded_mainloop_lock
(
sys
->
mainloop
);
vlc_pa_lock
(
);
pa_operation
*
op
=
pa_stream_cork
(
s
,
1
,
NULL
,
NULL
);
pa_operation
*
op
=
pa_stream_cork
(
s
,
1
,
NULL
,
NULL
);
if
(
op
!=
NULL
)
if
(
op
!=
NULL
)
pa_operation_unref
(
op
);
pa_operation_unref
(
op
);
pa_threaded_mainloop_unlock
(
sys
->
mainloop
);
vlc_pa_unlock
(
);
(
void
)
i_date
;
(
void
)
i_date
;
}
}
static
int
VolumeSet
(
aout_instance_t
*
aout
,
audio_volume_t
vol
,
bool
mute
)
static
int
VolumeSet
(
aout_instance_t
*
aout
,
audio_volume_t
vol
,
bool
mute
)
{
{
aout_sys_t
*
sys
=
aout
->
output
.
p_sys
;
aout_sys_t
*
sys
=
aout
->
output
.
p_sys
;
pa_threaded_mainloop
*
mainloop
=
sys
->
mainloop
;
pa_operation
*
op
;
pa_operation
*
op
;
uint32_t
idx
=
pa_stream_get_index
(
sys
->
stream
);
uint32_t
idx
=
pa_stream_get_index
(
sys
->
stream
);
...
@@ -367,14 +332,14 @@ static int VolumeSet(aout_instance_t *aout, audio_volume_t vol, bool mute)
...
@@ -367,14 +332,14 @@ static int VolumeSet(aout_instance_t *aout, audio_volume_t vol, bool mute)
pa_sw_cvolume_multiply_scalar
(
&
cvolume
,
&
sys
->
cvolume
,
sys
->
base_volume
);
pa_sw_cvolume_multiply_scalar
(
&
cvolume
,
&
sys
->
cvolume
,
sys
->
base_volume
);
assert
(
pa_cvolume_valid
(
&
cvolume
));
assert
(
pa_cvolume_valid
(
&
cvolume
));
pa_threaded_mainloop_lock
(
mainloop
);
vlc_pa_lock
(
);
op
=
pa_context_set_sink_input_volume
(
sys
->
context
,
idx
,
&
cvolume
,
NULL
,
NULL
);
op
=
pa_context_set_sink_input_volume
(
sys
->
context
,
idx
,
&
cvolume
,
NULL
,
NULL
);
if
(
likely
(
op
!=
NULL
))
if
(
likely
(
op
!=
NULL
))
pa_operation_unref
(
op
);
pa_operation_unref
(
op
);
op
=
pa_context_set_sink_input_mute
(
sys
->
context
,
idx
,
mute
,
NULL
,
NULL
);
op
=
pa_context_set_sink_input_mute
(
sys
->
context
,
idx
,
mute
,
NULL
,
NULL
);
if
(
likely
(
op
!=
NULL
))
if
(
likely
(
op
!=
NULL
))
pa_operation_unref
(
op
);
pa_operation_unref
(
op
);
pa_threaded_mainloop_unlock
(
mainloop
);
vlc_pa_unlock
(
);
return
0
;
return
0
;
}
}
...
@@ -391,15 +356,15 @@ static int StreamMove(vlc_object_t *obj, const char *varname, vlc_value_t old,
...
@@ -391,15 +356,15 @@ static int StreamMove(vlc_object_t *obj, const char *varname, vlc_value_t old,
(
void
)
varname
;
(
void
)
old
;
(
void
)
varname
;
(
void
)
old
;
pa_threaded_mainloop_lock
(
sys
->
mainloop
);
vlc_pa_lock
(
);
op
=
pa_context_move_sink_input_by_index
(
sys
->
context
,
idx
,
sink_idx
,
op
=
pa_context_move_sink_input_by_index
(
sys
->
context
,
idx
,
sink_idx
,
NULL
,
NULL
);
NULL
,
NULL
);
if
(
likely
(
op
!=
NULL
))
{
if
(
likely
(
op
!=
NULL
))
{
pa_operation_unref
(
op
);
pa_operation_unref
(
op
);
msg_Dbg
(
aout
,
"moving to sink %"
PRIu32
,
sink_idx
);
msg_Dbg
(
aout
,
"moving to sink %"
PRIu32
,
sink_idx
);
}
else
}
else
error
(
aout
,
"cannot move sink"
,
sys
->
context
);
vlc_pa_error
(
obj
,
"cannot move sink"
,
sys
->
context
);
pa_threaded_mainloop_unlock
(
sys
->
mainloop
);
vlc_pa_unlock
(
);
return
(
op
!=
NULL
)
?
VLC_SUCCESS
:
VLC_EGENERIC
;
return
(
op
!=
NULL
)
?
VLC_SUCCESS
:
VLC_EGENERIC
;
}
}
...
@@ -534,53 +499,31 @@ static int Open(vlc_object_t *obj)
...
@@ -534,53 +499,31 @@ static int Open(vlc_object_t *obj)
aout_sys_t
*
sys
=
malloc
(
sizeof
(
*
sys
));
aout_sys_t
*
sys
=
malloc
(
sizeof
(
*
sys
));
if
(
unlikely
(
sys
==
NULL
))
if
(
unlikely
(
sys
==
NULL
))
return
VLC_ENOMEM
;
return
VLC_ENOMEM
;
pa_context
*
ctx
=
vlc_pa_connect
(
obj
);
if
(
ctx
==
NULL
)
{
free
(
sys
);
return
VLC_EGENERIC
;
}
aout
->
output
.
p_sys
=
sys
;
aout
->
output
.
p_sys
=
sys
;
sys
->
context
=
NULL
;
sys
->
stream
=
NULL
;
sys
->
stream
=
NULL
;
sys
->
context
=
ctx
;
/* Channel volume */
/* Channel volume */
sys
->
base_volume
=
PA_VOLUME_NORM
;
sys
->
base_volume
=
PA_VOLUME_NORM
;
pa_cvolume_set
(
&
sys
->
cvolume
,
ss
.
channels
,
PA_VOLUME_NORM
);
pa_cvolume_set
(
&
sys
->
cvolume
,
ss
.
channels
,
PA_VOLUME_NORM
);
/* Allocate threaded main loop */
vlc_pa_lock
();
pa_threaded_mainloop
*
mainloop
=
pa_threaded_mainloop_new
();
if
(
unlikely
(
mainloop
==
NULL
))
{
free
(
sys
);
return
VLC_ENOMEM
;
}
sys
->
mainloop
=
mainloop
;
if
(
pa_threaded_mainloop_start
(
mainloop
)
<
0
)
{
pa_threaded_mainloop_free
(
mainloop
);
free
(
sys
);
return
VLC_ENOMEM
;
}
pa_threaded_mainloop_lock
(
mainloop
);
/* Connect to PulseAudio server */
char
*
user_agent
=
var_InheritString
(
aout
,
"user-agent"
);
pa_context
*
ctx
=
pa_context_new
(
pa_threaded_mainloop_get_api
(
mainloop
),
user_agent
);
free
(
user_agent
);
if
(
unlikely
(
ctx
==
NULL
))
goto
fail
;
sys
->
context
=
ctx
;
pa_context_set_state_callback
(
ctx
,
context_state_cb
,
mainloop
);
if
(
pa_context_connect
(
ctx
,
NULL
,
0
,
NULL
)
<
0
||
context_wait
(
mainloop
,
ctx
))
{
error
(
aout
,
"cannot connect to server"
,
ctx
);
goto
fail
;
}
/* Create a playback stream */
/* Create a playback stream */
pa_stream
*
s
=
pa_stream_new
(
ctx
,
"audio stream"
,
&
ss
,
&
map
);
pa_stream
*
s
=
pa_stream_new
(
ctx
,
"audio stream"
,
&
ss
,
&
map
);
if
(
s
==
NULL
)
{
if
(
s
==
NULL
)
{
error
(
aout
,
"cannot create stream
"
,
ctx
);
vlc_pa_error
(
obj
,
"stream creation failure
"
,
ctx
);
goto
fail
;
goto
fail
;
}
}
sys
->
stream
=
s
;
sys
->
stream
=
s
;
pa_stream_set_state_callback
(
s
,
stream_state_cb
,
mainloop
);
pa_stream_set_state_callback
(
s
,
stream_state_cb
,
NULL
);
pa_stream_set_moved_callback
(
s
,
stream_moved_cb
,
aout
);
pa_stream_set_moved_callback
(
s
,
stream_moved_cb
,
aout
);
pa_stream_set_overflow_callback
(
s
,
stream_overflow_cb
,
aout
);
pa_stream_set_overflow_callback
(
s
,
stream_overflow_cb
,
aout
);
pa_stream_set_started_callback
(
s
,
stream_started_cb
,
aout
);
pa_stream_set_started_callback
(
s
,
stream_started_cb
,
aout
);
...
@@ -588,8 +531,8 @@ static int Open(vlc_object_t *obj)
...
@@ -588,8 +531,8 @@ static int Open(vlc_object_t *obj)
pa_stream_set_underflow_callback
(
s
,
stream_underflow_cb
,
aout
);
pa_stream_set_underflow_callback
(
s
,
stream_underflow_cb
,
aout
);
if
(
pa_stream_connect_playback
(
s
,
NULL
,
&
attr
,
flags
,
NULL
,
NULL
)
<
0
if
(
pa_stream_connect_playback
(
s
,
NULL
,
&
attr
,
flags
,
NULL
,
NULL
)
<
0
||
stream_wait
(
mainloop
,
s
))
{
||
stream_wait
(
s
))
{
error
(
aout
,
"cannot connect stream
"
,
ctx
);
vlc_pa_error
(
obj
,
"stream connection failure
"
,
ctx
);
goto
fail
;
goto
fail
;
}
}
...
@@ -610,7 +553,7 @@ static int Open(vlc_object_t *obj)
...
@@ -610,7 +553,7 @@ static int Open(vlc_object_t *obj)
if
(
op
!=
NULL
)
if
(
op
!=
NULL
)
pa_operation_unref
(
op
);
pa_operation_unref
(
op
);
stream_moved_cb
(
s
,
aout
);
stream_moved_cb
(
s
,
aout
);
pa_threaded_mainloop_unlock
(
mainloop
);
vlc_pa_unlock
(
);
aout
->
output
.
pf_play
=
Play
;
aout
->
output
.
pf_play
=
Play
;
aout
->
output
.
pf_pause
=
Pause
;
aout
->
output
.
pf_pause
=
Pause
;
...
@@ -618,7 +561,7 @@ static int Open(vlc_object_t *obj)
...
@@ -618,7 +561,7 @@ static int Open(vlc_object_t *obj)
return
VLC_SUCCESS
;
return
VLC_SUCCESS
;
fail:
fail:
pa_threaded_mainloop_unlock
(
mainloop
);
vlc_pa_unlock
(
);
Close
(
obj
);
Close
(
obj
);
return
VLC_EGENERIC
;
return
VLC_EGENERIC
;
}
}
...
@@ -630,7 +573,6 @@ static void Close (vlc_object_t *obj)
...
@@ -630,7 +573,6 @@ static void Close (vlc_object_t *obj)
{
{
aout_instance_t
*
aout
=
(
aout_instance_t
*
)
obj
;
aout_instance_t
*
aout
=
(
aout_instance_t
*
)
obj
;
aout_sys_t
*
sys
=
aout
->
output
.
p_sys
;
aout_sys_t
*
sys
=
aout
->
output
.
p_sys
;
pa_threaded_mainloop
*
mainloop
=
sys
->
mainloop
;
pa_context
*
ctx
=
sys
->
context
;
pa_context
*
ctx
=
sys
->
context
;
pa_stream
*
s
=
sys
->
stream
;
pa_stream
*
s
=
sys
->
stream
;
...
@@ -640,7 +582,7 @@ static void Close (vlc_object_t *obj)
...
@@ -640,7 +582,7 @@ static void Close (vlc_object_t *obj)
var_Destroy
(
aout
,
"audio-device"
);
var_Destroy
(
aout
,
"audio-device"
);
}
}
pa_threaded_mainloop_lock
(
mainloop
);
vlc_pa_lock
(
);
if
(
s
!=
NULL
)
{
if
(
s
!=
NULL
)
{
pa_operation
*
op
;
pa_operation
*
op
;
...
@@ -653,9 +595,8 @@ static void Close (vlc_object_t *obj)
...
@@ -653,9 +595,8 @@ static void Close (vlc_object_t *obj)
pa_stream_disconnect
(
s
);
pa_stream_disconnect
(
s
);
pa_stream_unref
(
s
);
pa_stream_unref
(
s
);
}
}
if
(
ctx
!=
NULL
)
vlc_pa_unlock
();
pa_context_unref
(
ctx
);
pa_threaded_mainloop_unlock
(
mainloop
);
vlc_pa_disconnect
(
obj
,
ctx
);
pa_threaded_mainloop_free
(
mainloop
);
free
(
sys
);
free
(
sys
);
}
}
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