Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
vlc-1.1
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-1.1
Commits
1e4bfd0d
Commit
1e4bfd0d
authored
Jul 18, 2004
by
Cyril Deguet
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
* all: now both GLX 1.2 and 1.3 are supported
parent
3a6efa71
Changes
5
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
199 additions
and
133 deletions
+199
-133
modules/visualization/galaktos/glx.c
modules/visualization/galaktos/glx.c
+184
-125
modules/visualization/galaktos/glx.h
modules/visualization/galaktos/glx.h
+1
-2
modules/visualization/galaktos/main.c
modules/visualization/galaktos/main.c
+3
-3
modules/visualization/galaktos/plugin.c
modules/visualization/galaktos/plugin.c
+5
-3
modules/visualization/galaktos/plugin.h
modules/visualization/galaktos/plugin.h
+6
-0
No files found.
modules/visualization/galaktos/glx.c
View file @
1e4bfd0d
...
@@ -28,13 +28,16 @@
...
@@ -28,13 +28,16 @@
#include <GL/glx.h>
#include <GL/glx.h>
/* Local prototypes */
/* Local prototypes */
static
void
CreateWindow
(
galaktos_thread_t
*
p_thread
,
XVisualInfo
*
p_vi
,
int
i_width
,
int
i_height
,
int
b_fullscreen
);
static
int
InitGLX12
(
galaktos_thread_t
*
p_thread
);
static
int
InitGLX13
(
galaktos_thread_t
*
p_thread
);
static
void
CreateWindow
(
galaktos_thread_t
*
p_thread
,
XVisualInfo
*
p_vi
);
typedef
struct
typedef
struct
{
{
Display
*
p_display
;
Display
*
p_display
;
int
b_glx13
;
GLXContext
gwctx
;
GLXContext
gwctx
;
Window
wnd
;
Window
wnd
;
GLXWindow
gwnd
;
GLXWindow
gwnd
;
...
@@ -46,28 +49,11 @@ glx_data_t;
...
@@ -46,28 +49,11 @@ glx_data_t;
#define OS_DATA ((glx_data_t*)(p_thread->p_os_data))
#define OS_DATA ((glx_data_t*)(p_thread->p_os_data))
int
galaktos_glx_init
(
galaktos_thread_t
*
p_thread
,
int
i_width
,
int
i_height
,
int
galaktos_glx_init
(
galaktos_thread_t
*
p_thread
)
int
b_fullscreen
)
{
{
Display
*
p_display
;
Display
*
p_display
;
int
i_opcode
,
i_evt
,
i_err
;
int
i_opcode
,
i_evt
,
i_err
;
int
i_maj
,
i_min
;
int
i_maj
,
i_min
;
int
i_nbelem
;
GLXFBConfig
*
p_fbconfs
,
fbconf
;
XSetWindowAttributes
xattr
;
XVisualInfo
*
p_vi
;
GLXContext
gwctx
;
int
i
;
GLXPbuffer
gpbuf
;
#if 1
int
p_attr
[]
=
{
GLX_RED_SIZE
,
5
,
GLX_GREEN_SIZE
,
5
,
GLX_BLUE_SIZE
,
5
,
GLX_DOUBLEBUFFER
,
True
,
GLX_DRAWABLE_TYPE
,
GLX_WINDOW_BIT
,
0
};
#else
int
p_attr
[]
=
{
GLX_RGBA
,
GLX_RED_SIZE
,
5
,
GLX_GREEN_SIZE
,
5
,
GLX_BLUE_SIZE
,
5
,
GLX_DOUBLEBUFFER
,
0
};
#endif
/* Initialize OS data */
/* Initialize OS data */
p_thread
->
p_os_data
=
malloc
(
sizeof
(
glx_data_t
)
);
p_thread
->
p_os_data
=
malloc
(
sizeof
(
glx_data_t
)
);
...
@@ -98,13 +84,171 @@ int galaktos_glx_init( galaktos_thread_t *p_thread, int i_width, int i_height,
...
@@ -98,13 +84,171 @@ int galaktos_glx_init( galaktos_thread_t *p_thread, int i_width, int i_height,
msg_Err
(
p_thread
,
"glXQueryVersion failed"
);
msg_Err
(
p_thread
,
"glXQueryVersion failed"
);
return
-
1
;
return
-
1
;
}
}
#if 1
if
(
i_maj
<=
0
||
((
i_maj
==
1
)
&&
(
i_min
<
3
))
)
if
(
i_maj
<=
0
||
((
i_maj
==
1
)
&&
(
i_min
<
3
))
)
{
{
msg_Err
(
p_thread
,
"GLX 1.3 is needed"
);
OS_DATA
->
b_glx13
=
0
;
msg_Info
(
p_thread
,
"Using GLX 1.2 API"
);
if
(
InitGLX12
(
p_thread
)
==
-
1
)
{
return
-
1
;
}
}
else
{
OS_DATA
->
b_glx13
=
1
;
msg_Info
(
p_thread
,
"Using GLX 1.3 API"
);
if
(
InitGLX13
(
p_thread
)
==
-
1
)
{
return
-
1
;
}
}
XMapWindow
(
p_display
,
OS_DATA
->
wnd
);
if
(
p_thread
->
b_fullscreen
)
{
//XXX
XMoveWindow
(
p_display
,
OS_DATA
->
wnd
,
0
,
0
);
}
XFlush
(
p_display
);
return
0
;
}
int
galaktos_glx_handle_events
(
galaktos_thread_t
*
p_thread
)
{
Display
*
p_display
;
p_display
=
OS_DATA
->
p_display
;
/* loop on X11 events */
while
(
XPending
(
p_display
)
>
0
)
{
XEvent
evt
;
XNextEvent
(
p_display
,
&
evt
);
switch
(
evt
.
type
)
{
case
ClientMessage
:
{
/* Delete notification */
if
(
(
evt
.
xclient
.
format
==
32
)
&&
((
Atom
)
evt
.
xclient
.
data
.
l
[
0
]
==
OS_DATA
->
wm_delete
)
)
{
return
1
;
}
break
;
}
}
}
return
0
;
}
void
galaktos_glx_activate_pbuffer
(
galaktos_thread_t
*
p_thread
)
{
glXMakeContextCurrent
(
OS_DATA
->
p_display
,
OS_DATA
->
gpbuf
,
OS_DATA
->
gpbuf
,
OS_DATA
->
gpctx
);
}
void
galaktos_glx_activate_window
(
galaktos_thread_t
*
p_thread
)
{
if
(
OS_DATA
->
b_glx13
)
{
glXMakeContextCurrent
(
OS_DATA
->
p_display
,
OS_DATA
->
gwnd
,
OS_DATA
->
gwnd
,
OS_DATA
->
gwctx
);
}
else
{
glXMakeCurrent
(
OS_DATA
->
p_display
,
OS_DATA
->
wnd
,
OS_DATA
->
gwctx
);
}
}
void
galaktos_glx_swap
(
galaktos_thread_t
*
p_thread
)
{
if
(
OS_DATA
->
b_glx13
)
{
glXSwapBuffers
(
OS_DATA
->
p_display
,
OS_DATA
->
gwnd
);
}
else
{
glXSwapBuffers
(
OS_DATA
->
p_display
,
OS_DATA
->
wnd
);
}
}
void
galaktos_glx_done
(
galaktos_thread_t
*
p_thread
)
{
Display
*
p_display
;
p_display
=
OS_DATA
->
p_display
;
if
(
OS_DATA
->
b_glx13
)
{
glXDestroyContext
(
p_display
,
OS_DATA
->
gpctx
);
glXDestroyPbuffer
(
p_display
,
OS_DATA
->
gpbuf
);
}
glXDestroyContext
(
p_display
,
OS_DATA
->
gwctx
);
if
(
OS_DATA
->
b_glx13
)
{
glXDestroyWindow
(
p_display
,
OS_DATA
->
gwnd
);
}
XDestroyWindow
(
p_display
,
OS_DATA
->
wnd
);
XCloseDisplay
(
p_display
);
}
int
InitGLX12
(
galaktos_thread_t
*
p_thread
)
{
Display
*
p_display
;
XVisualInfo
*
p_vi
;
GLXContext
gwctx
;
int
p_attr
[]
=
{
GLX_RGBA
,
GLX_RED_SIZE
,
5
,
GLX_GREEN_SIZE
,
5
,
GLX_BLUE_SIZE
,
5
,
GLX_DOUBLEBUFFER
,
0
};
p_display
=
OS_DATA
->
p_display
;
p_vi
=
glXChooseVisual
(
p_display
,
DefaultScreen
(
p_display
),
p_attr
);
if
(
!
p_vi
)
{
msg_Err
(
p_thread
,
"Cannot get GLX 1.2 visual"
);
return
-
1
;
return
-
1
;
}
}
/* Create the window */
CreateWindow
(
p_thread
,
p_vi
);
/* Create an OpenGL context */
OS_DATA
->
gwctx
=
gwctx
=
glXCreateContext
(
p_display
,
p_vi
,
0
,
True
);
if
(
!
gwctx
)
{
msg_Err
(
p_thread
,
"Cannot create OpenGL context"
);
XFree
(
p_vi
);
return
-
1
;
}
XFree
(
p_vi
);
return
0
;
}
int
InitGLX13
(
galaktos_thread_t
*
p_thread
)
{
Display
*
p_display
;
int
i_nbelem
;
GLXFBConfig
*
p_fbconfs
,
fbconf
;
XVisualInfo
*
p_vi
;
GLXContext
gwctx
;
int
i
;
GLXPbuffer
gpbuf
;
int
p_attr
[]
=
{
GLX_RED_SIZE
,
5
,
GLX_GREEN_SIZE
,
5
,
GLX_BLUE_SIZE
,
5
,
GLX_DOUBLEBUFFER
,
True
,
GLX_DRAWABLE_TYPE
,
GLX_WINDOW_BIT
,
0
};
p_display
=
OS_DATA
->
p_display
;
/* Get the FB configuration */
/* Get the FB configuration */
p_fbconfs
=
glXChooseFBConfig
(
p_display
,
0
,
p_attr
,
&
i_nbelem
);
p_fbconfs
=
glXChooseFBConfig
(
p_display
,
0
,
p_attr
,
&
i_nbelem
);
if
(
(
i_nbelem
<=
0
)
||
!
p_fbconfs
)
if
(
(
i_nbelem
<=
0
)
||
!
p_fbconfs
)
...
@@ -126,21 +270,12 @@ int galaktos_glx_init( galaktos_thread_t *p_thread, int i_width, int i_height,
...
@@ -126,21 +270,12 @@ int galaktos_glx_init( galaktos_thread_t *p_thread, int i_width, int i_height,
XFree
(
p_fbconfs
);
XFree
(
p_fbconfs
);
return
-
1
;
return
-
1
;
}
}
#else
p_vi
=
glXChooseVisual
(
p_display
,
DefaultScreen
(
p_display
),
p_attr
);
if
(
!
p_vi
)
{
msg_Err
(
p_thread
,
"Cannot get GLX 1.2 visual"
);
return
-
1
;
}
#endif
/* Create the window */
/* Create the window */
CreateWindow
(
p_thread
,
p_vi
,
i_width
,
i_height
,
b_fullscreen
);
CreateWindow
(
p_thread
,
p_vi
);
XFree
(
p_vi
);
XFree
(
p_vi
);
#if 1
/* Create the GLX window */
/* Create the GLX window */
OS_DATA
->
gwnd
=
glXCreateWindow
(
p_display
,
fbconf
,
OS_DATA
->
wnd
,
NULL
);
OS_DATA
->
gwnd
=
glXCreateWindow
(
p_display
,
fbconf
,
OS_DATA
->
wnd
,
NULL
);
if
(
OS_DATA
->
gwnd
==
None
)
if
(
OS_DATA
->
gwnd
==
None
)
...
@@ -206,118 +341,42 @@ int galaktos_glx_init( galaktos_thread_t *p_thread, int i_width, int i_height,
...
@@ -206,118 +341,42 @@ int galaktos_glx_init( galaktos_thread_t *p_thread, int i_width, int i_height,
}
}
XFree
(
p_fbconfs
);
XFree
(
p_fbconfs
);
#else
/* Create an OpenGL context */
OS_DATA
->
gwctx
=
gwctx
=
glXCreateContext
(
p_display
,
p_vi
,
0
,
True
);
if
(
!
gwctx
)
{
msg_Err
(
p_thread
,
"Cannot create OpenGL context"
);
XFree
(
p_fbconfs
);
return
-
1
;
}
XFree
(
p_vi
);
#endif
XMapWindow
(
p_display
,
OS_DATA
->
wnd
);
if
(
b_fullscreen
)
{
XMoveWindow
(
p_display
,
OS_DATA
->
wnd
,
0
,
0
);
}
XFlush
(
p_display
);
// glXMakeContextCurrent( p_display, OS_DATA->gwnd, OS_DATA->gwnd, gwctx );
// glXMakeCurrent( p_display, OS_DATA->wnd, OS_DATA->gwctx );
return
0
;
return
0
;
}
}
int
galaktos_glx_handle_events
(
galaktos_thread_t
*
p_thread
)
{
Display
*
p_display
;
p_display
=
OS_DATA
->
p_display
;
void
CreateWindow
(
galaktos_thread_t
*
p_thread
,
XVisualInfo
*
p_vi
)
/* loop on X11 events */
while
(
XPending
(
p_display
)
>
0
)
{
XEvent
evt
;
XNextEvent
(
p_display
,
&
evt
);
switch
(
evt
.
type
)
{
case
ClientMessage
:
{
/* Delete notification */
if
(
(
evt
.
xclient
.
format
==
32
)
&&
((
Atom
)
evt
.
xclient
.
data
.
l
[
0
]
==
OS_DATA
->
wm_delete
)
)
{
return
1
;
}
break
;
}
}
}
return
0
;
}
void
galaktos_glx_activate_pbuffer
(
galaktos_thread_t
*
p_thread
)
{
glXMakeContextCurrent
(
OS_DATA
->
p_display
,
OS_DATA
->
gpbuf
,
OS_DATA
->
gpbuf
,
OS_DATA
->
gpctx
);
}
void
galaktos_glx_activate_window
(
galaktos_thread_t
*
p_thread
)
{
glXMakeContextCurrent
(
OS_DATA
->
p_display
,
OS_DATA
->
gwnd
,
OS_DATA
->
gwnd
,
OS_DATA
->
gwctx
);
// glXMakeCurrent( OS_DATA->p_display, OS_DATA->wnd, OS_DATA->gwctx );
}
void
galaktos_glx_swap
(
galaktos_thread_t
*
p_thread
)
{
glXSwapBuffers
(
OS_DATA
->
p_display
,
OS_DATA
->
gwnd
);
}
void
galaktos_glx_done
(
galaktos_thread_t
*
p_thread
)
{
Display
*
p_display
;
p_display
=
OS_DATA
->
p_display
;
glXDestroyContext
(
p_display
,
OS_DATA
->
gpctx
);
glXDestroyPbuffer
(
p_display
,
OS_DATA
->
gpbuf
);
glXDestroyContext
(
p_display
,
OS_DATA
->
gwctx
);
glXDestroyWindow
(
p_display
,
OS_DATA
->
gwnd
);
XDestroyWindow
(
p_display
,
OS_DATA
->
wnd
);
XCloseDisplay
(
p_display
);
}
void
CreateWindow
(
galaktos_thread_t
*
p_thread
,
XVisualInfo
*
p_vi
,
int
i_width
,
int
i_height
,
int
b_fullscreen
)
{
{
Display
*
p_display
;
Display
*
p_display
;
XSetWindowAttributes
xattr
;
XSetWindowAttributes
xattr
;
Window
wnd
;
Window
wnd
;
Colormap
cm
;
XSizeHints
*
p_size_hints
;
XSizeHints
*
p_size_hints
;
Atom
prop
;
Atom
prop
;
mwmhints_t
mwmhints
;
mwmhints_t
mwmhints
;
p_display
=
OS_DATA
->
p_display
;
p_display
=
OS_DATA
->
p_display
;
/* Create a colormap */
cm
=
XCreateColormap
(
p_display
,
RootWindow
(
p_display
,
p_vi
->
screen
),
p_vi
->
visual
,
AllocNone
);
/* Create the window */
/* Create the window */
xattr
.
background_pixel
=
BlackPixel
(
p_display
,
DefaultScreen
(
p_display
)
);
xattr
.
background_pixel
=
BlackPixel
(
p_display
,
DefaultScreen
(
p_display
)
);
xattr
.
border_pixel
=
0
;
xattr
.
border_pixel
=
0
;
xattr
.
colormap
=
cm
;
OS_DATA
->
wnd
=
wnd
=
XCreateWindow
(
p_display
,
DefaultRootWindow
(
p_display
),
OS_DATA
->
wnd
=
wnd
=
XCreateWindow
(
p_display
,
DefaultRootWindow
(
p_display
),
0
,
0
,
i_width
,
i_height
,
0
,
p_vi
->
depth
,
InputOutput
,
p_vi
->
visual
,
0
,
0
,
p_thread
->
i_width
,
p_thread
->
i_height
,
0
,
p_vi
->
depth
,
CWBackPixel
|
CWBorderPixel
,
&
xattr
);
InputOutput
,
p_vi
->
visual
,
CWBackPixel
|
CWBorderPixel
|
CWColormap
,
&
xattr
);
/* Allow the window to be deleted by the window manager */
/* Allow the window to be deleted by the window manager */
OS_DATA
->
wm_delete
=
XInternAtom
(
p_display
,
"WM_DELETE_WINDOW"
,
False
);
OS_DATA
->
wm_delete
=
XInternAtom
(
p_display
,
"WM_DELETE_WINDOW"
,
False
);
XSetWMProtocols
(
p_display
,
wnd
,
&
OS_DATA
->
wm_delete
,
1
);
XSetWMProtocols
(
p_display
,
wnd
,
&
OS_DATA
->
wm_delete
,
1
);
if
(
b_fullscreen
)
if
(
p_thread
->
b_fullscreen
)
{
{
mwmhints
.
flags
=
MWM_HINTS_DECORATIONS
;
mwmhints
.
flags
=
MWM_HINTS_DECORATIONS
;
mwmhints
.
decorations
=
False
;
mwmhints
.
decorations
=
False
;
...
@@ -331,10 +390,10 @@ void CreateWindow( galaktos_thread_t *p_thread, XVisualInfo *p_vi,
...
@@ -331,10 +390,10 @@ void CreateWindow( galaktos_thread_t *p_thread, XVisualInfo *p_vi,
/* Prevent the window from being resized */
/* Prevent the window from being resized */
p_size_hints
=
XAllocSizeHints
();
p_size_hints
=
XAllocSizeHints
();
p_size_hints
->
flags
=
PMinSize
|
PMaxSize
;
p_size_hints
->
flags
=
PMinSize
|
PMaxSize
;
p_size_hints
->
min_width
=
i_width
;
p_size_hints
->
min_width
=
p_thread
->
i_width
;
p_size_hints
->
min_height
=
i_height
;
p_size_hints
->
min_height
=
p_thread
->
i_height
;
p_size_hints
->
max_width
=
i_width
;
p_size_hints
->
max_width
=
p_thread
->
i_width
;
p_size_hints
->
max_height
=
i_height
;
p_size_hints
->
max_height
=
p_thread
->
i_height
;
XSetWMNormalHints
(
p_display
,
wnd
,
p_size_hints
);
XSetWMNormalHints
(
p_display
,
wnd
,
p_size_hints
);
XFree
(
p_size_hints
);
XFree
(
p_size_hints
);
}
}
...
...
modules/visualization/galaktos/glx.h
View file @
1e4bfd0d
...
@@ -26,8 +26,7 @@
...
@@ -26,8 +26,7 @@
#include "plugin.h"
#include "plugin.h"
int
galaktos_glx_init
(
galaktos_thread_t
*
p_thread
,
int
i_width
,
int
i_height
,
int
galaktos_glx_init
(
galaktos_thread_t
*
p_thread
);
int
b_fullscreen
);
void
galaktos_glx_done
(
galaktos_thread_t
*
p_thread
);
void
galaktos_glx_done
(
galaktos_thread_t
*
p_thread
);
int
galaktos_glx_handle_events
(
galaktos_thread_t
*
p_thread
);
int
galaktos_glx_handle_events
(
galaktos_thread_t
*
p_thread
);
void
galaktos_glx_activate_pbuffer
(
galaktos_thread_t
*
p_thread
);
void
galaktos_glx_activate_pbuffer
(
galaktos_thread_t
*
p_thread
);
...
...
modules/visualization/galaktos/main.c
View file @
1e4bfd0d
...
@@ -127,8 +127,8 @@ int galaktos_init( galaktos_thread_t *p_thread )
...
@@ -127,8 +127,8 @@ int galaktos_init( galaktos_thread_t *p_thread )
initPresetLoader
();
initPresetLoader
();
/* Load default preset directory */
/* Load default preset directory */
//
loadPresetDir("/home/cyril/.vlc/galaktos");
loadPresetDir
(
"/home/cyril/.vlc/galaktos"
);
loadPresetDir
(
"/etc/projectM/presets"
);
//
loadPresetDir("/etc/projectM/presets");
initPCM
(
maxsamples
);
initPCM
(
maxsamples
);
initBeatDetect
();
initBeatDetect
();
...
...
modules/visualization/galaktos/plugin.c
View file @
1e4bfd0d
...
@@ -113,7 +113,10 @@ static int Open( vlc_object_t *p_this )
...
@@ -113,7 +113,10 @@ static int Open( vlc_object_t *p_this )
p_thread
->
i_cur_sample
=
0
;
p_thread
->
i_cur_sample
=
0
;
bzero
(
p_thread
->
p_data
,
2
*
2
*
512
);
bzero
(
p_thread
->
p_data
,
2
*
2
*
512
);
galaktos_glx_init
(
p_thread
,
600
,
600
,
0
);
p_thread
->
i_width
=
600
;
p_thread
->
i_height
=
600
;
p_thread
->
b_fullscreen
=
0
;
galaktos_glx_init
(
p_thread
);
galaktos_init
(
p_thread
);
galaktos_init
(
p_thread
);
p_thread
->
i_channels
=
aout_FormatNbChannels
(
&
p_filter
->
input
);
p_thread
->
i_channels
=
aout_FormatNbChannels
(
&
p_filter
->
input
);
...
@@ -199,10 +202,9 @@ static void Thread( vlc_object_t *p_this )
...
@@ -199,10 +202,9 @@ static void Thread( vlc_object_t *p_this )
int
timed
=
0
;
int
timed
=
0
;
int
timestart
=
0
;
int
timestart
=
0
;
int
mspf
=
0
;
int
mspf
=
0
;
int
w
=
600
,
h
=
600
;
galaktos_glx_activate_window
(
p_thread
);
galaktos_glx_activate_window
(
p_thread
);
setup_opengl
(
w
,
h
);
setup_opengl
(
p_thread
->
i_width
,
p_thread
->
i_height
);
CreateRenderTarget
(
512
,
&
RenderTargetTextureID
,
NULL
);
CreateRenderTarget
(
512
,
&
RenderTargetTextureID
,
NULL
);
timestart
=
mdate
()
/
1000
;
timestart
=
mdate
()
/
1000
;
...
...
modules/visualization/galaktos/plugin.h
View file @
1e4bfd0d
...
@@ -35,9 +35,15 @@ typedef struct
...
@@ -35,9 +35,15 @@ typedef struct
char
*
psz_title
;
char
*
psz_title
;
/* Window properties */
int
i_width
;
int
i_height
;
int
b_fullscreen
;
/* Audio properties */
/* Audio properties */
int
i_channels
;
int
i_channels
;
/* Audio buffer */
int16_t
p_data
[
2
][
512
];
int16_t
p_data
[
2
][
512
];
int
i_cur_sample
;
int
i_cur_sample
;
...
...
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