/* * Copyright (c) 2012 Sacha Refshauge * */ // Qt 4.7+ / 5.0+ implementation of the framework. // Currently supports: Android, Symbian, Blackberry, Maemo/Meego, Linux, Windows, Mac OSX #include #include #include #include #include #include #include #if QT_VERSION > QT_VERSION_CHECK(5, 0, 0) #include #endif #ifdef __SYMBIAN32__ #include #include #include "SymbianMediaKeys.h" #endif #ifdef QT_HAS_SDL #include "SDL/SDLJoystick.h" #include "SDL_audio.h" #endif #include "QtMain.h" #include "math/math_util.h" #include InputState* input_state; #ifdef QT_HAS_SDL extern void mixaudio(void *userdata, Uint8 *stream, int len) { NativeMix((short *)stream, len / 4); } #endif std::string System_GetProperty(SystemProperty prop) { switch (prop) { case SYSPROP_NAME: #ifdef __SYMBIAN32__ return "Qt:Symbian"; #elif defined(BLACKBERRY) return "Qt:Blackberry"; #elif defined(MAEMO) return "Qt:Maemo"; #elif defined(ANDROID) return "Qt:Android"; #elif defined(Q_OS_LINUX) return "Qt:Linux"; #elif defined(_WIN32) return "Qt:Windows"; #elif defined(Q_OS_MAC) return "Qt:Mac"; #else return "Qt"; #endif case SYSPROP_LANGREGION: return QLocale::system().name().toStdString(); default: return ""; } } void System_SendMessage(const char *command, const char *parameter) { if (!strcmp(command, "finish")) { qApp->exit(0); } } bool System_InputBoxGetString(const char *title, const char *defaultValue, char *outValue, size_t outLength) { QString text = emugl->InputBoxGetQString(QString(title), QString(defaultValue)); if (text.isEmpty()) return false; strcpy(outValue, text.toStdString().c_str()); return true; } void Vibrate(int length_ms) { if (length_ms == -1 || length_ms == -3) length_ms = 50; else if (length_ms == -2) length_ms = 25; // Symbian only for now #if defined(__SYMBIAN32__) QFeedbackHapticsEffect effect; effect.setIntensity(0.8); effect.setDuration(length_ms); effect.start(); #endif } void LaunchBrowser(const char *url) { QDesktopServices::openUrl(QUrl(url)); } float CalculateDPIScale() { // Sane default rather than check DPI #ifdef __SYMBIAN32__ return 1.4f; #elif defined(USING_GLES2) return 1.2f; #else return 1.0f; #endif } static int mainInternal(QApplication &a) { #ifdef MOBILE_DEVICE emugl = new MainUI(); emugl->resize(pixel_xres, pixel_yres); emugl->showFullScreen(); #endif EnableFZ(); #ifdef __SYMBIAN32__ // Disable screensaver QScopedPointer ssObject(new QSystemScreenSaver(emugl)); ssObject->setScreenSaverInhibit(); QScopedPointer mediakeys(new SymbianMediaKeys()); #endif #ifdef QT_HAS_SDL SDLJoystick joy(true); joy.startEventLoop(); SDL_Init(SDL_INIT_AUDIO); SDL_AudioSpec fmt, ret_fmt; memset(&fmt, 0, sizeof(fmt)); fmt.freq = 44100; fmt.format = AUDIO_S16; fmt.channels = 2; fmt.samples = 2048; fmt.callback = &mixaudio; fmt.userdata = (void *)0; if (SDL_OpenAudio(&fmt, &ret_fmt) < 0) { ELOG("Failed to open audio: %s", SDL_GetError()); } else { if (ret_fmt.samples != fmt.samples) // Notify, but still use it ELOG("Output audio samples: %d (requested: %d)", ret_fmt.samples, fmt.samples); if (ret_fmt.freq != fmt.freq || ret_fmt.format != fmt.format || ret_fmt.channels != fmt.channels) { ELOG("Sound buffer format does not match requested format."); ELOG("Output audio freq: %d (requested: %d)", ret_fmt.freq, fmt.freq); ELOG("Output audio format: %d (requested: %d)", ret_fmt.format, fmt.format); ELOG("Output audio channels: %d (requested: %d)", ret_fmt.channels, fmt.channels); ELOG("Provided output format does not match requirement, turning audio off"); SDL_CloseAudio(); } } // Audio must be unpaused _after_ NativeInit() SDL_PauseAudio(0); #else QScopedPointer thread(new QThread); QScopedPointer audio(new MainAudio()); audio->moveToThread(thread.data()); QObject::connect(thread.data(), SIGNAL(started()), audio.data(), SLOT(run())); thread->start(); #endif int ret = a.exec(); #ifndef QT_HAS_SDL thread->quit(); #endif return ret; } #ifndef QT_HAS_SDL Q_DECL_EXPORT #endif int main(int argc, char *argv[]) { #if defined(Q_OS_LINUX) && !defined(MAEMO) QApplication::setAttribute(Qt::AA_X11InitThreads, true); #endif QApplication a(argc, argv); QSize res = QApplication::desktop()->screenGeometry().size(); if (res.width() < res.height()) res.transpose(); pixel_xres = res.width(); pixel_yres = res.height(); g_dpi_scale = CalculateDPIScale(); dp_xres = (int)(pixel_xres * g_dpi_scale); dp_yres = (int)(pixel_yres * g_dpi_scale); net::Init(); std::string savegame_dir = "."; std::string assets_dir = "."; #if QT_VERSION > QT_VERSION_CHECK(5, 0, 0) savegame_dir = QStandardPaths::writableLocation(QStandardPaths::HomeLocation).toStdString(); assets_dir = QStandardPaths::writableLocation(QStandardPaths::DataLocation).toStdString(); #elif defined(__SYMBIAN32__) savegame_dir = "E:/PPSSPP"; assets_dir = "E:/PPSSPP"; #elif defined(BLACKBERRY) savegame_dir = "/accounts/1000/shared/misc"; assets_dir = "app/native/assets"; #elif defined(MAEMO) savegame_dir = "/home/user/MyDocs/PPSSPP"; assets_dir = "/opt/PPSSPP"; #endif savegame_dir += "/"; assets_dir += "/"; NativeInit(argc, (const char **)argv, savegame_dir.c_str(), assets_dir.c_str(), "BADCOFFEE"); int ret = mainInternal(a); #ifndef MOBILE_DEVICE exit(0); #endif NativeShutdownGraphics(); #ifdef QT_HAS_SDL SDL_PauseAudio(1); SDL_CloseAudio(); #endif NativeShutdown(); net::Shutdown(); return ret; }