Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
W
wireplumber
Manage
Activity
Members
Labels
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package Registry
Model registry
Operate
Environments
Terraform modules
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
pkg
wireplumber
Commits
b376c5d7
Commit
b376c5d7
authored
5 years ago
by
George Kiagiadakis
Browse files
Options
Downloads
Patches
Plain Diff
modules: add a basic default session implementation as a module
parent
02c69fd2
No related branches found
No related tags found
No related merge requests found
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
meson.build
+1
-0
1 addition, 0 deletions
meson.build
modules/meson.build
+13
-0
13 additions, 0 deletions
modules/meson.build
modules/module-default-session.c
+334
-0
334 additions, 0 deletions
modules/module-default-session.c
with
348 additions
and
0 deletions
meson.build
+
1
−
0
View file @
b376c5d7
...
...
@@ -20,4 +20,5 @@ gnome = import('gnome')
wp_lib_include_dir
=
include_directories
(
'lib'
)
subdir
(
'lib'
)
subdir
(
'modules'
)
subdir
(
'src'
)
This diff is collapsed.
Click to expand it.
modules/meson.build
0 → 100644
+
13
−
0
View file @
b376c5d7
common_c_args
=
[
'-D_GNU_SOURCE'
,
'-DG_LOG_USE_STRUCTURED'
,
]
shared_library
(
'wireplumber-module-default-session'
,
[
'module-default-session.c'
],
c_args
:
[
common_c_args
,
'-DG_LOG_DOMAIN="wireplumber-module-default-session"'
],
install
:
true
,
#install_dir : modules_install_dir,
dependencies
:
[
wp_dep
,
pipewire_dep
],
)
This diff is collapsed.
Click to expand it.
modules/module-default-session.c
0 → 100644
+
334
−
0
View file @
b376c5d7
/* WirePlumber
*
* Copyright © 2019 Collabora Ltd.
* @author George Kiagiadakis <george.kiagiadakis@collabora.com>
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#include
<wp/plugin.h>
#include
<wp/session.h>
#include
<pipewire/pipewire.h>
#include
<spa/param/audio/format-utils.h>
#define MIN_QUANTUM_SIZE 64
#define MAX_QUANTUM_SIZE 1024
G_DECLARE_FINAL_TYPE
(
DefaultSession
,
session
,
DEFAULT
,
SESSION
,
WpSession
)
G_DECLARE_FINAL_TYPE
(
DefaultSessionPlugin
,
plugin
,
DEFAULT
,
SESSION_PLUGIN
,
WpPlugin
)
/* DefaultSession */
struct
_DefaultSession
{
WpSession
parent
;
WpProxy
*
device_node
;
struct
pw_node_proxy
*
dsp_proxy
;
struct
spa_audio_info_raw
format
;
guint32
media_type
;
guint32
session_id
;
};
G_DEFINE_TYPE
(
DefaultSession
,
session
,
WP_TYPE_SESSION
)
static
void
session_init
(
DefaultSession
*
self
)
{
}
static
void
session_finalize
(
GObject
*
obj
)
{
DefaultSession
*
self
=
DEFAULT_SESSION
(
obj
);
G_OBJECT_CLASS
(
session_parent_class
)
->
finalize
(
obj
);
}
static
void
session_class_init
(
DefaultSessionClass
*
klass
)
{
GObjectClass
*
object_class
=
(
GObjectClass
*
)
klass
;
object_class
->
finalize
=
session_finalize
;
}
static
DefaultSession
*
session_new
(
WpProxy
*
device_node
,
guint32
type
,
WpSessionDirection
dir
)
{
DefaultSession
*
sess
=
g_object_new
(
session_get_type
(),
"direction"
,
dir
,
NULL
);
sess
->
device_node
=
device_node
;
sess
->
media_type
=
type
;
return
sess
;
}
/* DefaultSessionPlugin */
struct
_DefaultSessionPlugin
{
WpPlugin
parent
;
};
G_DEFINE_TYPE
(
DefaultSessionPlugin
,
plugin
,
WP_TYPE_PLUGIN
)
static
void
device_node_destroyed
(
WpProxy
*
device_node
,
DefaultSession
*
session
)
{
g_autoptr
(
WpObject
)
core
=
NULL
;
g_autoptr
(
WpSessionRegistry
)
sr
=
NULL
;
g_info
(
"Proxy %u destroyed - unregistering session %u"
,
wp_proxy_get_id
(
device_node
),
session
->
session_id
);
core
=
wp_proxy_get_core
(
device_node
);
sr
=
wp_object_get_interface
(
core
,
WP_TYPE_SESSION_REGISTRY
);
g_return_if_fail
(
sr
!=
NULL
);
wp_session_registry_unregister_session
(
sr
,
session
->
session_id
);
}
static
gboolean
handle_node
(
WpPlugin
*
self
,
WpProxy
*
proxy
)
{
g_autoptr
(
WpObject
)
core
=
NULL
;
g_autoptr
(
WpSessionRegistry
)
sr
=
NULL
;
g_autoptr
(
GError
)
error
=
NULL
;
g_autoptr
(
DefaultSession
)
session
=
NULL
;
const
gchar
*
media_class
,
*
ptr
;
WpSessionDirection
direction
;
guint32
media_type
;
guint32
sess_id
;
ptr
=
media_class
=
wp_pipewire_properties_get
(
WP_PIPEWIRE_PROPERTIES
(
proxy
),
"media.class"
);
if
(
g_str_has_prefix
(
ptr
,
"Audio/"
))
{
ptr
+=
strlen
(
"Audio/"
);
media_type
=
SPA_MEDIA_TYPE_audio
;
}
else
if
(
g_str_has_prefix
(
ptr
,
"Video/"
))
{
ptr
+=
strlen
(
"Video/"
);
media_type
=
SPA_MEDIA_TYPE_video
;
}
else
{
goto
out
;
}
if
(
strcmp
(
ptr
,
"Sink"
)
==
0
)
direction
=
WP_SESSION_DIRECTION_OUTPUT
;
else
if
(
strcmp
(
ptr
,
"Source"
)
==
0
)
direction
=
WP_SESSION_DIRECTION_INPUT
;
else
goto
out
;
g_info
(
"Creating session for node %u (%s), media.class = '%s'"
,
wp_proxy_get_id
(
proxy
),
wp_proxy_get_spa_type_string
(
proxy
),
media_class
);
session
=
session_new
(
proxy
,
media_type
,
direction
);
core
=
wp_plugin_get_core
(
self
);
sr
=
wp_object_get_interface
(
core
,
WP_TYPE_SESSION_REGISTRY
);
g_return_val_if_fail
(
sr
!=
NULL
,
FALSE
);
if
((
sess_id
=
wp_session_registry_register_session
(
sr
,
WP_SESSION
(
session
),
&
error
))
==
-
1
)
{
g_warning
(
"Error registering session: %s"
,
error
->
message
);
return
FALSE
;
}
session
->
session_id
=
sess_id
;
g_object_set_data_full
(
G_OBJECT
(
proxy
),
"module-default-session.session"
,
g_object_ref
(
session
),
g_object_unref
);
g_signal_connect_object
(
proxy
,
"destroyed"
,
(
GCallback
)
device_node_destroyed
,
session
,
0
);
return
TRUE
;
out:
g_message
(
"Unrecognized media.class '%s' - not handling proxy %u (%s)"
,
media_class
,
wp_proxy_get_id
(
proxy
),
wp_proxy_get_spa_type_string
(
proxy
));
return
FALSE
;
}
static
gboolean
plug_dsp
(
WpProxy
*
node
)
{
DefaultSession
*
session
;
g_autoptr
(
WpObject
)
core
=
NULL
;
g_autoptr
(
WpPipewireObjects
)
pw_objects
=
NULL
;
struct
pw_core_proxy
*
core_proxy
;
g_autoptr
(
WpPipewireProperties
)
pw_props
=
NULL
;
struct
pw_properties
*
props
;
const
char
*
name
;
enum
pw_direction
reverse_direction
;
uint8_t
buf
[
1024
];
struct
spa_pod_builder
b
=
{
0
,
};
struct
spa_pod
*
param
;
session
=
g_object_get_data
(
G_OBJECT
(
node
),
"module-default-session.session"
);
g_return_val_if_fail
(
session
->
media_type
==
SPA_MEDIA_TYPE_audio
,
G_SOURCE_REMOVE
);
g_info
(
"making audio dsp for session %u"
,
session
->
session_id
);
core
=
wp_proxy_get_core
(
node
);
pw_objects
=
wp_object_get_interface
(
core
,
WP_TYPE_PIPEWIRE_OBJECTS
);
core_proxy
=
pw_remote_get_core_proxy
(
wp_pipewire_objects_get_pw_remote
(
pw_objects
));
pw_props
=
wp_object_get_interface
(
WP_OBJECT
(
node
),
WP_TYPE_PIPEWIRE_PROPERTIES
);
props
=
pw_properties_new_dict
(
wp_pipewire_properties_get_as_spa_dict
(
pw_props
));
if
((
name
=
pw_properties_get
(
props
,
"device.nick"
))
==
NULL
)
name
=
"unnamed"
;
pw_properties_set
(
props
,
"audio-dsp.name"
,
name
);
pw_properties_setf
(
props
,
"audio-dsp.direction"
,
"%d"
,
wp_session_get_direction
(
WP_SESSION
(
session
)));
pw_properties_setf
(
props
,
"audio-dsp.maxbuffer"
,
"%ld"
,
MAX_QUANTUM_SIZE
*
sizeof
(
float
));
session
->
dsp_proxy
=
pw_core_proxy_create_object
(
core_proxy
,
"audio-dsp"
,
PW_TYPE_INTERFACE_Node
,
PW_VERSION_NODE
,
&
props
->
dict
,
0
);
pw_properties_free
(
props
);
reverse_direction
=
(
wp_session_get_direction
(
WP_SESSION
(
session
))
==
WP_SESSION_DIRECTION_INPUT
)
?
PW_DIRECTION_OUTPUT
:
PW_DIRECTION_INPUT
;
spa_pod_builder_init
(
&
b
,
buf
,
sizeof
(
buf
));
param
=
spa_format_audio_raw_build
(
&
b
,
SPA_PARAM_Format
,
&
session
->
format
);
param
=
spa_pod_builder_add_object
(
&
b
,
SPA_TYPE_OBJECT_ParamProfile
,
SPA_PARAM_Profile
,
SPA_PARAM_PROFILE_direction
,
SPA_POD_Id
(
reverse_direction
),
SPA_PARAM_PROFILE_format
,
SPA_POD_Pod
(
param
));
pw_node_proxy_set_param
((
struct
pw_node_proxy
*
)
session
->
dsp_proxy
,
SPA_PARAM_Profile
,
0
,
param
);
return
G_SOURCE_REMOVE
;
}
static
void
audio_port_enum_params_done
(
GObject
*
proxy
,
GAsyncResult
*
res
,
gpointer
data
)
{
g_autoptr
(
GError
)
error
=
NULL
;
g_autoptr
(
GPtrArray
)
params
=
NULL
;
DefaultSession
*
session
;
struct
spa_audio_info_raw
info
=
{
0
,
};
guint32
media_type
,
media_subtype
;
guint
i
;
g_debug
(
"done enumerating port %u params"
,
wp_proxy_get_id
(
WP_PROXY
(
proxy
)));
params
=
wp_proxy_enum_params_finish
(
WP_PROXY
(
proxy
),
res
,
&
error
);
if
(
!
params
)
{
g_warning
(
"%s"
,
error
->
message
);
return
;
}
session
=
g_object_get_data
(
proxy
,
"module-default-session.session"
);
for
(
i
=
0
;
i
<
params
->
len
;
i
++
)
{
struct
spa_pod
*
param
=
g_ptr_array_index
(
params
,
i
);
if
(
spa_format_parse
(
param
,
&
media_type
,
&
media_subtype
)
<
0
)
return
;
if
(
media_type
!=
SPA_MEDIA_TYPE_audio
||
media_subtype
!=
SPA_MEDIA_SUBTYPE_raw
)
return
;
spa_pod_fixate
(
param
);
if
(
spa_format_audio_raw_parse
(
param
,
&
info
)
<
0
)
return
;
if
(
info
.
channels
>
session
->
format
.
channels
)
session
->
format
=
info
;
}
g_idle_add_full
(
G_PRIORITY_DEFAULT_IDLE
,
(
GSourceFunc
)
plug_dsp
,
g_object_ref
(
proxy
),
g_object_unref
);
}
static
gboolean
handle_audio_port
(
WpPlugin
*
self
,
WpProxy
*
proxy
)
{
wp_proxy_enum_params
(
proxy
,
SPA_PARAM_EnumFormat
,
audio_port_enum_params_done
,
NULL
);
return
TRUE
;
}
static
gboolean
handle_pw_proxy
(
WpPlugin
*
self
,
WpProxy
*
proxy
)
{
g_autoptr
(
WpObject
)
core
=
NULL
;
g_autoptr
(
WpProxy
)
parent
=
NULL
;
g_autoptr
(
WpProxyRegistry
)
reg
=
NULL
;
DefaultSession
*
session
;
if
(
wp_proxy_get_spa_type
(
proxy
)
!=
PW_TYPE_INTERFACE_Port
&&
wp_proxy_get_spa_type
(
proxy
)
!=
PW_TYPE_INTERFACE_Node
)
return
FALSE
;
core
=
wp_plugin_get_core
(
self
);
reg
=
wp_object_get_interface
(
core
,
WP_TYPE_PROXY_REGISTRY
);
parent
=
wp_proxy_registry_get_proxy
(
reg
,
wp_proxy_get_parent_id
(
proxy
));
if
(
wp_proxy_get_spa_type
(
parent
)
==
PW_TYPE_INTERFACE_Device
&&
wp_proxy_get_spa_type
(
proxy
)
==
PW_TYPE_INTERFACE_Node
)
{
g_debug
(
"handling node %u (parent device %u)"
,
wp_proxy_get_id
(
proxy
),
wp_proxy_get_id
(
parent
));
return
handle_node
(
self
,
proxy
);
}
else
if
(
wp_proxy_get_spa_type
(
parent
)
==
PW_TYPE_INTERFACE_Node
&&
wp_proxy_get_spa_type
(
proxy
)
==
PW_TYPE_INTERFACE_Port
&&
(
session
=
g_object_get_data
(
G_OBJECT
(
parent
),
"module-default-session.session"
))
&&
session
->
media_type
==
SPA_MEDIA_TYPE_audio
)
{
g_debug
(
"handling audio port %u (parent node %u)"
,
wp_proxy_get_id
(
proxy
),
wp_proxy_get_id
(
parent
));
return
handle_audio_port
(
self
,
proxy
);
}
return
FALSE
;
}
static
void
plugin_init
(
DefaultSessionPlugin
*
self
)
{
}
static
void
plugin_class_init
(
DefaultSessionPluginClass
*
klass
)
{
WpPluginClass
*
plugin_class
=
WP_PLUGIN_CLASS
(
klass
);
plugin_class
->
handle_pw_proxy
=
handle_pw_proxy
;
}
static
const
WpPluginMetadata
plugin_metadata
=
{
.
rank
=
WP_PLUGIN_RANK_UPSTREAM
,
.
name
=
"default-session"
,
.
description
=
"Provides the default WpSession implementation"
,
.
author
=
"George Kiagiadakis <george.kiagiadakis@collabora.com>"
,
.
license
=
"LGPL-2.1-or-later"
,
.
version
=
"0.1"
,
.
origin
=
"https://gitlab.freedesktop.org/gkiagia/wireplumber"
};
void
WP_MODULE_INIT_SYMBOL
(
WpPluginRegistry
*
registry
)
{
wp_plugin_registry_register_static
(
registry
,
plugin_get_type
(),
&
plugin_metadata
,
sizeof
(
plugin_metadata
));
}
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment