Commit 13543580 authored by Sam Hocevar's avatar Sam Hocevar

* ./src/playlist/playlist.c: don't run the playlist by default.

  * ./src/libvlc.c: if items are specified in the commandline, run the playlist.
  * ./src/vlc.c: don't rely on internal vlc types (mtime_t).
parent 04b80451
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* vlc.h: global header for vlc * vlc.h: global header for vlc
***************************************************************************** *****************************************************************************
* Copyright (C) 1998, 1999, 2000 VideoLAN * Copyright (C) 1998, 1999, 2000 VideoLAN
* $Id: vlc.h,v 1.13 2002/08/26 23:36:20 sam Exp $ * $Id: vlc.h,v 1.14 2002/09/29 18:19:53 sam Exp $
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
...@@ -45,6 +45,7 @@ typedef int vlc_status_t; ...@@ -45,6 +45,7 @@ typedef int vlc_status_t;
#define VLC_EMODULE -2 /* Module not found */ #define VLC_EMODULE -2 /* Module not found */
#define VLC_ESTATUS -3 /* Invalid status */ #define VLC_ESTATUS -3 /* Invalid status */
#define VLC_ETHREAD -4 /* Could not spawn thread */ #define VLC_ETHREAD -4 /* Could not spawn thread */
#define VLC_EOBJECT -5 /* Object not found */
#define VLC_EEXIT -255 /* Program exited */ #define VLC_EEXIT -255 /* Program exited */
#define VLC_EGENERIC -666 /* Generic error */ #define VLC_EGENERIC -666 /* Generic error */
...@@ -105,7 +106,6 @@ vlc_status_t vlc_status ( void ); ...@@ -105,7 +106,6 @@ vlc_status_t vlc_status ( void );
vlc_error_t vlc_create ( void ); vlc_error_t vlc_create ( void );
vlc_error_t vlc_init ( int, char *[] ); vlc_error_t vlc_init ( int, char *[] );
vlc_error_t vlc_run ( void );
vlc_error_t vlc_die ( void ); vlc_error_t vlc_die ( void );
vlc_error_t vlc_destroy ( void ); vlc_error_t vlc_destroy ( void );
...@@ -113,6 +113,11 @@ vlc_error_t vlc_set ( const char *, const char * ); ...@@ -113,6 +113,11 @@ vlc_error_t vlc_set ( const char *, const char * );
vlc_error_t vlc_add_intf ( const char *, vlc_bool_t ); vlc_error_t vlc_add_intf ( const char *, vlc_bool_t );
vlc_error_t vlc_add_target ( const char *, int, int ); vlc_error_t vlc_add_target ( const char *, int, int );
vlc_error_t vlc_play ( );
vlc_error_t vlc_pause ( );
vlc_error_t vlc_stop ( void );
vlc_error_t vlc_fullscreen ( );
/***************************************************************************** /*****************************************************************************
* Exported libvlc reentrant API * Exported libvlc reentrant API
*****************************************************************************/ *****************************************************************************/
...@@ -120,7 +125,6 @@ vlc_status_t vlc_status_r ( vlc_t * ); ...@@ -120,7 +125,6 @@ vlc_status_t vlc_status_r ( vlc_t * );
vlc_t * vlc_create_r ( void ); vlc_t * vlc_create_r ( void );
vlc_error_t vlc_init_r ( vlc_t *, int, char *[] ); vlc_error_t vlc_init_r ( vlc_t *, int, char *[] );
vlc_error_t vlc_run_r ( vlc_t * );
vlc_error_t vlc_die_r ( vlc_t * ); vlc_error_t vlc_die_r ( vlc_t * );
vlc_error_t vlc_destroy_r ( vlc_t * ); vlc_error_t vlc_destroy_r ( vlc_t * );
...@@ -128,6 +132,11 @@ vlc_error_t vlc_set_r ( vlc_t *, const char *, const char * ); ...@@ -128,6 +132,11 @@ vlc_error_t vlc_set_r ( vlc_t *, const char *, const char * );
vlc_error_t vlc_add_intf_r ( vlc_t *, const char *, vlc_bool_t ); vlc_error_t vlc_add_intf_r ( vlc_t *, const char *, vlc_bool_t );
vlc_error_t vlc_add_target_r ( vlc_t *, const char *, int, int ); vlc_error_t vlc_add_target_r ( vlc_t *, const char *, int, int );
vlc_error_t vlc_play_r ( vlc_t * );
vlc_error_t vlc_pause_r ( vlc_t * );
vlc_error_t vlc_stop_r ( vlc_t * );
vlc_error_t vlc_fullscreen_r ( vlc_t * );
# ifdef __cplusplus # ifdef __cplusplus
} }
# endif # endif
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* libvlc.c: main libvlc source * libvlc.c: main libvlc source
***************************************************************************** *****************************************************************************
* Copyright (C) 1998-2002 VideoLAN * Copyright (C) 1998-2002 VideoLAN
* $Id: libvlc.c,v 1.32 2002/09/26 22:40:24 massiot Exp $ * $Id: libvlc.c,v 1.33 2002/09/29 18:19:53 sam Exp $
* *
* Authors: Vincent Seguin <seguin@via.ecp.fr> * Authors: Vincent Seguin <seguin@via.ecp.fr>
* Samuel Hocevar <sam@zoy.org> * Samuel Hocevar <sam@zoy.org>
...@@ -51,7 +51,7 @@ ...@@ -51,7 +51,7 @@
#endif #endif
#ifdef WIN32 /* optind, getopt(), included in unistd.h */ #ifdef WIN32 /* optind, getopt(), included in unistd.h */
# include "GNUgetopt/getopt.h" # include "extras/GNUgetopt/getopt.h"
#endif #endif
#ifdef HAVE_LOCALE_H #ifdef HAVE_LOCALE_H
...@@ -306,7 +306,7 @@ vlc_error_t vlc_init_r( vlc_t *p_vlc, int i_argc, char *ppsz_argv[] ) ...@@ -306,7 +306,7 @@ vlc_error_t vlc_init_r( vlc_t *p_vlc, int i_argc, char *ppsz_argv[] )
/* Check for short help option */ /* Check for short help option */
if( config_GetInt( p_vlc, "help" ) ) if( config_GetInt( p_vlc, "help" ) )
{ {
fprintf( stderr, _("Usage: %s [options] [parameters] [files]...\n\n"), fprintf( stderr, _("Usage: %s [options] [items]...\n\n"),
p_vlc->psz_object_name ); p_vlc->psz_object_name );
Usage( p_vlc, "main" ); Usage( p_vlc, "main" );
Usage( p_vlc, "help" ); Usage( p_vlc, "help" );
...@@ -507,34 +507,6 @@ vlc_error_t vlc_init_r( vlc_t *p_vlc, int i_argc, char *ppsz_argv[] ) ...@@ -507,34 +507,6 @@ vlc_error_t vlc_init_r( vlc_t *p_vlc, int i_argc, char *ppsz_argv[] )
return VLC_SUCCESS; return VLC_SUCCESS;
} }
/*****************************************************************************
* vlc_run: run vlc
*****************************************************************************
* XXX: This function opens an interface plugin and runs it. If b_block is set
* to 0, vlc_add_intf will return immediately and let the interface run in a
* separate thread. If b_block is set to 1, vlc_add_intf will continue until
* user requests to quit.
*****************************************************************************/
vlc_error_t vlc_run( void )
{
return vlc_run_r( ( i_vlc == 1 ) ? pp_vlc[0] : NULL );
}
vlc_error_t vlc_run_r( vlc_t *p_vlc )
{
/* Check that the handle is valid */
if( !p_vlc || p_vlc->i_status != VLC_STATUS_STOPPED )
{
fprintf( stderr, "error: invalid status (!STOPPED)\n" );
return VLC_ESTATUS;
}
/* Update the handle status */
p_vlc->i_status = VLC_STATUS_RUNNING;
return VLC_SUCCESS;
}
/***************************************************************************** /*****************************************************************************
* vlc_add_intf: add an interface * vlc_add_intf: add an interface
***************************************************************************** *****************************************************************************
...@@ -614,76 +586,16 @@ vlc_error_t vlc_destroy( void ) ...@@ -614,76 +586,16 @@ vlc_error_t vlc_destroy( void )
vlc_error_t vlc_destroy_r( vlc_t *p_vlc ) vlc_error_t vlc_destroy_r( vlc_t *p_vlc )
{ {
int i_index; int i_index;
intf_thread_t * p_intf;
playlist_t * p_playlist;
vout_thread_t * p_vout;
aout_instance_t * p_aout;
/* Check that the handle is valid */ /* Check that the handle is valid */
if( !p_vlc || (p_vlc->i_status != VLC_STATUS_RUNNING if( !p_vlc || (p_vlc->i_status != VLC_STATUS_STOPPED
&& p_vlc->i_status != VLC_STATUS_STOPPED
&& p_vlc->i_status != VLC_STATUS_CREATED) ) && p_vlc->i_status != VLC_STATUS_CREATED) )
{ {
fprintf( stderr, "error: invalid status " fprintf( stderr, "error: invalid status "
"(!RUNNING&&!STOPPED&&!CREATED)\n" ); "(!STOPPED&&!CREATED)\n" );
return VLC_ESTATUS; return VLC_ESTATUS;
} }
if( p_vlc->i_status == VLC_STATUS_RUNNING )
{
/*
* Ask the interfaces to stop and destroy them
*/
msg_Dbg( p_vlc, "removing all interfaces" );
while( (p_intf = vlc_object_find( p_vlc, VLC_OBJECT_INTF,
FIND_CHILD )) )
{
intf_StopThread( p_intf );
vlc_object_detach( p_intf );
vlc_object_release( p_intf );
intf_Destroy( p_intf );
}
/*
* Free playlists
*/
msg_Dbg( p_vlc, "removing all playlists" );
while( (p_playlist = vlc_object_find( p_vlc, VLC_OBJECT_PLAYLIST,
FIND_CHILD )) )
{
vlc_object_detach( p_playlist );
vlc_object_release( p_playlist );
playlist_Destroy( p_playlist );
}
/*
* Free video outputs
*/
msg_Dbg( p_vlc, "removing all video outputs" );
while( (p_vout = vlc_object_find( p_vlc, VLC_OBJECT_VOUT,
FIND_CHILD )) )
{
vlc_object_detach( p_vout );
vlc_object_release( p_vout );
vout_DestroyThread( p_vout );
}
/*
* Free audio outputs
*/
msg_Dbg( p_vlc, "removing all audio outputs" );
while( (p_aout = vlc_object_find( p_vlc, VLC_OBJECT_AOUT,
FIND_CHILD )) )
{
vlc_object_detach( (vlc_object_t *)p_aout );
vlc_object_release( (vlc_object_t *)p_aout );
aout_Delete( p_aout );
}
/* Update the handle status */
p_vlc->i_status = VLC_STATUS_STOPPED;
}
if( p_vlc->i_status == VLC_STATUS_STOPPED ) if( p_vlc->i_status == VLC_STATUS_STOPPED )
{ {
/* /*
...@@ -967,6 +879,178 @@ vlc_error_t vlc_set_r( vlc_t *p_vlc, const char *psz_var, const char *psz_val ) ...@@ -967,6 +879,178 @@ vlc_error_t vlc_set_r( vlc_t *p_vlc, const char *psz_var, const char *psz_val )
return VLC_SUCCESS; return VLC_SUCCESS;
} }
/* XXX: temporary hacks */
/*****************************************************************************
* vlc_play: play
*****************************************************************************/
vlc_error_t vlc_play( )
{
return vlc_play_r( ( i_vlc == 1 ) ? pp_vlc[0] : NULL );
}
vlc_error_t vlc_play_r( vlc_t *p_vlc )
{
playlist_t * p_playlist;
/* Check that the handle is valid */
if( !p_vlc || p_vlc->i_status != VLC_STATUS_STOPPED )
{
fprintf( stderr, "error: invalid status (!STOPPED)\n" );
return VLC_ESTATUS;
}
/* Update the handle status */
p_vlc->i_status = VLC_STATUS_RUNNING;
p_playlist = vlc_object_find( p_vlc, VLC_OBJECT_PLAYLIST, FIND_CHILD );
if( !p_playlist )
{
return VLC_EOBJECT;
}
vlc_mutex_lock( &p_playlist->object_lock );
if( p_playlist->i_size )
{
vlc_mutex_unlock( &p_playlist->object_lock );
playlist_Play( p_playlist );
}
else
{
vlc_mutex_unlock( &p_playlist->object_lock );
}
vlc_object_release( p_playlist );
return VLC_SUCCESS;
}
/*****************************************************************************
* vlc_stop: stop
*****************************************************************************/
vlc_error_t vlc_stop( )
{
return vlc_stop_r( ( i_vlc == 1 ) ? pp_vlc[0] : NULL );
}
vlc_error_t vlc_stop_r( vlc_t *p_vlc )
{
intf_thread_t * p_intf;
playlist_t * p_playlist;
vout_thread_t * p_vout;
aout_instance_t * p_aout;
/* Check that the handle is valid */
if( !p_vlc || ( p_vlc->i_status != VLC_STATUS_STOPPED
&& p_vlc->i_status != VLC_STATUS_RUNNING ) )
{
fprintf( stderr, "error: invalid status (!STOPPED&&!RUNNING)\n" );
return VLC_ESTATUS;
}
/*
* Ask the interfaces to stop and destroy them
*/
msg_Dbg( p_vlc, "removing all interfaces" );
while( (p_intf = vlc_object_find( p_vlc, VLC_OBJECT_INTF, FIND_CHILD )) )
{
intf_StopThread( p_intf );
vlc_object_detach( p_intf );
vlc_object_release( p_intf );
intf_Destroy( p_intf );
}
/*
* Free playlists
*/
msg_Dbg( p_vlc, "removing all playlists" );
while( (p_playlist = vlc_object_find( p_vlc, VLC_OBJECT_PLAYLIST,
FIND_CHILD )) )
{
vlc_object_detach( p_playlist );
vlc_object_release( p_playlist );
playlist_Destroy( p_playlist );
}
/*
* Free video outputs
*/
msg_Dbg( p_vlc, "removing all video outputs" );
while( (p_vout = vlc_object_find( p_vlc, VLC_OBJECT_VOUT, FIND_CHILD )) )
{
vlc_object_detach( p_vout );
vlc_object_release( p_vout );
vout_DestroyThread( p_vout );
}
/*
* Free audio outputs
*/
msg_Dbg( p_vlc, "removing all audio outputs" );
while( (p_aout = vlc_object_find( p_vlc, VLC_OBJECT_AOUT, FIND_CHILD )) )
{
vlc_object_detach( (vlc_object_t *)p_aout );
vlc_object_release( (vlc_object_t *)p_aout );
aout_Delete( p_aout );
}
/* Update the handle status */
p_vlc->i_status = VLC_STATUS_STOPPED;
return VLC_SUCCESS;
}
/*****************************************************************************
* vlc_pause: toggle pause
*****************************************************************************/
vlc_error_t vlc_pause( )
{
return vlc_pause_r( ( i_vlc == 1 ) ? pp_vlc[0] : NULL );
}
vlc_error_t vlc_pause_r( vlc_t *p_vlc )
{
input_thread_t *p_input;
p_input = vlc_object_find( p_vlc, VLC_OBJECT_INPUT, FIND_CHILD );
if( !p_input )
{
return VLC_EOBJECT;
}
input_SetStatus( p_input, INPUT_STATUS_PAUSE );
vlc_object_release( p_input );
return VLC_SUCCESS;
}
/*****************************************************************************
* vlc_fullscreen: toggle fullscreen mode
*****************************************************************************/
vlc_error_t vlc_fullscreen( )
{
return vlc_fullscreen_r( ( i_vlc == 1 ) ? pp_vlc[0] : NULL );
}
vlc_error_t vlc_fullscreen_r( vlc_t *p_vlc )
{
vout_thread_t *p_vout;
p_vout = vlc_object_find( p_vlc, VLC_OBJECT_VOUT, FIND_CHILD );
if( !p_vout )
{
return VLC_EOBJECT;
}
p_vout->i_changes |= VOUT_FULLSCREEN_CHANGE;
vlc_object_release( p_vout );
return VLC_SUCCESS;
}
/* following functions are local */ /* following functions are local */
/***************************************************************************** /*****************************************************************************
...@@ -982,7 +1066,7 @@ static int GetFilenames( vlc_t *p_vlc, int i_argc, char *ppsz_argv[] ) ...@@ -982,7 +1066,7 @@ static int GetFilenames( vlc_t *p_vlc, int i_argc, char *ppsz_argv[] )
for( i_opt = optind; i_opt < i_argc; i_opt++ ) for( i_opt = optind; i_opt < i_argc; i_opt++ )
{ {
vlc_add_target_r( p_vlc, ppsz_argv[ i_opt ], vlc_add_target_r( p_vlc, ppsz_argv[ i_opt ],
PLAYLIST_APPEND, PLAYLIST_END ); PLAYLIST_APPEND | PLAYLIST_GO, PLAYLIST_END );
} }
return VLC_SUCCESS; return VLC_SUCCESS;
...@@ -1210,7 +1294,7 @@ static void ListModules( vlc_t *p_this ) ...@@ -1210,7 +1294,7 @@ static void ListModules( vlc_t *p_this )
#endif #endif
/* Usage */ /* Usage */
fprintf( stderr, _("Usage: %s [options] [parameters] [files]...\n\n"), fprintf( stderr, _("Usage: %s [options] [items]...\n\n"),
p_this->p_vlc->psz_object_name ); p_this->p_vlc->psz_object_name );
fprintf( stderr, _("[module] [description]\n") ); fprintf( stderr, _("[module] [description]\n") );
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* configuration.c management of the modules configuration * configuration.c management of the modules configuration
***************************************************************************** *****************************************************************************
* Copyright (C) 2001 VideoLAN * Copyright (C) 2001 VideoLAN
* $Id: configuration.c,v 1.38 2002/08/20 18:25:42 sam Exp $ * $Id: configuration.c,v 1.39 2002/09/29 18:19:53 sam Exp $
* *
* Authors: Gildas Bazin <gbazin@netcourrier.com> * Authors: Gildas Bazin <gbazin@netcourrier.com>
* *
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
# include <getopt.h> /* getopt() */ # include <getopt.h> /* getopt() */
# endif # endif
#else #else
# include "GNUgetopt/getopt.h" # include "extras/GNUgetopt/getopt.h"
#endif #endif
#if defined(HAVE_GETPWUID) #if defined(HAVE_GETPWUID)
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* playlist.c : Playlist management functions * playlist.c : Playlist management functions
***************************************************************************** *****************************************************************************
* Copyright (C) 1999-2001 VideoLAN * Copyright (C) 1999-2001 VideoLAN
* $Id: playlist.c,v 1.13 2002/08/29 23:53:22 massiot Exp $ * $Id: playlist.c,v 1.14 2002/09/29 18:19:53 sam Exp $
* *
* Authors: Samuel Hocevar <sam@zoy.org> * Authors: Samuel Hocevar <sam@zoy.org>
* *
...@@ -62,7 +62,7 @@ playlist_t * __playlist_Create ( vlc_object_t *p_parent ) ...@@ -62,7 +62,7 @@ playlist_t * __playlist_Create ( vlc_object_t *p_parent )
} }
p_playlist->p_input = NULL; p_playlist->p_input = NULL;
p_playlist->i_status = PLAYLIST_RUNNING; p_playlist->i_status = PLAYLIST_STOPPED;
p_playlist->i_index = -1; p_playlist->i_index = -1;
p_playlist->i_size = 0; p_playlist->i_size = 0;
p_playlist->pp_items = NULL; p_playlist->pp_items = NULL;
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* vlc.c: the vlc player * vlc.c: the vlc player
***************************************************************************** *****************************************************************************
* Copyright (C) 1998-2001 VideoLAN * Copyright (C) 1998-2001 VideoLAN
* $Id: vlc.c,v 1.10 2002/08/20 18:08:51 sam Exp $ * $Id: vlc.c,v 1.11 2002/09/29 18:19:53 sam Exp $
* *
* Authors: Vincent Seguin <seguin@via.ecp.fr> * Authors: Vincent Seguin <seguin@via.ecp.fr>
* Samuel Hocevar <sam@zoy.org> * Samuel Hocevar <sam@zoy.org>
...@@ -28,9 +28,12 @@ ...@@ -28,9 +28,12 @@
#include <stdio.h> /* fprintf() */ #include <stdio.h> /* fprintf() */
#include <stdlib.h> /* putenv(), strtol(), */ #include <stdlib.h> /* putenv(), strtol(), */
#include <signal.h> /* SIGHUP, SIGINT, SIGKILL */ #include <signal.h> /* SIGHUP, SIGINT, SIGKILL */
#include <time.h> /* time() */
#include <vlc/vlc.h> #include <vlc/vlc.h>
#include "config.h"
/***************************************************************************** /*****************************************************************************
* Local prototypes. * Local prototypes.
*****************************************************************************/ *****************************************************************************/
...@@ -87,7 +90,7 @@ int main( int i_argc, char *ppsz_argv[] ) ...@@ -87,7 +90,7 @@ int main( int i_argc, char *ppsz_argv[] )
} }
/* Run libvlc, in non-blocking mode */ /* Run libvlc, in non-blocking mode */
err = vlc_run(); err = vlc_play();
/* Add background interfaces */ /* Add background interfaces */
#if 0 #if 0
...@@ -103,7 +106,10 @@ int main( int i_argc, char *ppsz_argv[] ) ...@@ -103,7 +106,10 @@ int main( int i_argc, char *ppsz_argv[] )
/* Add a blocking interface and keep the return value */ /* Add a blocking interface and keep the return value */
err = vlc_add_intf( NULL, VLC_TRUE ); err = vlc_add_intf( NULL, VLC_TRUE );
/* Finish the threads and destroy the libvlc structure */ /* Finish the threads */
vlc_stop();
/* Destroy the libvlc structure */
vlc_destroy(); vlc_destroy();
return err; return err;
...@@ -118,7 +124,7 @@ int main( int i_argc, char *ppsz_argv[] ) ...@@ -118,7 +124,7 @@ int main( int i_argc, char *ppsz_argv[] )
*****************************************************************************/ *****************************************************************************/
static void SigHandler( int i_signal ) static void SigHandler( int i_signal )
{ {
static mtime_t abort_time = 0; static time_t abort_time = 0;
static volatile vlc_bool_t b_die = VLC_FALSE; static volatile vlc_bool_t b_die = VLC_FALSE;
/* Once a signal has been trapped, the termination sequence will be /* Once a signal has been trapped, the termination sequence will be
...@@ -128,7 +134,7 @@ static void SigHandler( int i_signal ) ...@@ -128,7 +134,7 @@ static void SigHandler( int i_signal )
if( !b_die ) if( !b_die )
{ {
b_die = VLC_TRUE; b_die = VLC_TRUE;
abort_time = mdate(); abort_time = time( NULL );
fprintf( stderr, "signal %d received, terminating vlc - do it " fprintf( stderr, "signal %d received, terminating vlc - do it "
"again in case it gets stuck\n", i_signal ); "again in case it gets stuck\n", i_signal );
...@@ -136,9 +142,9 @@ static void SigHandler( int i_signal ) ...@@ -136,9 +142,9 @@ static void SigHandler( int i_signal )
/* Acknowledge the signal received */ /* Acknowledge the signal received */
vlc_die(); vlc_die();
} }
else if( mdate() > abort_time + 1000000 ) else if( time( NULL ) > abort_time + 2 )
{ {
/* If user asks again 1 second later, die badly */ /* If user asks again 1 or 2 seconds later, die badly */
signal( SIGINT, SIG_DFL ); signal( SIGINT, SIG_DFL );
signal( SIGHUP, SIG_DFL ); signal( SIGHUP, SIG_DFL );
signal( SIGQUIT, SIG_DFL ); signal( SIGQUIT, SIG_DFL );
...@@ -147,7 +153,7 @@ static void SigHandler( int i_signal ) ...@@ -147,7 +153,7 @@ static void SigHandler( int i_signal )
fprintf( stderr, "user insisted too much, dying badly\n" ); fprintf( stderr, "user insisted too much, dying badly\n" );
exit( 1 ); abort();
} }
} }
#endif #endif
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment