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
59b29b20
Commit
59b29b20
authored
Nov 01, 2008
by
Lukas Durfina
Committed by
Jean-Baptiste Kempf
Nov 07, 2008
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
libvlc: better audio handling
Signed-off-by:
Jean-Baptiste Kempf
<
jb@videolan.org
>
parent
1e2f42cb
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
457 additions
and
28 deletions
+457
-28
include/vlc/libvlc.h
include/vlc/libvlc.h
+146
-4
include/vlc/libvlc_structures.h
include/vlc/libvlc_structures.h
+23
-0
src/control/audio.c
src/control/audio.c
+277
-24
src/libvlc.sym
src/libvlc.sym
+11
-0
No files found.
include/vlc/libvlc.h
View file @
59b29b20
...
@@ -1022,6 +1022,135 @@ VLC_PUBLIC_API void libvlc_video_set_viewport( libvlc_instance_t *, const libvlc
...
@@ -1022,6 +1022,135 @@ VLC_PUBLIC_API void libvlc_video_set_viewport( libvlc_instance_t *, const libvlc
* @{
* @{
*/
*/
/**
* Audio device types
*/
typedef
enum
libvlc_audio_output_device_types_t
{
libvlc_AudioOutputDevice_Error
=
-
1
,
libvlc_AudioOutputDevice_Mono
=
1
,
libvlc_AudioOutputDevice_Stereo
=
2
,
libvlc_AudioOutputDevice_2F2R
=
4
,
libvlc_AudioOutputDevice_3F2R
=
5
,
libvlc_AudioOutputDevice_5_1
=
6
,
libvlc_AudioOutputDevice_6_1
=
7
,
libvlc_AudioOutputDevice_7_1
=
8
,
libvlc_AudioOutputDevice_SPDIF
=
10
}
libvlc_audio_output_device_types_t
;
/**
* Audio channels
*/
typedef
enum
libvlc_audio_output_channel_t
{
libvlc_AudioChannel_Error
=
-
1
,
libvlc_AudioChannel_Stereo
=
1
,
libvlc_AudioChannel_RStereo
=
2
,
libvlc_AudioChannel_Left
=
3
,
libvlc_AudioChannel_Right
=
4
,
libvlc_AudioChannel_Dolbys
=
5
}
libvlc_audio_output_channel_t
;
/**
* Get the list of available audio outputs
*
* \param p_instance libvlc instance
* \param p_e an initialized exception pointer
* \return list of available audio outputs, at the end free it with
* \see libvlc_audio_output_list_release \see libvlc_audio_output_t
*/
VLC_PUBLIC_API
libvlc_audio_output_t
*
libvlc_audio_output_list_get
(
libvlc_instance_t
*
,
libvlc_exception_t
*
);
/**
* Free the list of available audio outputs
*
* \param p_list list with audio outputs for release
*/
VLC_PUBLIC_API
void
libvlc_audio_output_list_release
(
libvlc_audio_output_t
*
);
/**
* Set the audio output.
* Change will be applied after stop and play.
*
* \param p_instance libvlc instance
* \param psz_name name of audio output,
* use psz_name of \see libvlc_audio_output_t
* \return true if function succeded
*/
VLC_PUBLIC_API
int
libvlc_audio_output_set
(
libvlc_instance_t
*
,
const
char
*
);
/**
* Get count of devices for audio output, these devices are hardware oriented
* like analor or digital output of sound card
*
* \param p_instance libvlc instance
* \param psz_audio_output - name of audio output, \see libvlc_audio_output_t
* \return number of devices
*/
VLC_PUBLIC_API
int
libvlc_audio_output_device_count
(
libvlc_instance_t
*
,
const
char
*
);
/**
* Get long name of device, if not available short name given
*
* \param p_instance libvlc instance
* \param psz_audio_output - name of audio output, \see libvlc_audio_output_t
* \param i_device device index
* \return long name of device
*/
VLC_PUBLIC_API
char
*
libvlc_audio_output_device_longname
(
libvlc_instance_t
*
,
const
char
*
,
int
);
/**
* Get id name of device
*
* \param p_instance libvlc instance
* \param psz_audio_output - name of audio output, \see libvlc_audio_output_t
* \param i_device device index
* \return id name of device, use for setting device, need to be free after use
*/
VLC_PUBLIC_API
char
*
libvlc_audio_output_device_id
(
libvlc_instance_t
*
,
const
char
*
,
int
);
/**
* Set device for using
*
* \param p_instance libvlc instance
* \param psz_audio_output - name of audio output, \see libvlc_audio_output_t
* \param psz_device_id device
*/
VLC_PUBLIC_API
void
libvlc_audio_output_device_set
(
libvlc_instance_t
*
,
const
char
*
,
const
char
*
);
/**
* Get current audio device type. Device type describes something like
* character of output sound - stereo sound, 2.1, 5.1 etc
*
* \param p_instance vlc instance
* \param p_e an initialized exception pointer
* \return the audio devices type \see libvlc_audio_output_device_types_t
*/
VLC_PUBLIC_API
int
libvlc_audio_output_get_device_type
(
libvlc_instance_t
*
,
libvlc_exception_t
*
);
/**
* Set current audio device type.
*
* \param p_instance vlc instance
* \param device_type the audio device type,
according to \see libvlc_audio_output_device_types_t
* \param p_e an initialized exception pointer
*/
VLC_PUBLIC_API
void
libvlc_audio_output_set_device_type
(
libvlc_instance_t
*
,
int
,
libvlc_exception_t
*
);
/**
/**
* Toggle mute status.
* Toggle mute status.
*
*
...
@@ -1075,6 +1204,16 @@ VLC_PUBLIC_API void libvlc_audio_set_volume( libvlc_instance_t *, int, libvlc_ex
...
@@ -1075,6 +1204,16 @@ VLC_PUBLIC_API void libvlc_audio_set_volume( libvlc_instance_t *, int, libvlc_ex
*/
*/
VLC_PUBLIC_API
int
libvlc_audio_get_track_count
(
libvlc_media_player_t
*
,
libvlc_exception_t
*
);
VLC_PUBLIC_API
int
libvlc_audio_get_track_count
(
libvlc_media_player_t
*
,
libvlc_exception_t
*
);
/**
* Get the description of available audio tracks.
*
* \param p_mi media player
* \param p_e an initialized exception
* \return list with description of available audio tracks
*/
VLC_PUBLIC_API
libvlc_track_description_t
*
libvlc_audio_get_track_description
(
libvlc_media_player_t
*
,
libvlc_exception_t
*
);
/**
/**
* Get current audio track.
* Get current audio track.
*
*
...
@@ -1098,18 +1237,21 @@ VLC_PUBLIC_API void libvlc_audio_set_track( libvlc_media_player_t *, int, libvlc
...
@@ -1098,18 +1237,21 @@ VLC_PUBLIC_API void libvlc_audio_set_track( libvlc_media_player_t *, int, libvlc
*
*
* \param p_instance vlc instance
* \param p_instance vlc instance
* \param p_e an initialized exception pointer
* \param p_e an initialized exception pointer
* \return the audio channel
(int)
* \return the audio channel
\see libvlc_audio_output_channel_t
*/
*/
VLC_PUBLIC_API
int
libvlc_audio_get_channel
(
libvlc_instance_t
*
,
libvlc_exception_t
*
);
VLC_PUBLIC_API
int
libvlc_audio_get_channel
(
libvlc_instance_t
*
,
libvlc_exception_t
*
);
/**
/**
* Set current audio channel.
* Set current audio channel.
*
*
* \param p_instance vlc instance
* \param p_instance vlc instance
* \param
i_channel the audio channel (int)
* \param
channel the audio channel, \see libvlc_audio_output_channel_t
* \param p_e an initialized exception pointer
* \param p_e an initialized exception pointer
*/
*/
VLC_PUBLIC_API
void
libvlc_audio_set_channel
(
libvlc_instance_t
*
,
int
,
libvlc_exception_t
*
);
VLC_PUBLIC_API
void
libvlc_audio_set_channel
(
libvlc_instance_t
*
,
int
,
libvlc_exception_t
*
);
/** @} audio */
/** @} audio */
...
...
include/vlc/libvlc_structures.h
View file @
59b29b20
...
@@ -233,6 +233,29 @@ typedef struct libvlc_track_description_t
...
@@ -233,6 +233,29 @@ typedef struct libvlc_track_description_t
/**@} */
/**@} */
/*****************************************************************************
* Audio
*****************************************************************************/
/** \defgroup libvlc_audio libvlc_audio
* \ingroup libvlc_media_player
* LibVLC Audio handling
* @{
*/
/**
* Description for audio output. It contains
* name, description and pointer to next record.
*/
typedef
struct
libvlc_audio_output_t
{
char
*
psz_name
;
char
*
psz_description
;
struct
libvlc_audio_output_t
*
p_next
;
}
libvlc_audio_output_t
;
/**@} */
/*****************************************************************************
/*****************************************************************************
* Video
* Video
...
...
src/control/audio.c
View file @
59b29b20
...
@@ -36,6 +36,9 @@
...
@@ -36,6 +36,9 @@
static
aout_instance_t
*
GetAOut
(
libvlc_instance_t
*
p_instance
,
static
aout_instance_t
*
GetAOut
(
libvlc_instance_t
*
p_instance
,
libvlc_exception_t
*
p_exception
)
libvlc_exception_t
*
p_exception
)
{
{
if
(
!
p_instance
)
return
NULL
;
aout_instance_t
*
p_aout
=
NULL
;
aout_instance_t
*
p_aout
=
NULL
;
p_aout
=
vlc_object_find
(
p_instance
->
p_libvlc_int
,
VLC_OBJECT_AOUT
,
FIND_CHILD
);
p_aout
=
vlc_object_find
(
p_instance
->
p_libvlc_int
,
VLC_OBJECT_AOUT
,
FIND_CHILD
);
...
@@ -48,6 +51,269 @@ static aout_instance_t *GetAOut( libvlc_instance_t *p_instance,
...
@@ -48,6 +51,269 @@ static aout_instance_t *GetAOut( libvlc_instance_t *p_instance,
return
p_aout
;
return
p_aout
;
}
}
/*****************************************
* Get the list of available audio outputs
*****************************************/
VLC_PUBLIC_API
libvlc_audio_output_t
*
libvlc_audio_output_list_get
(
libvlc_instance_t
*
p_instance
,
libvlc_exception_t
*
p_e
)
{
VLC_UNUSED
(
p_instance
);
libvlc_audio_output_t
*
p_list
=
NULL
,
*
p_actual
=
NULL
,
*
p_previous
=
NULL
;
module_t
**
module_list
=
module_list_get
(
NULL
);
for
(
size_t
i
=
0
;
module_list
[
i
];
i
++
)
{
module_t
*
p_module
=
module_list
[
i
];
if
(
module_provides
(
p_module
,
"audio output"
)
)
{
if
(
p_actual
==
NULL
)
{
p_actual
=
(
libvlc_audio_output_t
*
)
malloc
(
sizeof
(
libvlc_audio_output_t
)
);
if
(
p_actual
==
NULL
)
{
libvlc_exception_raise
(
p_e
,
"Not enough memory"
);
libvlc_audio_output_list_release
(
p_list
);
module_list_free
(
module_list
);
return
NULL
;
}
if
(
p_list
==
NULL
)
{
p_list
=
p_actual
;
p_previous
=
p_actual
;
}
}
p_actual
->
psz_name
=
strdup
(
module_get_name
(
p_module
,
false
)
);
p_actual
->
psz_description
=
strdup
(
module_get_name
(
p_module
,
true
)
);
p_actual
->
p_next
=
NULL
;
if
(
p_previous
!=
p_actual
)
/* not first item */
p_previous
->
p_next
=
p_actual
;
p_previous
=
p_actual
;
p_actual
=
p_actual
->
p_next
;
}
}
module_list_free
(
module_list
);
return
p_list
;
}
/********************************************
* Free the list of available audio outputs
***********************************************/
VLC_PUBLIC_API
void
libvlc_audio_output_list_release
(
libvlc_audio_output_t
*
p_list
)
{
libvlc_audio_output_t
*
p_actual
,
*
p_before
;
p_actual
=
p_list
;
while
(
p_actual
)
{
free
(
p_actual
->
psz_name
);
free
(
p_actual
->
psz_description
);
p_before
=
p_actual
;
p_actual
=
p_before
->
p_next
;
free
(
p_before
);
}
}
/***********************
* Set the audio output.
***********************/
VLC_PUBLIC_API
int
libvlc_audio_output_set
(
libvlc_instance_t
*
p_instance
,
const
char
*
psz_name
)
{
if
(
module_exists
(
psz_name
)
)
{
config_PutPsz
(
p_instance
->
p_libvlc_int
,
"aout"
,
psz_name
);
return
true
;
}
else
return
false
;
}
/****************************
* Get count of devices.
*****************************/
int
libvlc_audio_output_device_count
(
libvlc_instance_t
*
p_instance
,
const
char
*
psz_audio_output
)
{
char
*
psz_config_name
=
NULL
;
if
(
!
psz_audio_output
)
return
0
;
if
(
asprintf
(
&
psz_config_name
,
"%s-audio-device"
,
psz_audio_output
)
==
-
1
)
return
0
;
module_config_t
*
p_module_config
=
config_FindConfig
(
VLC_OBJECT
(
p_instance
->
p_libvlc_int
),
psz_config_name
);
if
(
p_module_config
&&
p_module_config
->
pf_update_list
)
{
vlc_value_t
val
;
val
.
psz_string
=
strdup
(
p_module_config
->
value
.
psz
);
p_module_config
->
pf_update_list
(
VLC_OBJECT
(
p_instance
->
p_libvlc_int
),
psz_config_name
,
val
,
val
,
NULL
);
free
(
val
.
psz_string
);
free
(
psz_config_name
);
return
p_module_config
->
i_list
;
}
else
free
(
psz_config_name
);
return
0
;
}
/********************************
* Get long name of device
*********************************/
char
*
libvlc_audio_output_device_longname
(
libvlc_instance_t
*
p_instance
,
const
char
*
psz_audio_output
,
int
i_device
)
{
char
*
psz_config_name
=
NULL
;
if
(
!
psz_audio_output
)
return
NULL
;
if
(
asprintf
(
&
psz_config_name
,
"%s-audio-device"
,
psz_audio_output
)
==
-
1
)
return
NULL
;
module_config_t
*
p_module_config
=
config_FindConfig
(
VLC_OBJECT
(
p_instance
->
p_libvlc_int
),
psz_config_name
);
if
(
p_module_config
)
{
// refresh if there arent devices
if
(
p_module_config
->
i_list
<
2
&&
p_module_config
->
pf_update_list
)
{
vlc_value_t
val
;
val
.
psz_string
=
strdup
(
p_module_config
->
value
.
psz
);
p_module_config
->
pf_update_list
(
VLC_OBJECT
(
p_instance
->
p_libvlc_int
),
psz_config_name
,
val
,
val
,
NULL
);
free
(
val
.
psz_string
);
}
free
(
psz_config_name
);
if
(
i_device
>=
0
&&
i_device
<
p_module_config
->
i_list
)
{
if
(
p_module_config
->
ppsz_list_text
[
i_device
]
)
return
strdup
(
p_module_config
->
ppsz_list_text
[
i_device
]
);
else
return
strdup
(
p_module_config
->
ppsz_list
[
i_device
]
);
}
}
else
free
(
psz_config_name
);
return
NULL
;
}
/********************************
* Get id name of device
*********************************/
char
*
libvlc_audio_output_device_id
(
libvlc_instance_t
*
p_instance
,
const
char
*
psz_audio_output
,
int
i_device
)
{
char
*
psz_config_name
=
NULL
;
if
(
!
psz_audio_output
)
return
NULL
;
if
(
asprintf
(
&
psz_config_name
,
"%s-audio-device"
,
psz_audio_output
)
==
-
1
)
return
NULL
;
module_config_t
*
p_module_config
=
config_FindConfig
(
VLC_OBJECT
(
p_instance
->
p_libvlc_int
),
psz_config_name
);
if
(
p_module_config
)
{
// refresh if there arent devices
if
(
p_module_config
->
i_list
<
2
&&
p_module_config
->
pf_update_list
)
{
vlc_value_t
val
;
val
.
psz_string
=
strdup
(
p_module_config
->
value
.
psz
);
p_module_config
->
pf_update_list
(
VLC_OBJECT
(
p_instance
->
p_libvlc_int
),
psz_config_name
,
val
,
val
,
NULL
);
free
(
val
.
psz_string
);
}
free
(
psz_config_name
);
if
(
i_device
>=
0
&&
i_device
<
p_module_config
->
i_list
)
return
strdup
(
p_module_config
->
ppsz_list
[
i_device
]
);
}
else
free
(
psz_config_name
);
return
NULL
;
}
/*****************************
* Set device for using
*****************************/
VLC_PUBLIC_API
void
libvlc_audio_output_device_set
(
libvlc_instance_t
*
p_instance
,
const
char
*
psz_audio_output
,
const
char
*
psz_device_id
)
{
char
*
psz_config_name
=
NULL
;
if
(
!
psz_audio_output
||
!
psz_device_id
)
return
;
if
(
asprintf
(
&
psz_config_name
,
"%s-audio-device"
,
psz_audio_output
)
==
-
1
)
return
;
config_PutPsz
(
p_instance
->
p_libvlc_int
,
psz_config_name
,
psz_device_id
);
free
(
psz_config_name
);
}
/*****************************************************************************
* libvlc_audio_output_get_device_type : Get the current audio device type
*****************************************************************************/
int
libvlc_audio_output_get_device_type
(
libvlc_instance_t
*
p_instance
,
libvlc_exception_t
*
p_e
)
{
aout_instance_t
*
p_aout
=
GetAOut
(
p_instance
,
p_e
);
if
(
p_aout
)
{
vlc_value_t
val
;
var_Get
(
p_aout
,
"audio-device"
,
&
val
);
vlc_object_release
(
p_aout
);
return
val
.
i_int
;
}
libvlc_exception_raise
(
p_e
,
"Unable to get audio output"
);
return
libvlc_AudioOutputDevice_Error
;
}
/*****************************************************************************
* libvlc_audio_output_set_device_type : Set the audio device type
*****************************************************************************/
void
libvlc_audio_output_set_device_type
(
libvlc_instance_t
*
p_instance
,
int
device_type
,
libvlc_exception_t
*
p_e
)
{
aout_instance_t
*
p_aout
=
GetAOut
(
p_instance
,
p_e
);
if
(
p_aout
)
{
vlc_value_t
val
;
int
i_ret
=
-
1
;
val
.
i_int
=
(
int
)
device_type
;
i_ret
=
var_Set
(
p_aout
,
"audio-device"
,
val
);
if
(
i_ret
<
0
)
{
libvlc_exception_raise
(
p_e
,
"Failed setting audio device"
);
vlc_object_release
(
p_aout
);
return
;
}
vlc_object_release
(
p_aout
);
}
}
/*****************************************************************************
/*****************************************************************************
* libvlc_audio_get_mute : Get the volume state, true if muted
* libvlc_audio_get_mute : Get the volume state, true if muted
...
@@ -217,7 +483,7 @@ void libvlc_audio_set_track( libvlc_media_player_t *p_mi, int i_track,
...
@@ -217,7 +483,7 @@ void libvlc_audio_set_track( libvlc_media_player_t *p_mi, int i_track,
* libvlc_audio_get_channel : Get the current audio channel
* libvlc_audio_get_channel : Get the current audio channel
*****************************************************************************/
*****************************************************************************/
int
libvlc_audio_get_channel
(
libvlc_instance_t
*
p_instance
,
int
libvlc_audio_get_channel
(
libvlc_instance_t
*
p_instance
,
libvlc_exception_t
*
p_e
)
libvlc_exception_t
*
p_e
)
{
{
aout_instance_t
*
p_aout
=
GetAOut
(
p_instance
,
p_e
);
aout_instance_t
*
p_aout
=
GetAOut
(
p_instance
,
p_e
);
if
(
p_aout
)
if
(
p_aout
)
...
@@ -228,13 +494,15 @@ int libvlc_audio_get_channel( libvlc_instance_t *p_instance,
...
@@ -228,13 +494,15 @@ int libvlc_audio_get_channel( libvlc_instance_t *p_instance,
vlc_object_release
(
p_aout
);
vlc_object_release
(
p_aout
);
return
val
.
i_int
;
return
val
.
i_int
;
}
}
return
-
1
;
libvlc_exception_raise
(
p_e
,
"Unable to get audio output"
);
return
libvlc_AudioChannel_Error
;
}
}
/*****************************************************************************
/*****************************************************************************
* libvlc_audio_set_channel : Set the current audio channel
* libvlc_audio_set_channel : Set the current audio channel
*****************************************************************************/
*****************************************************************************/
void
libvlc_audio_set_channel
(
libvlc_instance_t
*
p_instance
,
int
i_channel
,
void
libvlc_audio_set_channel
(
libvlc_instance_t
*
p_instance
,
int
channel
,
libvlc_exception_t
*
p_e
)
libvlc_exception_t
*
p_e
)
{
{
aout_instance_t
*
p_aout
=
GetAOut
(
p_instance
,
p_e
);
aout_instance_t
*
p_aout
=
GetAOut
(
p_instance
,
p_e
);
...
@@ -243,27 +511,12 @@ void libvlc_audio_set_channel( libvlc_instance_t *p_instance, int i_channel,
...
@@ -243,27 +511,12 @@ void libvlc_audio_set_channel( libvlc_instance_t *p_instance, int i_channel,
vlc_value_t
val
;
vlc_value_t
val
;
int
i_ret
=
-
1
;
int
i_ret
=
-
1
;
val
.
i_int
=
i_channel
;
val
.
i_int
=
channel
;
switch
(
i_channel
)
i_ret
=
var_Set
(
p_aout
,
"audio-channels"
,
val
);
{
if
(
i_ret
<
0
)
case
AOUT_VAR_CHAN_RSTEREO
:
libvlc_exception_raise
(
p_e
,
"Failed setting audio channel"
);
case
AOUT_VAR_CHAN_STEREO
:
case
AOUT_VAR_CHAN_LEFT
:
case
AOUT_VAR_CHAN_RIGHT
:
case
AOUT_VAR_CHAN_DOLBYS
:
i_ret
=
var_Set
(
p_aout
,
"audio-channels"
,
val
);
if
(
i_ret
<
0
)
{
libvlc_exception_raise
(
p_e
,
"Failed setting audio channel"
);
vlc_object_release
(
p_aout
);
return
;
}
vlc_object_release
(
p_aout
);
return
;
/* Found */
default:
libvlc_exception_raise
(
p_e
,
"Audio channel out of range"
);
break
;
}
vlc_object_release
(
p_aout
);
vlc_object_release
(
p_aout
);
}
}
}
}
src/libvlc.sym
View file @
59b29b20
libvlc_add_intf
libvlc_add_intf
libvlc_audio_output_device_count
libvlc_audio_output_device_id
libvlc_audio_output_device_longname
libvlc_audio_output_device_set
libvlc_audio_output_get_device_type
libvlc_audio_output_list_get
libvlc_audio_output_list_release
libvlc_audio_output_set
libvlc_audio_output_set_device_type
libvlc_audio_get_channel
libvlc_audio_get_channel
libvlc_audio_get_device
libvlc_audio_get_mute
libvlc_audio_get_mute
libvlc_audio_get_track
libvlc_audio_get_track
libvlc_audio_get_track_count
libvlc_audio_get_track_count
libvlc_audio_get_track_description
libvlc_audio_get_track_description
libvlc_audio_get_volume
libvlc_audio_get_volume
libvlc_audio_set_channel
libvlc_audio_set_channel
libvlc_audio_set_device
libvlc_audio_set_mute
libvlc_audio_set_mute
libvlc_audio_set_track
libvlc_audio_set_track
libvlc_audio_set_volume
libvlc_audio_set_volume
...
...
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