Browse Source

build: drop support for SDL v1.

The only reason we had to keep this was for emscripten builds. We can
now use SDL v2 using “emconfigure ./configure CFLAGS="-s USE_SDL=2” and
a few additional flags.

SDL_Mixer v2 is not available in emscripten packages but either it will
be added at some time, or I will get rid of it altogether. An alternate
solution could be this code snippet I found:

    cd SDL2_mixer
    emconfigure ./configure --prefix=$(pwd)/dist --enable-music-ogg --disable-music-ogg-shared CFLAGS="-s USE_VORBIS=1"
    emmake make install
legacy
Sam Hocevar 6 years ago
parent
commit
a18ccb3987
8 changed files with 62 additions and 216 deletions
  1. +2
    -79
      build/autotools/m4/lol-sdl.m4
  2. +1
    -1
      build/lol-build
  3. +3
    -3
      src/application/application.cpp
  4. +3
    -3
      src/eglapp.cpp
  5. +1
    -1
      src/lol/engine-internal.h
  6. +1
    -1
      src/lol/engine.h
  7. +4
    -21
      src/platform/sdl/sdlapp.cpp
  8. +47
    -107
      src/platform/sdl/sdlinput.cpp

+ 2
- 79
build/autotools/m4/lol-sdl.m4 View File

@@ -16,7 +16,6 @@ dnl
AC_DEFUN([LOL_AC_CHECK_SDL],
[
ac_cv_my_have_sdl="no"
ac_cv_my_have_old_sdl="no"
ac_cv_my_have_sdl_image="no"
ac_cv_my_have_sdl_mixer="no"
if test "${enable_sdl}" != "no"; then
@@ -25,7 +24,6 @@ fi
AM_CONDITIONAL(LOL_USE_SDL, test "${ac_cv_my_have_sdl}" != "no")
AM_CONDITIONAL(LOL_USE_SDL_MIXER, test "${ac_cv_my_have_sdl_mixer}" != "no")
AM_CONDITIONAL(LOL_USE_SDL_IMAGE, test "${ac_cv_my_have_sdl_image}" != "no")
AM_CONDITIONAL(LOL_USE_OLD_SDL, test "${ac_cv_my_have_old_sdl}" != "no")
])

# LOL_AC_CHECK_SDL_INNER()
@@ -36,15 +34,13 @@ dnl Find which version of SDL to use (always required on Linux or Win32)
dnl
dnl Defined C/C++ macros:
dnl LOL_USE_SDL -- whether SDL v2 was found
dnl LOL_USE_OLD_SDL -- whether SDL v1 was found
dnl LOL_USE_SDL_IMAGE -- whether SDL_image (v1 or v2) was found
dnl LOL_USE_SDL_MIXER -- whether SDL_mixer (v1 or v2) was found
dnl LOL_USE_SDL_IMAGE -- whether SDL_image was found
dnl LOL_USE_SDL_MIXER -- whether SDL_mixer was found
dnl HAVE_SDL_H -- whether to include <SDL.h>
dnl HAVE_SDL_SDL_H -- whether to include <SDL/SDL.h>
dnl HAVE_SDL2_SDL_H -- whether to include <SDL2/SDL.h>
dnl Generated automake conditionals:
dnl LOL_USE_SDL -- whether SDL v2 was found
dnl LOL_USE_OLD_SDL -- whether SDL v1 was found
dnl LOL_USE_SDL_IMAGE -- whether SDL_image was found
dnl LOL_USE_SDL_MIXER -- whether SDL_mixer was found
dnl Generated shell variables:
@@ -105,75 +101,6 @@ if test "x${ac_cv_my_have_sdl}" = xno; then
fi


dnl Then, try the proper pkg-config check for SDL 1.x

if test "x${ac_cv_my_have_sdl}" = xno \
-a "x${ac_cv_my_have_old_sdl}" = xno; then
PKG_CHECK_MODULES(SDL, sdl,
[ac_cv_my_have_old_sdl="yes"
PKG_CHECK_MODULES(SDLMIXER, SDL_mixer,
[ac_cv_my_have_sdl_mixer="yes"
AC_DEFINE(HAVE_SDL_MIXER_H, 1, Define to 1 to use SDL_mixer.h)],
[:])
PKG_CHECK_MODULES(SDLIMAGE, SDL_image,
[ac_cv_my_have_sdl_image="yes"
AC_DEFINE(HAVE_SDL_IMAGE_H, 1, Define to 1 to use SDL_image.h)],
[:])
SDL_CFLAGS="${SDL_CFLAGS} ${SDLMIXER_CFLAGS} ${SDLIMAGE_CFLAGS}"
SDL_LIBS="${SDL_LIBS} ${SDLMIXER_LIBS} ${SDLIMAGE_LIBS}"
AC_DEFINE(HAVE_SDL_H, 1, Define to 1 to use SDL.h)],
[:])
fi


dnl Then the old sdl-config method

if test "x${ac_cv_my_have_sdl}" = xno \
-a "x${ac_cv_my_have_old_sdl}" = xno \
-a "x${cross_compiling}" != xyes; then
AC_PATH_PROG(SDL_CONFIG, sdl-config, no)
if test "${SDL_CONFIG}" != "no" && "${SDL_CONFIG}" --version >/dev/null; then
ac_cv_my_have_old_sdl="yes"
SDL_CFLAGS="${SDL_CFLAGS} `${SDL_CONFIG} --cflags`"
SDL_LIBS="${SDL_LIBS} `${SDL_CONFIG} --libs`"
AC_DEFINE(HAVE_SDL_H, 1, Define to 1 to use SDL.h)
fi
fi


dnl Finally, try direct inclusion

if test "x${ac_cv_my_have_sdl}" = xno \
-a "x${ac_cv_my_have_old_sdl}" = xno; then
save_CPPFLAGS="${CPPFLAGS}"
save_LIBS="${LIBS}"
CPPFLAGS="${CPPFLAGS} ${SDL_CFLAGS}"
LIBS="${LIBS} ${SDL_LIBS}"
AC_CHECK_HEADERS(SDL.h SDL/SDL.h, [ac_cv_my_have_old_sdl="yes"])
if test "x${ac_cv_my_have_old_sdl}" != xno; then
AC_CHECK_HEADERS(SDL_mixer.h SDL/SDL_mixer.h,
[ac_cv_my_have_sdl_mixer="yes"])
AC_CHECK_HEADERS(SDL_image.h SDL/SDL_image.h,
[ac_cv_my_have_sdl_image="yes"])
AC_CHECK_LIB(SDL, main,
[SDL_LIBS="${SDL_LIBS} -lSDL"],
[ac_cv_my_have_old_sdl="no"])
AC_CHECK_LIB(SDLmain, main,
[SDL_LIBS="${SDL_LIBS} -lSDLmain -lSDL"])
AC_CHECK_LIB(SDL_mixer, main,
[SDLMIXER_LIBS="${SDLMIXER_LIBS} -lSDL_mixer"],
[ac_cv_my_have_sdl_mixer="no"])
AC_CHECK_LIB(SDL_image, main,
[SDLIMAGE_LIBS="${SDLIMAGE_LIBS} -lSDL_image"],
[ac_cv_my_have_sdl_image="no"])
fi
SDL_CFLAGS="${SDL_CFLAGS} ${SDLMIXER_CFLAGS} ${SDLIMAGE_CFLAGS}"
SDL_LIBS="${SDL_LIBS} ${SDLMIXER_LIBS} ${SDLIMAGE_LIBS}"
CPPFLAGS="${save_CPPFLAGS}"
LIBS="${save_LIBS}"
fi


dnl Convert all this into conditionals

if test "x${ac_cv_my_have_sdl}" = xno; then
@@ -194,9 +121,5 @@ else
AC_DEFINE(LOL_USE_SDL_IMAGE, 1, Define to 1 to use SDL_image)
fi

if test "x${ac_cv_my_have_old_sdl}" != xno; then
AC_DEFINE(LOL_USE_OLD_SDL, 1, Define to 1 to use SDL)
fi

]) # LOL_AC_CHECK_SDL_INNER


+ 1
- 1
build/lol-build View File

@@ -276,7 +276,7 @@ configure()
;;
web-*)
# We use --enable-release otherwise builds are really too slow
do_configure --enable-release $HOSTFLAGS $BUILDFLAGS CC=emcc CXX=em++ AR=emar RANLIB=emranlib PKG_CONFIG=/bin/false SDL_CONFIG=/bin/false ac_cv_exeext=".${platform##web-}"
do_configure --enable-release $HOSTFLAGS $BUILDFLAGS CC=emcc CXX=em++ AR=emar RANLIB=emranlib PKG_CONFIG=/bin/false SDL_CONFIG=/bin/false ac_cv_exeext=".${platform##web-}" CPPFLAGS="-s USE_SDL=2" CXXFLAGS="-s USE_SDL=2" CFLAGS="-s USE_SDL=2"
;;
*)
PATH="$PATH" do_configure CFLAGS="$CXXFLAGS" CXXFLAGS="$CXXFLAGS"


+ 3
- 3
src/application/application.cpp View File

@@ -22,7 +22,7 @@
# include "platform/nacl/nacl-app.h"
#elif __ANDROID__
# include "platform/android/androidapp.h"
#elif LOL_USE_SDL || LOL_USE_OLD_SDL
#elif LOL_USE_SDL
# include "platform/sdl/sdlapp.h"
# include "platform/sdl/sdlinput.h"
#elif HAVE_GLES_2X
@@ -89,7 +89,7 @@ protected:
//NOT HANDLED YET
#elif __ANDROID__
//NOT HANDLED YET
#elif LOL_USE_SDL || LOL_USE_OLD_SDL
#elif LOL_USE_SDL
SdlAppDisplay display;
#elif HAVE_GLES_2X
/* FIXME: this macro is only deactivated if we include "lolgl.h" */
@@ -149,7 +149,7 @@ class ApplicationData
NaClApp app;
#elif __ANDROID__
AndroidApp app;
#elif LOL_USE_SDL || LOL_USE_OLD_SDL
#elif LOL_USE_SDL
SdlApp app;
#elif HAVE_GLES_2X
/* FIXME: this macro is only deactivated if we include "lolgl.h" */


+ 3
- 3
src/eglapp.cpp View File

@@ -24,7 +24,7 @@
# include <EGL/eglext.h>
#endif

#if LOL_USE_SDL || LOL_USE_OLD_SDL
#if LOL_USE_SDL
# if HAVE_SDL2_SDL_H
# include <SDL2/SDL.h>
# elif HAVE_SDL_SDL_H
@@ -36,7 +36,7 @@

#include "lolgl.h"
#include "eglapp.h"
#if LOL_USE_SDL || LOL_USE_OLD_SDL
#if LOL_USE_SDL
# include "platform/sdl/sdlinput.h"
#endif

@@ -251,7 +251,7 @@ EglApp::EglApp(char const *title, ivec2 res, float fps) :
data->screen_size = uvec2(gwa.width, gwa.height);
# endif

# if LOL_USE_SDL || LOL_USE_OLD_SDL
# if LOL_USE_SDL
new SdlInput(res.x, res.y, data->screen_size.x, data->screen_size.y);
# endif



+ 1
- 1
src/lol/engine-internal.h View File

@@ -30,7 +30,7 @@
#endif

/* If using SDL on Windows or OS X, let it override main() */
#if (LOL_USE_SDL || LOL_USE_OLD_SDL) && (_WIN32 || __APPLE__)
#if LOL_USE_SDL && (_WIN32 || __APPLE__)
# include <SDL_main.h>
#endif



+ 1
- 1
src/lol/engine.h View File

@@ -25,7 +25,7 @@
#endif

/* If using SDL on Windows or OS X, let it override main() */
#if (LOL_USE_SDL || LOL_USE_OLD_SDL) && (_WIN32 || __APPLE__)
#if LOL_USE_SDL && (_WIN32 || __APPLE__)
# include <SDL_main.h>
#endif



+ 4
- 21
src/platform/sdl/sdlapp.cpp View File

@@ -12,7 +12,7 @@

#include <lol/engine-internal.h>

#if LOL_USE_SDL || LOL_USE_OLD_SDL
#if LOL_USE_SDL
# if HAVE_SDL2_SDL_H
# include <SDL2/SDL.h>
# elif HAVE_SDL_SDL_H
@@ -43,8 +43,6 @@ private:
#if LOL_USE_SDL
SDL_Window *m_window;
SDL_GLContext m_glcontext;
#elif LOL_USE_OLD_SDL
SDL_Surface *m_window;
#endif
};

@@ -54,7 +52,7 @@ private:
SdlAppDisplay::SdlAppDisplay(char const *title, ivec2 res)
: data(new SdlAppDisplayData())
{
#if LOL_USE_SDL || LOL_USE_OLD_SDL
#if LOL_USE_SDL
ivec2 window_size = res;
ivec2 screen_size = res;

@@ -123,9 +121,6 @@ SdlAppDisplay::~SdlAppDisplay()
SDL_GL_DeleteContext(data->m_glcontext);
SDL_DestroyWindow(data->m_window);
}
#elif LOL_USE_OLD_SDL
if (data->m_window)
SDL_FreeSurface(data->m_window);
#endif

delete data;
@@ -135,16 +130,12 @@ void SdlAppDisplay::SetResolution(ivec2 resolution)
{
#if LOL_USE_SDL
SDL_SetWindowSize(data->m_window, resolution.x, resolution.y);
#elif LOL_USE_OLD_SDL
//Not implemented
#endif
}
void SdlAppDisplay::SetPosition(ivec2 position)
{
#if LOL_USE_SDL
SDL_SetWindowPosition(data->m_window, position.x, position.y);
#elif LOL_USE_OLD_SDL
//Not implemented
#endif
}

@@ -160,8 +151,6 @@ void SdlAppDisplay::Disable()
{
#if LOL_USE_SDL
SDL_GL_SwapWindow(data->m_window);
#elif LOL_USE_OLD_SDL
SDL_GL_SwapBuffers();
#endif
}

@@ -175,8 +164,6 @@ const char* SceneDisplay::GetPhysicalName(int index)
{
return SDL_GetDisplayName(index);
}
#elif LOL_USE_OLD_SDL
// Not implemented
#endif

/*
@@ -190,8 +177,6 @@ private:
#if LOL_USE_SDL
SDL_Window *m_window;
SDL_GLContext m_glcontext;
#elif LOL_USE_OLD_SDL
SDL_Surface *m_window;
#endif
};

@@ -202,7 +187,7 @@ SdlApp::SdlApp(char const *title, ivec2 res, float fps) :
data(new SdlAppData())
{
UNUSED(title);
#if LOL_USE_SDL || LOL_USE_OLD_SDL
#if LOL_USE_SDL
ivec2 window_size = res;
ivec2 screen_size = res;

@@ -223,7 +208,7 @@ SdlApp::SdlApp(char const *title, ivec2 res, float fps) :

void SdlApp::ShowPointer(bool show)
{
#if LOL_USE_SDL || LOL_USE_OLD_SDL
#if LOL_USE_SDL
SDL_ShowCursor(show ? 1 : 0);
#endif
}
@@ -238,8 +223,6 @@ SdlApp::~SdlApp()
{
#if LOL_USE_SDL
SDL_Quit();
#elif LOL_USE_OLD_SDL
SDL_Quit();
#endif
delete data;
}


+ 47
- 107
src/platform/sdl/sdlinput.cpp View File

@@ -12,7 +12,7 @@

#include <lol/engine-internal.h>

#if LOL_USE_SDL || LOL_USE_OLD_SDL
#if LOL_USE_SDL
# if HAVE_SDL2_SDL_H
# include <SDL2/SDL.h>
# elif HAVE_SDL_SDL_H
@@ -39,65 +39,52 @@
namespace lol
{

#if LOL_USE_OLD_SDL
/* Quick and dirty for now... This is deprecated anyway. */
static int sdl12_to_scancode(int ch, int sc)
//-------------------------------------------------------------------------
#define _SC(id, str, name) static const uint16_t SDLOL_##name = id;
#include "input/keys.h"
//-------------------------------------------------------------------------
static bool ScanCodeIsValid(int sc)
{
if (ch >= 'a' && ch <= 'z')
ch = ch - 'a' + 'A';

# define _SC(id, str, name) if (ch == str[0]) return id;
# include "input/keys.h"

return 0;
}
#else
//-------------------------------------------------------------------------
# define _SC(id, str, name) static const uint16_t SDLOL_##name = id;
# include "input/keys.h"
//-------------------------------------------------------------------------
static bool ScanCodeIsValid(int sc)
switch (sc)
{
switch (sc)
{
# define _SC(id, str, name) \
case id: return true;
# include "input/keys.h"
default: return false;
}
return false;
#define _SC(id, str, name) \
case id: return true;
#include "input/keys.h"
default: return false;
}
//-------------------------------------------------------------------------
/* DEBUG STUFF
static String ScanCodeToText(int sc)
return false;
}

//-------------------------------------------------------------------------
/* DEBUG STUFF
static String ScanCodeToText(int sc)
{
switch (sc)
{
switch (sc)
{
# define _SC(id, str, name) \
case id: return String(str);
# include "input/keys.h"
default:
msg::error("ScanCodeToText unknown scancode %0d\n", sc);
}
return String();
#define _SC(id, str, name) \
case id: return String(str);
#include "input/keys.h"
default:
msg::error("ScanCodeToText unknown scancode %0d\n", sc);
}
*/
//-------------------------------------------------------------------------
/* DEBUG STUFF
static String ScanCodeToName(int sc)
return String();
}
*/
//-------------------------------------------------------------------------
/* DEBUG STUFF
static String ScanCodeToName(int sc)
{
switch (sc)
{
switch (sc)
{
# define _SC(id, str, name) \
#define _SC(id, str, name) \
case id: return String(#name);
# include "input/keys.h"
default:
msg::error("ScanCodeToText unknown scancode %0d\n", sc);
}
return String();
#include "input/keys.h"
default:
msg::error("ScanCodeToText unknown scancode %0d\n", sc);
}
*/
#endif
return String();
}
*/

/*
* SDL Input implementation class
@@ -123,7 +110,7 @@ private:
m_tick_in_draw_thread(false)
{ }

#if LOL_USE_SDL || LOL_USE_OLD_SDL
#if LOL_USE_SDL
array<SDL_Joystick *, InputDeviceInternal *> m_joysticks;
InputDeviceInternal *m_mouse;
InputDeviceInternal *m_keyboard;
@@ -148,19 +135,14 @@ SdlInput::SdlInput(int app_w, int app_h, int screen_w, int screen_h)
m_data->m_tick_in_draw_thread = true;
#endif

#if LOL_USE_OLD_SDL
/* Enable Unicode translation of keyboard events */
SDL_EnableUNICODE(1);
#endif

#if LOL_USE_SDL || LOL_USE_OLD_SDL
#if LOL_USE_SDL
SDL_Init(SDL_INIT_TIMER | SDL_INIT_JOYSTICK);
#endif

m_data->m_keyboard = InputDeviceInternal::CreateStandardKeyboard();
m_data->m_mouse = InputDeviceInternal::CreateStandardMouse();

#if LOL_USE_SDL || LOL_USE_OLD_SDL
#if LOL_USE_SDL
# if !EMSCRIPTEN
# if SDL_FORCE_POLL_JOYSTICK
SDL_JoystickEventState(SDL_QUERY);
@@ -180,8 +162,6 @@ SdlInput::SdlInput(int app_w, int app_h, int screen_w, int screen_h)
* it won't think there is only one trigger axis. */
# if LOL_USE_SDL
char const *name = SDL_JoystickName(sdlstick);
# elif LOL_USE_OLD_SDL
char const *name = SDL_JoystickName(i);
# endif
if (strstr(name, "HDAPS")
# if LOL_USE_XINPUT
@@ -210,7 +190,7 @@ SdlInput::SdlInput(int app_w, int app_h, int screen_w, int screen_h)

SdlInput::~SdlInput()
{
#if (LOL_USE_SDL || LOL_USE_OLD_SDL) && !EMSCRIPTEN
#if LOL_USE_SDL && !EMSCRIPTEN
/* Unregister all the joysticks we added */
while (m_data->m_joysticks.count())
{
@@ -240,7 +220,7 @@ void SdlInput::TickDraw(float seconds, Scene &scene)

void SdlInputData::Tick(float seconds)
{
#if LOL_USE_SDL || LOL_USE_OLD_SDL
#if LOL_USE_SDL
/* FIXME: maybe we should make use of this? */
UNUSED(seconds);

@@ -258,12 +238,10 @@ void SdlInputData::Tick(float seconds)

m_mouse->SetAxis(4, 0);

# if !LOL_USE_OLD_SDL
if (m_keyboard->IsTextInputActive())
SDL_StartTextInput();
else
SDL_StopTextInput();
# endif

/* Handle keyboard and WM events */
SDL_Event event;
@@ -277,12 +255,7 @@ void SdlInputData::Tick(float seconds)

case SDL_KEYDOWN:
case SDL_KEYUP:
# if LOL_USE_OLD_SDL
switch (int sc = sdl12_to_scancode(event.key.keysym.sym,
event.key.keysym.scancode))
# else
switch (int sc = event.key.keysym.scancode)
# endif
{
//Lock management
case SDLOL_CapsLock:
@@ -314,10 +287,6 @@ void SdlInputData::Tick(float seconds)
}
# endif
default:
# if LOL_USE_OLD_SDL
m_keyboard->SetKey(sc ? sc : event.key.keysym.scancode,
event.type == SDL_KEYDOWN);
# else
if (ScanCodeIsValid(sc))
{
//Set key updates the corresponding key
@@ -334,27 +303,15 @@ void SdlInputData::Tick(float seconds)
msg::error("unknown keypress (sym 0x%02x, scancode %0d)\n",
event.key.keysym.sym, event.key.keysym.scancode);
*/
# endif
}
break;

# if !LOL_USE_OLD_SDL
//case SDL_TEXTEDITING: //TODO: handle that ?
case SDL_TEXTINPUT:
m_keyboard->AddText(event.text.text);
break;

# endif

# if LOL_USE_OLD_SDL
case SDL_MOUSEBUTTONDOWN:
case SDL_MOUSEBUTTONUP:
if (event.button.button != SDL_BUTTON_WHEELUP && event.button.button != SDL_BUTTON_WHEELDOWN)
m_mouse->SetKey(event.button.button - 1, event.type == SDL_MOUSEBUTTONDOWN);
else
m_mouse->SetAxis(4, (event.button.button != SDL_BUTTON_WHEELUP) ? (1) : (-1));
break;
# else
case SDL_MOUSEBUTTONDOWN:
case SDL_MOUSEBUTTONUP:
//event.button.which
@@ -378,7 +335,6 @@ void SdlInputData::Tick(float seconds)
}
break;
}
# endif

# if !SDL_FORCE_POLL_JOYSTICK
case SDL_JOYAXISMOTION:
@@ -400,8 +356,6 @@ void SdlInputData::Tick(float seconds)
m_mousecapture = InputDeviceInternal::GetMouseCapture();
# if LOL_USE_SDL
SDL_SetRelativeMouseMode(m_mousecapture ? SDL_TRUE : SDL_FALSE);
# elif LOL_USE_OLD_SDL
SDL_WM_GrabInput(m_mousecapture ? SDL_GRAB_ON : SDL_GRAB_OFF);
# endif
mouse = (ivec2)m_app / 2;
SdlInputData::SetMousePos(mouse);
@@ -424,14 +378,6 @@ void SdlInputData::Tick(float seconds)
m_mouse->SetAxis(3,-(mouse.y - vprevmouse.y));
}

//Mouse is focused, Validate the InScreen Key
//Hardcoded 3, not very nice.
# if !EMSCRIPTEN && LOL_USE_OLD_SDL
m_mouse->SetKey(3, !!(SDL_GetAppState() & SDL_APPMOUSEFOCUS));
# else
//Handled in PollEvent
# endif

if (m_mousecapture)
{
mouse = ivec2(m_app * .5f);
@@ -450,10 +396,7 @@ ivec2 SdlInputData::GetMousePos()
{
ivec2 ret(-1, -1);

#if LOL_USE_SDL || LOL_USE_OLD_SDL
# if !EMSCRIPTEN && LOL_USE_OLD_SDL
if (SDL_GetAppState() & SDL_APPMOUSEFOCUS)
# endif
#if LOL_USE_SDL
{
SDL_GetMouseState(&ret.x, &ret.y);
ret.y = Video::GetSize().y - 1 - ret.y;
@@ -464,13 +407,10 @@ ivec2 SdlInputData::GetMousePos()

void SdlInputData::SetMousePos(ivec2 position)
{
UNUSED(position);
#if LOL_USE_SDL
// FIXME: how do I warped mouse?
UNUSED(position);
#elif LOL_USE_OLD_SDL
SDL_WarpMouse((uint16_t)position.x, (uint16_t)position.y);
#else
UNUSED(position);
//SDL_WarpMouse((uint16_t)position.x, (uint16_t)position.y);
#endif
}



Loading…
Cancel
Save