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
1bfd25be
Commit
1bfd25be
authored
Oct 21, 2009
by
Max Kellermann
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
output/jack: connect to server on MPD startup
.. and keep up the JACK connection while MPD runs. Allocate the ring buffers on the first open, and free them at MPD exit.
parent
cee216f2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
119 additions
and
68 deletions
+119
-68
NEWS
NEWS
+1
-0
jack_output_plugin.c
src/output/jack_output_plugin.c
+118
-68
No files found.
NEWS
View file @
1bfd25be
...
@@ -33,6 +33,7 @@ ver 0.16 (20??/??/??)
...
@@ -33,6 +33,7 @@ ver 0.16 (20??/??/??)
- pulse: renamed context to "Music Player Daemon"
- pulse: renamed context to "Music Player Daemon"
- pulse: connect to server on MPD startup, implement pause
- pulse: connect to server on MPD startup, implement pause
- jack: don't disconnect during pause
- jack: don't disconnect during pause
- jack: connect to server on MPD startup
* mixers:
* mixers:
- removed support for legacy mixer configuration
- removed support for legacy mixer configuration
- reimplemented software volume as mixer+filter plugin
- reimplemented software volume as mixer+filter plugin
...
...
src/output/jack_output_plugin.c
View file @
1bfd25be
...
@@ -75,43 +75,6 @@ jack_output_quark(void)
...
@@ -75,43 +75,6 @@ jack_output_quark(void)
return
g_quark_from_static_string
(
"jack_output"
);
return
g_quark_from_static_string
(
"jack_output"
);
}
}
static
void
mpd_jack_client_free
(
struct
jack_data
*
jd
)
{
assert
(
jd
!=
NULL
);
if
(
jd
->
client
!=
NULL
)
{
jack_deactivate
(
jd
->
client
);
jack_client_close
(
jd
->
client
);
jd
->
client
=
NULL
;
}
for
(
unsigned
i
=
0
;
i
<
G_N_ELEMENTS
(
jd
->
ringbuffer
);
++
i
)
{
if
(
jd
->
ringbuffer
[
i
]
!=
NULL
)
{
jack_ringbuffer_free
(
jd
->
ringbuffer
[
i
]);
jd
->
ringbuffer
[
i
]
=
NULL
;
}
}
}
static
void
mpd_jack_free
(
struct
jack_data
*
jd
)
{
assert
(
jd
!=
NULL
);
for
(
unsigned
i
=
0
;
i
<
G_N_ELEMENTS
(
jd
->
output_ports
);
++
i
)
g_free
(
jd
->
output_ports
[
i
]);
g_free
(
jd
);
}
static
void
mpd_jack_finish
(
void
*
data
)
{
struct
jack_data
*
jd
=
data
;
mpd_jack_free
(
jd
);
}
static
int
static
int
mpd_jack_process
(
jack_nframes_t
nframes
,
void
*
arg
)
mpd_jack_process
(
jack_nframes_t
nframes
,
void
*
arg
)
{
{
...
@@ -185,12 +148,69 @@ mpd_jack_info(const char *msg)
...
@@ -185,12 +148,69 @@ mpd_jack_info(const char *msg)
}
}
#endif
#endif
/**
* Disconnect the JACK client.
*/
static
void
mpd_jack_disconnect
(
struct
jack_data
*
jd
)
{
assert
(
jd
!=
NULL
);
assert
(
jd
->
client
!=
NULL
);
jack_deactivate
(
jd
->
client
);
jack_client_close
(
jd
->
client
);
jd
->
client
=
NULL
;
}
/**
* Connect the JACK client and performs some basic setup
* (e.g. register callbacks).
*/
static
bool
mpd_jack_connect
(
struct
jack_data
*
jd
,
GError
**
error_r
)
{
assert
(
jd
!=
NULL
);
jd
->
shutdown
=
false
;
if
((
jd
->
client
=
jack_client_new
(
jd
->
name
))
==
NULL
)
{
g_set_error
(
error_r
,
jack_output_quark
(),
0
,
"Failed to connect to JACK server"
);
return
false
;
}
jack_set_process_callback
(
jd
->
client
,
mpd_jack_process
,
jd
);
jack_on_shutdown
(
jd
->
client
,
mpd_jack_shutdown
,
jd
);
for
(
unsigned
i
=
0
;
i
<
G_N_ELEMENTS
(
jd
->
ports
);
++
i
)
{
jd
->
ports
[
i
]
=
jack_port_register
(
jd
->
client
,
port_names
[
i
],
JACK_DEFAULT_AUDIO_TYPE
,
JackPortIsOutput
,
0
);
if
(
jd
->
ports
[
i
]
==
NULL
)
{
g_set_error
(
error_r
,
jack_output_quark
(),
0
,
"Cannot register output port
\"
%s
\"
"
,
port_names
[
i
]);
mpd_jack_disconnect
(
jd
);
return
false
;
}
}
return
true
;
}
static
bool
mpd_jack_test_default_device
(
void
)
{
return
true
;
}
static
void
*
static
void
*
mpd_jack_init
(
G_GNUC_UNUSED
const
struct
audio_format
*
audio_format
,
mpd_jack_init
(
G_GNUC_UNUSED
const
struct
audio_format
*
audio_format
,
const
struct
config_param
*
param
,
GError
**
error_r
)
const
struct
config_param
*
param
,
GError
**
error_r
)
{
{
struct
jack_data
*
jd
;
struct
jack_data
*
jd
;
const
char
*
value
;
const
char
*
value
;
GError
*
error
=
NULL
;
jd
=
g_new
(
struct
jack_data
,
1
);
jd
=
g_new
(
struct
jack_data
,
1
);
jd
->
name
=
config_get_block_string
(
param
,
"name"
,
"mpd_jack"
);
jd
->
name
=
config_get_block_string
(
param
,
"name"
,
"mpd_jack"
);
...
@@ -220,56 +240,86 @@ mpd_jack_init(G_GNUC_UNUSED const struct audio_format *audio_format,
...
@@ -220,56 +240,86 @@ mpd_jack_init(G_GNUC_UNUSED const struct audio_format *audio_format,
jd
->
ringbuffer_size
=
jd
->
ringbuffer_size
=
config_get_block_unsigned
(
param
,
"ringbuffer_size"
,
32768
);
config_get_block_unsigned
(
param
,
"ringbuffer_size"
,
32768
);
for
(
unsigned
i
=
0
;
i
<
G_N_ELEMENTS
(
jd
->
ringbuffer
);
++
i
)
jd
->
ringbuffer
[
i
]
=
NULL
;
jack_set_error_function
(
mpd_jack_error
);
jack_set_error_function
(
mpd_jack_error
);
#ifdef HAVE_JACK_SET_INFO_FUNCTION
#ifdef HAVE_JACK_SET_INFO_FUNCTION
jack_set_info_function
(
mpd_jack_info
);
jack_set_info_function
(
mpd_jack_info
);
#endif
#endif
if
(
!
mpd_jack_connect
(
jd
,
&
error
))
{
/* this is non-fatal - it's enough to connect when
playback starts */
g_warning
(
"%s"
,
error
->
message
);
g_error_free
(
error
);
}
return
jd
;
return
jd
;
}
}
static
bool
static
void
mpd_jack_
test_default_device
(
void
)
mpd_jack_
finish
(
void
*
data
)
{
{
return
true
;
struct
jack_data
*
jd
=
data
;
if
(
jd
->
client
!=
NULL
)
mpd_jack_disconnect
(
jd
);
for
(
unsigned
i
=
0
;
i
<
G_N_ELEMENTS
(
jd
->
ringbuffer
);
++
i
)
{
if
(
jd
->
ringbuffer
[
i
]
!=
NULL
)
{
jack_ringbuffer_free
(
jd
->
ringbuffer
[
i
]);
jd
->
ringbuffer
[
i
]
=
NULL
;
}
}
for
(
unsigned
i
=
0
;
i
<
G_N_ELEMENTS
(
jd
->
output_ports
);
++
i
)
g_free
(
jd
->
output_ports
[
i
]);
g_free
(
jd
);
}
/**
* Stops the playback on the JACK connection.
*/
static
void
mpd_jack_stop
(
struct
jack_data
*
jd
)
{
assert
(
jd
!=
NULL
);
if
(
jd
->
client
==
NULL
)
return
;
if
(
jd
->
shutdown
)
/* the connection has failed; close it */
mpd_jack_disconnect
(
jd
);
else
/* the connection is alive: just stop playback */
jack_deactivate
(
jd
->
client
);
}
}
static
bool
static
bool
mpd_jack_
connec
t
(
struct
jack_data
*
jd
,
GError
**
error_r
)
mpd_jack_
star
t
(
struct
jack_data
*
jd
,
GError
**
error_r
)
{
{
const
char
*
output_ports
[
2
],
**
jports
;
const
char
*
output_ports
[
2
],
**
jports
;
if
(
jd
->
client
==
NULL
&&
!
mpd_jack_connect
(
jd
,
error_r
))
return
false
;
/* allocate the ring buffers on the first open(); these
persist until MPD exits. It's too unsafe to delete them
because we can never know when mpd_jack_process() gets
called */
for
(
unsigned
i
=
0
;
i
<
G_N_ELEMENTS
(
jd
->
ringbuffer
);
++
i
)
for
(
unsigned
i
=
0
;
i
<
G_N_ELEMENTS
(
jd
->
ringbuffer
);
++
i
)
if
(
jd
->
ringbuffer
[
i
]
==
NULL
)
jd
->
ringbuffer
[
i
]
=
jd
->
ringbuffer
[
i
]
=
jack_ringbuffer_create
(
jd
->
ringbuffer_size
);
jack_ringbuffer_create
(
jd
->
ringbuffer_size
);
jd
->
shutdown
=
false
;
if
((
jd
->
client
=
jack_client_new
(
jd
->
name
))
==
NULL
)
{
g_set_error
(
error_r
,
jack_output_quark
(),
0
,
"Failed to connect to JACK server"
);
return
false
;
}
jack_set_process_callback
(
jd
->
client
,
mpd_jack_process
,
jd
);
jack_on_shutdown
(
jd
->
client
,
mpd_jack_shutdown
,
jd
);
for
(
unsigned
i
=
0
;
i
<
G_N_ELEMENTS
(
jd
->
ports
);
++
i
)
{
jd
->
ports
[
i
]
=
jack_port_register
(
jd
->
client
,
port_names
[
i
],
JACK_DEFAULT_AUDIO_TYPE
,
JackPortIsOutput
,
0
);
if
(
jd
->
ports
[
i
]
==
NULL
)
{
g_set_error
(
error_r
,
jack_output_quark
(),
0
,
"Cannot register output port
\"
%s
\"
"
,
port_names
[
i
]);
return
false
;
}
}
if
(
jack_activate
(
jd
->
client
)
)
{
if
(
jack_activate
(
jd
->
client
)
)
{
g_set_error
(
error_r
,
jack_output_quark
(),
0
,
g_set_error
(
error_r
,
jack_output_quark
(),
0
,
"cannot activate client"
);
"cannot activate client"
);
mpd_jack_stop
(
jd
);
return
false
;
return
false
;
}
}
...
@@ -281,6 +331,7 @@ mpd_jack_connect(struct jack_data *jd, GError **error_r)
...
@@ -281,6 +331,7 @@ mpd_jack_connect(struct jack_data *jd, GError **error_r)
if
(
jports
==
NULL
)
{
if
(
jports
==
NULL
)
{
g_set_error
(
error_r
,
jack_output_quark
(),
0
,
g_set_error
(
error_r
,
jack_output_quark
(),
0
,
"no ports found"
);
"no ports found"
);
mpd_jack_stop
(
jd
);
return
false
;
return
false
;
}
}
...
@@ -310,6 +361,7 @@ mpd_jack_connect(struct jack_data *jd, GError **error_r)
...
@@ -310,6 +361,7 @@ mpd_jack_connect(struct jack_data *jd, GError **error_r)
if
(
jports
!=
NULL
)
if
(
jports
!=
NULL
)
free
(
jports
);
free
(
jports
);
mpd_jack_stop
(
jd
);
return
false
;
return
false
;
}
}
}
}
...
@@ -329,10 +381,8 @@ mpd_jack_open(void *data, struct audio_format *audio_format, GError **error_r)
...
@@ -329,10 +381,8 @@ mpd_jack_open(void *data, struct audio_format *audio_format, GError **error_r)
jd
->
pause
=
false
;
jd
->
pause
=
false
;
if
(
!
mpd_jack_connect
(
jd
,
error_r
))
{
if
(
!
mpd_jack_start
(
jd
,
error_r
))
mpd_jack_client_free
(
jd
);
return
false
;
return
false
;
}
set_audioformat
(
jd
,
audio_format
);
set_audioformat
(
jd
,
audio_format
);
jd
->
audio_format
=
*
audio_format
;
jd
->
audio_format
=
*
audio_format
;
...
@@ -345,7 +395,7 @@ mpd_jack_close(G_GNUC_UNUSED void *data)
...
@@ -345,7 +395,7 @@ mpd_jack_close(G_GNUC_UNUSED void *data)
{
{
struct
jack_data
*
jd
=
data
;
struct
jack_data
*
jd
=
data
;
mpd_jack_
client_free
(
jd
);
mpd_jack_
stop
(
jd
);
}
}
static
inline
jack_default_audio_sample_t
static
inline
jack_default_audio_sample_t
...
...
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