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
3c1bacbd
Commit
3c1bacbd
authored
Nov 11, 2009
by
Max Kellermann
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
decoder/flac: use the new API functions
Use the type and function names of the libFLAC 1.1.3 API. Map the new API to the old one with macros.
parent
d5ed2343
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
89 additions
and
124 deletions
+89
-124
flac_compat.h
src/decoder/flac_compat.h
+37
-79
flac_plugin.c
src/decoder/flac_plugin.c
+52
-45
No files found.
src/decoder/flac_compat.h
View file @
3c1bacbd
...
...
@@ -27,97 +27,55 @@
#include <FLAC/export.h>
#if !defined(FLAC_API_VERSION_CURRENT) || FLAC_API_VERSION_CURRENT <= 7
# include <FLAC/seekable_stream_decoder.h>
# define flac_decoder FLAC__SeekableStreamDecoder
# define flac_new() FLAC__seekable_stream_decoder_new()
# define flac_get_decode_position(x,y) \
FLAC__seekable_stream_decoder_get_decode_position(x,y)
# define flac_get_state(x) FLAC__seekable_stream_decoder_get_state(x)
# define flac_process_single(x) FLAC__seekable_stream_decoder_process_single(x)
# define flac_process_metadata(x) \
FLAC__seekable_stream_decoder_process_until_end_of_metadata(x)
# define flac_seek_absolute(x,y) \
FLAC__seekable_stream_decoder_seek_absolute(x,y)
# define flac_finish(x) FLAC__seekable_stream_decoder_finish(x)
# define flac_delete(x) FLAC__seekable_stream_decoder_delete(x)
# define flac_decoder_eof FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM
/* starting with libFLAC 1.1.3, the SeekableStreamDecoder has been
merged into the StreamDecoder. The following macros try to emulate
the new API for libFLAC 1.1.2 by mapping MPD's StreamDecoder calls
to the old SeekableStreamDecoder API. */
#define FLAC__StreamDecoder FLAC__SeekableStreamDecoder
#define FLAC__stream_decoder_new FLAC__seekable_stream_decoder_new
#define FLAC__stream_decoder_get_decode_position FLAC__seekable_stream_decoder_get_decode_position
#define FLAC__stream_decoder_get_state FLAC__seekable_stream_decoder_get_state
#define FLAC__stream_decoder_process_single FLAC__seekable_stream_decoder_process_single
#define FLAC__stream_decoder_process_until_end_of_metadata FLAC__seekable_stream_decoder_process_until_end_of_metadata
#define FLAC__stream_decoder_seek_absolute FLAC__seekable_stream_decoder_seek_absolute
#define FLAC__stream_decoder_finish FLAC__seekable_stream_decoder_finish
#define FLAC__stream_decoder_delete FLAC__seekable_stream_decoder_delete
#define FLAC__STREAM_DECODER_END_OF_STREAM FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM
typedef
unsigned
flac_read_status_size_t
;
# define flac_read_status FLAC__SeekableStreamDecoderReadStatus
# define flac_read_status_continue \
FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK
# define flac_read_status_eof FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK
# define flac_read_status_abort \
FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR
# define flac_seek_status FLAC__SeekableStreamDecoderSeekStatus
# define flac_seek_status_ok FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK
# define flac_seek_status_error FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR
# define flac_tell_status FLAC__SeekableStreamDecoderTellStatus
# define flac_tell_status_ok FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK
# define flac_tell_status_error \
FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR
# define flac_tell_status_unsupported \
FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR
# define flac_length_status FLAC__SeekableStreamDecoderLengthStatus
# define flac_length_status_ok FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK
# define flac_length_status_error \
FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_ERROR
# define flac_length_status_unsupported \
FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_ERROR
#define FLAC__StreamDecoderReadStatus FLAC__SeekableStreamDecoderReadStatus
#define FLAC__STREAM_DECODER_READ_STATUS_CONTINUE FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK
#define FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK
#define FLAC__STREAM_DECODER_READ_STATUS_ABORT FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR
#define FLAC__StreamDecoderSeekStatus FLAC__SeekableStreamDecoderSeekStatus
#define FLAC__STREAM_DECODER_SEEK_STATUS_OK FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK
#define FLAC__STREAM_DECODER_SEEK_STATUS_ERROR FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR
#define FLAC__STREAM_DECODER_SEEK_STATUS_UNSUPPORTED FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR
#define FLAC__StreamDecoderTellStatus FLAC__SeekableStreamDecoderTellStatus
#define FLAC__STREAM_DECODER_TELL_STATUS_OK FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK
#define FLAC__STREAM_DECODER_TELL_STATUS_ERROR FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR
#define FLAC__STREAM_DECODER_TELL_STATUS_UNSUPPORTED FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR
#define FLAC__StreamDecoderLengthStatus FLAC__SeekableStreamDecoderLengthStatus
#define FLAC__STREAM_DECODER_LENGTH_STATUS_OK FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK
#define FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_ERROR
#define FLAC__STREAM_DECODER_LENGTH_STATUS_UNSUPPORTED FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_ERROR
#else
/* FLAC_API_VERSION_CURRENT > 7 */
# include <FLAC/stream_decoder.h>
# define flac_decoder FLAC__StreamDecoder
# define flac_new() FLAC__stream_decoder_new()
# define flac_init(a,b,c,d,e,f,g,h,i,j) \
(FLAC__stream_decoder_init_stream(a,b,c,d,e,f,g,h,i,j) \
== FLAC__STREAM_DECODER_INIT_STATUS_OK)
# define flac_ogg_init(a,b,c,d,e,f,g,h,i,j) \
(FLAC__stream_decoder_init_ogg_stream(a,b,c,d,e,f,g,h,i,j) \
== FLAC__STREAM_DECODER_INIT_STATUS_OK)
# define flac_get_decode_position(x,y) \
FLAC__stream_decoder_get_decode_position(x,y)
# define flac_get_state(x) FLAC__stream_decoder_get_state(x)
# define flac_process_single(x) FLAC__stream_decoder_process_single(x)
# define flac_process_metadata(x) \
FLAC__stream_decoder_process_until_end_of_metadata(x)
# define flac_seek_absolute(x,y) FLAC__stream_decoder_seek_absolute(x,y)
# define flac_finish(x) FLAC__stream_decoder_finish(x)
# define flac_delete(x) FLAC__stream_decoder_delete(x)
# define flac_decoder_eof FLAC__STREAM_DECODER_END_OF_STREAM
typedef
size_t
flac_read_status_size_t
;
# define flac_read_status FLAC__StreamDecoderReadStatus
# define flac_read_status_continue \
FLAC__STREAM_DECODER_READ_STATUS_CONTINUE
# define flac_read_status_eof FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM
# define flac_read_status_abort FLAC__STREAM_DECODER_READ_STATUS_ABORT
# define flac_seek_status FLAC__StreamDecoderSeekStatus
# define flac_seek_status_ok FLAC__STREAM_DECODER_SEEK_STATUS_OK
# define flac_seek_status_error FLAC__STREAM_DECODER_SEEK_STATUS_ERROR
# define flac_seek_status_unsupported \
FLAC__STREAM_DECODER_SEEK_STATUS_UNSUPPORTED
# define flac_tell_status FLAC__StreamDecoderTellStatus
# define flac_tell_status_ok FLAC__STREAM_DECODER_TELL_STATUS_OK
# define flac_tell_status_error FLAC__STREAM_DECODER_TELL_STATUS_ERROR
# define flac_tell_status_unsupported \
FLAC__STREAM_DECODER_TELL_STATUS_UNSUPPORTED
# define flac_length_status FLAC__StreamDecoderLengthStatus
# define flac_length_status_ok FLAC__STREAM_DECODER_LENGTH_STATUS_OK
# define flac_length_status_error FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR
# define flac_length_status_unsupported \
FLAC__STREAM_DECODER_LENGTH_STATUS_UNSUPPORTED
#endif
/* FLAC_API_VERSION_CURRENT >= 7 */
...
...
src/decoder/flac_plugin.c
View file @
3c1bacbd
...
...
@@ -40,8 +40,8 @@
/* this code was based on flac123, from flac-tools */
static
flac_read_s
tatus
flac_read_cb
(
G_GNUC_UNUSED
const
flac_d
ecoder
*
fd
,
static
FLAC__StreamDecoderReadS
tatus
flac_read_cb
(
G_GNUC_UNUSED
const
FLAC__StreamD
ecoder
*
fd
,
FLAC__byte
buf
[],
flac_read_status_size_t
*
bytes
,
void
*
fdata
)
{
...
...
@@ -55,53 +55,53 @@ flac_read_cb(G_GNUC_UNUSED const flac_decoder *fd,
if
(
r
==
0
)
{
if
(
decoder_get_command
(
data
->
decoder
)
!=
DECODE_COMMAND_NONE
||
input_stream_eof
(
data
->
input_stream
))
return
flac_read_status_eof
;
return
FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM
;
else
return
flac_read_status_abort
;
return
FLAC__STREAM_DECODER_READ_STATUS_ABORT
;
}
return
flac_read_status_continue
;
return
FLAC__STREAM_DECODER_READ_STATUS_CONTINUE
;
}
static
flac_seek_s
tatus
flac_seek_cb
(
G_GNUC_UNUSED
const
flac_d
ecoder
*
fd
,
static
FLAC__StreamDecoderSeekS
tatus
flac_seek_cb
(
G_GNUC_UNUSED
const
FLAC__StreamD
ecoder
*
fd
,
FLAC__uint64
offset
,
void
*
fdata
)
{
struct
flac_data
*
data
=
(
struct
flac_data
*
)
fdata
;
if
(
!
input_stream_seek
(
data
->
input_stream
,
offset
,
SEEK_SET
))
return
flac_seek_status_error
;
return
FLAC__STREAM_DECODER_SEEK_STATUS_ERROR
;
return
flac_seek_status_ok
;
return
FLAC__STREAM_DECODER_SEEK_STATUS_OK
;
}
static
flac_tell_s
tatus
flac_tell_cb
(
G_GNUC_UNUSED
const
flac_d
ecoder
*
fd
,
static
FLAC__StreamDecoderTellS
tatus
flac_tell_cb
(
G_GNUC_UNUSED
const
FLAC__StreamD
ecoder
*
fd
,
FLAC__uint64
*
offset
,
void
*
fdata
)
{
struct
flac_data
*
data
=
(
struct
flac_data
*
)
fdata
;
*
offset
=
(
long
)(
data
->
input_stream
->
offset
);
return
flac_tell_status_ok
;
return
FLAC__STREAM_DECODER_TELL_STATUS_OK
;
}
static
flac_length_s
tatus
flac_length_cb
(
G_GNUC_UNUSED
const
flac_d
ecoder
*
fd
,
static
FLAC__StreamDecoderLengthS
tatus
flac_length_cb
(
G_GNUC_UNUSED
const
FLAC__StreamD
ecoder
*
fd
,
FLAC__uint64
*
length
,
void
*
fdata
)
{
struct
flac_data
*
data
=
(
struct
flac_data
*
)
fdata
;
if
(
data
->
input_stream
->
size
<
0
)
return
flac_length_status_unsupported
;
return
FLAC__STREAM_DECODER_LENGTH_STATUS_UNSUPPORTED
;
*
length
=
(
size_t
)
(
data
->
input_stream
->
size
);
return
flac_length_status_ok
;
return
FLAC__STREAM_DECODER_LENGTH_STATUS_OK
;
}
static
FLAC__bool
flac_eof_cb
(
G_GNUC_UNUSED
const
flac_d
ecoder
*
fd
,
void
*
fdata
)
flac_eof_cb
(
G_GNUC_UNUSED
const
FLAC__StreamD
ecoder
*
fd
,
void
*
fdata
)
{
struct
flac_data
*
data
=
(
struct
flac_data
*
)
fdata
;
...
...
@@ -111,7 +111,7 @@ flac_eof_cb(G_GNUC_UNUSED const flac_decoder *fd, void *fdata)
}
static
void
flac_error_cb
(
G_GNUC_UNUSED
const
flac_d
ecoder
*
fd
,
flac_error_cb
(
G_GNUC_UNUSED
const
FLAC__StreamD
ecoder
*
fd
,
FLAC__StreamDecoderErrorStatus
status
,
void
*
fdata
)
{
flac_error_common_cb
(
"flac"
,
status
,
(
struct
flac_data
*
)
fdata
);
...
...
@@ -206,14 +206,14 @@ static void flacPrintErroredState(FLAC__StreamDecoderState state)
}
#endif
/* FLAC_API_VERSION_CURRENT >= 7 */
static
void
flacMetadata
(
G_GNUC_UNUSED
const
flac_d
ecoder
*
dec
,
static
void
flacMetadata
(
G_GNUC_UNUSED
const
FLAC__StreamD
ecoder
*
dec
,
const
FLAC__StreamMetadata
*
block
,
void
*
vdata
)
{
flac_metadata_common_cb
(
block
,
(
struct
flac_data
*
)
vdata
);
}
static
FLAC__StreamDecoderWriteStatus
flac_write_cb
(
const
flac_d
ecoder
*
dec
,
const
FLAC__Frame
*
frame
,
flac_write_cb
(
const
FLAC__StreamD
ecoder
*
dec
,
const
FLAC__Frame
*
frame
,
const
FLAC__int32
*
const
buf
[],
void
*
vdata
)
{
FLAC__uint32
samples
=
frame
->
header
.
blocksize
;
...
...
@@ -224,7 +224,7 @@ flac_write_cb(const flac_decoder *dec, const FLAC__Frame *frame,
timeChange
=
((
float
)
samples
)
/
frame
->
header
.
sample_rate
;
data
->
time
+=
timeChange
;
flac
_get_decode_position
(
dec
,
&
newPosition
);
FLAC__stream_decoder
_get_decode_position
(
dec
,
&
newPosition
);
if
(
data
->
position
&&
newPosition
>=
data
->
position
)
{
assert
(
timeChange
>=
0
);
...
...
@@ -397,7 +397,7 @@ flac_tag_dup(const char *file)
}
static
void
flac_decoder_loop
(
struct
flac_data
*
data
,
flac_d
ecoder
*
flac_dec
,
flac_decoder_loop
(
struct
flac_data
*
data
,
FLAC__StreamD
ecoder
*
flac_dec
,
FLAC__uint64
t_start
,
FLAC__uint64
t_end
)
{
struct
decoder
*
decoder
=
data
->
decoder
;
...
...
@@ -418,7 +418,7 @@ flac_decoder_loop(struct flac_data *data, flac_decoder *flac_dec,
data
->
audio_format
.
sample_rate
;
if
(
seek_sample
>=
t_start
&&
(
t_end
==
0
||
seek_sample
<=
t_end
)
&&
flac
_seek_absolute
(
flac_dec
,
seek_sample
))
{
FLAC__stream_decoder
_seek_absolute
(
flac_dec
,
seek_sample
))
{
data
->
next_frame
=
seek_sample
;
data
->
time
=
(
float
)(
seek_sample
-
t_start
)
/
data
->
audio_format
.
sample_rate
;
...
...
@@ -427,14 +427,14 @@ flac_decoder_loop(struct flac_data *data, flac_decoder *flac_dec,
}
else
decoder_seek_error
(
decoder
);
}
else
if
(
cmd
==
DECODE_COMMAND_STOP
||
flac_get_state
(
flac_dec
)
==
flac_decoder_eof
)
FLAC__stream_decoder_get_state
(
flac_dec
)
==
FLAC__STREAM_DECODER_END_OF_STREAM
)
break
;
if
(
t_end
!=
0
&&
data
->
next_frame
>=
t_end
)
/* end of this sub track */
break
;
if
(
!
flac
_process_single
(
flac_dec
))
{
if
(
!
FLAC__stream_decoder
_process_single
(
flac_dec
))
{
cmd
=
decoder_get_command
(
decoder
);
if
(
cmd
!=
DECODE_COMMAND_SEEK
)
break
;
...
...
@@ -442,8 +442,8 @@ flac_decoder_loop(struct flac_data *data, flac_decoder *flac_dec,
}
if
(
cmd
!=
DECODE_COMMAND_STOP
)
{
flacPrintErroredState
(
flac
_get_state
(
flac_dec
));
flac
_finish
(
flac_dec
);
flacPrintErroredState
(
FLAC__stream_decoder
_get_state
(
flac_dec
));
FLAC__stream_decoder
_finish
(
flac_dec
);
}
}
...
...
@@ -452,11 +452,11 @@ flac_decode_internal(struct decoder * decoder,
struct
input_stream
*
input_stream
,
bool
is_ogg
)
{
flac_d
ecoder
*
flac_dec
;
FLAC__StreamD
ecoder
*
flac_dec
;
struct
flac_data
data
;
const
char
*
err
=
NULL
;
if
(
!
(
flac_dec
=
flac
_new
()))
if
(
!
(
flac_dec
=
FLAC__stream_decoder
_new
()))
return
;
flac_data_init
(
&
data
,
decoder
,
input_stream
);
data
.
tag
=
tag_new
();
...
...
@@ -470,11 +470,18 @@ flac_decode_internal(struct decoder * decoder,
if
(
is_ogg
)
{
#if defined(FLAC_API_VERSION_CURRENT) && FLAC_API_VERSION_CURRENT > 7
if
(
!
flac_ogg_init
(
flac_dec
,
flac_read_cb
,
flac_seek_cb
,
flac_tell_cb
,
flac_length_cb
,
flac_eof_cb
,
flac_write_cb
,
flacMetadata
,
flac_error_cb
,
(
void
*
)
&
data
))
{
FLAC__StreamDecoderInitStatus
status
=
FLAC__stream_decoder_init_ogg_stream
(
flac_dec
,
flac_read_cb
,
flac_seek_cb
,
flac_tell_cb
,
flac_length_cb
,
flac_eof_cb
,
flac_write_cb
,
flacMetadata
,
flac_error_cb
,
(
void
*
)
&
data
);
if
(
status
!=
FLAC__STREAM_DECODER_INIT_STATUS_OK
)
{
err
=
"doing Ogg init()"
;
goto
fail
;
}
...
...
@@ -492,7 +499,7 @@ flac_decode_internal(struct decoder * decoder,
}
}
if
(
!
flac_process
_metadata
(
flac_dec
))
{
if
(
!
FLAC__stream_decoder_process_until_end_of
_metadata
(
flac_dec
))
{
err
=
"problem reading metadata"
;
goto
fail
;
}
...
...
@@ -512,7 +519,7 @@ flac_decode_internal(struct decoder * decoder,
fail:
flac_data_deinit
(
&
data
);
flac
_delete
(
flac_dec
);
FLAC__stream_decoder
_delete
(
flac_dec
);
if
(
err
)
g_warning
(
"%s
\n
"
,
err
);
...
...
@@ -541,7 +548,7 @@ flac_container_decode(struct decoder* decoder,
FLAC__uint64
track_time
=
0
;
FLAC__StreamMetadata
*
cs
=
NULL
;
flac_d
ecoder
*
flac_dec
;
FLAC__StreamD
ecoder
*
flac_dec
;
struct
flac_data
data
;
const
char
*
err
=
NULL
;
...
...
@@ -574,7 +581,7 @@ flac_container_decode(struct decoder* decoder,
return
;
}
if
(
!
(
flac_dec
=
flac
_new
()))
if
(
!
(
flac_dec
=
FLAC__stream_decoder
_new
()))
{
g_free
(
pathname
);
return
;
...
...
@@ -619,7 +626,7 @@ flac_container_decode(struct decoder* decoder,
}
}
if
(
!
flac_process
_metadata
(
flac_dec
))
if
(
!
FLAC__stream_decoder_process_until_end_of
_metadata
(
flac_dec
))
{
err
=
"problem reading metadata"
;
goto
fail
;
...
...
@@ -642,7 +649,7 @@ flac_container_decode(struct decoder* decoder,
true
,
data
.
total_time
);
// seek to song start (order is important: after decoder init)
flac
_seek_absolute
(
flac_dec
,
(
FLAC__uint64
)
t_start
);
FLAC__stream_decoder
_seek_absolute
(
flac_dec
,
(
FLAC__uint64
)
t_start
);
data
.
next_frame
=
t_start
;
flac_decoder_loop
(
&
data
,
flac_dec
,
t_start
,
t_end
);
...
...
@@ -652,7 +659,7 @@ fail:
g_free
(
pathname
);
flac_data_deinit
(
&
data
);
flac
_delete
(
flac_dec
);
FLAC__stream_decoder
_delete
(
flac_dec
);
if
(
err
)
g_warning
(
"%s
\n
"
,
err
);
...
...
@@ -667,12 +674,12 @@ flac_filedecode_internal(struct decoder* decoder,
const
char
*
fname
,
bool
is_ogg
)
{
flac_d
ecoder
*
flac_dec
;
FLAC__StreamD
ecoder
*
flac_dec
;
struct
flac_data
data
;
const
char
*
err
=
NULL
;
unsigned
int
flac_err_state
=
0
;
if
(
!
(
flac_dec
=
flac
_new
()))
if
(
!
(
flac_dec
=
FLAC__stream_decoder
_new
()))
return
;
flac_data_init
(
&
data
,
decoder
,
NULL
);
...
...
@@ -722,7 +729,7 @@ flac_filedecode_internal(struct decoder* decoder,
}
}
if
(
!
flac_process
_metadata
(
flac_dec
))
if
(
!
FLAC__stream_decoder_process_until_end_of
_metadata
(
flac_dec
))
{
err
=
"problem reading metadata"
;
goto
fail
;
...
...
@@ -744,7 +751,7 @@ flac_filedecode_internal(struct decoder* decoder,
fail:
flac_data_deinit
(
&
data
);
flac
_delete
(
flac_dec
);
FLAC__stream_decoder
_delete
(
flac_dec
);
if
(
err
)
g_warning
(
"%s
\n
"
,
err
);
...
...
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