diff --git a/.clang-format b/.clang-format index 1ecd79864..5c7892c40 100644 --- a/.clang-format +++ b/.clang-format @@ -62,7 +62,7 @@ IndentPPDirectives: None IndentRequiresClause: true IndentWidth: 4 IndentWrappedFunctionNames: false -InsertBraces: true +InsertBraces: false InsertNewlineAtEOF: true InsertTrailingCommas: None IntegerLiteralSeparator: @@ -101,7 +101,7 @@ PenaltyIndentedWhitespace: 0 PenaltyReturnTypeOnItsOwnLine: 60 PointerAlignment: Left PPIndentWidth: -1 -QualifierAlignment: Left +QualifierAlignment: Leave ReferenceAlignment: Pointer RemoveBracesLLVM: false RemoveParentheses: Leave @@ -148,6 +148,5 @@ SpacesInLineCommentPrefix: SpacesInParens: Never SpacesInSquareBrackets: false Standard: Latest -TabWidth: 8 UseTab: Never ... diff --git a/.clang-tidy b/.clang-tidy index 2bf615398..4e516575e 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -13,8 +13,6 @@ Checks: > -modernize-use-trailing-return-type, performance-*, readability-*, - WarningsAsErrors: '' -HeaderFilterRegex: '' FormatStyle: 'file' ... diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7af06bf06..125320228 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -12,4 +12,5 @@ repos: - repo: https://github.com/pre-commit/mirrors-clang-format rev: 'v19.1.4' hooks: - - id: clang-format + - id: clang-format + types_or: [c++, c] diff --git a/src/bin/apps/rv/main.cpp b/src/bin/apps/rv/main.cpp index dc1c91bef..2948dc641 100644 --- a/src/bin/apps/rv/main.cpp +++ b/src/bin/apps/rv/main.cpp @@ -1,27 +1,27 @@ //****************************************************************************** // Copyright (c) 2001-2005 Tweak Inc. All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #ifdef _MSC_VER - // - // We are targetting at least XP, (IE no windows95, etc). - // - #define WINVER 0x0501 - #define _WIN32_WINNT 0x0501 - #include - #include - #include - #include - #include - // - // NOTE: win_pthreads, which supplies implement.h, seems - // targetted at an earlier version of windows (pre-XP). If you - // include implement.h here, it won't compile. But as far as I - // can tell, it's not needed, so just leave it out. - // - // #include +// +// We are targetting at least XP, (IE no windows95, etc). +// +#define WINVER 0x0501 +#define _WIN32_WINNT 0x0501 +#include +#include +#include +#include +#include +// +// NOTE: win_pthreads, which supplies implement.h, seems +// targetted at an earlier version of windows (pre-XP). If you +// include implement.h here, it won't compile. But as far as I +// can tell, it's not needed, so just leave it out. +// +// #include #endif #ifdef PLATFORM_LINUX @@ -86,13 +86,13 @@ #include #ifndef PLATFORM_WINDOWS - #include - #include - #include +#include +#include +#include #else - #include - #include - #include +#include +#include +#include #endif #include @@ -105,7 +105,7 @@ extern const char* rv_linux_dark; // RV third party optional customization #if defined(RV_THIRD_PARTY_CUSTOMIZATION) - extern void rvThirdPartyCustomization(TwkApp::Bundle& bundle, char* licarg); +extern void rvThirdPartyCustomization(TwkApp::Bundle& bundle, char* licarg); #endif // @@ -115,10 +115,10 @@ extern const char* rv_linux_dark; #if MAJOR_VERSION == 99 #if NDEBUG -//#error ********* NO VERSION INFORMATION *********** +// #error ********* NO VERSION INFORMATION *********** #else #ifndef _MSC_VER -#warning ********* NO VERSION INFORMATION *********** +#warning********* NO VERSION INFORMATION *********** #endif #endif #endif @@ -182,17 +182,17 @@ string scarfFile(const string& fileName) return buffer.str(); } -#define EXECUTABLE_SHORT_NAME "rv" +#define EXECUTABLE_SHORT_NAME "rv" #define EXECUTABLE_SHORT_NAME_CAPS "RV" -TwkApp::QTBundle bundle(EXECUTABLE_SHORT_NAME, MAJOR_VERSION, MINOR_VERSION, REVISION_NUMBER); +TwkApp::QTBundle bundle(EXECUTABLE_SHORT_NAME, MAJOR_VERSION, MINOR_VERSION, + REVISION_NUMBER); #ifdef PLATFORM_LINUX extern "C" int XInitThreads(); #endif -int -utf8Main(int argc, char *argv[]) +int utf8Main(int argc, char* argv[]) { #ifdef PLATFORM_LINUX XInitThreads(); @@ -212,44 +212,46 @@ utf8Main(int argc, char *argv[]) const char* pythonPath = getenv("PYTHONPATH"); const char* pythonHome = getenv("PYTHONHOME"); - if (pythonPath) pythonPath = strdup(pythonPath); - if (pythonHome) pythonHome = strdup(pythonHome); - - #ifndef PLATFORM_WINDOWS - // - // Check the per-process limit on open file descriptors and - // reset the soft limit to the hard limit. - // - struct rlimit rlim; - getrlimit (RLIMIT_NOFILE, &rlim); - rlim.rlim_cur = rlim.rlim_max; - setrlimit (RLIMIT_NOFILE, &rlim); - getrlimit (RLIMIT_NOFILE, &rlim); - if (rlim.rlim_cur < rlim.rlim_max) - { - cerr << "WARNING: unable to increase open file limit above " << rlim.rlim_cur << endl; - } - #else - _setmaxstdio(2048); - #endif - - #ifdef PLATFORM_WINDOWS - // - // RV is a "GUI" app, so by default we get no output in the - // console, so "rv.exe -help" doesn't work, etc. Here we - // reattach to the starting console, so we do get that - // output. - // - HANDLE hand = GetStdHandle(STD_OUTPUT_HANDLE); - - if ( (hand == INVALID_HANDLE_VALUE || - GetFileType(hand) == FILE_TYPE_UNKNOWN) && - AttachConsole(ATTACH_PARENT_PROCESS)) - { - freopen("CON", "w", stdout); - freopen("CON", "w", stderr); - } - #endif + if (pythonPath) + pythonPath = strdup(pythonPath); + if (pythonHome) + pythonHome = strdup(pythonHome); + +#ifndef PLATFORM_WINDOWS + // + // Check the per-process limit on open file descriptors and + // reset the soft limit to the hard limit. + // + struct rlimit rlim; + getrlimit(RLIMIT_NOFILE, &rlim); + rlim.rlim_cur = rlim.rlim_max; + setrlimit(RLIMIT_NOFILE, &rlim); + getrlimit(RLIMIT_NOFILE, &rlim); + if (rlim.rlim_cur < rlim.rlim_max) + { + cerr << "WARNING: unable to increase open file limit above " + << rlim.rlim_cur << endl; + } +#else + _setmaxstdio(2048); +#endif + +#ifdef PLATFORM_WINDOWS + // + // RV is a "GUI" app, so by default we get no output in the + // console, so "rv.exe -help" doesn't work, etc. Here we + // reattach to the starting console, so we do get that + // output. + // + HANDLE hand = GetStdHandle(STD_OUTPUT_HANDLE); + + if ((hand == INVALID_HANDLE_VALUE || GetFileType(hand) == FILE_TYPE_UNKNOWN) + && AttachConsole(ATTACH_PARENT_PROCESS)) + { + freopen("CON", "w", stdout); + freopen("CON", "w", stderr); + } +#endif // // Check for a valid HOME. If we are on Windows and HOME is not set then @@ -257,22 +259,24 @@ utf8Main(int argc, char *argv[]) // if (!getenv("HOME")) { - #ifdef PLATFORM_WINDOWS - if (getenv("HOMEDRIVE") && getenv("HOMEPATH")) - { - string home = string(getenv("HOMEDRIVE")) + getenv("HOMEPATH"); - setEnvVar("HOME", home.c_str()); - cout << "INFO: Using '" << home << "' for $HOME." << endl; - } - else - #endif - { - cerr << "ERROR: $HOME is not set in the environment and is required." << endl; - exit(-1); - } +#ifdef PLATFORM_WINDOWS + if (getenv("HOMEDRIVE") && getenv("HOMEPATH")) + { + string home = string(getenv("HOMEDRIVE")) + getenv("HOMEPATH"); + setEnvVar("HOME", home.c_str()); + cout << "INFO: Using '" << home << "' for $HOME." << endl; + } + else +#endif + { + cerr + << "ERROR: $HOME is not set in the environment and is required." + << endl; + exit(-1); + } } - if(getenv("LANG")) + if (getenv("LANG")) { std::string originalLocale = getenv("LANG"); setEnvVar("ORIGINALLOCAL", originalLocale.c_str()); @@ -287,13 +291,15 @@ utf8Main(int argc, char *argv[]) TwkFB::ThreadPool::initialize(); // Qt 5.12.1 specific - // Disable Qt Quick hardware rendering because QwebEngineView conflicts with QGLWidget - setEnvVar( "QT_QUICK_BACKEND", "software"); + // Disable Qt Quick hardware rendering because QwebEngineView conflicts with + // QGLWidget + setEnvVar("QT_QUICK_BACKEND", "software"); #if defined(PLATFORM_LINUX) // Work around for Wacom Tablet issue on linux - // Note: This is a Qt 5.12.4 regression (https://bugreports.qt.io/browse/QTBUG-77826) - setEnvVar( "QT_XCB_TABLET_LEGACY_COORDINATES", "1"); + // Note: This is a Qt 5.12.4 regression + // (https://bugreports.qt.io/browse/QTBUG-77826) + setEnvVar("QT_XCB_TABLET_LEGACY_COORDINATES", "1"); #endif // Prevent crash at startup when multithreaded upload is enabled @@ -305,9 +311,10 @@ utf8Main(int argc, char *argv[]) string altPrefsPath; for (size_t i = 0; i < argc; i++) { - if (i < argc-1 && !strcmp(argv[i], "-prefsPath")) altPrefsPath = argv[i+1]; + if (i < argc - 1 && !strcmp(argv[i], "-prefsPath")) + altPrefsPath = argv[i + 1]; } - Rv::RvApplication::initializeQSettings (altPrefsPath); + Rv::RvApplication::initializeQSettings(altPrefsPath); bool noPrefs = false; bool resetPrefs = false; @@ -317,44 +324,50 @@ utf8Main(int argc, char *argv[]) // Expand any rvlink urls in argv // - vector newArgv; + vector newArgv; for (int i = 0; i < argc; ++i) { - if (0 == strncmp ("rvlink://", argv[i], 9)) + if (0 == strncmp("rvlink://", argv[i], 9)) { - Rv::RvApplication::parseURL (argv[i], newArgv); + Rv::RvApplication::parseURL(argv[i], newArgv); } - else newArgv.push_back (argv[i]); + else + newArgv.push_back(argv[i]); } argv = &(newArgv[0]); argc = newArgv.size(); for (size_t i = 0; i < argc; i++) { - if (!strcmp(argv[i], "-noPrefs")) noPrefs = true; - else if (!strcmp(argv[i], "-resetPrefs")) resetPrefs = true; + if (!strcmp(argv[i], "-noPrefs")) + noPrefs = true; + else if (!strcmp(argv[i], "-resetPrefs")) + resetPrefs = true; } for (size_t i = 0; i < argc; i++) { if (!strcmp(argv[i], "-bakeURL")) { - string url = Rv::RvApplication::bakeCommandLineURL (argc, argv); + string url = Rv::RvApplication::bakeCommandLineURL(argc, argv); cerr << "Baked URL: " << url << endl; exit(0); } if (!strcmp(argv[i], "-encodeURL")) { - string url = Rv::RvApplication::encodeCommandLineURL (argc, argv); + string url = Rv::RvApplication::encodeCommandLineURL(argc, argv); cerr << "Encoded URL: " << url << endl; exit(0); } } Rv::Options& opts = Rv::Options::sharedOptions(); - if (resetPrefs) Rv::RvPreferences::resetPreferencesFile(); - if (!noPrefs) Rv::RvPreferences::loadSettingsIntoOptions(opts); - else Rv::PackageManager::setIgnorePrefs(true); + if (resetPrefs) + Rv::RvPreferences::resetPreferencesFile(); + if (!noPrefs) + Rv::RvPreferences::loadSettingsIntoOptions(opts); + else + Rv::PackageManager::setIgnorePrefs(true); Rv::Options::manglePerSourceArgs(argv, argc); Rv::Options prefOpts = opts; @@ -366,17 +379,15 @@ utf8Main(int argc, char *argv[]) // Call the deploy functions // - TWK_DEPLOY_APP_OBJECT dobj(MAJOR_VERSION, - MINOR_VERSION, - REVISION_NUMBER, - argc, argv, - RELEASE_DESCRIPTION, + TWK_DEPLOY_APP_OBJECT dobj(MAJOR_VERSION, MINOR_VERSION, REVISION_NUMBER, + argc, argv, RELEASE_DESCRIPTION, "HEAD=" GIT_HEAD); Imf::staticInitialize(); - TwkFB::GenericIO::init(); // Initialize TwkFB::GenericIO plugins statics - TwkMovie::GenericIO::init(); // Initialize TwkMovie::GenericIO plugins statics + TwkFB::GenericIO::init(); // Initialize TwkFB::GenericIO plugins statics + TwkMovie::GenericIO::init(); // Initialize TwkMovie::GenericIO plugins + // statics IPCore::Application::cacheEnvVars(); @@ -397,29 +408,31 @@ utf8Main(int argc, char *argv[]) // Parse cmd line args // - int strictlicense = 0; - char *prefsPath = 0; + int strictlicense = 0; + char* prefsPath = 0; int sleepTime = 0; - if (arg_parse - (argc, argv, - "", "", - RV_ARG_EXAMPLES, - "", "", - RV_ARG_SEQUENCE_HELP, - "", "", - RV_ARG_SOURCE_OPTIONS(opts), - "", "", - "", ARG_SUBR(Rv::RvApplication::parseInFiles), "Input sequence patterns, images, movies, or directories ", - RV_ARG_PARSE_OPTIONS(opts), - "-strictlicense", ARG_FLAG(&strictlicense), "Exit rather than consume an RV license if no rvsolo licenses are available", - "-prefsPath %S", &prefsPath, "Alternate path to preferences directory", + if (arg_parse( + argc, argv, "", "", RV_ARG_EXAMPLES, "", "", RV_ARG_SEQUENCE_HELP, + "", "", RV_ARG_SOURCE_OPTIONS(opts), "", "", "", + ARG_SUBR(Rv::RvApplication::parseInFiles), + "Input sequence patterns, images, movies, or directories ", + RV_ARG_PARSE_OPTIONS(opts), "-strictlicense", + ARG_FLAG(&strictlicense), + "Exit rather than consume an RV license if no rvsolo licenses are " + "available", + "-prefsPath %S", &prefsPath, + "Alternate path to preferences directory", #if defined(PLATFORM_LINUX) - "-scheduler %S", &opts.schedulePolicy, "Thread scheduling policy (may require root)", - "-priorities %d %d", &opts.displayPriority, &opts.audioPriority, "Set display and audio thread priorities (may require root)", + "-scheduler %S", &opts.schedulePolicy, + "Thread scheduling policy (may require root)", "-priorities %d %d", + &opts.displayPriority, &opts.audioPriority, + "Set display and audio thread priorities (may require root)", #endif - "-sleep %d", &sleepTime, "Sleep (in seconds) before starting to allow attaching debugger", - NULL) < 0) + "-sleep %d", &sleepTime, + "Sleep (in seconds) before starting to allow attaching debugger", + NULL) + < 0) { exit(-1); } @@ -429,18 +442,21 @@ utf8Main(int argc, char *argv[]) // a traditional X11 geometry flag, which it's not, so prevent // this by switching it to "geometri" if it's in argv. // - for (int i = 0; i < argc; ++i) if (strcmp(argv[i], "-geometry") == 0) argv[i][8] = 'i'; + for (int i = 0; i < argc; ++i) + if (strcmp(argv[i], "-geometry") == 0) + argv[i][8] = 'i'; if (sleepTime > 0) { cout << "INFO: sleeping " << sleepTime << " seconds" << endl; - std::this_thread::sleep_for( std::chrono::seconds( sleepTime ) ); + std::this_thread::sleep_for(std::chrono::seconds(sleepTime)); cout << "INFO: continuing after sleep" << endl; } if (opts.showVersion) { - cout << MAJOR_VERSION << "." << MINOR_VERSION << "." << REVISION_NUMBER << endl; + cout << MAJOR_VERSION << "." << MINOR_VERSION << "." << REVISION_NUMBER + << endl; exit(0); } @@ -464,8 +480,10 @@ utf8Main(int argc, char *argv[]) unsigned int policy = SCHED_OTHER; - if (!strcmp(opts.schedulePolicy, "SCHED_RR")) policy = SCHED_RR; - else if (!strcmp(opts.schedulePolicy, "SCHED_FIFO")) policy = SCHED_FIFO; + if (!strcmp(opts.schedulePolicy, "SCHED_RR")) + policy = SCHED_RR; + else if (!strcmp(opts.schedulePolicy, "SCHED_FIFO")) + policy = SCHED_FIFO; if (policy != SCHED_OTHER) { @@ -488,7 +506,6 @@ utf8Main(int argc, char *argv[]) #endif } - // // Banners // @@ -508,8 +525,8 @@ utf8Main(int argc, char *argv[]) else { Imf::setGlobalThreadCount(TwkUtil::SystemInfo::numCPUs() > 1 - ? (TwkUtil::SystemInfo::numCPUs()-1) - : 1); + ? (TwkUtil::SystemInfo::numCPUs() - 1) + : 1); } // @@ -517,10 +534,10 @@ utf8Main(int argc, char *argv[]) // // Required by the Live Review RV plugin React component's scroll bars - std::vector arguments( argv, argv + argc ); + std::vector arguments(argv, argv + argc); static char enableOverlayScrollbar[] = "--enable-features=OverlayScrollbar"; - arguments.emplace_back( enableOverlayScrollbar ); - argc = static_cast( arguments.size() ); + arguments.emplace_back(enableOverlayScrollbar); + argc = static_cast(arguments.size()); argv = &arguments[0]; // @@ -531,7 +548,9 @@ utf8Main(int argc, char *argv[]) QTranslator* translator = new QTranslator(); QLocale locale = QLocale(getenv("ORIGINALLOCAL")); - if (translator->load(locale, QLatin1String("i18n"), "_",QLatin1String(":/translations"))) { + if (translator->load(locale, QLatin1String("i18n"), "_", + QLatin1String(":/translations"))) + { app->installTranslator(translator); } @@ -543,7 +562,7 @@ utf8Main(int argc, char *argv[]) Rv::RvApplication* rvapp = new Rv::RvApplication(argc, argv); - rvapp->setExecutableNameCaps ("RV"); + rvapp->setExecutableNameCaps("RV"); app->installEventFilter(rvapp); app->setQuitOnLastWindowClosed(true); @@ -562,7 +581,8 @@ utf8Main(int argc, char *argv[]) if (bundle.top() == "") { - cerr << "ERROR: can't locate RV home directory (is it installed in root?)" + cerr << "ERROR: can't locate RV home directory (is it installed in " + "root?)" << endl; exit(-1); @@ -571,21 +591,30 @@ utf8Main(int argc, char *argv[]) bundle.setEnvVar("RV_PYTHONPATH_EXTERNAL", (pythonPath) ? pythonPath : ""); bundle.setEnvVar("RV_PYTHONHOME_EXTERNAL", (pythonHome) ? pythonHome : ""); - if (getenv("RV_APP_RVIO")) bundle.setEnvVar("RV_APP_RVIO_SET_BY_USER", "true"); - else bundle.setEnvVar("RV_APP_RVIO", bundle.executableFile("rvio")); + if (getenv("RV_APP_RVIO")) + bundle.setEnvVar("RV_APP_RVIO_SET_BY_USER", "true"); + else + bundle.setEnvVar("RV_APP_RVIO", bundle.executableFile("rvio")); bundle.setEnvVar("RV_APP_RV_SHORT_NAME", EXECUTABLE_SHORT_NAME); bundle.setEnvVar("RV_APP_RV", bundle.executableFile(EXECUTABLE_SHORT_NAME)); bundle.setEnvVar("RV_APP_MANUAL", bundle.resource("rv_manual", "pdf")); - bundle.setEnvVar("RV_APP_MANUAL_HTML", bundle.resource("rv_manual", "html")); - bundle.setEnvVar("RV_APP_SDI_MANUAL", bundle.resource("rvsdi_manual", "pdf")); - bundle.setEnvVar("RV_APP_SDI_MANUAL_HTML", bundle.resource("rvsdi_manual", "html")); - bundle.setEnvVar("RV_APP_REFERENCE_MANUAL", bundle.resource("rv_reference", "pdf")); - bundle.setEnvVar("RV_APP_REFERENCE_MANUAL_HTML", bundle.resource("rv_reference", "html")); + bundle.setEnvVar("RV_APP_MANUAL_HTML", + bundle.resource("rv_manual", "html")); + bundle.setEnvVar("RV_APP_SDI_MANUAL", + bundle.resource("rvsdi_manual", "pdf")); + bundle.setEnvVar("RV_APP_SDI_MANUAL_HTML", + bundle.resource("rvsdi_manual", "html")); + bundle.setEnvVar("RV_APP_REFERENCE_MANUAL", + bundle.resource("rv_reference", "pdf")); + bundle.setEnvVar("RV_APP_REFERENCE_MANUAL_HTML", + bundle.resource("rv_reference", "html")); bundle.setEnvVar("RV_APP_MU_MANUAL", bundle.resource("mu", "pdf")); bundle.setEnvVar("RV_APP_GTO_REFERENCE", bundle.resource("gto", "pdf")); - bundle.setEnvVar("RV_APP_RELEASE_NOTES", bundle.resource("rv_release_notes", "html")); - bundle.setEnvVar("RV_APP_LICENSES_NOTES", bundle.resource("rv_client_licenses", "html")); + bundle.setEnvVar("RV_APP_RELEASE_NOTES", + bundle.resource("rv_release_notes", "html")); + bundle.setEnvVar("RV_APP_LICENSES_NOTES", + bundle.resource("rv_client_licenses", "html")); bundle.addPathToEnvVar("OIIO_LIBRARY_PATH", bundle.appPluginPath("OIIO")); // @@ -597,7 +626,8 @@ utf8Main(int argc, char *argv[]) bundle.setEnvVar("RV_APP_INIT", muInitFile.c_str()); bundle.setEnvVar("RV_APP_PYINIT", pyInitFile.c_str()); - if (opts.initscript) muInitFile = opts.initscript; + if (opts.initscript) + muInitFile = opts.initscript; // RV third party optional customization #if defined(RV_THIRD_PARTY_CUSTOMIZATION) @@ -615,7 +645,6 @@ utf8Main(int argc, char *argv[]) cerr << " some plugins may not have been loaded." << endl; } - TwkMovie::GenericIO::addPlugin(new MovieFBIO()); TwkMovie::GenericIO::addPlugin(new MovieProceduralIO()); @@ -625,21 +654,24 @@ utf8Main(int argc, char *argv[]) TwkFB::GenericIO::compileExtensionSet(predicateFileExtensions()); - #ifdef PLATFORM_WINDOWS - DWORD targetClass = HIGH_PRIORITY_CLASS; - if (getenv("RV_REALTIME_PRIORITY_CLASS")) targetClass = REALTIME_PRIORITY_CLASS; - DWORD proClass1 = GetPriorityClass (GetCurrentProcess()); - if (0 == SetPriorityClass (GetCurrentProcess(), targetClass)) - { - cerr << "ERROR: SetPriorityClass failed, error " << GetLastError() << endl; - } - DWORD proClass2 = GetPriorityClass (GetCurrentProcess()); - if (proClass2 != targetClass) - { - cerr << "WARNING: failed to set Priority Class, class " << hex << showbase << - int(proClass1) << " -> " << int(proClass2) << noshowbase << dec << endl; - } - #endif +#ifdef PLATFORM_WINDOWS + DWORD targetClass = HIGH_PRIORITY_CLASS; + if (getenv("RV_REALTIME_PRIORITY_CLASS")) + targetClass = REALTIME_PRIORITY_CLASS; + DWORD proClass1 = GetPriorityClass(GetCurrentProcess()); + if (0 == SetPriorityClass(GetCurrentProcess(), targetClass)) + { + cerr << "ERROR: SetPriorityClass failed, error " << GetLastError() + << endl; + } + DWORD proClass2 = GetPriorityClass(GetCurrentProcess()); + if (proClass2 != targetClass) + { + cerr << "WARNING: failed to set Priority Class, class " << hex + << showbase << int(proClass1) << " -> " << int(proClass2) + << noshowbase << dec << endl; + } +#endif // // QT starts here @@ -650,10 +682,11 @@ utf8Main(int argc, char *argv[]) pthread_win32_process_attach_np(); #endif - //Rv::dumpApplicationPalette(); + // Rv::dumpApplicationPalette(); Rv::initializeDefaultPalette(); - if (!getenv("RV_DARK")) bundle.setEnvVar("RV_DARK", "", true); + if (!getenv("RV_DARK")) + bundle.setEnvVar("RV_DARK", "", true); QString csstext; @@ -665,9 +698,9 @@ utf8Main(int argc, char *argv[]) else { csstext = QString(rv_linux_dark) - .arg(opts.fontSize1) - .arg(opts.fontSize2) - .arg(opts.fontSize2-1); + .arg(opts.fontSize1) + .arg(opts.fontSize2) + .arg(opts.fontSize2 - 1); } if (!opts.qtstyle || !strcmp(opts.qtstyle, "RV")) @@ -695,18 +728,17 @@ utf8Main(int argc, char *argv[]) exit(-1); } - TwkApp::initWithFile(TwkApp::muContext(), - TwkApp::muProcess(), - TwkApp::muModuleList(), - muInitFile.c_str()); + TwkApp::initWithFile(TwkApp::muContext(), TwkApp::muProcess(), + TwkApp::muModuleList(), muInitFile.c_str()); - TwkApp::pyInitWithFile(pyInitFile.c_str(), Rv::pyRvAppCommands(), Rv::pyUICommands()); + TwkApp::pyInitWithFile(pyInitFile.c_str(), Rv::pyRvAppCommands(), + Rv::pyUICommands()); } - catch (const exception &e) + catch (const exception& e) { cerr << "ERROR: during initialization: " << e.what() << endl; rvapp->console()->processLastTextBuffer(); - exit( -1 ); + exit(-1); } // @@ -715,12 +747,14 @@ utf8Main(int argc, char *argv[]) // that point. // - #ifdef PLATFORM_WINDOWS - TwkGLF::FBOVideoDevice* dummyDev = new TwkGLF::FBOVideoDevice(0, 10, 10, false); +#ifdef PLATFORM_WINDOWS + TwkGLF::FBOVideoDevice* dummyDev = + new TwkGLF::FBOVideoDevice(0, 10, 10, false); IPCore::ImageRenderer::queryGL(); - const char* glVersion =(const char*)glGetString(GL_SHADING_LANGUAGE_VERSION); + const char* glVersion = + (const char*)glGetString(GL_SHADING_LANGUAGE_VERSION); IPCore::Shader::Function::useShadingLanguageVersion(glVersion); - #endif +#endif // // Organize the input file list @@ -760,10 +794,9 @@ utf8Main(int argc, char *argv[]) cerr << exc; exit(-1); } - catch (const exception &e) + catch (const exception& e) { - cerr << "ERROR: Unhandled exception during execution: " - << e.what() + cerr << "ERROR: Unhandled exception during execution: " << e.what() << endl; exit(-1); @@ -782,7 +815,7 @@ utf8Main(int argc, char *argv[]) TwkFB::ThreadPool::shutdown(); TwkMovie::GenericIO::shutdown(); // Shutdown TwkMovie::GenericIO plugins - TwkFB::GenericIO::shutdown(); // Shutdown TwkFB::GenericIO plugins + TwkFB::GenericIO::shutdown(); // Shutdown TwkFB::GenericIO plugins TwkGLF::UninitPBOPools(); diff --git a/src/bin/apps/rv/utf8WinMain.cpp b/src/bin/apps/rv/utf8WinMain.cpp index 5422e96df..89b181f2b 100644 --- a/src/bin/apps/rv/utf8WinMain.cpp +++ b/src/bin/apps/rv/utf8WinMain.cpp @@ -1,6 +1,6 @@ // -// Copyright (C) 2023 Autodesk, Inc. All Rights Reserved. -// -// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2023 Autodesk, Inc. All Rights Reserved. // -#include "../../utf8WinMain.cpp" \ No newline at end of file +// SPDX-License-Identifier: Apache-2.0 +// +#include "../../utf8WinMain.cpp" diff --git a/src/bin/apps/rvpkg/main.cpp b/src/bin/apps/rvpkg/main.cpp index 3bc3d4693..e3930d75c 100644 --- a/src/bin/apps/rvpkg/main.cpp +++ b/src/bin/apps/rvpkg/main.cpp @@ -1,27 +1,27 @@ //****************************************************************************** // Copyright (c) 2001-2005 Tweak Inc. All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #ifdef _MSC_VER - // - // We are targetting at least XP, (IE no windows95, etc). - // - #define WINVER 0x0501 - #define _WIN32_WINNT 0x0501 - #include - #include - #include - #include - #include - // - // NOTE: win_pthreads, which supplies implement.h, seems - // targetted at an earlier version of windows (pre-XP). If you - // include implement.h here, it won't compile. But as far as I - // can tell, it's not needed, so just leave it out. - // - // #include +// +// We are targetting at least XP, (IE no windows95, etc). +// +#define WINVER 0x0501 +#define _WIN32_WINNT 0x0501 +#include +#include +#include +#include +#include +// +// NOTE: win_pthreads, which supplies implement.h, seems +// targetted at an earlier version of windows (pre-XP). If you +// include implement.h here, it won't compile. But as far as I +// can tell, it's not needed, so just leave it out. +// +// #include #endif #include @@ -67,10 +67,10 @@ #if MAJOR_VERSION == 99 #if NDEBUG -//#error ********* NO VERSION INFORMATION *********** +// #error ********* NO VERSION INFORMATION *********** #else #ifndef _MSC_VER -#warning ********* NO VERSION INFORMATION *********** +#warning********* NO VERSION INFORMATION *********** #endif #endif #endif @@ -126,7 +126,8 @@ bool hasPathInEnv(const string& var, const string& path0) for (size_t i = 0; i < tokens.size(); i++) { - if (tokens[i] == path) return true; + if (tokens[i] == path) + return true; } } @@ -143,13 +144,11 @@ void includeIfNotThere(const string& path0) } } - vector inputArgs; -int -parseInFiles(int argc, char *argv[]) +int parseInFiles(int argc, char* argv[]) { - for (int i=0; i& outindexlist) +void matchingPackages(const PackageManager::PackageList& inlist, + vector& outindexlist) { set indexSet; @@ -217,12 +217,11 @@ void matchingPackages (const PackageManager::PackageList& inlist, for (set::iterator i = indexSet.begin(); i != indexSet.end(); ++i) { - outindexlist.push_back(*i); + outindexlist.push_back(*i); } } -int -utf8Main(int argc, char *argv[]) +int utf8Main(int argc, char* argv[]) { QCoreApplication app(argc, argv); @@ -230,19 +229,19 @@ utf8Main(int argc, char *argv[]) // Parse cmd line args // - int install = 0; - int uninstall = 0; - int list = 0; - int info = 0; - int add = 0; - char* addDir = 0; - int remove = 0; - int env = 0; - int force = 0; - int optin = 0; - char* filename = 0; - char* withDir = 0; - char* onlyDir = 0; + int install = 0; + int uninstall = 0; + int list = 0; + int info = 0; + int add = 0; + char* addDir = 0; + int remove = 0; + int env = 0; + int force = 0; + int optin = 0; + char* filename = 0; + char* withDir = 0; + char* onlyDir = 0; // // We handle the '--help' flag by changing it to '-help' for @@ -257,39 +256,63 @@ utf8Main(int argc, char *argv[]) } } - if (arg_parse - (argc, argv, - "", "Usage: rvpkg command line .rvpkg management", - "", " In examples below 'area' means a support area", - "", " Many commands can use one of: package name, rvpkg file name,", - "", " or full path to rvpkg file. the commands -remove, -info,", - "", " -install, -uninstall, operating on already added packages.", - "", " They will not work on packages not visible to -list", - "", "", - "", " List all in RV_SUPPORT_PATH: rvpkg -list", - "", " List in specific area: rvpkg -list -only /path/to/support/area", - "", " List including an area: rvpkg -list -include /path/to/additional/support/area", - "", " Info about a package: rvpkg -info /path/to/file.rvpkg", - "", " Add package(s) to an area: rvpkg -add /path/to/area /path/to/file1.rvpkg /path/to/file2.rvpkg ...", - "", " Remove package(s): rvpkg -remove /path/to/file1.rvpkg ...", - "", " Install package(s): rvpkg -install /path/to/file1.rvpkg ...", - "", " Uninstall package(s): rvpkg -uninstall /path/to/file1.rvpkg ...", - "", " Add and install package(s): rvpkg -install -add /path/to/area /path/to/file1.rvpkg ...", - "", " Opt-in all users to optional package(s): rvpkg -optin /path/to/file1.rvpkg ...", - "", "", - "", ARG_SUBR(parseInFiles), "Input packages names or rvpkg files", - "-include %S", &withDir, "include directory as if part of RV_SUPPORT_PATH", - "-env", ARG_FLAG(&env), "show RV_SUPPORT_PATH include app areas", - "-only %S", &onlyDir, "use directory as sole content of RV_SUPPORT_PATH", - "-add %S", &addDir, "add packages to specified support directory", - "-remove", ARG_FLAG(&remove), "remove packages (by name, rvpkg name, or full path to rvpkg)", - "-install", ARG_FLAG(&install), "install packages (by name, rvpkg name, or full path to rvpkg)", - "-uninstall", ARG_FLAG(&uninstall), "uninstall packages (by name, rvpkg name, or full path to rvpkg)", - "-optin", ARG_FLAG(&optin), "make installed optional packages opt-in by default for all users", - "-list", ARG_FLAG(&list), "list installed packages", - "-info", ARG_FLAG(&info), "detailed info about packages (by name, rvpkg name, or full path to rvpkg)", - "-force", ARG_FLAG(&force), "Assume answer is 'y' to any confirmations -- don't be interactive", - NULL) < 0) + if (arg_parse( + argc, argv, "", "Usage: rvpkg command line .rvpkg management", "", + " In examples below 'area' means a support area", "", + " Many commands can use one of: package name, rvpkg file name,", + "", " or full path to rvpkg file. the commands -remove, -info,", + "", " -install, -uninstall, operating on already added packages.", + "", " They will not work on packages not visible to -list", "", "", + "", " List all in RV_SUPPORT_PATH: rvpkg -list", "", + " List in specific area: rvpkg -list -only " + "/path/to/support/area", + "", + " List including an area: rvpkg -list -include " + "/path/to/additional/support/area", + "", + " Info about a package: rvpkg -info " + "/path/to/file.rvpkg", + "", + " Add package(s) to an area: rvpkg -add " + "/path/to/area /path/to/file1.rvpkg /path/to/file2.rvpkg ...", + "", + " Remove package(s): rvpkg -remove " + "/path/to/file1.rvpkg ...", + "", + " Install package(s): rvpkg -install " + "/path/to/file1.rvpkg ...", + "", + " Uninstall package(s): rvpkg -uninstall " + "/path/to/file1.rvpkg ...", + "", + " Add and install package(s): rvpkg -install -add " + "/path/to/area /path/to/file1.rvpkg ...", + "", + " Opt-in all users to optional package(s): rvpkg -optin " + "/path/to/file1.rvpkg ...", + "", "", "", ARG_SUBR(parseInFiles), + "Input packages names or rvpkg files", "-include %S", &withDir, + "include directory as if part of RV_SUPPORT_PATH", "-env", + ARG_FLAG(&env), "show RV_SUPPORT_PATH include app areas", + "-only %S", &onlyDir, + "use directory as sole content of RV_SUPPORT_PATH", "-add %S", + &addDir, "add packages to specified support directory", "-remove", + ARG_FLAG(&remove), + "remove packages (by name, rvpkg name, or full path to rvpkg)", + "-install", ARG_FLAG(&install), + "install packages (by name, rvpkg name, or full path to rvpkg)", + "-uninstall", ARG_FLAG(&uninstall), + "uninstall packages (by name, rvpkg name, or full path to rvpkg)", + "-optin", ARG_FLAG(&optin), + "make installed optional packages opt-in by default for all users", + "-list", ARG_FLAG(&list), "list installed packages", "-info", + ARG_FLAG(&info), + "detailed info about packages (by name, rvpkg name, or full path " + "to rvpkg)", + "-force", ARG_FLAG(&force), + "Assume answer is 'y' to any confirmations -- don't be interactive", + NULL) + < 0) { exit(-1); } @@ -326,7 +349,8 @@ utf8Main(int argc, char *argv[]) if ((remove || add || install || uninstall) && (list || info)) { - cerr << "ERROR: -list and -info do not work with other arguments" << endl; + cerr << "ERROR: -list and -info do not work with other arguments" + << endl; exit(-1); } @@ -366,9 +390,12 @@ utf8Main(int argc, char *argv[]) } #endif - if (addDir) includeIfNotThere(addDir); - else if (withDir) includeIfNotThere(withDir); - else if (onlyDir) setEnvVar("RV_SUPPORT_PATH", onlyDir); + if (addDir) + includeIfNotThere(addDir); + else if (withDir) + includeIfNotThere(withDir); + else if (onlyDir) + setEnvVar("RV_SUPPORT_PATH", onlyDir); BundleType bundle(APPNAME, MAJOR_VERSION, MINOR_VERSION, REVISION_NUMBER); @@ -387,18 +414,16 @@ utf8Main(int argc, char *argv[]) exit(0); } - TWK_DEPLOY_APP_OBJECT dobj(MAJOR_VERSION, - MINOR_VERSION, - REVISION_NUMBER, - argc, argv, - RELEASE_DESCRIPTION, + TWK_DEPLOY_APP_OBJECT dobj(MAJOR_VERSION, MINOR_VERSION, REVISION_NUMBER, + argc, argv, RELEASE_DESCRIPTION, "HEAD=" GIT_HEAD); Rv::PackageManager manager; manager.loadPackages(); PackageManager::PackageList& packages = manager.packageList(); - if (force) manager.setNoConfirmation(); + if (force) + manager.setNoConfirmation(); if (list) { @@ -414,9 +439,7 @@ utf8Main(int argc, char *argv[]) cout << " " << (p.loadable ? "L" : "-"); cout << " " << (p.optional ? "O" : "-"); - cout << " " << p.version - << " \"" << p.name - << "\" " << p.file + cout << " " << p.version << " \"" << p.name << "\" " << p.file << endl; } } @@ -444,7 +467,11 @@ utf8Main(int argc, char *argv[]) cout << "Organization: " << p.organization << endl; cout << "Contact: " << p.contact << endl; cout << "URL: " << p.url << endl; - cout << "Requires: " << p.requires << endl; + cout << "Requires: " + << p. + requires + << + endl; cout << "RV-Version: " << p.rvversion << endl; cout << "OpenRV-Version: " << p.openrvversion << endl; cout << "Hidden: " << (p.hidden ? "YES" : "NO") << endl; @@ -490,8 +517,7 @@ utf8Main(int argc, char *argv[]) if (!p.optional) { cerr << "ERROR: " << p.file.toUtf8().constData() - << " is not an optional package -- ignoring" - << endl; + << " is not an optional package -- ignoring" << endl; continue; } @@ -500,7 +526,8 @@ utf8Main(int argc, char *argv[]) if (!info.exists()) { - cerr << "ERROR: " << p.file.toUtf8().constData() << " doesn't exist -- ignoring" << endl; + cerr << "ERROR: " << p.file.toUtf8().constData() + << " doesn't exist -- ignoring" << endl; continue; } @@ -513,20 +540,20 @@ utf8Main(int argc, char *argv[]) if (!rvloadInfo.exists()) { cerr << "ERROR: missing rvload2 file at " - << rvload2.toUtf8().constData() - << " -- ignoring" - << endl; + << rvload2.toUtf8().constData() << " -- ignoring" << endl; break; } - PackageManager::ModeEntryList entries = manager.loadModeFile(rvload2); + PackageManager::ModeEntryList entries = + manager.loadModeFile(rvload2); // // Just force the package to become not optional // QString basename = info.fileName(); - cout << "INFO: for package " << basename.toUtf8().constData() << endl; + cout << "INFO: for package " << basename.toUtf8().constData() + << endl; for (size_t i = 0; i < entries.size(); i++) { @@ -538,8 +565,7 @@ utf8Main(int argc, char *argv[]) entry.optional = false; cout << "INFO: opting-in all users for mode " - << entry.name.toUtf8().constData() - << endl; + << entry.name.toUtf8().constData() << endl; } } @@ -559,35 +585,42 @@ utf8Main(int argc, char *argv[]) string curFile = inputArgs[i]; // Checking to see if the file is a bundle - if (manager.isBundle(QString::fromStdString(curFile))) { + if (manager.isBundle(QString::fromStdString(curFile))) + { cout << "INFO: Bundle detected, unpacking now." << endl; // Unpacking bundle QString toUnzip = QString::fromStdString(curFile); string addDirStr = addDir; - QString outputDir = QString::fromStdString(addDirStr.append("/Packages")); + QString outputDir = + QString::fromStdString(addDirStr.append("/Packages")); addedPackages = manager.handleBundle(toUnzip, outputDir); // Ensuring that the bundle unpacked successfully - if (addedPackages.size() > 0) + if (addedPackages.size() > 0) { cout << "INFO: Bundle unpacked successfully " << endl; cout << "INFO: Added the following packages..." << endl; - for (QString s : addedPackages) + for (QString s : addedPackages) { cout << s.toStdString() << endl; } - } else { + } + else + { cerr << "ERROR: Unable to install bundle." << endl; } - } else { + } + else + { files.push_back(inputArgs[i].c_str()); } } - // Adding bundle subpackages to input arguments to allow for chain calls (e.g. -install -add ...) - if (addedPackages.size() > 0) + // Adding bundle subpackages to input arguments to allow for chain calls + // (e.g. -install -add ...) + if (addedPackages.size() > 0) { for (QString s : addedPackages) @@ -611,20 +644,22 @@ utf8Main(int argc, char *argv[]) { QString name(inputArgs[i].c_str()); QString base = name.split("/").back(); - + // Bundles do not need to be modified and should instead be removed - if (manager.isBundle(base)) continue; + if (manager.isBundle(base)) + continue; QDir dir(addDir); - dir.cd("Packages"); // Automatically navigating into the Packages directory - if (!dir.exists()) exit(-1); + dir.cd("Packages"); // Automatically navigating into the Packages + // directory + if (!dir.exists()) + exit(-1); QString path = dir.absoluteFilePath(base); inputArgs[i] = path.toUtf8().constData(); } } - if (install) { cout << "INFO: Installing package..." << endl; @@ -644,8 +679,9 @@ utf8Main(int argc, char *argv[]) // Ensuring package not installed already if (p.installed) { - cout << "WARNING: " << p.name << " is already installed" << endl; - } + cout << "WARNING: " << p.name << " is already installed" + << endl; + } else { @@ -705,4 +741,4 @@ utf8Main(int argc, char *argv[]) } return 0; -} \ No newline at end of file +} diff --git a/src/bin/apps/rvpkg/utf8Main.cpp b/src/bin/apps/rvpkg/utf8Main.cpp index 69e097cc9..7c46f886c 100644 --- a/src/bin/apps/rvpkg/utf8Main.cpp +++ b/src/bin/apps/rvpkg/utf8Main.cpp @@ -1,6 +1,6 @@ // -// Copyright (C) 2023 Autodesk, Inc. All Rights Reserved. -// -// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2023 Autodesk, Inc. All Rights Reserved. // -#include "../../utf8Main.cpp" \ No newline at end of file +// SPDX-License-Identifier: Apache-2.0 +// +#include "../../utf8Main.cpp" diff --git a/src/bin/apps/rvprof/VisMainWindow.cpp b/src/bin/apps/rvprof/VisMainWindow.cpp index f44709a05..9fe6da5c3 100644 --- a/src/bin/apps/rvprof/VisMainWindow.cpp +++ b/src/bin/apps/rvprof/VisMainWindow.cpp @@ -1,45 +1,37 @@ // -// Copyright (C) 2023 Autodesk, Inc. All Rights Reserved. -// -// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2023 Autodesk, Inc. All Rights Reserved. +// +// SPDX-License-Identifier: Apache-2.0 // #include "VisMainWindow.h" #include #include #include #ifdef PLATFORM_DARWIN - #include +#include #else - #include +#include #endif using namespace TwkGLText; -inline void glVertex( const TwkMath::Vec3f &v ) -{ - glVertex3fv( ( GLfloat * )( &v ) ); -} +inline void glVertex(const TwkMath::Vec3f& v) { glVertex3fv((GLfloat*)(&v)); } -inline void glVertex( const TwkMath::Vec4f &v ) -{ - glVertex4fv( ( GLfloat * )( &v ) ); -} +inline void glVertex(const TwkMath::Vec4f& v) { glVertex4fv((GLfloat*)(&v)); } -inline TwkMath::Mat44f getMatrix( GLenum matrix ) +inline TwkMath::Mat44f getMatrix(GLenum matrix) { GLfloat m[16]; - glGetFloatv( matrix, m ); + glGetFloatv(matrix, m); // Unfortunately, open GL stores matrices in COLUMN-major // format, whereas we store them in the much more sane ROW-major // format. - return TwkMath::Mat44f( m[0], m[4], m[8], m[12], - m[1], m[5], m[9], m[13], - m[2], m[6], m[10], m[14], - m[3], m[7], m[11], m[15] ); + return TwkMath::Mat44f(m[0], m[4], m[8], m[12], m[1], m[5], m[9], m[13], + m[2], m[6], m[10], m[14], m[3], m[7], m[11], m[15]); } -inline void glLoadMatrix( const TwkMath::Mat44f &m ) +inline void glLoadMatrix(const TwkMath::Mat44f& m) { GLfloat mv[16]; @@ -63,10 +55,10 @@ inline void glLoadMatrix( const TwkMath::Mat44f &m ) mv[14] = m[2][3]; mv[15] = m[3][3]; - glLoadMatrixf( mv ); + glLoadMatrixf(mv); } -inline void glMultMatrix( const TwkMath::Mat44f &m ) +inline void glMultMatrix(const TwkMath::Mat44f& m) { GLfloat mv[16]; @@ -90,7 +82,7 @@ inline void glMultMatrix( const TwkMath::Mat44f &m ) mv[14] = m[2][3]; mv[15] = m[3][3]; - glMultMatrixf( mv ); + glMultMatrixf(mv); } using namespace std; @@ -98,9 +90,9 @@ using namespace TwkMath; //---------------------------------------------------------------------- -VisMainWindow::VisMainWindow(QWidget *parent) : - m_mouseTime(0.0), - QMainWindow(parent) +VisMainWindow::VisMainWindow(QWidget* parent) + : m_mouseTime(0.0) + , QMainWindow(parent) { m_ui.setupUi(this); @@ -114,18 +106,24 @@ VisMainWindow::VisMainWindow(QWidget *parent) : connect(m_ui.actionOpen, SIGNAL(triggered()), this, SLOT(openFile())); connect(m_ui.actionQuit, SIGNAL(triggered()), this, SLOT(quit())); - connect(m_ui.actionShow_Raw_Profile_Data, SIGNAL(triggered()), this, SLOT(showFile())); - connect(m_dockUI.startEdit, SIGNAL(editingFinished()), this, SLOT(rangeChanged())); - connect(m_dockUI.endEdit, SIGNAL(editingFinished()), this, SLOT(rangeChanged())); - - connect(m_dockUI.startTimeEdit, SIGNAL(editingFinished()), this, SLOT(rangeChanged())); - connect(m_dockUI.endTimeEdit, SIGNAL(editingFinished()), this, SLOT(rangeChanged())); - - connect(m_dockUI.showIdealFramesButton, SIGNAL(stateChanged(int)), - this, SLOT(showIdealFrames(int))); - connect(m_dockUI.showEvalTimingButton, SIGNAL(stateChanged(int)), - this, SLOT(showEvalTiming(int))); - connect(m_dockUI.actualFPSEdit, SIGNAL(editingFinished()), this, SLOT(fpsChanged())); + connect(m_ui.actionShow_Raw_Profile_Data, SIGNAL(triggered()), this, + SLOT(showFile())); + connect(m_dockUI.startEdit, SIGNAL(editingFinished()), this, + SLOT(rangeChanged())); + connect(m_dockUI.endEdit, SIGNAL(editingFinished()), this, + SLOT(rangeChanged())); + + connect(m_dockUI.startTimeEdit, SIGNAL(editingFinished()), this, + SLOT(rangeChanged())); + connect(m_dockUI.endTimeEdit, SIGNAL(editingFinished()), this, + SLOT(rangeChanged())); + + connect(m_dockUI.showIdealFramesButton, SIGNAL(stateChanged(int)), this, + SLOT(showIdealFrames(int))); + connect(m_dockUI.showEvalTimingButton, SIGNAL(stateChanged(int)), this, + SLOT(showEvalTiming(int))); + connect(m_dockUI.actualFPSEdit, SIGNAL(editingFinished()), this, + SLOT(fpsChanged())); m_glWidget = new GLView(this, m_dockUI.readoutEdit, this); setCentralWidget(m_glWidget); @@ -134,8 +132,7 @@ VisMainWindow::VisMainWindow(QWidget *parent) : qApp->installEventFilter(this); } -bool -VisMainWindow::eventFilter(QObject *obj, QEvent *event) +bool VisMainWindow::eventFilter(QObject* obj, QEvent* event) { if (event->type() == QEvent::FileOpen) { @@ -154,17 +151,16 @@ VisMainWindow::eventFilter(QObject *obj, QEvent *event) return QMainWindow::eventFilter(obj, event); } -void -VisMainWindow::openFile() +void VisMainWindow::openFile() { - QString filename = - QFileDialog::getOpenFileName(this, "Select File", ".", UI_APPLICATION_NAME " Profile Data (*.rvprof *.timedata)"); + QString filename = QFileDialog::getOpenFileName( + this, "Select File", ".", + UI_APPLICATION_NAME " Profile Data (*.rvprof *.timedata)"); readFile(filename); } - -void -VisMainWindow::readFile(const QString& filename) + +void VisMainWindow::readFile(const QString& filename) { QFile infile(filename); @@ -172,18 +168,20 @@ VisMainWindow::readFile(const QString& filename) if (!infile.exists()) { - cerr << "ERROR: file doesn't exist: " << filename.toUtf8().constData() << endl; + cerr << "ERROR: file doesn't exist: " << filename.toUtf8().constData() + << endl; return; - } + } - if (!infile.open(QIODevice::ReadOnly | QIODevice::Text)) + if (!infile.open(QIODevice::ReadOnly | QIODevice::Text)) { cerr << "ERROR: can't open: " << filename.toUtf8().constData() << endl; return; } QFileInfo info(filename); - setWindowTitle(QString(UI_APPLICATION_NAME " Profile Viewer -- %1").arg(info.baseName())); + setWindowTitle(QString(UI_APPLICATION_NAME " Profile Viewer -- %1") + .arg(info.baseName())); DataVector data; @@ -194,7 +192,8 @@ VisMainWindow::readFile(const QString& filename) QByteArray array = infile.readLine(); QString line(array); fileContents += line; - if (line.startsWith("#") || line == "") continue; + if (line.startsWith("#") || line == "") + continue; QStringList parts = line.split(","); if (line.contains("=")) @@ -204,47 +203,46 @@ VisMainWindow::readFile(const QString& filename) // DataElement e; -#define OFFSET_PAIR(NAME,FIELD) \ - {#NAME "0", ((char*)&e.FIELD ## 0) - ((char*)&e)},\ - {#NAME "1", ((char*)&e.FIELD ## 1) - ((char*)&e)} - -#define OFFSET_SINGLE(NAME,FIELD) \ - {#NAME, ((char*)&e.FIELD) - ((char*)&e)} - - NameOffsetPair offsets[] = { - OFFSET_PAIR(R,render), - OFFSET_PAIR(S,swap), - OFFSET_PAIR(E,eval), - OFFSET_PAIR(U,userRender), - OFFSET_PAIR(FC,frameChange), - OFFSET_PAIR(IR,internalRender), - OFFSET_PAIR(PR,prefetch), - OFFSET_PAIR(CT,cacheTest), - OFFSET_PAIR(EI,evalGraph), - OFFSET_PAIR(ID,evalID), - OFFSET_PAIR(CQ,cacheQuery), - OFFSET_PAIR(CE,cacheEval), - OFFSET_PAIR(IO,io), - OFFSET_PAIR(THA,restartA), - OFFSET_PAIR(THB,restartB), - OFFSET_PAIR(CTL,cacheTestLock), - OFFSET_PAIR(DSDP,setDisplayFrame), - OFFSET_PAIR(FCT,frameCachedTest), - OFFSET_PAIR(WAK,awaken), - OFFSET_PAIR(PRR,prefetchRender), - {0, 0} - }; - +#define OFFSET_PAIR(NAME, FIELD) \ + {#NAME "0", ((char*)&e.FIELD##0) - ((char*)&e)}, \ + {#NAME "1", ((char*)&e.FIELD##1) - ((char*)&e)} + +#define OFFSET_SINGLE(NAME, FIELD) {#NAME, ((char*)&e.FIELD) - ((char*)&e)} + + NameOffsetPair offsets[] = {OFFSET_PAIR(R, render), + OFFSET_PAIR(S, swap), + OFFSET_PAIR(E, eval), + OFFSET_PAIR(U, userRender), + OFFSET_PAIR(FC, frameChange), + OFFSET_PAIR(IR, internalRender), + OFFSET_PAIR(PR, prefetch), + OFFSET_PAIR(CT, cacheTest), + OFFSET_PAIR(EI, evalGraph), + OFFSET_PAIR(ID, evalID), + OFFSET_PAIR(CQ, cacheQuery), + OFFSET_PAIR(CE, cacheEval), + OFFSET_PAIR(IO, io), + OFFSET_PAIR(THA, restartA), + OFFSET_PAIR(THB, restartB), + OFFSET_PAIR(CTL, cacheTestLock), + OFFSET_PAIR(DSDP, setDisplayFrame), + OFFSET_PAIR(FCT, frameCachedTest), + OFFSET_PAIR(WAK, awaken), + OFFSET_PAIR(PRR, prefetchRender), + {0, 0}}; + memset(&e, 0, sizeof(DataElement)); - + for (size_t i = 0; i < parts.size(); i++) { QStringList nameValue = parts[i].split("="); if (nameValue.size() != 2) { - cout << "ERROR: reading file " << filename.toUtf8().constData() << endl; - cout << "ERROR: reading this field: \"" << parts[i].toUtf8().constData() << "\"" << endl; + cout << "ERROR: reading file " + << filename.toUtf8().constData() << endl; + cout << "ERROR: reading this field: \"" + << parts[i].toUtf8().constData() << "\"" << endl; continue; } @@ -252,18 +250,26 @@ VisMainWindow::readFile(const QString& filename) { if (nameValue[0] == p->name) { - *(double*)((char*)&e + p->offset) = nameValue[1].toDouble(); + *(double*)((char*)&e + p->offset) = + nameValue[1].toDouble(); break; } } - if (nameValue[0] == "GC") e.gccount = nameValue[1].toInt(); - else if (nameValue[0] == "F") e.frame = nameValue[1].toInt(); - else if (nameValue[0] == "EST") e.expectedSyncTime = nameValue[1].toFloat(); - else if (nameValue[0] == "DCO") e.deviceClockOffset = nameValue[1].toFloat(); - else if (nameValue[0] == "PRUP") e.prefetchUploadPlane = nameValue[1].toFloat(); - else if (nameValue[0] == "RRUP") e.renderUploadPlane = nameValue[1].toFloat(); - else if (nameValue[0] == "RFW") e.renderFenceWait = nameValue[1].toFloat(); + if (nameValue[0] == "GC") + e.gccount = nameValue[1].toInt(); + else if (nameValue[0] == "F") + e.frame = nameValue[1].toInt(); + else if (nameValue[0] == "EST") + e.expectedSyncTime = nameValue[1].toFloat(); + else if (nameValue[0] == "DCO") + e.deviceClockOffset = nameValue[1].toFloat(); + else if (nameValue[0] == "PRUP") + e.prefetchUploadPlane = nameValue[1].toFloat(); + else if (nameValue[0] == "RRUP") + e.renderUploadPlane = nameValue[1].toFloat(); + else if (nameValue[0] == "RFW") + e.renderFenceWait = nameValue[1].toFloat(); } data.push_back(e); @@ -273,69 +279,69 @@ VisMainWindow::readFile(const QString& filename) // // OLD FORMAT(S) // - + if (parts.size() > 12) { DataElement e; size_t index = 0; - e.render0 = parts[index++].toDouble(); - e.render1 = parts[index++].toDouble(); - e.swap0 = parts[index++].toDouble(); - e.swap1 = parts[index++].toDouble(); - e.eval0 = parts[index++].toDouble(); - e.eval1 = parts[index++].toDouble(); - e.userRender0 = parts[index++].toDouble(); - e.userRender1 = parts[index++].toDouble(); - e.frameChange0 = parts[index++].toDouble(); - e.frameChange1 = parts[index++].toDouble(); + e.render0 = parts[index++].toDouble(); + e.render1 = parts[index++].toDouble(); + e.swap0 = parts[index++].toDouble(); + e.swap1 = parts[index++].toDouble(); + e.eval0 = parts[index++].toDouble(); + e.eval1 = parts[index++].toDouble(); + e.userRender0 = parts[index++].toDouble(); + e.userRender1 = parts[index++].toDouble(); + e.frameChange0 = parts[index++].toDouble(); + e.frameChange1 = parts[index++].toDouble(); e.internalRender0 = parts[index++].toDouble(); e.internalRender1 = parts[index++].toDouble(); - e.prefetch0 = parts[index++].toDouble(); - e.prefetch1 = parts[index++].toDouble(); + e.prefetch0 = parts[index++].toDouble(); + e.prefetch1 = parts[index++].toDouble(); if (parts.size() > 22) { - e.cacheTest0 = parts[index++].toDouble(); - e.cacheTest1 = parts[index++].toDouble(); - e.evalGraph0 = parts[index++].toDouble(); - e.evalGraph1 = parts[index++].toDouble(); + e.cacheTest0 = parts[index++].toDouble(); + e.cacheTest1 = parts[index++].toDouble(); + e.evalGraph0 = parts[index++].toDouble(); + e.evalGraph1 = parts[index++].toDouble(); } else { - e.cacheTest0 = 0; - e.cacheTest1 = 0; - e.evalGraph0 = 0; - e.evalGraph1 = 0; + e.cacheTest0 = 0; + e.cacheTest1 = 0; + e.evalGraph0 = 0; + e.evalGraph1 = 0; } if (parts.size() > 16) { - e.evalID0 = parts[index++].toDouble(); - e.evalID1 = parts[index++].toDouble(); - e.cacheQuery0 = parts[index++].toDouble(); - e.cacheQuery1 = parts[index++].toDouble(); - e.cacheEval0 = parts[index++].toDouble(); - e.cacheEval1 = parts[index++].toDouble(); + e.evalID0 = parts[index++].toDouble(); + e.evalID1 = parts[index++].toDouble(); + e.cacheQuery0 = parts[index++].toDouble(); + e.cacheQuery1 = parts[index++].toDouble(); + e.cacheEval0 = parts[index++].toDouble(); + e.cacheEval1 = parts[index++].toDouble(); if (parts.size() >= 28) { - e.io0 = parts[index++].toDouble(); - e.io1 = parts[index++].toDouble(); + e.io0 = parts[index++].toDouble(); + e.io1 = parts[index++].toDouble(); } } else { - e.evalID0 = 0; - e.evalID1 = 0; - e.cacheQuery0 = 0; - e.cacheQuery1 = 0; - e.cacheEval0 = 0; - e.cacheEval1 = 0; + e.evalID0 = 0; + e.evalID1 = 0; + e.cacheQuery0 = 0; + e.cacheQuery1 = 0; + e.cacheEval0 = 0; + e.cacheEval1 = 0; } - e.gccount = parts[index++].toInt(); - e.frame = parts[index++].toInt(); + e.gccount = parts[index++].toInt(); + e.frame = parts[index++].toInt(); data.push_back(e); } @@ -347,85 +353,76 @@ VisMainWindow::readFile(const QString& filename) m_fileViewUI.plainTextEdit->setPlainText(fileContents); } -void -VisMainWindow::showFile() +void VisMainWindow::showFile() { - if (m_fileViewDialog->isVisible()) m_fileViewDialog->hide(); - else m_fileViewDialog->show(); + if (m_fileViewDialog->isVisible()) + m_fileViewDialog->hide(); + else + m_fileViewDialog->show(); } -void -VisMainWindow::quit() -{ - qApp->quit(); -} +void VisMainWindow::quit() { qApp->quit(); } -void -VisMainWindow::showIdealFrames(int b) +void VisMainWindow::showIdealFrames(int b) { m_glWidget->setShowIdealFrames(b == Qt::Checked); } -void -VisMainWindow::showEvalTiming(int b) +void VisMainWindow::showEvalTiming(int b) { m_glWidget->setShowEvalTiming(b == Qt::Checked); } -void -VisMainWindow::fpsChanged() +void VisMainWindow::fpsChanged() { m_glWidget->setActualFPS(m_dockUI.actualFPSEdit->text().toFloat()); } -void -VisMainWindow::updateTimeRangeFromGLView() +void VisMainWindow::updateTimeRangeFromGLView() { - m_dockUI.startTimeEdit->setText(QString("%1").arg(m_glWidget->rangeStart())); - m_dockUI.endTimeEdit-> setText(QString("%1").arg(m_glWidget->rangeEnd())); + m_dockUI.startTimeEdit->setText( + QString("%1").arg(m_glWidget->rangeStart())); + m_dockUI.endTimeEdit->setText(QString("%1").arg(m_glWidget->rangeEnd())); } -void -VisMainWindow::updateActualFPSFromGLView() +void VisMainWindow::updateActualFPSFromGLView() { m_dockUI.actualFPSEdit->setText(QString("%1").arg(m_glWidget->actualFPS())); } -void -VisMainWindow::setShowIdealFrames() +void VisMainWindow::setShowIdealFrames() { m_dockUI.showIdealFramesButton->setCheckState(Qt::Checked); } -void -VisMainWindow::rangeChanged() +void VisMainWindow::rangeChanged() { float startTime = m_dockUI.startTimeEdit->text().toFloat(); - float endTime = m_dockUI.endTimeEdit->text().toFloat(); + float endTime = m_dockUI.endTimeEdit->text().toFloat(); - if (startTime < endTime) + if (startTime < endTime) { - m_glWidget->setTimeRange(startTime, endTime); + m_glWidget->setTimeRange(startTime, endTime); } else { - int start = m_dockUI.startEdit->text().toInt(); - int end = m_dockUI.endEdit->text().toInt(); + int start = m_dockUI.startEdit->text().toInt(); + int end = m_dockUI.endEdit->text().toInt(); - if (end < start) - { - end = start; - m_dockUI.endEdit->setText(QString("%1").arg(end)); - } + if (end < start) + { + end = start; + m_dockUI.endEdit->setText(QString("%1").arg(end)); + } - m_glWidget->setRange(start, end); + m_glWidget->setRange(start, end); } const DataVector& data = m_glWidget->data(); size_t i0 = m_glWidget->startIndex(); size_t i1 = m_glWidget->endIndex(); - + float minRR = 1000000; float maxRR = 0; double rr = 0; @@ -434,20 +431,21 @@ VisMainWindow::rangeChanged() if (i0 < data.size() && i1 < data.size()) { double startTime = data[i0].swap1; - double endTime = data[i1-1].swap1; + double endTime = data[i1 - 1].swap1; int frames = data[i1].frame - data[i0].frame + 1; float fps = float(frames) / (endTime - startTime); m_glWidget->setComputedFPS(fps); m_dockUI.fpsLabel->setText(QString("%1").arg(fps)); - m_dockUI.totalTimeLabel->setText(QString("%1 sec").arg(endTime-startTime)); + m_dockUI.totalTimeLabel->setText( + QString("%1 sec").arg(endTime - startTime)); for (size_t i = i0; i <= i1; i++) { if (i > 0) { - float d = data[i].swap1 - data[i-1].swap1; + float d = data[i].swap1 - data[i - 1].swap1; rr += d * d; count++; minRR = std::min(d, minRR); @@ -467,37 +465,41 @@ VisMainWindow::rangeChanged() } // yes, this is right, its inverted so min is max - if (minRR > 0) m_dockUI.maxVariationLabel->setText(QString("%1 Hz").arg(1.0/ minRR)); - if (maxRR > 0) m_dockUI.minVariationLabel->setText(QString("%1 Hz").arg(1.0/ maxRR)); + if (minRR > 0) + m_dockUI.maxVariationLabel->setText( + QString("%1 Hz").arg(1.0 / minRR)); + if (maxRR > 0) + m_dockUI.minVariationLabel->setText( + QString("%1 Hz").arg(1.0 / maxRR)); } } //---------------------------------------------------------------------- GLView::GLView(QWidget* parent, QTextEdit* readout, VisMainWindow* visWin) - : QGLWidget(QGLFormat(QGL::DoubleBuffer|QGL::SampleBuffers|QGL::Rgba), parent, NULL, Qt::Widget), - m_scale(1.0), - m_xtran(0), - m_ytran(0), - m_rangeStart(0), - m_rangeEnd(0), - m_rangeStartIndex(size_t(-1)), - m_rangeEndIndex(size_t(-1)), - m_actualFPS(0.0), - m_showIdealFrames(false), - m_showEvalTiming(true), - m_readoutSample(-1), - m_readout(readout), - m_computedRefresh(0.0), - m_computedFPS(0.0), - m_visWin(visWin) + : QGLWidget(QGLFormat(QGL::DoubleBuffer | QGL::SampleBuffers | QGL::Rgba), + parent, NULL, Qt::Widget) + , m_scale(1.0) + , m_xtran(0) + , m_ytran(0) + , m_rangeStart(0) + , m_rangeEnd(0) + , m_rangeStartIndex(size_t(-1)) + , m_rangeEndIndex(size_t(-1)) + , m_actualFPS(0.0) + , m_showIdealFrames(false) + , m_showEvalTiming(true) + , m_readoutSample(-1) + , m_readout(readout) + , m_computedRefresh(0.0) + , m_computedFPS(0.0) + , m_visWin(visWin) { m_matrix.makeIdentity(); setMouseTracking(true); } -void -GLView::setRange(int start, int end) +void GLView::setRange(int start, int end) { bool foundStart = false; bool foundEnd = false; @@ -511,7 +513,7 @@ GLView::setRange(int start, int end) foundStart = true; } - if (m_data[i].frame == end+1 && !foundEnd) + if (m_data[i].frame == end + 1 && !foundEnd) { if (i > 0) { @@ -525,8 +527,7 @@ GLView::setRange(int start, int end) updateGL(); } -void -GLView::setTimeRange(float start, float end) +void GLView::setTimeRange(float start, float end) { bool foundStart = false; bool foundEnd = false; @@ -550,16 +551,16 @@ GLView::setTimeRange(float start, float end) } } } - // cerr << "rangeEnd " << m_rangeEnd << " index " << m_rangeEndIndex << endl; + // cerr << "rangeEnd " << m_rangeEnd << " index " << m_rangeEndIndex << + // endl; updateGL(); } -void -GLView::setData(const DataVector& data) +void GLView::setData(const DataVector& data) { m_data = data; m_startTime = m_data.front().render0; - m_endTime = m_data.back().swap1; + m_endTime = m_data.back().swap1; for (size_t i = 0; i < m_data.size(); i++) { @@ -572,7 +573,7 @@ GLView::setData(const DataVector& data) } else { - DataElement& e0 = m_data[i-1]; + DataElement& e0 = m_data[i - 1]; e.repeatframe = e.frame == e0.frame; e.collectionOccured = e.gccount != e0.gccount; e0.singleFrame = !e0.repeatframe && !e.repeatframe; @@ -582,67 +583,62 @@ GLView::setData(const DataVector& data) /* float d = (m_endTime - m_startTime); float y = d / float(width()); - m_matrix = scaleMatrix(Vec(d, d, 1)) - * translationMatrix(Vec(-m_startTime + 0.02, y * 0.25, 0)); + m_matrix = scaleMatrix(Vec(d, d, 1)) + * translationMatrix(Vec(-m_startTime + 0.02, y * 0.25, + 0)); */ - float d = 1.0; - float y = 4.0 * (m_endTime - m_startTime)/height(); - m_matrix = scaleMatrix(Vec(d, d, 1)) - * translationMatrix(Vec(-m_startTime , y, 0)); + float d = 1.0; + float y = 4.0 * (m_endTime - m_startTime) / height(); + m_matrix = scaleMatrix(Vec(d, d, 1)) + * translationMatrix(Vec(-m_startTime, y, 0)); updateGL(); } -void -GLView::rebuildIdealFrames() +void GLView::rebuildIdealFrames() { - if (m_actualFPS < 0) return; + if (m_actualFPS < 0) + return; } -void -GLView::setActualFPS(float fps) -{ - m_actualFPS = fps; +void GLView::setActualFPS(float fps) +{ + m_actualFPS = fps; updateGL(); } -void -GLView::setShowEvalTiming(bool b) +void GLView::setShowEvalTiming(bool b) { m_showEvalTiming = b; updateGL(); } -void -GLView::setShowIdealFrames(bool b) -{ - m_showIdealFrames = b; +void GLView::setShowIdealFrames(bool b) +{ + m_showIdealFrames = b; updateGL(); } -void -GLView::setComputedRefresh(float rate) +void GLView::setComputedRefresh(float rate) { m_computedRefresh = 1.0 / rate; updateGL(); } -void -GLView::setComputedFPS(float fps) +void GLView::setComputedFPS(float fps) { m_computedFPS = fps; updateGL(); } -int -GLView::timeToSample (float t) +int GLView::timeToSample(float t) { for (size_t i = 0; i < m_data.size(); i++) { const DataElement& e = m_data[i]; - if ((e.prefetch1 != 0.0 && e.prefetch1 >= t) || - (e.prefetch1 == 0.0 && e.swap1 >= t)) + if ((e.prefetch1 != 0.0 && e.prefetch1 >= t) + || (e.prefetch1 == 0.0 && e.swap1 >= t)) { return i; } @@ -650,195 +646,268 @@ GLView::timeToSample (float t) return -1; } -#define APP0(str) m_readoutHtml.append(QString( str )) -#define APP1(str,a1) m_readoutHtml.append(QString( str ).arg(a1)) -#define APP2(str,a1,a2) m_readoutHtml.append(QString( str ).arg(a1).arg(a2)) -#define APP3(str,a1,a2,a3) m_readoutHtml.append(QString( str ).arg(a1).arg(a2).arg(a3)) -#define APPBR() m_readoutHtml.append(QString("\n
\n")) -#define APPCOLSTART(r,g,b) m_readoutHtml.append(QString("%1").arg(indent).arg(int(r*255),2,16,QChar('0')).arg(int(g*255),2,16,QChar('0')).arg(int(b*255),2,16,QChar('0'))) -#define APPCOLEND() m_readoutHtml.append(QString("")) -#define APPCOLTXT(r,g,b,s) m_readoutHtml.append(QString("%1♦♦♦♦ %5").arg(indent).arg(int(r*255),2,16,QChar('0')).arg(int(g*255),2,16,QChar('0')).arg(int(b*255),2,16,QChar('0')).arg(s)) - -#define APPITEM(str,a1) APP3(QString(str) + QString(", start %1, end %2, total %3
\n"), a1 ## 0, a1 ## 1, a1 ## 1 - a1 ## 0) - -#define APPDELTAITEM(str,a1) APP1(QString(str) + QString(", total %1
\n"), a1) - -#define APPITEMTEST(bold,str,a1,r,g,b) \ - if (a1 ## 1 - a1 ## 0 > 0.0000) \ - { \ - APPCOLTXT(r, g, b, bold ": "); \ - APPITEM (str, a1); \ - } - -#define APPDELTAITEMTEST(bold,str,a1,r,g,b) \ - if (a1 > 0.0000) \ - { \ - APPCOLTXT(r, g, b, bold ": "); \ - APP1(str ", total %1
\n", a1); \ - } +#define APP0(str) m_readoutHtml.append(QString(str)) +#define APP1(str, a1) m_readoutHtml.append(QString(str).arg(a1)) +#define APP2(str, a1, a2) m_readoutHtml.append(QString(str).arg(a1).arg(a2)) +#define APP3(str, a1, a2, a3) \ + m_readoutHtml.append(QString(str).arg(a1).arg(a2).arg(a3)) +#define APPBR() m_readoutHtml.append(QString("\n
\n")) +#define APPCOLSTART(r, g, b) \ + m_readoutHtml.append(QString("%1") \ + .arg(indent) \ + .arg(int(r * 255), 2, 16, QChar('0')) \ + .arg(int(g * 255), 2, 16, QChar('0')) \ + .arg(int(b * 255), 2, 16, QChar('0'))) +#define APPCOLEND() m_readoutHtml.append(QString("")) +#define APPCOLTXT(r, g, b, s) \ + m_readoutHtml.append( \ + QString("%1♦♦♦♦ " \ + "%5") \ + .arg(indent) \ + .arg(int(r * 255), 2, 16, QChar('0')) \ + .arg(int(g * 255), 2, 16, QChar('0')) \ + .arg(int(b * 255), 2, 16, QChar('0')) \ + .arg(s)) + +#define APPITEM(str, a1) \ + APP3(QString(str) + QString(", start %1, end %2, total %3
\n"), a1##0, \ + a1##1, a1##1 - a1##0) + +#define APPDELTAITEM(str, a1) \ + APP1(QString(str) + QString(", total %1
\n"), a1) + +#define APPITEMTEST(bold, str, a1, r, g, b) \ + if (a1##1 - a1##0 > 0.0000) \ + { \ + APPCOLTXT(r, g, b, bold ": "); \ + APPITEM(str, a1); \ + } -#define APPITEMTESTBOLD(bold,str,a1) \ - if (a1 ## 1 - a1 ## 0 > 0.0000) \ - { \ - m_readoutHtml.append(QString("%1%2 ").arg(indent).arg(bold));\ - APPITEM (str, a1); \ - } +#define APPDELTAITEMTEST(bold, str, a1, r, g, b) \ + if (a1 > 0.0000) \ + { \ + APPCOLTXT(r, g, b, bold ": "); \ + APP1(str ", total %1
\n", a1); \ + } +#define APPITEMTESTBOLD(bold, str, a1) \ + if (a1##1 - a1##0 > 0.0000) \ + { \ + m_readoutHtml.append(QString("%1%2 ").arg(indent).arg(bold)); \ + APPITEM(str, a1); \ + } -void -GLView::generateHtml() +void GLView::generateHtml() { m_readoutHtml = ""; QString indent; QString spaces = QString("      "); - if (m_readoutSample < 0 || m_readoutSample >= m_data.size()) return; + if (m_readoutSample < 0 || m_readoutSample >= m_data.size()) + return; const DataElement& e = m_data[m_readoutSample]; - const DataElement& elast = m_data[(m_readoutSample == 0) ? 0 : m_readoutSample - 1]; + const DataElement& elast = + m_data[(m_readoutSample == 0) ? 0 : m_readoutSample - 1]; - APP0 (""); - APP1 ("Start with frame %1, ", elast.frame); - APP1 ("swap to frame %1.", e.frame); + APP0(""); + APP1("Start with frame %1, ", elast.frame); + APP1("swap to frame %1.", e.frame); APPBR(); APPBR(); - APPCOLTXT ((e.repeatframe ? 0.6 : 1), .3, .3, "render start: "); - APPITEM ("from begin of GLView::paint, until we wait for swap", e.render); - - indent = spaces; - APPCOLTXT (.3, 1, .3, "evaluate (render) start: "); - APPITEM ("Evaluation during Session::render (Session::evaluateForDisplay)", e.eval); - - if (e.cacheTest0 < e.eval1) - { - QString saveIndent = indent; - indent = saveIndent+spaces; - APPITEMTEST ("cacheTest", "test to see if image is in cache, IPGraph::evaluateAtFrame()", e.cacheTest, 1, 1, 0); - - indent = saveIndent+spaces+spaces; - APPITEMTESTBOLD ("cacheTestLock", "acquire lock on frame cache", e.cacheTestLock); - APPITEMTESTBOLD ("setDisplayFrame", "set display frame on frame cache", e.setDisplayFrame); - APPITEMTESTBOLD ("frameCachedTest", "check that all FBs for this frame are in cache", e.frameCachedTest); + APPCOLTXT((e.repeatframe ? 0.6 : 1), .3, .3, "render start: "); + APPITEM("from begin of GLView::paint, until we wait for swap", e.render); - indent = saveIndent+spaces; - APPITEMTESTBOLD ("evalGraph", "get the FBs for this frame from cache.", e.evalGraph); - } - - - indent = spaces; - APPCOLTXT (.3, 1, .3, "evaluate (render) end"); - APPBR(); + indent = spaces; + APPCOLTXT(.3, 1, .3, "evaluate (render) start: "); + APPITEM("Evaluation during Session::render (Session::evaluateForDisplay)", + e.eval); - APPCOLTXT (1, .6, .6, "internalRender: "); - APPITEM ("Internal render time, total time in CompositeRenderer::render", e.internalRender); - - indent = spaces+spaces; - APPITEMTEST ("userRender", "userRender code (handling \"render\" event). only time delta is valid.", e.userRender, .6, .6, 1); - APPITEMTEST ("frameChange", "internal frameChangedMessage processing plug \"frame-changed\" user event.", e.frameChange, 1, 1, .6); + if (e.cacheTest0 < e.eval1) + { + QString saveIndent = indent; + indent = saveIndent + spaces; + APPITEMTEST( + "cacheTest", + "test to see if image is in cache, IPGraph::evaluateAtFrame()", + e.cacheTest, 1, 1, 0); + + indent = saveIndent + spaces + spaces; + APPITEMTESTBOLD("cacheTestLock", "acquire lock on frame cache", + e.cacheTestLock); + APPITEMTESTBOLD("setDisplayFrame", "set display frame on frame cache", + e.setDisplayFrame); + APPITEMTESTBOLD("frameCachedTest", + "check that all FBs for this frame are in cache", + e.frameCachedTest); + + indent = saveIndent + spaces; + APPITEMTESTBOLD("evalGraph", "get the FBs for this frame from cache.", + e.evalGraph); + } - APPDELTAITEMTEST ("renderFenceWait", "total fence wait time. should only be non-zero in presentation mode.", e.renderFenceWait, .6, .2, .2); - APPDELTAITEMTEST ("renderUploadPlane", "total time in uploadPlane(). should only be non-zero if upload did not complete in prefetch.", e.renderUploadPlane, .6, .2, .6); + indent = spaces; + APPCOLTXT(.3, 1, .3, "evaluate (render) end"); + APPBR(); - indent = spaces; - APPCOLTXT (1, .6, .6, "internalRender end"); - APPBR(); + APPCOLTXT(1, .6, .6, "internalRender: "); + APPITEM("Internal render time, total time in CompositeRenderer::render", + e.internalRender); + + indent = spaces + spaces; + APPITEMTEST("userRender", + "userRender code (handling \"render\" event). only time delta " + "is valid.", + e.userRender, .6, .6, 1); + APPITEMTEST("frameChange", + "internal frameChangedMessage processing plug " + "\"frame-changed\" user event.", + e.frameChange, 1, 1, .6); + + APPDELTAITEMTEST( + "renderFenceWait", + "total fence wait time. should only be non-zero in presentation mode.", + e.renderFenceWait, .6, .2, .2); + APPDELTAITEMTEST("renderUploadPlane", + "total time in uploadPlane(). should only be non-zero if " + "upload did not complete in prefetch.", + e.renderUploadPlane, .6, .2, .6); + + indent = spaces; + APPCOLTXT(1, .6, .6, "internalRender end"); + APPBR(); indent = ""; - APPCOLTXT ((e.repeatframe ? 0.6 : 1), .3, .3, "render end"); + APPCOLTXT((e.repeatframe ? 0.6 : 1), .3, .3, "render end"); APPBR(); float swapDiff = e.swap1 - e.swap0; - float swapRate = (swapDiff == 0.0) ? 0.0 : 1.0/swapDiff; + float swapRate = (swapDiff == 0.0) ? 0.0 : 1.0 / swapDiff; QString swapText; - if (swapRate != 0.0 && m_computedRefresh != 0.0 && swapRate < 1.0/m_computedRefresh) + if (swapRate != 0.0 && m_computedRefresh != 0.0 + && swapRate < 1.0 / m_computedRefresh) { - swapText = QString("rendering complete, waiting for buffer swap, equiv rate = %1").arg(swapRate); + swapText = QString("rendering complete, waiting for buffer swap, " + "equiv rate = %1") + .arg(swapRate); } else { - swapText = QString("rendering complete, waiting for buffer swap, equiv rate = %1").arg(swapRate); + swapText = + QString( + "rendering complete, waiting for buffer swap, equiv rate = %1") + .arg(swapRate); } - APPITEMTEST ("buffer swap / vsync", swapText, e.swap, .3, .3, .75); - - APPITEMTEST ("awaken", "awaken caching threads post-render", e.awaken, .2, .6, .6); - - APPCOLTXT (.7, 1, 1, "prefetch: "); - APPITEM ("time spent in Session::postRender, including eval time if prefetching.", e.prefetch); - - if (e.cacheTest1 > e.prefetch0) - { - QString saveIndent = indent; - indent = saveIndent+spaces; - APPITEMTEST ("cacheTest", "test to see if image is in cache, IPGraph::evaluateAtFrame()", e.cacheTest, 1, 1, 0); + APPITEMTEST("buffer swap / vsync", swapText, e.swap, .3, .3, .75); - indent = saveIndent+spaces+spaces; + APPITEMTEST("awaken", "awaken caching threads post-render", e.awaken, .2, + .6, .6); - APPITEMTESTBOLD ("cacheTestLock", "acquire lock on frame cache", e.cacheTestLock); - APPITEMTESTBOLD ("setDisplayFrame", "set display frame on frame cache", e.setDisplayFrame); - APPITEMTESTBOLD ("frameCachedTest", "check that all FBs for this frame are in cache", e.frameCachedTest); + APPCOLTXT(.7, 1, 1, "prefetch: "); + APPITEM("time spent in Session::postRender, including eval time if " + "prefetching.", + e.prefetch); - indent = saveIndent+spaces; - APPITEMTESTBOLD ("evalGraph", "get the FBs for this frame from cache.", e.evalGraph); - } + if (e.cacheTest1 > e.prefetch0) + { + QString saveIndent = indent; + indent = saveIndent + spaces; + APPITEMTEST( + "cacheTest", + "test to see if image is in cache, IPGraph::evaluateAtFrame()", + e.cacheTest, 1, 1, 0); + + indent = saveIndent + spaces + spaces; + + APPITEMTESTBOLD("cacheTestLock", "acquire lock on frame cache", + e.cacheTestLock); + APPITEMTESTBOLD("setDisplayFrame", "set display frame on frame cache", + e.setDisplayFrame); + APPITEMTESTBOLD("frameCachedTest", + "check that all FBs for this frame are in cache", + e.frameCachedTest); + + indent = saveIndent + spaces; + APPITEMTESTBOLD("evalGraph", "get the FBs for this frame from cache.", + e.evalGraph); + } - indent = spaces; - APPCOLTXT (.6, .2, .2, "prefetchRender: "); - APPITEM ("total prefetch rendertime, CompositeRenderer::prefetch.", e.prefetchRender); + indent = spaces; + APPCOLTXT(.6, .2, .2, "prefetchRender: "); + APPITEM("total prefetch rendertime, CompositeRenderer::prefetch.", + e.prefetchRender); - indent = spaces+spaces; - APPDELTAITEMTEST ("prefetchUploadPlanes", "time spent in uploadPlanes, may be zero of upload is async", e.prefetchUploadPlane, .6, .2, .6); + indent = spaces + spaces; + APPDELTAITEMTEST( + "prefetchUploadPlanes", + "time spent in uploadPlanes, may be zero of upload is async", + e.prefetchUploadPlane, .6, .2, .6); - indent = spaces; - APPCOLTXT (.6, .2, .2, "prefetchRender end "); - APPBR(); + indent = spaces; + APPCOLTXT(.6, .2, .2, "prefetchRender end "); + APPBR(); indent = ""; - APPCOLTXT (.7, 1, 1, "prefetch end"); + APPCOLTXT(.7, 1, 1, "prefetch end"); APPBR(); APPBR(); - APP0 ("Cache Node Evaluation Items (CacheIPNode::evaluate) These may be garbled by timing issues if caching is happening during playback.
"); - - indent = spaces; - APPITEMTEST ("evalID", "evaluate identifiers preparatory to looking them up in the cache", e.evalID, .75, 1, .75); - APPITEMTEST ("cacheQuery", "evaluate identifiers preparatory to looking them up in the cache.", e.cacheQuery, 0, .75, 1); - APPITEMTEST ("cacheEval", "actually evaluate the FBs for this frame.", e.cacheEval, 1, .6, 1); - APPITEMTESTBOLD ("IO", "FileSource calling imagesAtFrame on it's movies.", e.io); + APP0("Cache Node Evaluation Items (CacheIPNode::evaluate) These " + "may be garbled by timing issues if caching is happening during " + "playback.
"); + + indent = spaces; + APPITEMTEST( + "evalID", + "evaluate identifiers preparatory to looking them up in the cache", + e.evalID, .75, 1, .75); + APPITEMTEST( + "cacheQuery", + "evaluate identifiers preparatory to looking them up in the cache.", + e.cacheQuery, 0, .75, 1); + APPITEMTEST("cacheEval", "actually evaluate the FBs for this frame.", + e.cacheEval, 1, .6, 1); + APPITEMTESTBOLD("IO", "FileSource calling imagesAtFrame on it's movies.", + e.io); indent = ""; APPBR(); - APP1 ("%1 Garbage collections so far.", e.gccount); + APP1("%1 Garbage collections so far.", e.gccount); APPBR(); - APP3 ("Expected time of next vsync: %1, which is in the %2 (%3 sec from end of render).", - e.expectedSyncTime, ((e.expectedSyncTime < e.render1) ? "past" : "future"), (e.expectedSyncTime-e.render1)); + APP3("Expected time of next vsync: %1, which is in the %2 (%3 sec from end " + "of render).", + e.expectedSyncTime, + ((e.expectedSyncTime < e.render1) ? "past" : "future"), + (e.expectedSyncTime - e.render1)); if (e.deviceClockOffset != 0.0) { APPBR(); - APP1 ("Elapsed play time - Device clock = %1 seconds.", e.deviceClockOffset); + APP1("Elapsed play time - Device clock = %1 seconds.", + e.deviceClockOffset); } - APP0 (""); + APP0(""); // cerr << m_readoutHtml.toStdString() << endl; } -int -GLView::sampleFromMousePosition(float x, float y) +int GLView::sampleFromMousePosition(float x, float y) { - float tx = m_startTime + (x / width()) * (m_endTime - m_startTime); - float ty = m_startTime + (-y / height()) * (m_endTime - m_startTime) * (height() / width()); + float tx = m_startTime + (x / width()) * (m_endTime - m_startTime); + float ty = + m_startTime + + (-y / height()) * (m_endTime - m_startTime) * (height() / width()); Matrix m = m_matrix; m.invert(); Vec t = m * Vec(tx, ty, 0); - return timeToSample (t.x); + return timeToSample(t.x); } -void -GLView::mouseMoveEvent(QMouseEvent* event) +void GLView::mouseMoveEvent(QMouseEvent* event) { QPoint dp = event->pos() - m_mouseDown; float w = width(); @@ -846,7 +915,8 @@ GLView::mouseMoveEvent(QMouseEvent* event) if (event->buttons() == Qt::NoButton) { - int sample = sampleFromMousePosition (event->pos().x(), event->pos().y()); + int sample = + sampleFromMousePosition(event->pos().x(), event->pos().y()); if (sample != m_readoutSample) { @@ -860,32 +930,26 @@ GLView::mouseMoveEvent(QMouseEvent* event) if (event->buttons() & Qt::RightButton) { Vec t(.5 * (m_endTime - m_startTime), - .5 * (m_endTime - m_startTime) * (h / w), - 0); + .5 * (m_endTime - m_startTime) * (h / w), 0); float a = dp.x() * .8; a *= 0.001; a += 1.0; - m_matrix = - translationMatrix(t) - * scaleMatrix(Vec(a, a, 1)) - * translationMatrix(-t) - * m_matrix; + m_matrix = translationMatrix(t) + * scaleMatrix(Vec(a, a, 1)) + * translationMatrix(-t) * m_matrix; } - else - if (event->buttons() & Qt::LeftButton) + else if (event->buttons() & Qt::LeftButton) { - Vec t = Vec(dp.x() / w * (m_endTime - m_startTime), - -dp.y() / h * (m_endTime - m_startTime) * (h / w), - 0); - m_matrix = translationMatrix(t) * m_matrix; + Vec t = Vec(dp.x() / w * (m_endTime - m_startTime), + -dp.y() / h * (m_endTime - m_startTime) * (h / w), 0); + m_matrix = translationMatrix(t) * m_matrix; } m_mouseDown = event->pos(); updateGL(); } -void -GLView::autoRangeProcessing() +void GLView::autoRangeProcessing() { if (m_rangeEnd > m_rangeStart) { @@ -898,8 +962,7 @@ GLView::autoRangeProcessing() } } -void -GLView::mousePressEvent(QMouseEvent* event) +void GLView::mousePressEvent(QMouseEvent* event) { m_mouseDown = event->pos(); @@ -907,52 +970,59 @@ GLView::mousePressEvent(QMouseEvent* event) { if (event->modifiers() & Qt::ShiftModifier) { - int sample = sampleFromMousePosition (event->pos().x(), event->pos().y()); + int sample = + sampleFromMousePosition(event->pos().x(), event->pos().y()); m_rangeStartIndex = sample; while (m_rangeStartIndex > 1) { - const DataElement& one = m_data[m_rangeStartIndex-1]; + const DataElement& one = m_data[m_rangeStartIndex - 1]; const DataElement& two = m_data[m_rangeStartIndex]; - if (one.expectedSyncTime == 0.0 || two.expectedSyncTime == 0.0) break; - if (one.frame > two.frame) break; + if (one.expectedSyncTime == 0.0 || two.expectedSyncTime == 0.0) + break; + if (one.frame > two.frame) + break; --m_rangeStartIndex; } ++m_rangeStartIndex; int frame = m_data[m_rangeStartIndex].frame; - while (frame == m_data[m_rangeStartIndex].frame) ++m_rangeStartIndex; + while (frame == m_data[m_rangeStartIndex].frame) + ++m_rangeStartIndex; m_rangeStart = m_data[m_rangeStartIndex].render0; m_rangeEndIndex = sample; - while (m_rangeEndIndex < m_data.size()-1) + while (m_rangeEndIndex < m_data.size() - 1) { - const DataElement& one = m_data[m_rangeEndIndex-1]; + const DataElement& one = m_data[m_rangeEndIndex - 1]; const DataElement& two = m_data[m_rangeEndIndex]; - if (one.expectedSyncTime == 0.0 || two.expectedSyncTime == 0.0) break; - if (one.frame > two.frame) break; + if (one.expectedSyncTime == 0.0 || two.expectedSyncTime == 0.0) + break; + if (one.frame > two.frame) + break; ++m_rangeEndIndex; } --m_rangeEndIndex; frame = m_data[m_rangeEndIndex].frame; - while (frame == m_data[m_rangeEndIndex].frame) --m_rangeEndIndex; + while (frame == m_data[m_rangeEndIndex].frame) + --m_rangeEndIndex; m_rangeEnd = m_data[m_rangeEndIndex].swap1; autoRangeProcessing(); } - else - if (event->modifiers() & Qt::ControlModifier) + else if (event->modifiers() & Qt::ControlModifier) { - int sample = sampleFromMousePosition (event->pos().x(), event->pos().y()); + int sample = + sampleFromMousePosition(event->pos().x(), event->pos().y()); m_rangeStart = m_data[sample].render0; m_rangeStartIndex = sample; autoRangeProcessing(); } - else - if (event->modifiers() & Qt::AltModifier) + else if (event->modifiers() & Qt::AltModifier) { - int sample = sampleFromMousePosition (event->pos().x(), event->pos().y()); + int sample = + sampleFromMousePosition(event->pos().x(), event->pos().y()); m_rangeEnd = m_data[sample].swap1; m_rangeEndIndex = sample; autoRangeProcessing(); @@ -961,57 +1031,40 @@ GLView::mousePressEvent(QMouseEvent* event) updateGL(); } -void -GLView::mouseReleaseEvent(QMouseEvent* event) -{ -} +void GLView::mouseReleaseEvent(QMouseEvent* event) {} -void -GLView::wheelEvent(QWheelEvent* event) +void GLView::wheelEvent(QWheelEvent* event) { float w = width(); float h = height(); Vec t(.5 * (m_endTime - m_startTime), - .5 * (m_endTime - m_startTime) * (h / w), - 0); + .5 * (m_endTime - m_startTime) * (h / w), 0); float a = event->delta() * .8; a *= 0.001; a += 1.0; - m_matrix = - translationMatrix(t) - * scaleMatrix(Vec(a, a, 1)) - * translationMatrix(-t) - * m_matrix; + m_matrix = translationMatrix(t) * scaleMatrix(Vec(a, a, 1)) + * translationMatrix(-t) * m_matrix; updateGL(); } -void -GLView::initializeGL() +void GLView::initializeGL() { Context c = GLtext::newContext(); GLtext::setContext(c); GLtext::init(); } -void -GLView::resizeGL(int, int) -{ +void GLView::resizeGL(int, int) +{ glViewport(0, 0, width(), height()); - updateGL(); + updateGL(); } -static void drawBox( - float r, - float g, - float b, - float a, - float llx, - float lly, - float urx, - float ury) +static void drawBox(float r, float g, float b, float a, float llx, float lly, + float urx, float ury) { glColor4f(r, g, b, a); glBegin(GL_POLYGON); @@ -1022,19 +1075,8 @@ static void drawBox( glEnd(); } -static void drawBox( - float r, - float g, - float b, - float a, - float x0, - float y0, - float x1, - float y1, - float x2, - float y2, - float x3, - float y3) +static void drawBox(float r, float g, float b, float a, float x0, float y0, + float x1, float y1, float x2, float y2, float x3, float y3) { glColor4f(r, g, b, a); glBegin(GL_POLYGON); @@ -1045,13 +1087,16 @@ static void drawBox( glEnd(); } -void -GLView::paintGL() +void GLView::paintGL() { glViewport(0, 0, width(), height()); - glClearColor(0.5f, 0.5f, 0.5f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT); - if (m_data.empty()) { glFinish(); return; } + glClearColor(0.5f, 0.5f, 0.5f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + if (m_data.empty()) + { + glFinish(); + return; + } int idealStartIndex = -1; int lastIdealFrame = -1; @@ -1085,28 +1130,30 @@ GLView::paintGL() { const DataElement& e = m_data[i]; - // - // Red box: all GLview paint time; many other times are - // fractions of this time, so drawn over this box. brighter for - // the first time we've rendered this frame. This includs all of - // Sesssion::render(). - // + // + // Red box: all GLview paint time; many other times are + // fractions of this time, so drawn over this box. brighter for + // the first time we've rendered this frame. This includs all of + // Sesssion::render(). + // y0 = h0; - y1 = h/3.0; + y1 = h / 3.0; - drawBox(e.repeatframe ? 0.6 : 1, .3, .3, 1, e.render0, y0, e.render1, y1); + drawBox(e.repeatframe ? 0.6 : 1, .3, .3, 1, e.render0, y0, e.render1, + y1); - // - // Green box, drawn above render box. corresponds to Session's evaluateForDisplay(). - // + // + // Green box, drawn above render box. corresponds to Session's + // evaluateForDisplay(). + // y0 = y1; - y1 = 2*h/3.0; + y1 = 2 * h / 3.0; - drawBox (.3, 1, .3, 1, e.eval0, y0, e.eval1, y1); + drawBox(.3, 1, .3, 1, e.eval0, y0, e.eval1, y1); - if (m_showEvalTiming) + if (m_showEvalTiming) { // // Eval time components may come from evalFrameForDisplay (part of @@ -1121,12 +1168,12 @@ GLView::paintGL() y0 = y1; y1 = h; - // - // Yellow: Testing to see if image is already in cache, first part - // of IPGraph::evaluateAtFrame() - // + // + // Yellow: Testing to see if image is already in cache, first part + // of IPGraph::evaluateAtFrame() + // - drawBox (1, 1, 0, 1, e.cacheTest0, y0, e.cacheTest1, y1); + drawBox(1, 1, 0, 1, e.cacheTest0, y0, e.cacheTest1, y1); // // Below three happen in CacheNode::evaluate, so if caching is @@ -1134,41 +1181,43 @@ GLView::paintGL() // up (IE numbers here may have nothing to do with this frame). // - // - // Light green: In CacheNode::evaluate, evaluate the IDs - // prepratory to testing for presence in cache. - // + // + // Light green: In CacheNode::evaluate, evaluate the IDs + // prepratory to testing for presence in cache. + // - drawBox (.75, 1, .75, 1, e.evalID0, y0, e.evalID1, y1); + drawBox(.75, 1, .75, 1, e.evalID0, y0, e.evalID1, y1); - // - // Sky blue: Now we have the IDs, query the cache to see if they - // are there. - // + // + // Sky blue: Now we have the IDs, query the cache to see if they + // are there. + // - drawBox (0, .75, 1, 1, e.cacheQuery0, y0, e.cacheQuery1, y1); + drawBox(0, .75, 1, 1, e.cacheQuery0, y0, e.cacheQuery1, y1); - // - // Light magenta: If we didn't find our frame buffers in the - // cache, evaluate cache node input to get them. This color only - // appears if the display thread does the eval (caching is off). - // - - drawBox (1, .6, 1, 1, e.cacheEval0, y0, e.cacheEval1, y1); + // + // Light magenta: If we didn't find our frame buffers in the + // cache, evaluate cache node input to get them. This color only + // appears if the display thread does the eval (caching is off). + // + + drawBox(1, .6, 1, 1, e.cacheEval0, y0, e.cacheEval1, y1); } // - // Light red. Internal render time (total time in CompositeRenderer::render() - // Disjoint from eval time in total paint time, so draw in 2nd vertical third. + // Light red. Internal render time (total time in + // CompositeRenderer::render() Disjoint from eval time in total paint + // time, so draw in 2nd vertical third. // - y0 = h/3.0; - y1 = 2.0*h/3.0; + y0 = h / 3.0; + y1 = 2.0 * h / 3.0; - drawBox (1, .6, .6, 1, e.internalRender0, y0, e.internalRender1, y1); + drawBox(1, .6, .6, 1, e.internalRender0, y0, e.internalRender1, y1); // - // Next four are subsets of Internal Render, so draw above in top vertical third. + // Next four are subsets of Internal Render, so draw above in top + // vertical third. // y0 = y1; @@ -1183,7 +1232,7 @@ GLView::paintGL() x0 = e.internalRender0; x1 = x0 + e.userRender1 - e.userRender0; - drawBox (.6, .6, 1, 1, x0, y0, x1, y1); + drawBox(.6, .6, 1, 1, x0, y0, x1, y1); // // Light yellow. Time spent in "frame change", both internal @@ -1193,7 +1242,7 @@ GLView::paintGL() x0 = x1; x1 = x0 + e.frameChange1 - e.frameChange0; - drawBox (1, 1, .6, 1, x0, y0, x1, y1); + drawBox(1, 1, .6, 1, x0, y0, x1, y1); // // dark green. Total time spent waiting on glfences in render, should @@ -1203,17 +1252,18 @@ GLView::paintGL() x0 = x1; x1 = x0 + e.renderFenceWait; - drawBox (.6, .2, .2, 1, x0, y0, x1, y1); + drawBox(.6, .2, .2, 1, x0, y0, x1, y1); // // dark magenta. Total time spent in uploadPlane() in render, should - // only be non-zero if texture uploads did not complete during prefetch. + // only be non-zero if texture uploads did not complete during + // prefetch. // x0 = x1; x1 = x0 + e.renderUploadPlane; - drawBox (.6, .2, .6, 1, x0, y0, x1, y1); + drawBox(.6, .2, .6, 1, x0, y0, x1, y1); // // Dark blue. Swap wait. Full height @@ -1221,7 +1271,7 @@ GLView::paintGL() y0 = 0; y1 = h; - drawBox (.3, .3, .75, 1, e.swap0, y0, e.swap1, y1); + drawBox(.3, .3, .75, 1, e.swap0, y0, e.swap1, y1); // // Dark Cyan. Awakening caching threads (part of @@ -1230,19 +1280,19 @@ GLView::paintGL() y0 = 0; y1 = h; - drawBox (.2, .6, .6, 1, e.awaken0, y0, e.awaken1, y1); + drawBox(.2, .6, .6, 1, e.awaken0, y0, e.awaken1, y1); // // Light cyan. Prefetch (time spend in Session::postRender(). If // prefetch is on, this includes eval time (for next frame). // - y0 = h/3.0; - y1 = 2.0*h/3.0; + y0 = h / 3.0; + y1 = 2.0 * h / 3.0; if (e.prefetch0 != 0.0 && e.prefetch1 != 0.0) { - drawBox (.7, 1, 1, 1, e.prefetch0, y0, e.prefetch1, y1); + drawBox(.7, 1, 1, 1, e.prefetch0, y0, e.prefetch1, y1); } // @@ -1253,10 +1303,10 @@ GLView::paintGL() // in upper third. // - y0 = 2.0*h/3.0; + y0 = 2.0 * h / 3.0; y1 = h; - // + // // dark magenta. Total time spent in uploadPlane() in prefetch, should // really never be non-zero (because it should be asynchronous). // @@ -1266,7 +1316,7 @@ GLView::paintGL() x0 = e.prefetchRender0; x1 = x0 + e.prefetchUploadPlane; - drawBox (.6, .2, .6, 1, x0, y0, x1, y1); + drawBox(.6, .2, .6, 1, x0, y0, x1, y1); } // @@ -1286,7 +1336,7 @@ GLView::paintGL() // // Draw text last // - + for (size_t i = 0; i < m_data.size(); i++) { const DataElement& e = m_data[i]; @@ -1295,7 +1345,7 @@ GLView::paintGL() // Swap tick // glLineWidth(2.0); - glColor4f(0,0,0,.5); + glColor4f(0, 0, 0, .5); glBegin(GL_LINES); glVertex2f(e.swap1, h); glVertex2f(e.swap1, h + h * .1); @@ -1306,7 +1356,7 @@ GLView::paintGL() // if (e.expectedSyncTime != 0.0) { - glColor4f(.7,.2,.2,1); + glColor4f(.7, .2, .2, 1); glBegin(GL_LINES); glVertex2f(e.render0, 0); glVertex2f(e.expectedSyncTime, h); @@ -1315,7 +1365,9 @@ GLView::paintGL() GLtext::size(20.0); GLtext::color(.7, .2, .2, 1); - float s = 1.0 / (GLtext::globalAscenderHeight() - GLtext::globalDescenderHeight()); + float s = 1.0 + / (GLtext::globalAscenderHeight() + - GLtext::globalDescenderHeight()); ostringstream str; str << e.frame; glPushMatrix(); @@ -1327,12 +1379,14 @@ GLView::paintGL() // // Frame flags - // + // if (!e.repeatframe) { GLtext::size(20.0); GLtext::color(0, 0, 0, .7); - float s = 1.0 / (GLtext::globalAscenderHeight() - GLtext::globalDescenderHeight()); + float s = 1.0 + / (GLtext::globalAscenderHeight() + - GLtext::globalDescenderHeight()); ostringstream str; str << e.frame; @@ -1341,7 +1395,7 @@ GLView::paintGL() float th = (b.max.y - b.min.y) * s * 0.0065; float slop = .0008; - glColor4f(1,1,1,.5); + glColor4f(1, 1, 1, .5); glBegin(GL_POLYGON); glVertex2f(e.swap1 - slop, h + h * .11 - slop); glVertex2f(e.swap1 + tw + slop, h + h * .11 - slop); @@ -1349,7 +1403,7 @@ GLView::paintGL() glVertex2f(e.swap1 + tw + slop, h + h * .11 + th + slop); glVertex2f(e.swap1 - slop, h + h * .11 + th + slop); glEnd(); - + glPushMatrix(); glTranslatef(e.swap1, h + h * .11, 0); glScalef(s * .0065, s * .0065, 1.0); @@ -1362,7 +1416,7 @@ GLView::paintGL() // if (e.singleFrame) { - glColor4f(0, 0, 0,.7); + glColor4f(0, 0, 0, .7); glLineWidth(2.0); glBegin(GL_LINES); glVertex2f(e.swap1, h + h * .25); @@ -1371,7 +1425,9 @@ GLView::paintGL() GLtext::size(50.0); GLtext::color(1, 1, 1, 1); - float s = 1.0 / (GLtext::globalAscenderHeight() - GLtext::globalDescenderHeight()); + float s = 1.0 + / (GLtext::globalAscenderHeight() + - GLtext::globalDescenderHeight()); ostringstream str; str << "*1 "; @@ -1380,14 +1436,14 @@ GLView::paintGL() float th = (b.max.y - b.min.y) * s * 0.0065; float slop = .0008; - glColor4f(1,.5,0,.8); + glColor4f(1, .5, 0, .8); glBegin(GL_POLYGON); glVertex2f(e.swap1 - slop, h + h * .4 - slop); glVertex2f(e.swap1 + tw + slop, h + h * .4 - slop); glVertex2f(e.swap1 + tw + slop, h + h * .4 + th + slop); glVertex2f(e.swap1 - slop, h + h * .4 + th + slop); glEnd(); - + glPushMatrix(); glTranslatef(e.swap1, h + h * .4, 0); glScalef(s * .0065, s * .0065, 1.0); @@ -1397,7 +1453,7 @@ GLView::paintGL() if (e.collectionOccured) { - glColor4f(0, 0, 0,.7); + glColor4f(0, 0, 0, .7); glLineWidth(2.0); glBegin(GL_LINES); glVertex2f(e.swap1, h + h * .25); @@ -1406,7 +1462,9 @@ GLView::paintGL() GLtext::size(20.0); GLtext::color(0, 0, 0, .85); - float s = 1.0 / (GLtext::globalAscenderHeight() - GLtext::globalDescenderHeight()); + float s = 1.0 + / (GLtext::globalAscenderHeight() + - GLtext::globalDescenderHeight()); ostringstream str; str << "GC# " << e.gccount << " "; @@ -1415,14 +1473,14 @@ GLView::paintGL() float th = (b.max.y - b.min.y) * s * 0.0100; float slop = .0008; - glColor4f(1,0,1,.9); + glColor4f(1, 0, 1, .9); glBegin(GL_POLYGON); glVertex2f(e.swap1 - slop, h + h * .7 - slop); glVertex2f(e.swap1 + tw + slop, h + h * .7 - slop); glVertex2f(e.swap1 + tw + slop, h + h * .7 + th + slop); glVertex2f(e.swap1 - slop, h + h * .7 + th + slop); glEnd(); - + glPushMatrix(); glTranslatef(e.swap1, h + h * .7, 0); glScalef(s * .0100, s * .0100, 1.0); @@ -1430,7 +1488,8 @@ GLView::paintGL() glPopMatrix(); } - if (false && m_showIdealFrames && i >= m_rangeStartIndex && i <= m_rangeEndIndex) + if (false && m_showIdealFrames && i >= m_rangeStartIndex + && i <= m_rangeEndIndex) { if (idealStartIndex == -1) { @@ -1443,14 +1502,18 @@ GLView::paintGL() else { int startFrame = m_data[idealStartIndex].frame; - int frame = startFrame + int(0.5 + ((e.swap1 - m_data[idealStartIndex].swap1)*m_actualFPS)); + int frame = startFrame + + int(0.5 + + ((e.swap1 - m_data[idealStartIndex].swap1) + * m_actualFPS)); /* int nsyncs = i - m_rangeStartIndex; double t = nsyncs * m_computedRefresh; double t0 = (nsyncs - 1) * m_computedRefresh; int frame = m_actualFPS * t + m_data[m_rangeStartIndex].frame; - int previous = m_actualFPS * t0 + m_data[m_rangeStartIndex].frame; + int previous = m_actualFPS * t0 + + m_data[m_rangeStartIndex].frame; if (frame != previous) { @@ -1460,7 +1523,9 @@ GLView::paintGL() lastIdealFrame = frame; GLtext::size(20.0); GLtext::color(0, 0, 0, .7); - float s = 1.0 / (GLtext::globalAscenderHeight() - GLtext::globalDescenderHeight()); + float s = 1.0 + / (GLtext::globalAscenderHeight() + - GLtext::globalDescenderHeight()); ostringstream str; str << frame; @@ -1469,7 +1534,7 @@ GLView::paintGL() float th = (b.max.y - b.min.y) * s * 0.0065; float slop = .0008; - glColor4f(.5,1,1,.5); + glColor4f(.5, 1, 1, .5); glBegin(GL_POLYGON); glVertex2f(e.swap1 - slop, h + h * .21 - slop); glVertex2f(e.swap1 + tw + slop, h + h * .21 - slop); @@ -1477,7 +1542,7 @@ GLView::paintGL() glVertex2f(e.swap1 + tw + slop, h + h * .21 + th + slop); glVertex2f(e.swap1 - slop, h + h * .21 + th + slop); glEnd(); - + glPushMatrix(); glTranslatef(e.swap1, h + h * .21, 0); glScalef(s * .0065, s * .0065, 1.0); @@ -1490,49 +1555,52 @@ GLView::paintGL() if (m_showIdealFrames) { - idealStartIndex = m_rangeStartIndex; - - const DataElement& e = m_data[0]; - int i; - for (i = m_rangeStartIndex; m_data[i].repeatframe; ++i) ; - - int startFrame = m_data[i].frame; - double time = m_data[i].swap1; - double endTime = m_data[m_rangeEndIndex].swap1; - - for (int frame = startFrame+1; time < endTime; ++frame) - { - time = time + 1.0/m_actualFPS; - - GLtext::size(20.0); - GLtext::color(0, 0, 0, .7); - float s = 1.0 / (GLtext::globalAscenderHeight() - GLtext::globalDescenderHeight()); - ostringstream str; - str << frame; - - Box2f b = GLtext::bounds(str.str()); - float tw = (b.max.x - b.min.x) * s * 0.0065; - float th = (b.max.y - b.min.y) * s * 0.0065; - float slop = .0008; - - glColor4f(.5,1,1,.5); - glBegin(GL_POLYGON); - glVertex2f(time - slop, h + h * .21 - slop); - glVertex2f(time + tw + slop, h + h * .21 - slop); - glVertex2f(time + tw + slop * 6, h + h * .21 + th / 2); - glVertex2f(time + tw + slop, h + h * .21 + th + slop); - glVertex2f(time - slop, h + h * .21 + th + slop); - glEnd(); - - glPushMatrix(); - glTranslatef(time, h + h * .21, 0); - glScalef(s * .0065, s * .0065, 1.0); - GLtext::writeAt(0, 0, str.str()); - glPopMatrix(); - } + idealStartIndex = m_rangeStartIndex; + + const DataElement& e = m_data[0]; + int i; + for (i = m_rangeStartIndex; m_data[i].repeatframe; ++i) + ; + + int startFrame = m_data[i].frame; + double time = m_data[i].swap1; + double endTime = m_data[m_rangeEndIndex].swap1; + + for (int frame = startFrame + 1; time < endTime; ++frame) + { + time = time + 1.0 / m_actualFPS; + + GLtext::size(20.0); + GLtext::color(0, 0, 0, .7); + float s = 1.0 + / (GLtext::globalAscenderHeight() + - GLtext::globalDescenderHeight()); + ostringstream str; + str << frame; + + Box2f b = GLtext::bounds(str.str()); + float tw = (b.max.x - b.min.x) * s * 0.0065; + float th = (b.max.y - b.min.y) * s * 0.0065; + float slop = .0008; + + glColor4f(.5, 1, 1, .5); + glBegin(GL_POLYGON); + glVertex2f(time - slop, h + h * .21 - slop); + glVertex2f(time + tw + slop, h + h * .21 - slop); + glVertex2f(time + tw + slop * 6, h + h * .21 + th / 2); + glVertex2f(time + tw + slop, h + h * .21 + th + slop); + glVertex2f(time - slop, h + h * .21 + th + slop); + glEnd(); + + glPushMatrix(); + glTranslatef(time, h + h * .21, 0); + glScalef(s * .0065, s * .0065, 1.0); + GLtext::writeAt(0, 0, str.str()); + glPopMatrix(); + } } - glColor4f(0,0,0,.5); + glColor4f(0, 0, 0, .5); glLineWidth(2.0); glBegin(GL_LINES); @@ -1546,7 +1614,9 @@ GLView::paintGL() GLtext::size(100.0); GLtext::color(0, 0, 0, .5); - float s = 1.0 / (GLtext::globalAscenderHeight() - GLtext::globalDescenderHeight()); + float s = + 1.0 + / (GLtext::globalAscenderHeight() - GLtext::globalDescenderHeight()); for (int i = int(m_startTime); i < int(m_endTime - m_startTime + 1.0); i++) { @@ -1577,9 +1647,8 @@ GLView::paintGL() glPopMatrix(); } - //renderText(float(i), -0.01, 0, QString("%1").arg(i)); + // renderText(float(i), -0.01, 0, QString("%1").arg(i)); } glFinish(); } - diff --git a/src/bin/apps/rvprof/VisMainWindow.h b/src/bin/apps/rvprof/VisMainWindow.h index 13d478e82..b9a3614fd 100644 --- a/src/bin/apps/rvprof/VisMainWindow.h +++ b/src/bin/apps/rvprof/VisMainWindow.h @@ -1,9 +1,9 @@ // -// Copyright (c) 2008 Tweak Software. +// Copyright (c) 2008 Tweak Software. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// // #ifndef __playbackVis__VisMainWindow__h__ #define __playbackVis__VisMainWindow__h__ @@ -95,22 +95,27 @@ class GLView : public QGLWidget { Q_OBJECT - public: - +public: typedef TwkMath::Mat44f Matrix; typedef TwkMath::Vec3f Vec; GLView(QWidget* parent, QTextEdit* readout, VisMainWindow* visWin); void setData(const DataVector&); + DataVector& data() { return m_data; } void setRange(int start, int end); void setTimeRange(float start, float end); + size_t startIndex() const { return m_rangeStartIndex; } + size_t endIndex() const { return m_rangeEndIndex; } + double rangeStart() const { return m_rangeStart; } + double rangeEnd() const { return m_rangeEnd; } + float actualFPS() const { return m_actualFPS; } void setActualFPS(float fps); @@ -119,13 +124,13 @@ class GLView : public QGLWidget void setComputedRefresh(float); void setComputedFPS(float); - protected: +protected: void initializeGL(); void paintGL(); void resizeGL(int, int); void rebuildIdealFrames(); - int timeToSample(float t); - int sampleFromMousePosition(float x, float y); + int timeToSample(float t); + int sampleFromMousePosition(float x, float y); void generateHtml(); void autoRangeProcessing(); @@ -134,32 +139,32 @@ class GLView : public QGLWidget virtual void mouseReleaseEvent(QMouseEvent* event); virtual void wheelEvent(QWheelEvent* event); - private: +private: DataVector m_data; - double m_startTime; - double m_endTime; - float m_scale; - float m_xtran; - float m_ytran; - - float m_actualFPS; - bool m_showIdealFrames; - bool m_showEvalTiming; - float m_computedRefresh; - float m_computedFPS; - - float m_rangeStart; - float m_rangeEnd; - size_t m_rangeStartIndex; - size_t m_rangeEndIndex; + double m_startTime; + double m_endTime; + float m_scale; + float m_xtran; + float m_ytran; + + float m_actualFPS; + bool m_showIdealFrames; + bool m_showEvalTiming; + float m_computedRefresh; + float m_computedFPS; + + float m_rangeStart; + float m_rangeEnd; + size_t m_rangeStartIndex; + size_t m_rangeEndIndex; Matrix m_matrix; - QPoint m_mouseDown; + QPoint m_mouseDown; - QString m_readoutHtml; + QString m_readoutHtml; QTextEdit* m_readout; - int m_readoutSample; + int m_readoutSample; VisMainWindow* m_visWin; }; @@ -167,27 +172,27 @@ class VisMainWindow : public QMainWindow { Q_OBJECT - public: - VisMainWindow(QWidget *parent = 0); +public: + VisMainWindow(QWidget* parent = 0); void readFile(const QString&); - bool eventFilter(QObject *obj, QEvent *event); + bool eventFilter(QObject* obj, QEvent* event); void updateTimeRangeFromGLView(); void updateActualFPSFromGLView(); void setShowIdealFrames(); - public slots: +public slots: void rangeChanged(); void showIdealFrames(int); - private slots: +private slots: void openFile(); void showFile(); void quit(); void fpsChanged(); void showEvalTiming(int); - private: +private: GLView* m_glWidget; Ui::VisMainWindow m_ui; Ui::DockWidget m_dockUI; diff --git a/src/bin/apps/rvprof/main.cpp b/src/bin/apps/rvprof/main.cpp index 2d649f15c..258ed7dfc 100644 --- a/src/bin/apps/rvprof/main.cpp +++ b/src/bin/apps/rvprof/main.cpp @@ -1,7 +1,7 @@ // -// Copyright (C) 2023 Autodesk, Inc. All Rights Reserved. -// -// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2023 Autodesk, Inc. All Rights Reserved. +// +// SPDX-License-Identifier: Apache-2.0 // #include "../../utf8Main.h" @@ -28,19 +28,20 @@ fields:\n\ \n\ "; -int utf8Main(int argc, char *argv[]) +int utf8Main(int argc, char* argv[]) { QApplication app(argc, argv); VisMainWindow mainWindow; if (argc == 2) { - if (0 == strcmp(argv[1], "-help")) - { - cerr << usage; - exit (-1); - } - else mainWindow.readFile(argv[1]); + if (0 == strcmp(argv[1], "-help")) + { + cerr << usage; + exit(-1); + } + else + mainWindow.readFile(argv[1]); } mainWindow.show(); diff --git a/src/bin/apps/rvprof/utf8Main.cpp b/src/bin/apps/rvprof/utf8Main.cpp index 69e097cc9..7c46f886c 100644 --- a/src/bin/apps/rvprof/utf8Main.cpp +++ b/src/bin/apps/rvprof/utf8Main.cpp @@ -1,6 +1,6 @@ // -// Copyright (C) 2023 Autodesk, Inc. All Rights Reserved. -// -// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2023 Autodesk, Inc. All Rights Reserved. // -#include "../../utf8Main.cpp" \ No newline at end of file +// SPDX-License-Identifier: Apache-2.0 +// +#include "../../utf8Main.cpp" diff --git a/src/bin/apps/rvpush/RvPusher.cpp b/src/bin/apps/rvpush/RvPusher.cpp index 67f3628cb..5e98e5392 100644 --- a/src/bin/apps/rvpush/RvPusher.cpp +++ b/src/bin/apps/rvpush/RvPusher.cpp @@ -13,425 +13,433 @@ #include #ifdef PLATFORM_WINDOWS -#include // For Sleep +#include // For Sleep #else -#include // For usleep +#include // For usleep #endif #if 0 -#define DB( x ) cerr << dec << x << endl -#define DBL( level, x ) cerr << dec << x << endl +#define DB(x) cerr << dec << x << endl +#define DBL(level, x) cerr << dec << x << endl #else -#define DB( x ) -#define DBL( level, x ) +#define DB(x) +#define DBL(level, x) #endif using namespace std; -RvPusher::RvPusher( QCoreApplication& app, string tag, string cmd, - vector argv, QObject* parent ) - : QObject( parent ), - m_app( app ), - m_client( 0 ), - m_command( cmd ), - m_tag( tag ), - m_argv( argv ), - m_error( 0 ), - m_rvStarted( false ) +RvPusher::RvPusher(QCoreApplication& app, string tag, string cmd, + vector argv, QObject* parent) + : QObject(parent) + , m_app(app) + , m_client(0) + , m_command(cmd) + , m_tag(tag) + , m_argv(argv) + , m_error(0) + , m_rvStarted(false) { - // - // Make network client. If we can find a port number for a running rv, - // we'll connect to it later. - // - m_client = new TwkQtChat::Client( "rvpush-1", "rvpush", 0, false ); - - connect( m_client, SIGNAL( newContact( const QString& ) ), this, - SLOT( newContact( const QString& ) ) ); - - connect( m_client, SIGNAL( connectionFailed( QAbstractSocket::SocketError ) ), - this, SLOT( connectionFailed( QAbstractSocket::SocketError ) ) ); - - connect( m_client, SIGNAL( contactLeft( const QString& ) ), this, - SLOT( contactLeft( const QString& ) ) ); - - connect( m_client, SIGNAL( newMessage( const QString&, const QString& ) ), - this, SLOT( newMessage( const QString&, const QString& ) ) ); - - // - // Build list of possible tmp files holding rv port numbers. - // - buildFileList(); - - // - // Try the first possible port file. - // - m_currentFile = 0; - attemptConnection(); + // + // Make network client. If we can find a port number for a running rv, + // we'll connect to it later. + // + m_client = new TwkQtChat::Client("rvpush-1", "rvpush", 0, false); + + connect(m_client, SIGNAL(newContact(const QString&)), this, + SLOT(newContact(const QString&))); + + connect(m_client, SIGNAL(connectionFailed(QAbstractSocket::SocketError)), + this, SLOT(connectionFailed(QAbstractSocket::SocketError))); + + connect(m_client, SIGNAL(contactLeft(const QString&)), this, + SLOT(contactLeft(const QString&))); + + connect(m_client, SIGNAL(newMessage(const QString&, const QString&)), this, + SLOT(newMessage(const QString&, const QString&))); + + // + // Build list of possible tmp files holding rv port numbers. + // + buildFileList(); + + // + // Try the first possible port file. + // + m_currentFile = 0; + attemptConnection(); } void RvPusher::buildFileList() { - DB( "buildFileList" ); - - QDir tmp = QDir::temp(); + DB("buildFileList"); - if( !tmp.exists( "tweak_rv_proc" ) ) return; + QDir tmp = QDir::temp(); - tmp.cd( "tweak_rv_proc" ); + if (!tmp.exists("tweak_rv_proc")) + return; - // - // Get files in this dir (not subdirs), sorted by modification time. - // - QString tagString( m_tag.c_str() ); + tmp.cd("tweak_rv_proc"); - QFileInfoList rawList = tmp.entryInfoList( QDir::Files, QDir::Time ); + // + // Get files in this dir (not subdirs), sorted by modification time. + // + QString tagString(m_tag.c_str()); - for( int i = 0; i < rawList.size(); ++i ) - { - QStringList parts = rawList[i].fileName().split( "_" ); - QString name = parts.mid( 1 ).join( "_" ); + QFileInfoList rawList = tmp.entryInfoList(QDir::Files, QDir::Time); - if( ( parts.size() == 1 && tagString == "" ) || - ( parts.size() >= 2 && name == tagString ) ) + for (int i = 0; i < rawList.size(); ++i) { - m_fileList.push_back( rawList[i] ); + QStringList parts = rawList[i].fileName().split("_"); + QString name = parts.mid(1).join("_"); + + if ((parts.size() == 1 && tagString == "") + || (parts.size() >= 2 && name == tagString)) + { + m_fileList.push_back(rawList[i]); + } } - } - for( int i = 0; i < m_fileList.size(); ++i ) - { - DB( " file " << i << " '" - << m_fileList[i].absoluteFilePath().toStdString() << "'" ); - } + for (int i = 0; i < m_fileList.size(); ++i) + { + DB(" file " << i << " '" + << m_fileList[i].absoluteFilePath().toStdString() + << "'"); + } } void RvPusher::attemptConnection() { - DB( "attemptConnection currentFile " << m_currentFile << " fileList:" ); - for( int i = 0; i < m_fileList.size(); ++i ) - { - DB( " file " << i << " '" - << m_fileList[i].absoluteFilePath().toStdString() << "'" ); - } - - // - // Attempt to read port number from currentFile, try other files if this - // fails. When we have a candidate port, attempt a connection. This is - // an async operation, so if it fails, contactLeft() will send us back here - // (with a new currentFile). - // - - int port = 0; - - while( !port && m_currentFile < m_fileList.size() ) - { - port = 0; - QFile portFile( m_fileList[m_currentFile].absoluteFilePath() ); - - if( portFile.open( QIODevice::ReadOnly ) ) - { - // - // Read port number - // - char buf[256]; - - int status = portFile.readLine( buf, 256 ); - portFile.close(); - - if( -1 != status ) - { - QString str( buf ); - bool ok; - port = str.toInt( &ok ); - if( !ok ) port = 0; - - DB( " '" << portFile.fileName().toStdString() << "' gives port " - << port ); - } - } - - if( !port ) + DB("attemptConnection currentFile " << m_currentFile << " fileList:"); + for (int i = 0; i < m_fileList.size(); ++i) { - // - // This file gives no port (is unreadable or mal-formed), so - // remove it and try the next one. - // - DB( " removing " << portFile.fileName().toStdString() ); - QFile::remove( portFile.fileName() ); - ++m_currentFile; + DB(" file " << i << " '" + << m_fileList[i].absoluteFilePath().toStdString() + << "'"); } - } - if( !port ) - { // - // We've run out of files with no successful connection, so start a new rv, - // or exit. + // Attempt to read port number from currentFile, try other files if this + // fails. When we have a candidate port, attempt a connection. This is + // an async operation, so if it fails, contactLeft() will send us back here + // (with a new currentFile). // - QString rvExe; + int port = 0; - if( getenv( "RVPUSH_RV_EXECUTABLE_PATH" ) ) - rvExe = getenv( "RVPUSH_RV_EXECUTABLE_PATH" ); - else + while (!port && m_currentFile < m_fileList.size()) { - // - // Assume that rv we'll run is in same dir as rvpush. - // - rvExe = QCoreApplication::applicationDirPath(); - -#if defined( PLATFORM_WINDOWS ) - rvExe += "/rv.exe"; -#elif defined( PLATFORM_DARWIN ) - rvExe += "/RV"; -#else - rvExe += "/rv"; -#endif - } + port = 0; + QFile portFile(m_fileList[m_currentFile].absoluteFilePath()); - if( rvExe == "none" || !QFileInfo( rvExe ).isExecutable() ) - { - cerr << "ERROR: cannot connect to any running RV" << endl; - m_error = 11; + if (portFile.open(QIODevice::ReadOnly)) + { + // + // Read port number + // + char buf[256]; + + int status = portFile.readLine(buf, 256); + portFile.close(); + + if (-1 != status) + { + QString str(buf); + bool ok; + port = str.toInt(&ok); + if (!ok) + port = 0; + + DB(" '" << portFile.fileName().toStdString() + << "' gives port " << port); + } + } + + if (!port) + { + // + // This file gives no port (is unreadable or mal-formed), so + // remove it and try the next one. + // + DB(" removing " << portFile.fileName().toStdString()); + QFile::remove(portFile.fileName()); + ++m_currentFile; + } } - else + + if (!port) { - cerr << "INFO: cannot connect to any running RV, starting new one" - << endl; - - QStringList qargs; - - // - // Start a new rv with the appropriate tag. - // - if( m_tag != "" ) - { - qargs.push_back( "-networkTag" ); - qargs.push_back( m_tag.c_str() ); - } - - // - // New RV must be listening for future rvpush connections. - // - qargs.append( "-network" ); - - if( m_command == "mu-eval" ) - qargs.append( "-eval" ); - else if( m_command == "mu-eval-return" ) - qargs.append( "-eval" ); - else if( m_command == "py-eval" ) - qargs.append( "-pyeval" ); - else if( m_command == "py-eval-return" ) - qargs.append( "-pyeval" ); - else if( m_command == "py-exec" ) - qargs.append( "-pyeval" ); - - if( m_command == "url" ) - { - qargs.append( m_argv[0].c_str() ); - } - else - { - for( int i = 0; i < m_argv.size(); ++i ) + // + // We've run out of files with no successful connection, so start a new + // rv, or exit. + // + + QString rvExe; + + if (getenv("RVPUSH_RV_EXECUTABLE_PATH")) + rvExe = getenv("RVPUSH_RV_EXECUTABLE_PATH"); + else { -#ifdef PLATFORM_WINDOWS - if( m_command == "set" || m_command == "merge" ) - std::replace( m_argv[i].begin(), m_argv[i].end(), '\\', '/' ); + // + // Assume that rv we'll run is in same dir as rvpush. + // + rvExe = QCoreApplication::applicationDirPath(); + +#if defined(PLATFORM_WINDOWS) + rvExe += "/rv.exe"; +#elif defined(PLATFORM_DARWIN) + rvExe += "/RV"; +#else + rvExe += "/rv"; #endif - qargs.append( m_argv[i].c_str() ); } - } - DB( " starting '" << rvExe.toStdString() << "'" ); - for( int i = 0; i < qargs.size(); ++i ) - DB( " " << qargs[i].toStdString() ); + if (rvExe == "none" || !QFileInfo(rvExe).isExecutable()) + { + cerr << "ERROR: cannot connect to any running RV" << endl; + m_error = 11; + } + else + { + cerr << "INFO: cannot connect to any running RV, starting new one" + << endl; + + QStringList qargs; + + // + // Start a new rv with the appropriate tag. + // + if (m_tag != "") + { + qargs.push_back("-networkTag"); + qargs.push_back(m_tag.c_str()); + } + + // + // New RV must be listening for future rvpush connections. + // + qargs.append("-network"); + + if (m_command == "mu-eval") + qargs.append("-eval"); + else if (m_command == "mu-eval-return") + qargs.append("-eval"); + else if (m_command == "py-eval") + qargs.append("-pyeval"); + else if (m_command == "py-eval-return") + qargs.append("-pyeval"); + else if (m_command == "py-exec") + qargs.append("-pyeval"); + + if (m_command == "url") + { + qargs.append(m_argv[0].c_str()); + } + else + { + for (int i = 0; i < m_argv.size(); ++i) + { +#ifdef PLATFORM_WINDOWS + if (m_command == "set" || m_command == "merge") + std::replace(m_argv[i].begin(), m_argv[i].end(), '\\', + '/'); +#endif + qargs.append(m_argv[i].c_str()); + } + } - QProcess::startDetached( rvExe, qargs ); + DB(" starting '" << rvExe.toStdString() << "'"); + for (int i = 0; i < qargs.size(); ++i) + DB(" " << qargs[i].toStdString()); - DB( " done" ); + QProcess::startDetached(rvExe, qargs); - m_rvStarted = true; - m_error = 15; - } + DB(" done"); - m_app.quit(); - } - else - { - // - // We have a candidate port number, so try it. Success will send us - // to newContact(), failure to contactLeft(). - // - QHostAddress addr( "127.0.0.1" ); - m_client->connectTo( "rv", addr, port ); - } -} + m_rvStarted = true; + m_error = 15; + } -void RvPusher::newContact( const QString& contact ) -{ - // - // We've successfully connected, so send our one eval event, and exit unless - // we're waiting for a return value. - // - - m_contact = contact; - DB( "connected to " << contact.toStdString() ); - - bool rsvp = - ( m_command == "mu-eval-return" || m_command == "py-eval-return" ); - - if( m_command == "mu-eval" || m_command == "mu-eval-return" || - m_command == "py-eval" || m_command == "py-eval-return" || - m_command == "py-exec" ) - { - QString src = ""; - for( int i = 0; i < m_argv.size(); ++i ) + m_app.quit(); + } + else { - src += m_argv[i].c_str(); - src += " "; + // + // We have a candidate port number, so try it. Success will send us + // to newContact(), failure to contactLeft(). + // + QHostAddress addr("127.0.0.1"); + m_client->connectTo("rv", addr, port); } - DB( " " << m_command << " '" << src.toStdString() << "'" ); +} - QString com = "invalid"; +void RvPusher::newContact(const QString& contact) +{ + // + // We've successfully connected, so send our one eval event, and exit + // unless we're waiting for a return value. + // - if( m_command == "mu-eval" || m_command == "mu-eval-return" ) - com = "remote-eval"; - else if( m_command == "py-eval" || m_command == "py-eval-return" ) - com = "remote-pyeval"; - else - com = "remote-pyexec"; + m_contact = contact; + DB("connected to " << contact.toStdString()); bool rsvp = - ( m_command == "mu-eval-return" || m_command == "py-eval-return" ); + (m_command == "mu-eval-return" || m_command == "py-eval-return"); - m_client->sendEvent( m_contact, com, "*", src, rsvp ); - } - else if( m_command == "set" || m_command == "merge" ) - { - // - // If "set" clear the session before we add media, otherwise merge it in. - // - QString mu = ( m_command == "set" ) - ? "{ require rvui; rvui.clearEverything(); " - : "{ "; + if (m_command == "mu-eval" || m_command == "mu-eval-return" + || m_command == "py-eval" || m_command == "py-eval-return" + || m_command == "py-exec") + { + QString src = ""; + for (int i = 0; i < m_argv.size(); ++i) + { + src += m_argv[i].c_str(); + src += " "; + } + DB(" " << m_command << " '" << src.toStdString() << "'"); - // - // Run through args, use '+' instead of '-' for per-source args. - // + QString com = "invalid"; + + if (m_command == "mu-eval" || m_command == "mu-eval-return") + com = "remote-eval"; + else if (m_command == "py-eval" || m_command == "py-eval-return") + com = "remote-pyeval"; + else + com = "remote-pyexec"; - mu += "addSources(string[] {"; - bool inSource = false; + bool rsvp = + (m_command == "mu-eval-return" || m_command == "py-eval-return"); - for( int i = 0; i < m_argv.size(); ++i ) + m_client->sendEvent(m_contact, com, "*", src, rsvp); + } + else if (m_command == "set" || m_command == "merge") { - if( m_argv[i] == "[" ) - inSource = true; - else if( m_argv[i] == "]" ) - inSource = false; - else if( inSource && m_argv[i][0] == '-' && isalpha( m_argv[i][1] ) ) - m_argv[i][0] = '+'; - - // convert relative to absolute file path - QFileInfo curFileInfo( QString::fromStdString( m_argv[i] ) ); - // Not all arguements are file path. We change only if the arguement is an - // existing file. - if( curFileInfo.exists() && curFileInfo.isRelative() ) - { - m_argv[i] = curFileInfo.absoluteFilePath().toStdString(); - } + // + // If "set" clear the session before we add media, otherwise merge it + // in. + // + QString mu = (m_command == "set") + ? "{ require rvui; rvui.clearEverything(); " + : "{ "; + + // + // Run through args, use '+' instead of '-' for per-source args. + // + + mu += "addSources(string[] {"; + bool inSource = false; + + for (int i = 0; i < m_argv.size(); ++i) + { + if (m_argv[i] == "[") + inSource = true; + else if (m_argv[i] == "]") + inSource = false; + else if (inSource && m_argv[i][0] == '-' && isalpha(m_argv[i][1])) + m_argv[i][0] = '+'; + + // convert relative to absolute file path + QFileInfo curFileInfo(QString::fromStdString(m_argv[i])); + // Not all arguements are file path. We change only if the arguement + // is an existing file. + if (curFileInfo.exists() && curFileInfo.isRelative()) + { + m_argv[i] = curFileInfo.absoluteFilePath().toStdString(); + } #ifdef PLATFORM_WINDOWS - std::replace( m_argv[i].begin(), m_argv[i].end(), '\\', '/' ); + std::replace(m_argv[i].begin(), m_argv[i].end(), '\\', '/'); #endif - if( i ) - mu += ", \""; - else - mu += "\""; + if (i) + mu += ", \""; + else + mu += "\""; - mu += m_argv[i].c_str(); + mu += m_argv[i].c_str(); - mu += "\""; - } - mu += "}, \"rvpush\", false, "; - mu += ( ( m_command == "merge" ) ? "true);" : "false);" ); - mu += " mainWindowWidget().raise(); }"; + mu += "\""; + } + mu += "}, \"rvpush\", false, "; + mu += ((m_command == "merge") ? "true);" : "false);"); + mu += " mainWindowWidget().raise(); }"; - DB( " " << m_command << " '" << mu.toStdString() << "'" ); + DB(" " << m_command << " '" << mu.toStdString() << "'"); - m_client->sendEvent( m_contact, "remote-eval", "*", mu, false ); - } - else if( m_command == "url" ) - { - QString mu = "{ mainWindowWidget().raise(); "; + m_client->sendEvent(m_contact, "remote-eval", "*", mu, false); + } + else if (m_command == "url") + { + QString mu = "{ mainWindowWidget().raise(); "; - mu += "sessionFromUrl(\""; - mu += m_argv[0].c_str(); - mu += "\"); }"; + mu += "sessionFromUrl(\""; + mu += m_argv[0].c_str(); + mu += "\"); }"; - DB( " " << m_command << " '" << mu.toStdString() << "'" ); + DB(" " << m_command << " '" << mu.toStdString() << "'"); - m_client->sendEvent( m_contact, "remote-eval", "*", mu, false ); - } + m_client->sendEvent(m_contact, "remote-eval", "*", mu, false); + } - if( !rsvp ) disconnect(); + if (!rsvp) + disconnect(); } void RvPusher::disconnect() { - m_client->signOff( m_contact ); + m_client->signOff(m_contact); // // Allow time for the communication to finish before we bail. // #ifdef PLATFORM_WINDOWS - Sleep( 250 ); + Sleep(250); #else - usleep( 250000 ); + usleep(250000); #endif - m_app.quit(); + m_app.quit(); } -void RvPusher::connectionFailed( QAbstractSocket::SocketError error ) +void RvPusher::connectionFailed(QAbstractSocket::SocketError error) { - // - // Not sure under what circumstances we'd end up here, but if we do we - // should quit - // - DB( "error" ); - m_error = 4; - m_app.quit(); + // + // Not sure under what circumstances we'd end up here, but if we do we + // should quit + // + DB("error"); + m_error = 4; + m_app.quit(); } -void RvPusher::contactLeft( const QString& contact ) +void RvPusher::contactLeft(const QString& contact) { - DB( "contactLeft " << contact.toStdString() ); - - // - // Contact failed so remove this port file - // - DB( " removing " - << m_fileList[m_currentFile].absoluteFilePath().toStdString() ); - QFile::remove( m_fileList[m_currentFile].absoluteFilePath() ); - - // - // Increment file counter and try again - // - ++m_currentFile; - attemptConnection(); + DB("contactLeft " << contact.toStdString()); + + // + // Contact failed so remove this port file + // + DB(" removing " + << m_fileList[m_currentFile].absoluteFilePath().toStdString()); + QFile::remove(m_fileList[m_currentFile].absoluteFilePath()); + + // + // Increment file counter and try again + // + ++m_currentFile; + attemptConnection(); } -void RvPusher::newMessage( const QString& sender, const QString& inmessage ) +void RvPusher::newMessage(const QString& sender, const QString& inmessage) { - DB( "newMessage '" << inmessage.toStdString() << "'" ); + DB("newMessage '" << inmessage.toStdString() << "'"); - if( !inmessage.startsWith( "RETURN " ) ) return; + if (!inmessage.startsWith("RETURN ")) + return; - QString message = inmessage; - message.remove( 0, 7 ); + QString message = inmessage; + message.remove(0, 7); - DB( "returned '" << message.toStdString() << "'" ); + DB("returned '" << message.toStdString() << "'"); - cout << message.toStdString() << endl; + cout << message.toStdString() << endl; - disconnect(); + disconnect(); } diff --git a/src/bin/apps/rvpush/RvPusher.h b/src/bin/apps/rvpush/RvPusher.h index 6f5554ad5..28f0562fd 100644 --- a/src/bin/apps/rvpush/RvPusher.h +++ b/src/bin/apps/rvpush/RvPusher.h @@ -1,14 +1,14 @@ // -// Copyright (c) 2008 Tweak Software. +// Copyright (c) 2008 Tweak Software. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// // #ifndef __rvpush__RvPusher__h__ #define __rvpush__RvPusher__h__ -#if defined( _WIN32 ) +#if defined(_WIN32) #include #endif #include @@ -30,7 +30,8 @@ class RvPusher : public QObject Q_OBJECT public: - RvPusher(QCoreApplication&, string, string, vector, QObject *parent = 0); + RvPusher(QCoreApplication&, string, string, vector, + QObject* parent = 0); // // Errors can be encountered during construction, or later due to async @@ -47,23 +48,23 @@ private slots: void newContact(const QString&); void connectionFailed(QAbstractSocket::SocketError); void contactLeft(const QString&); - void newMessage (const QString&, const QString&); + void newMessage(const QString&, const QString&); private: void buildFileList(); void attemptConnection(); void disconnect(); - QCoreApplication& m_app; - TwkQtChat::Client* m_client; - QString m_contact; - string m_command; - string m_tag; - vector m_argv; - int m_error; - int m_currentFile; - QFileInfoList m_fileList; - bool m_rvStarted; + QCoreApplication& m_app; + TwkQtChat::Client* m_client; + QString m_contact; + string m_command; + string m_tag; + vector m_argv; + int m_error; + int m_currentFile; + QFileInfoList m_fileList; + bool m_rvStarted; }; #endif // __rvshell__ShellDialog__h__ diff --git a/src/bin/apps/rvpush/main.cpp b/src/bin/apps/rvpush/main.cpp index 801b35f02..94ae84cc9 100644 --- a/src/bin/apps/rvpush/main.cpp +++ b/src/bin/apps/rvpush/main.cpp @@ -1,7 +1,7 @@ // -// Copyright (C) 2023 Autodesk, Inc. All Rights Reserved. -// -// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2023 Autodesk, Inc. All Rights Reserved. +// +// SPDX-License-Identifier: Apache-2.0 // #include "../../utf8Main.h" @@ -63,66 +63,65 @@ usage: rvpush [-tag ] \n\ "; #if 0 -#define DB(x) cerr << dec << x << endl -#define DBL(level, x) cerr << dec << x << endl +#define DB(x) cerr << dec << x << endl +#define DBL(level, x) cerr << dec << x << endl #else -#define DB(x) +#define DB(x) #define DBL(level, x) #endif -int utf8Main(int argc, char *argv[]) +int utf8Main(int argc, char* argv[]) { - if (argc < 2 || strcmp (argv[1],"-help") == 0) + if (argc < 2 || strcmp(argv[1], "-help") == 0) { cerr << usage << endl; - exit (1); + exit(1); } int commandPos = 1; string tag; - DB ("argv1 '" << argv[1] << "'"); + DB("argv1 '" << argv[1] << "'"); if (string(argv[1]) == "-tag") { - if (argc < 3) - { - cerr << "ERROR: missing tag" << endl; - cerr << usage << endl; - exit (2); - } - tag = argv[2]; - commandPos = 3; + if (argc < 3) + { + cerr << "ERROR: missing tag" << endl; + cerr << usage << endl; + exit(2); + } + tag = argv[2]; + commandPos = 3; } string command = argv[commandPos]; - DB ("commandPos " << commandPos << " command " << command); - - if (command != "set" && - command != "merge" && - command != "mu-eval" && - command != "mu-eval-return" && - command != "py-eval" && - command != "py-eval-return" && - command != "py-exec" && - command != "url") + DB("commandPos " << commandPos << " command " << command); + + if (command != "set" && command != "merge" && command != "mu-eval" + && command != "mu-eval-return" && command != "py-eval" + && command != "py-eval-return" && command != "py-exec" + && command != "url") { cerr << usage << endl; - exit (3); + exit(3); } vector commandArgv; if (command == "url") { - string url; - - for (int i = commandPos+1; i < argc; ++i) - { - if (i > commandPos+1) url += " "; - url += argv[i]; - } - commandArgv.push_back (url); + string url; + + for (int i = commandPos + 1; i < argc; ++i) + { + if (i > commandPos + 1) + url += " "; + url += argv[i]; + } + commandArgv.push_back(url); } - else for (int i = commandPos+1; i < argc; ++i) commandArgv.push_back (argv[i]); - DB ("command " << command << " tag " << tag); - + else + for (int i = commandPos + 1; i < argc; ++i) + commandArgv.push_back(argv[i]); + DB("command " << command << " tag " << tag); + QCoreApplication app(argc, argv); RvPusher pusher(app, tag, command, commandArgv); @@ -133,9 +132,10 @@ int utf8Main(int argc, char *argv[]) // running RV over the network). // - if (pusher.error() == 0 && !pusher.rvStarted()) app.exec(); + if (pusher.error() == 0 && !pusher.rvStarted()) + app.exec(); - DB ("exiting, return " << pusher.error()); + DB("exiting, return " << pusher.error()); - exit (pusher.error()); + exit(pusher.error()); } diff --git a/src/bin/apps/rvpush/utf8Main.cpp b/src/bin/apps/rvpush/utf8Main.cpp index 69e097cc9..7c46f886c 100644 --- a/src/bin/apps/rvpush/utf8Main.cpp +++ b/src/bin/apps/rvpush/utf8Main.cpp @@ -1,6 +1,6 @@ // -// Copyright (C) 2023 Autodesk, Inc. All Rights Reserved. -// -// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2023 Autodesk, Inc. All Rights Reserved. // -#include "../../utf8Main.cpp" \ No newline at end of file +// SPDX-License-Identifier: Apache-2.0 +// +#include "../../utf8Main.cpp" diff --git a/src/bin/apps/rvshell/ShellDialog.cpp b/src/bin/apps/rvshell/ShellDialog.cpp index b1cf278c7..095a59e39 100644 --- a/src/bin/apps/rvshell/ShellDialog.cpp +++ b/src/bin/apps/rvshell/ShellDialog.cpp @@ -1,7 +1,7 @@ // -// Copyright (C) 2023 Autodesk, Inc. All Rights Reserved. -// -// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2023 Autodesk, Inc. All Rights Reserved. +// +// SPDX-License-Identifier: Apache-2.0 // #include #include @@ -14,9 +14,11 @@ using namespace std; static bool updateOnly = false; -ShellDialog::ShellDialog(QWidget *parent) : QMainWindow(parent) +ShellDialog::ShellDialog(QWidget* parent) + : QMainWindow(parent) { - if (getenv("RVSHELL_PIXEL_UPDATE_ONLY")) updateOnly = true; + if (getenv("RVSHELL_PIXEL_UPDATE_ONLY")) + updateOnly = true; setupUi(this); // @@ -36,15 +38,14 @@ ShellDialog::ShellDialog(QWidget *parent) : QMainWindow(parent) graphicsView->setScene(m_scene); connect(actionSend, SIGNAL(triggered()), this, SLOT(go())); - connect(actionQuit, SIGNAL(triggered()), - this, SLOT(quit())); + connect(actionQuit, SIGNAL(triggered()), this, SLOT(quit())); - connect(m_client, SIGNAL(newMessage(const QString &, const QString &)), - this, SLOT(appendMessage(const QString &, const QString &))); - connect(m_client, SIGNAL(newContact(const QString &)), - this, SLOT(newContact(const QString &))); - connect(m_client, SIGNAL(contactLeft(const QString &)), - this, SLOT(contactLeft(const QString &))); + connect(m_client, SIGNAL(newMessage(const QString&, const QString&)), this, + SLOT(appendMessage(const QString&, const QString&))); + connect(m_client, SIGNAL(newContact(const QString&)), this, + SLOT(newContact(const QString&))); + connect(m_client, SIGNAL(contactLeft(const QString&)), this, + SLOT(contactLeft(const QString&))); connect(sendImageButton, SIGNAL(clicked()), this, SLOT(sendImage())); @@ -52,28 +53,29 @@ ShellDialog::ShellDialog(QWidget *parent) : QMainWindow(parent) connect(stopButton, SIGNAL(clicked()), this, SLOT(stop())); connect(forwardButton, SIGNAL(clicked()), this, SLOT(forward())); connect(backButton, SIGNAL(clicked()), this, SLOT(back())); - connect(fullScreenButton, SIGNAL(clicked(bool)), this, SLOT(fullScreen(bool))); + connect(fullScreenButton, SIGNAL(clicked(bool)), this, + SLOT(fullScreen(bool))); connect(cacheButton, SIGNAL(clicked(bool)), this, SLOT(cacheOn(bool))); connect(loadImageButton, SIGNAL(clicked()), this, SLOT(loadImage())); m_tableFormat.setBorder(0); - //QTimer::singleShot(10 * 1000, this, SLOT(showInformation())); + // QTimer::singleShot(10 * 1000, this, SLOT(showInformation())); xTilesLineEdit->setText("1"); yTilesLineEdit->setText("1"); } -void ShellDialog::appendMessage(const QString &from, const QString &message) +void ShellDialog::appendMessage(const QString& from, const QString& message) { if (from.isEmpty() || message.isEmpty()) return; QTextCursor cursor(textEdit->textCursor()); cursor.movePosition(QTextCursor::End); - QTextTable *table = cursor.insertTable(1, 2, m_tableFormat); + QTextTable* table = cursor.insertTable(1, 2, m_tableFormat); table->cellAt(0, 0).firstCursorPosition().insertText("<" + from + "> "); table->cellAt(0, 1).firstCursorPosition().insertText(message); - QScrollBar *bar = textEdit->verticalScrollBar(); + QScrollBar* bar = textEdit->verticalScrollBar(); bar->setValue(bar->maximum()); } @@ -81,14 +83,17 @@ void ShellDialog::go() { QString text = plainTextEdit->toPlainText(); QString event = eventNameLineEdit->text(); - if (text.isEmpty()) return; - m_client->sendEvent(m_contact, event, eventTargetLineEdit->text(), text, true); - //plainTextEdit->clear(); + if (text.isEmpty()) + return; + m_client->sendEvent(m_contact, event, eventTargetLineEdit->text(), text, + true); + // plainTextEdit->clear(); } -void ShellDialog::newContact(const QString &contact) +void ShellDialog::newContact(const QString& contact) { - if (contact.isEmpty()) return; + if (contact.isEmpty()) + return; QColor color = textEdit->textColor(); textEdit->setTextColor(Qt::gray); @@ -100,11 +105,13 @@ void ShellDialog::newContact(const QString &contact) void ShellDialog::contactLeft(const QString& contact) { - if (contact.isEmpty()) return; + if (contact.isEmpty()) + return; - QList items = listWidget->findItems(contact, - Qt::MatchExactly); - if (items.isEmpty()) return; + QList items = + listWidget->findItems(contact, Qt::MatchExactly); + if (items.isEmpty()) + return; delete items.at(0); QColor color = textEdit->textColor(); @@ -117,9 +124,7 @@ void ShellDialog::contactLeft(const QString& contact) void ShellDialog::play() { - m_client->sendEvent(m_contact, - "remote-eval", - eventTargetLineEdit->text(), + m_client->sendEvent(m_contact, "remote-eval", eventTargetLineEdit->text(), "play();" "\"FRAME = \" + frame();", true); @@ -127,9 +132,7 @@ void ShellDialog::play() void ShellDialog::stop() { - m_client->sendEvent(m_contact, - "remote-eval", - eventTargetLineEdit->text(), + m_client->sendEvent(m_contact, "remote-eval", eventTargetLineEdit->text(), "stop();" "\"FRAME = \" + frame();", true); @@ -137,9 +140,7 @@ void ShellDialog::stop() void ShellDialog::forward() { - m_client->sendEvent(m_contact, - "remote-eval", - eventTargetLineEdit->text(), + m_client->sendEvent(m_contact, "remote-eval", eventTargetLineEdit->text(), "extra_commands.stepForward1();" "\"FRAME = \" + frame();", true); @@ -147,9 +148,7 @@ void ShellDialog::forward() void ShellDialog::back() { - m_client->sendEvent(m_contact, - "remote-eval", - eventTargetLineEdit->text(), + m_client->sendEvent(m_contact, "remote-eval", eventTargetLineEdit->text(), "extra_commands.stepBackward1();" "\"FRAME = \" + frame();", true); @@ -158,28 +157,25 @@ void ShellDialog::back() void ShellDialog::fullScreen(bool b) { QString msg = QString("fullScreenMode(%1)").arg(b ? "true" : "false"); - m_client->sendEvent(m_contact, - "remote-eval", - eventTargetLineEdit->text(), + m_client->sendEvent(m_contact, "remote-eval", eventTargetLineEdit->text(), msg); } void ShellDialog::cacheOn(bool b) { - QString msg = QString("setCacheMode(%1)").arg(b ? "CacheBuffer" : "CacheOff"); - m_client->sendEvent(m_contact, - "remote-eval", - eventTargetLineEdit->text(), + QString msg = + QString("setCacheMode(%1)").arg(b ? "CacheBuffer" : "CacheOff"); + m_client->sendEvent(m_contact, "remote-eval", eventTargetLineEdit->text(), msg); } void ShellDialog::loadImage() { - QString file = - QFileDialog::getOpenFileName(this, "Select Image", - ".", "Images (*.png *.xpm *.jpg)"); + QString file = QFileDialog::getOpenFileName(this, "Select Image", ".", + "Images (*.png *.xpm *.jpg)"); - if (file == "") return; + if (file == "") + return; if (!m_pixmap.load(file)) { @@ -188,10 +184,11 @@ void ShellDialog::loadImage() return; } - delete [] m_imageData; + delete[] m_imageData; m_imageData = 0; - if (m_pixmapItem) m_scene->removeItem(m_pixmapItem); + if (m_pixmapItem) + m_scene->removeItem(m_pixmapItem); m_pixmapItem = m_scene->addPixmap(m_pixmap); QImage image = m_pixmap.toImage(); @@ -199,13 +196,13 @@ void ShellDialog::loadImage() const size_t w = image.width(); const size_t h = image.height(); const size_t scanlineSize = w * 4; - m_imageData = new unsigned char [w * h * 4]; + m_imageData = new unsigned char[w * h * 4]; - for (size_t y=0; y < h; y++) + for (size_t y = 0; y < h; y++) { unsigned char* scanline = m_imageData + scanlineSize * y; - - for (size_t x=0; x < w; x++) + + for (size_t x = 0; x < w; x++) { QRgb p = image.pixel(int(x), int(h - y - 1)); scanline[x * 4 + 0] = qRed(p); @@ -224,7 +221,7 @@ void ShellDialog::loadImage() // m_mediaName = QTime::currentTime().toString( - QDate::currentDate().toString("yyyy-M-d-h:m:s:z")); + QDate::currentDate().toString("yyyy-M-d-h:m:s:z")); } void ShellDialog::sendImage() @@ -233,8 +230,9 @@ void ShellDialog::sendImage() // This is pointless if there's no image data // - if (!m_imageData) return; - + if (!m_imageData) + return; + static bool first = true; // @@ -255,10 +253,10 @@ void ShellDialog::sendImage() // Copy the QImage it into something we know the layout of // - const size_t w = m_pixmap.width(); - const size_t h = m_pixmap.height(); - const size_t scanlineSize = w * 4; - unsigned char* data = m_imageData; + const size_t w = m_pixmap.width(); + const size_t h = m_pixmap.height(); + const size_t scanlineSize = w * 4; + unsigned char* data = m_imageData; // // NOTE: don't get confused by the order in which we built up the @@ -285,72 +283,69 @@ void ShellDialog::sendImage() // new source, but we'll only need that to setup the source // pixels not when we send tiles. // - - if (first || !updateOnly) - { - first = false; - QString newImageSource = - QString("newImageSource( \"%1\", %2, %3, " // name, w, h - "%2, %3, 0, 0, " // uncrop w, h, x-off, y-off, - "1.0, 4, 8, false, " // pixaspect, 4 ch, 8 bit, nofloat - "1, 1, 24.0, " // fs, fe, fps - "nil, " // layers (none in this case) - "string[] {\"left\", \"right\"} )") // views - .arg(m_mediaName) - .arg(w) - .arg(h); - - // - // The "s" argument below will be the result of newImageSource() - // (which we constructed above) when we put this all - // together. For this example, we're sending stereo images (which - // is image the user chose and its inverse). - // - - QString leftPixels = "newImageSourcePixels( s, 1, nil, \"left\")"; - QString rightPixels = "newImageSourcePixels( s, 1, nil, \"right\")"; - - // - // Put together the newImageSource() and newImageSourcePixels() - // calls. Make a Mu lexical block and call the two - // newImageSourcePixels() calls with the result of - // newImageSource(). So the final string will look like this: - // - // { - // let s = newImageSource(...); - // newImageSourcePixels(s, ..., "left"); - // newImageSourcePixels(s, ..., "right"); - // } - // - // The entire thing will be evaluated in one go on the RV end. - // - - QString msg = QString("{ let s = %1; %2; %3; }") - .arg(newImageSource) - .arg(leftPixels) - .arg(rightPixels); - - // - // Send the command - // - - m_client->sendEvent(m_contact, - "remote-eval", - "*", - msg.toUtf8().data(), - true); - m_client->waitForSend(m_contact); - - if (!m_client->waitForMessage(m_contact)) + if (first || !updateOnly) { - QMessageBox::critical(this, "Timeout", - QString("%1 failed to respond in time").arg(m_contact)); - return; - } + first = false; + QString newImageSource = + QString("newImageSource( \"%1\", %2, %3, " // name, w, h + "%2, %3, 0, 0, " // uncrop w, h, x-off, y-off, + "1.0, 4, 8, false, " // pixaspect, 4 ch, 8 bit, nofloat + "1, 1, 24.0, " // fs, fe, fps + "nil, " // layers (none in this case) + "string[] {\"left\", \"right\"} )") // views + .arg(m_mediaName) + .arg(w) + .arg(h); + + // + // The "s" argument below will be the result of newImageSource() + // (which we constructed above) when we put this all + // together. For this example, we're sending stereo images (which + // is image the user chose and its inverse). + // + + QString leftPixels = "newImageSourcePixels( s, 1, nil, \"left\")"; + QString rightPixels = "newImageSourcePixels( s, 1, nil, \"right\")"; + + // + // Put together the newImageSource() and newImageSourcePixels() + // calls. Make a Mu lexical block and call the two + // newImageSourcePixels() calls with the result of + // newImageSource(). So the final string will look like this: + // + // { + // let s = newImageSource(...); + // newImageSourcePixels(s, ..., "left"); + // newImageSourcePixels(s, ..., "right"); + // } + // + // The entire thing will be evaluated in one go on the RV end. + // + + QString msg = QString("{ let s = %1; %2; %3; }") + .arg(newImageSource) + .arg(leftPixels) + .arg(rightPixels); + + // + // Send the command + // + + m_client->sendEvent(m_contact, "remote-eval", "*", msg.toUtf8().data(), + true); + + m_client->waitForSend(m_contact); + + if (!m_client->waitForMessage(m_contact)) + { + QMessageBox::critical( + this, "Timeout", + QString("%1 failed to respond in time").arg(m_contact)); + return; + } } - const unsigned char* d = m_imageData; size_t iw = w; size_t ih = h; @@ -364,13 +359,15 @@ void ShellDialog::sendImage() { size_t tw = iw / nx; size_t ix = tw * tx; - if (tx == (nx - 1)) tw = iw - tw * tx; // pick up the leftover + if (tx == (nx - 1)) + tw = iw - tw * tx; // pick up the leftover for (size_t ty = 0; !m_stop && ty < ny; ty++) { size_t th = ih / ny; size_t iy = th * ty; - if (ty == (ny - 1)) th = ih - th * ty; // pick up the leftover + if (ty == (ny - 1)) + th = ih - th * ty; // pick up the leftover #if 0 cout << "SENDING TILE (" << tx << ", " << ty << ")" @@ -389,15 +386,15 @@ void ShellDialog::sendImage() { for (size_t i = 0; i < tw * 4; i++) { - tile.push_back(ro + *(d + iy * (iw * 4) - + tr * (iw * 4) - + (ix * 4) + i)); + tile.push_back( + ro + + *(d + iy * (iw * 4) + tr * (iw * 4) + (ix * 4) + i)); } } if (tile.size() != (tw * th * 4)) { - cout << "bad tiles" << endl; + cout << "bad tiles" << endl; cout << "tile.size() = " << tile.size() << endl; cout << "tw * th * 4 = " << (tw * th * 4) << endl; } @@ -420,14 +417,24 @@ void ShellDialog::sendImage() // y (y tile pos) any int, default is 0 // f (frame) any int, default is 1 // - - QString interpLeft = QString( "PIXELTILE(" - "media=%1,view=left,w=%2,h=%3,x=%4,y=%5,f=1)") - .arg(m_mediaName).arg(tw).arg(th).arg(ix).arg(iy); - QString interpRight = QString( "PIXELTILE(" - "media=%1,view=right,w=%2,h=%3,x=%4,y=%5,f=1)") - .arg(m_mediaName).arg(tw).arg(th).arg(ix).arg(iy); + QString interpLeft = + QString("PIXELTILE(" + "media=%1,view=left,w=%2,h=%3,x=%4,y=%5,f=1)") + .arg(m_mediaName) + .arg(tw) + .arg(th) + .arg(ix) + .arg(iy); + + QString interpRight = + QString("PIXELTILE(" + "media=%1,view=right,w=%2,h=%3,x=%4,y=%5,f=1)") + .arg(m_mediaName) + .arg(tw) + .arg(th) + .arg(ix) + .arg(iy); m_client->sendData(m_contact, interpLeft, tile); m_client->waitForSend(m_contact); @@ -436,7 +443,7 @@ void ShellDialog::sendImage() // Make an inverted tile for the other eye // - for (int i=0; i < tile.size(); i++) + for (int i = 0; i < tile.size(); i++) { tile[i] = 255 - tile[i]; } @@ -455,17 +462,15 @@ void ShellDialog::sendImage() // we'll need to know about it. The contactLeft() slot // will be called during event processing causing the // m_stop member variable to be set to true. - // + // QCoreApplication::instance()->processEvents(); } } } -void -ShellDialog::quit() +void ShellDialog::quit() { - m_client->signOff (m_contact); + m_client->signOff(m_contact); qApp->quit(); } - diff --git a/src/bin/apps/rvshell/ShellDialog.h b/src/bin/apps/rvshell/ShellDialog.h index 1f0a8d20a..5aefe726f 100644 --- a/src/bin/apps/rvshell/ShellDialog.h +++ b/src/bin/apps/rvshell/ShellDialog.h @@ -1,9 +1,9 @@ // -// Copyright (c) 2008 Tweak Software. +// Copyright (c) 2008 Tweak Software. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// // #ifndef __rvshell__ShellDialog__h__ #define __rvshell__ShellDialog__h__ @@ -11,16 +11,19 @@ #include "ui_ShellDialog.h" #include -class ShellDialog : public QMainWindow, private Ui::ShellDialog +class ShellDialog + : public QMainWindow + , private Ui::ShellDialog { Q_OBJECT public: - ShellDialog(QWidget *parent = 0); + ShellDialog(QWidget* parent = 0); + TwkQtChat::Client* client() const { return m_client; } public slots: - void appendMessage(const QString &from, const QString &message); + void appendMessage(const QString& from, const QString& message); private slots: void go(); @@ -39,15 +42,15 @@ private slots: void sendImage(); private: - TwkQtChat::Client* m_client; - QTextTableFormat m_tableFormat; - QGraphicsScene* m_scene; - QPixmap m_pixmap; + TwkQtChat::Client* m_client; + QTextTableFormat m_tableFormat; + QGraphicsScene* m_scene; + QPixmap m_pixmap; QGraphicsPixmapItem* m_pixmapItem; - QString m_contact; - QString m_mediaName; - unsigned char* m_imageData; - bool m_stop; + QString m_contact; + QString m_mediaName; + unsigned char* m_imageData; + bool m_stop; }; #endif // __rvshell__ShellDialog__h__ diff --git a/src/bin/apps/rvshell/main.cpp b/src/bin/apps/rvshell/main.cpp index a2e9bbc1e..fde0501ef 100644 --- a/src/bin/apps/rvshell/main.cpp +++ b/src/bin/apps/rvshell/main.cpp @@ -16,7 +16,7 @@ using namespace std; -int utf8Main(int argc, char *argv[]) +int utf8Main(int argc, char* argv[]) { QApplication app(argc, argv); ShellDialog dialog; @@ -26,32 +26,30 @@ int utf8Main(int argc, char *argv[]) cout << endl; QHostInfo info = QHostInfo::fromName(argv[2]); int port = 45124; - if (argc == 4) port = atoi(argv[3]); + if (argc == 4) + port = atoi(argv[3]); QHostAddress addr; - for (int i=0; i < info.addresses().size(); i++) + for (int i = 0; i < info.addresses().size(); i++) { if (info.addresses()[i].protocol() == QAbstractSocket::IPv4Protocol) { addr = info.addresses()[i]; - cout << "found: " << info.addresses()[i].toString().toUtf8().data() << endl; + cout << "found: " + << info.addresses()[i].toString().toUtf8().data() << endl; break; } } - cout << "Connecting to " - << argv[1] - << " at " - << addr.toString().toUtf8().data() - << ":" << port - << endl; + cout << "Connecting to " << argv[1] << " at " + << addr.toString().toUtf8().data() << ":" << port << endl; dialog.client()->connectTo(argv[1], addr, port); } - else + else { cerr << "usage: rvshell [port]" << endl; - exit (1); + exit(1); } dialog.show(); diff --git a/src/bin/apps/rvshell/utf8Main.cpp b/src/bin/apps/rvshell/utf8Main.cpp index 69e097cc9..7c46f886c 100644 --- a/src/bin/apps/rvshell/utf8Main.cpp +++ b/src/bin/apps/rvshell/utf8Main.cpp @@ -1,6 +1,6 @@ // -// Copyright (C) 2023 Autodesk, Inc. All Rights Reserved. -// -// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2023 Autodesk, Inc. All Rights Reserved. // -#include "../../utf8Main.cpp" \ No newline at end of file +// SPDX-License-Identifier: Apache-2.0 +// +#include "../../utf8Main.cpp" diff --git a/src/bin/apps/utf8Main.cpp b/src/bin/apps/utf8Main.cpp index 72cb3b7c2..fe73b5853 100644 --- a/src/bin/apps/utf8Main.cpp +++ b/src/bin/apps/utf8Main.cpp @@ -6,44 +6,41 @@ // //*****************************************************************************/ -#if defined( _WIN32 ) +#if defined(_WIN32) #include #endif +int utf8Main(int argc, char* argv[]); -int utf8Main( int argc, char* argv[] ); - -#if defined( _WIN32 ) +#if defined(_WIN32) int wmain(int argc, wchar_t* wargv[]) { - // converts UCS2 arguements to utf-8 charset - char ** argv = new char * [argc]; - for (int argn = 0; argn < argc; argn++) - { - int sizeNeeded = WideCharToMultiByte(CP_UTF8, 0, wargv[argn], -1, NULL, 0, NULL, NULL); - if (sizeNeeded > 0 ) + // converts UCS2 arguements to utf-8 charset + char** argv = new char*[argc]; + for (int argn = 0; argn < argc; argn++) { - char * strTo = new char [sizeNeeded]; - WideCharToMultiByte(CP_UTF8, 0, wargv[argn], -1, strTo, sizeNeeded, NULL, NULL); - argv[argn] = strTo; + int sizeNeeded = WideCharToMultiByte(CP_UTF8, 0, wargv[argn], -1, NULL, + 0, NULL, NULL); + if (sizeNeeded > 0) + { + char* strTo = new char[sizeNeeded]; + WideCharToMultiByte(CP_UTF8, 0, wargv[argn], -1, strTo, sizeNeeded, + NULL, NULL); + argv[argn] = strTo; + } + else + argv[argn] = nullptr; } - else - argv[argn] = nullptr; - } - - int result = utf8Main(argc, argv); - - for (int argn = 0; argn < argc; argn++) - delete [] argv[argn]; - - delete [] argv; - - return result; + + int result = utf8Main(argc, argv); + + for (int argn = 0; argn < argc; argn++) + delete[] argv[argn]; + + delete[] argv; + + return result; } #else -int main(int argc, char* argv[]) -{ - return utf8Main(argc, argv); -} +int main(int argc, char* argv[]) { return utf8Main(argc, argv); } #endif - diff --git a/src/bin/apps/utf8Main.h b/src/bin/apps/utf8Main.h index 31f4a4b09..cd9b3d5dd 100644 --- a/src/bin/apps/utf8Main.h +++ b/src/bin/apps/utf8Main.h @@ -6,4 +6,4 @@ // //*****************************************************************************/ -int utf8Main( int argc, char* argv[] ); +int utf8Main(int argc, char* argv[]); diff --git a/src/bin/gtotools/gtofilter/main.cpp b/src/bin/gtotools/gtofilter/main.cpp index 25c760303..d535c026b 100644 --- a/src/bin/gtotools/gtofilter/main.cpp +++ b/src/bin/gtotools/gtofilter/main.cpp @@ -1,5 +1,5 @@ //****************************************************************************** -// Copyright (c) 2002 Tweak Inc. +// Copyright (c) 2002 Tweak Inc. // All rights reserved. // // SPDX-License-Identifier: Apache-2.0’ @@ -27,9 +27,9 @@ using namespace Gto; using namespace std; -bool verbose = false; -bool glob = true; -bool text = false; +bool verbose = false; +bool glob = true; +bool text = false; bool nocompress = false; regex_t excludeRegex; @@ -37,42 +37,42 @@ regex_t includeRegex; struct FullProperty { - string name; - string interp; - Object* object; - Component* component; + string name; + string interp; + Object* object; + Component* component; Components* componentList; - Property* property; + Property* property; }; typedef vector FullProperties; struct Empty_p { - bool operator() (Object* o) { return o->components.empty(); } + bool operator()(Object* o) { return o->components.empty(); } }; void gatherComponent(Object* o, Components& components, FullProperties& all) { - for (size_t j=0; j < components.size(); j++) + for (size_t j = 0; j < components.size(); j++) { Component* c = components[j]; - for (size_t q=0; q < c->properties.size(); q++) + for (size_t q = 0; q < c->properties.size(); q++) { Property* p = c->properties[q]; ostringstream fullname; fullname << o->name << "." << p->fullName; - + FullProperty fp; - fp.name = fullname.str(); - fp.object = o; - fp.component = c; + fp.name = fullname.str(); + fp.object = o; + fp.component = c; fp.componentList = &components; - fp.property = p; - fp.interp = p->interp; - + fp.property = p; + fp.interp = p->interp; + all.push_back(fp); } @@ -82,21 +82,19 @@ void gatherComponent(Object* o, Components& components, FullProperties& all) void gather(RawDataBase* db, FullProperties& all) { - for (size_t i=0; i < db->objects.size(); i++) + for (size_t i = 0; i < db->objects.size(); i++) { Object* o = db->objects[i]; gatherComponent(o, o->components, all); } } -void filter(RawDataBase* db, - FullProperties& properties, - const char *include, - const char *exclude) +void filter(RawDataBase* db, FullProperties& properties, const char* include, + const char* exclude) { - for (size_t i=0; i < properties.size(); i++) + for (size_t i = 0; i < properties.size(); i++) { - const FullProperty &fp = properties[i]; + const FullProperty& fp = properties[i]; bool imatch = false; bool ematch = false; @@ -115,11 +113,11 @@ void filter(RawDataBase* db, if (verbose && matched) { - cout << "gtomerge: include pattern matched " - << fp.name << endl; + cout << "gtomerge: include pattern matched " << fp.name << endl; } - if (matched) imatch = true; + if (matched) + imatch = true; } if (exclude) @@ -137,42 +135,38 @@ void filter(RawDataBase* db, if (verbose && matched) { - cout << "gtomerge: exclude pattern matched " - << fp.name << endl; + cout << "gtomerge: exclude pattern matched " << fp.name << endl; } - if (matched) ematch = true; + if (matched) + ematch = true; } if (include && imatch && exclude && ematch) { - cout << "gtomerge: including " << fp.name - << " despite matching include and exclude pattern" - << endl; + cout << "gtomerge: including " << fp.name + << " despite matching include and exclude pattern" << endl; } - else if ((include && !exclude && !imatch) || - (!include && exclude && ematch) || - (include && !imatch && exclude && ematch)) + else if ((include && !exclude && !imatch) + || (!include && exclude && ematch) + || (include && !imatch && exclude && ematch)) { - Object *o = fp.object; - Component *c = fp.component; - Property *p = fp.property; + Object* o = fp.object; + Component* c = fp.component; + Property* p = fp.property; - c->properties.erase( find(c->properties.begin(), - c->properties.end(), - p) ); + c->properties.erase( + find(c->properties.begin(), c->properties.end(), p)); if (c->properties.empty()) { - fp.componentList->erase( find(fp.componentList->begin(), - fp.componentList->end(), - c) ); + fp.componentList->erase(find(fp.componentList->begin(), + fp.componentList->end(), c)); if (fp.object->components.empty()) { - db->objects.erase( find(db->objects.begin(), - db->objects.end(), - o) ); + db->objects.erase( + find(db->objects.begin(), db->objects.end(), o)); } } } @@ -184,16 +178,14 @@ void filter(RawDataBase* db, size_t n = db->objects.size(); - db->objects.erase(remove_if(db->objects.begin(), - db->objects.end(), - Empty_p()), - db->objects.end()); + db->objects.erase( + remove_if(db->objects.begin(), db->objects.end(), Empty_p()), + db->objects.end()); if (verbose && n != db->objects.size()) { cout << "gtofilter: removed " << (n - db->objects.size()) - << " empty objects from input" - << endl; + << " empty objects from input" << endl; } } @@ -209,35 +201,38 @@ void usage() << "-ee/--exclude regex exclusion regex\n" << "-v verbose\n" << endl; - + exit(-1); } - -int utf8Main(int argc, char *argv[]) + +int utf8Main(int argc, char* argv[]) { - char *inFile = 0; - char *outFile = 0; - char *includeExpr = 0; - char *excludeExpr = 0; + char* inFile = 0; + char* outFile = 0; + char* includeExpr = 0; + char* excludeExpr = 0; - for (int i=1; i < argc; i++) + for (int i = 1; i < argc; i++) { if (!strcmp(argv[i], "-o")) { i++; - if (i >= argc) usage(); + if (i >= argc) + usage(); outFile = argv[i]; } else if (!strcmp(argv[i], "-ie") || !strcmp(argv[i], "--include")) { i++; - if (i >= argc) usage(); + if (i >= argc) + usage(); includeExpr = argv[i]; } else if (!strcmp(argv[i], "-ee") || !strcmp(argv[i], "--exclude")) { i++; - if (i >= argc) usage(); + if (i >= argc) + usage(); excludeExpr = argv[i]; } else if (!strcmp(argv[i], "-v")) @@ -266,14 +261,15 @@ int utf8Main(int argc, char *argv[]) } else { - if (inFile) usage(); + if (inFile) + usage(); inFile = argv[i]; } } if (!inFile || !outFile) { - cout << "no infile or outfile specified.\n" << flush; + cout << "no infile or outfile specified.\n" << flush; cout << endl; usage(); } @@ -308,12 +304,11 @@ int utf8Main(int argc, char *argv[]) if (!reader.open(inFile)) { - cerr << "ERROR: unable to read file " << inFile - << endl; + cerr << "ERROR: unable to read file " << inFile << endl; exit(-1); } - RawDataBase *db = reader.dataBase(); + RawDataBase* db = reader.dataBase(); FullProperties allProperties; gather(db, allProperties); filter(db, allProperties, includeExpr, excludeExpr); @@ -326,18 +321,19 @@ int utf8Main(int argc, char *argv[]) RawDataBaseWriter writer; Writer::FileType type = Writer::CompressedGTO; - if (nocompress) type = Writer::BinaryGTO; - if (text) type = Writer::TextGTO; + if (nocompress) + type = Writer::BinaryGTO; + if (text) + type = Writer::TextGTO; if (!writer.write(outFile, *db, type)) { - cerr << "ERROR: unable to write file " << outFile - << endl; - exit(-1); + cerr << "ERROR: unable to write file " << outFile << endl; + exit(-1); } else { - cout << "Wrote file " << outFile << endl; + cout << "Wrote file " << outFile << endl; } return 0; diff --git a/src/bin/gtotools/gtofilter/utf8Main.cpp b/src/bin/gtotools/gtofilter/utf8Main.cpp index 69e097cc9..7c46f886c 100644 --- a/src/bin/gtotools/gtofilter/utf8Main.cpp +++ b/src/bin/gtotools/gtofilter/utf8Main.cpp @@ -1,6 +1,6 @@ // -// Copyright (C) 2023 Autodesk, Inc. All Rights Reserved. -// -// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2023 Autodesk, Inc. All Rights Reserved. // -#include "../../utf8Main.cpp" \ No newline at end of file +// SPDX-License-Identifier: Apache-2.0 +// +#include "../../utf8Main.cpp" diff --git a/src/bin/gtotools/gtoimage/main.cpp b/src/bin/gtotools/gtoimage/main.cpp index 1e881ee35..6135afd45 100644 --- a/src/bin/gtotools/gtoimage/main.cpp +++ b/src/bin/gtotools/gtoimage/main.cpp @@ -21,47 +21,42 @@ using namespace std; //---------------------------------------------------------------------- -string -basename(string path) +string basename(string path) { - size_t lastSlash = path.rfind( "/" ); + size_t lastSlash = path.rfind("/"); if (lastSlash == path.npos) { return path; } - return path.substr( lastSlash + 1, path.size() ); + return path.substr(lastSlash + 1, path.size()); } - -string -extension(const std::string& path) +string extension(const std::string& path) { string filename(basename(path)); - if (filename.find( "." ) == filename.npos) + if (filename.find(".") == filename.npos) { return string(""); } else { - return filename.substr( filename.rfind(".") + 1, filename.size() ); + return filename.substr(filename.rfind(".") + 1, filename.size()); } } -string -prefix( string path ) +string prefix(string path) { - string filename( basename( path ) ); - if( filename.find( "." ) == filename.npos ) + string filename(basename(path)); + if (filename.find(".") == filename.npos) { return filename; } - return filename.substr( 0, filename.find( "." ) ); + return filename.substr(0, filename.find(".")); } - //---------------------------------------------------------------------- struct Image @@ -74,33 +69,31 @@ struct Image size_t size; size_t pixelSize; - float* floatPixel(int x, int y) - { - return floatData + y * w * channels + x * channels; + float* floatPixel(int x, int y) + { + return floatData + y * w * channels + x * channels; } - short* shortPixel(int x, int y) - { - return shortData + y * w * channels + x * channels; + short* shortPixel(int x, int y) + { + return shortData + y * w * channels + x * channels; } char* charPixel(int x, int y) { - return charData + y * w * channels + x * channels; + return charData + y * w * channels + x * channels; } union { float* floatData; short* shortData; - char* charData; - void* voidData; + char* charData; + void* voidData; }; }; - -Image* -readTIFF(const std::string& imgFileName) +Image* readTIFF(const std::string& imgFileName) { Image* image = new Image; @@ -113,62 +106,62 @@ readTIFF(const std::string& imgFileName) TIFF* tif = TIFFOpen(imgFileName.c_str(), "r"); - if (!tif) return 0; - - unsigned short *sampleinfo; + if (!tif) + return 0; + + unsigned short* sampleinfo; unsigned short extrasamples; unsigned short bbs; - TIFFGetField( tif, TIFFTAG_IMAGEWIDTH, &image->w); - TIFFGetField( tif, TIFFTAG_IMAGELENGTH, &image->h); - TIFFGetField( tif, TIFFTAG_BITSPERSAMPLE, &image->bbs ); + TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &image->w); + TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &image->h); + TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &image->bbs); + + TIFFGetFieldDefaulted(tif, TIFFTAG_EXTRASAMPLES, &extrasamples, + &sampleinfo); - TIFFGetFieldDefaulted( tif, TIFFTAG_EXTRASAMPLES, - &extrasamples, &sampleinfo ); - image->channels = extrasamples ? 4 : 3; - + switch (image->bbs) { - case 32: - image->floatData = new float[image->w * image->h * image->channels]; - image->type = Float; - - for (int y = 0; y < image->h; ++y) - { - TIFFReadScanline(tif, image->floatPixel(0, image->h - y - 1), y); - } - break; - - case 16: - image->shortData = new short[image->w * image->h * image->channels]; - image->type = Short; - - for (int y = 0; y < image->h; ++y ) - { - TIFFReadScanline(tif, image->shortPixel(0, image->h - y - 1), y); - } - break; - - case 8: - image->charData = new char[image->w * image->h * image->channels]; - image->type = Byte; - - for (int y = 0; y < image->h; ++y ) - { - TIFFReadScanline( tif, image->charPixel(0, image->h - y - 1), y ); - } - break; + case 32: + image->floatData = new float[image->w * image->h * image->channels]; + image->type = Float; + + for (int y = 0; y < image->h; ++y) + { + TIFFReadScanline(tif, image->floatPixel(0, image->h - y - 1), y); + } + break; + + case 16: + image->shortData = new short[image->w * image->h * image->channels]; + image->type = Short; + + for (int y = 0; y < image->h; ++y) + { + TIFFReadScanline(tif, image->shortPixel(0, image->h - y - 1), y); + } + break; + + case 8: + image->charData = new char[image->w * image->h * image->channels]; + image->type = Byte; + + for (int y = 0; y < image->h; ++y) + { + TIFFReadScanline(tif, image->charPixel(0, image->h - y - 1), y); + } + break; } - + TIFFClose(tif); return image; } //---------------------------------------------------------------------- -Object* -makeImageObject(Image* image, const char* inFile) +Object* makeImageObject(Image* image, const char* inFile) { Object* o = new Object(prefix(inFile), GTO_PROTOCOL_IMAGE, 1); @@ -184,8 +177,8 @@ makeImageObject(Image* image, const char* inFile) p = new Property("originalEncoding", "filetype", String, 1, 1, true); p->stringData[0] = "TIFF"; c[0]->properties.push_back(p); - - const char *itype = image->channels == 3 ? "RGB" : "RGBA"; + + const char* itype = image->channels == 3 ? "RGB" : "RGBA"; p = new Property(GTO_PROPERTY_TYPE, String, 1, 1, true); p->stringData[0] = itype; @@ -196,7 +189,7 @@ makeImageObject(Image* image, const char* inFile) p->int32Data[1] = image->h; c[0]->properties.push_back(p); - p = new Property(GTO_PROPERTY_PIXELS, itype, (Gto::DataType)image->type, + p = new Property(GTO_PROPERTY_PIXELS, itype, (Gto::DataType)image->type, image->w * image->h, image->channels, false); p->voidData = image->voidData; c[0]->properties.push_back(p); @@ -204,11 +197,9 @@ makeImageObject(Image* image, const char* inFile) return o; } - //---------------------------------------------------------------------- -void -usage() +void usage() { cout << "gtoimage [OPTIONS] INFILE OUTFILE" << endl << endl @@ -217,20 +208,20 @@ usage() << "-t text GTO output" << endl << "-nc uncompressed GTO output" << endl << endl; - + exit(-1); } //---------------------------------------------------------------------- -int utf8Main(int argc, char *argv[]) +int utf8Main(int argc, char* argv[]) { - char* inFile = 0; - char* outFile = 0; - int nocompress = 0; - int text = 0; - - for (int i=1; i < argc; i++) + char* inFile = 0; + char* outFile = 0; + int nocompress = 0; + int text = 0; + + for (int i = 1; i < argc; i++) { if (!strcmp(argv[i], "-t")) { @@ -242,9 +233,12 @@ int utf8Main(int argc, char *argv[]) } else { - if (!inFile) inFile = argv[i]; - else if (!outFile) outFile = argv[i]; - else usage(); + if (!inFile) + inFile = argv[i]; + else if (!outFile) + outFile = argv[i]; + else + usage(); } } @@ -254,7 +248,7 @@ int utf8Main(int argc, char *argv[]) if (!inFile || !outFile) { - cerr << "ERROR: no infile or outfile specified.\n" << endl; + cerr << "ERROR: no infile or outfile specified.\n" << endl; usage(); } @@ -297,8 +291,10 @@ int utf8Main(int argc, char *argv[]) { RawDataBaseWriter writer; Writer::FileType type = Writer::CompressedGTO; - if (nocompress) type = Writer::BinaryGTO; - if (text) type = Writer::TextGTO; + if (nocompress) + type = Writer::BinaryGTO; + if (text) + type = Writer::TextGTO; if (!writer.write(outFile, *db, type)) { diff --git a/src/bin/gtotools/gtoimage/utf8Main.cpp b/src/bin/gtotools/gtoimage/utf8Main.cpp index 69e097cc9..7c46f886c 100644 --- a/src/bin/gtotools/gtoimage/utf8Main.cpp +++ b/src/bin/gtotools/gtoimage/utf8Main.cpp @@ -1,6 +1,6 @@ // -// Copyright (C) 2023 Autodesk, Inc. All Rights Reserved. -// -// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2023 Autodesk, Inc. All Rights Reserved. // -#include "../../utf8Main.cpp" \ No newline at end of file +// SPDX-License-Identifier: Apache-2.0 +// +#include "../../utf8Main.cpp" diff --git a/src/bin/gtotools/gtoinfo/main.cpp b/src/bin/gtotools/gtoinfo/main.cpp index a418f102e..b899d1015 100644 --- a/src/bin/gtotools/gtoinfo/main.cpp +++ b/src/bin/gtotools/gtoinfo/main.cpp @@ -5,7 +5,6 @@ // SPDX-License-Identifier: Apache-2.0’ // - #include "../../utf8Main.h" #include @@ -22,80 +21,73 @@ using namespace std; -bool outputStrings = false; -bool outputData = false; -bool outputHeader = true; -bool formatData = false; -bool readAll = false; +bool outputStrings = false; +bool outputData = false; +bool outputHeader = true; +bool formatData = false; +bool readAll = false; bool numericStrings = false; -bool filtered = false; -bool outputInterp = false; +bool filtered = false; +bool outputInterp = false; typedef set PropertySet; -typedef set ObjectSet; +typedef set ObjectSet; PropertySet filteredProperties; ObjectSet filteredObjects; - class Reader : public Gto::Reader { public: Reader(unsigned int mode) - : Gto::Reader(mode), - m_objectName(Gto::uint32(-1)) {} + : Gto::Reader(mode) + , m_objectName(Gto::uint32(-1)) + { + } - Gto::uint32 m_objectName; - std::string m_componentName; - vector m_buffer; + Gto::uint32 m_objectName; + std::string m_componentName; + vector m_buffer; typedef Gto::Reader::Request Request; - void headerOutput(const Gto::Reader::PropertyInfo&); - void outputPropertyHeader(const Gto::Reader::PropertyInfo &); - void outputStringTable(); - - virtual void descriptionComplete(); + void headerOutput(const Gto::Reader::PropertyInfo&); + void outputPropertyHeader(const Gto::Reader::PropertyInfo&); + void outputStringTable(); - virtual Request object(const std::string& name, - const std::string& protocol, - unsigned int protocolVersion, - const Gto::Reader::ObjectInfo &header); + virtual void descriptionComplete(); - virtual Request component(const std::string& name, - const std::string& interp, - const Gto::Reader::ComponentInfo &header); + virtual Request object(const std::string& name, const std::string& protocol, + unsigned int protocolVersion, + const Gto::Reader::ObjectInfo& header); - virtual Request property(const std::string& name, - const std::string& interp, - const Gto::Reader::PropertyInfo &header); + virtual Request component(const std::string& name, + const std::string& interp, + const Gto::Reader::ComponentInfo& header); - virtual void* data(const PropertyInfo&, size_t bytes); - virtual void dataRead(const PropertyInfo&); + virtual Request property(const std::string& name, const std::string& interp, + const Gto::Reader::PropertyInfo& header); - virtual void data(const PropertyInfo&, - const float*, size_t numItems); + virtual void* data(const PropertyInfo&, size_t bytes); + virtual void dataRead(const PropertyInfo&); - virtual void data(const PropertyInfo&, - const double*, size_t numItems); + virtual void data(const PropertyInfo&, const float*, size_t numItems); - virtual void data(const PropertyInfo&, - const int*, size_t numItems); + virtual void data(const PropertyInfo&, const double*, size_t numItems); - virtual void data(const PropertyInfo&, - const unsigned short*, size_t numItems); + virtual void data(const PropertyInfo&, const int*, size_t numItems); - virtual void data(const PropertyInfo&, - const unsigned char*, size_t numItems); + virtual void data(const PropertyInfo&, const unsigned short*, + size_t numItems); - virtual void data(const PropertyInfo&, bool); + virtual void data(const PropertyInfo&, const unsigned char*, + size_t numItems); + virtual void data(const PropertyInfo&, bool); }; - -void -Reader::headerOutput(const Gto::Reader::PropertyInfo& pinfo) +void Reader::headerOutput(const Gto::Reader::PropertyInfo& pinfo) { const Gto::Reader::ComponentInfo* cinfo = pinfo.component; - const Gto::Reader::ObjectInfo* oinfo = cinfo->object; + const Gto::Reader::ObjectInfo* oinfo = cinfo->object; if (m_objectName != oinfo->name) { @@ -106,13 +98,9 @@ Reader::headerOutput(const Gto::Reader::PropertyInfo& pinfo) m_objectName = oinfo->name; m_componentName = ""; - cout << "object \"" - << stringFromId(m_objectName) - << "\" protocol \"" - << stringFromId(oinfo->protocolName) - << "\" v" - << oinfo->protocolVersion - << endl; + cout << "object \"" << stringFromId(m_objectName) << "\" protocol \"" + << stringFromId(oinfo->protocolName) << "\" v" + << oinfo->protocolVersion << endl; } if (m_componentName != cinfo->fullName) @@ -123,14 +111,11 @@ Reader::headerOutput(const Gto::Reader::PropertyInfo& pinfo) m_componentName = cinfo->fullName; - cout << " component \"" - << cinfo->fullName - << "\""; + cout << " component \"" << cinfo->fullName << "\""; if (outputInterp && stringFromId(cinfo->interpretation) != "") { - cout << " interpret as \"" - << stringFromId(cinfo->interpretation) + cout << " interpret as \"" << stringFromId(cinfo->interpretation) << "\" "; } @@ -138,8 +123,7 @@ Reader::headerOutput(const Gto::Reader::PropertyInfo& pinfo) } } -void -Reader::descriptionComplete() +void Reader::descriptionComplete() { union EndianTest { @@ -153,8 +137,8 @@ Reader::descriptionComplete() if (outputHeader) { - cout << "GTO file version " << fileHeader().version - << ", " << fileHeader().numStrings << " strings, "; + cout << "GTO file version " << fileHeader().version << ", " + << fileHeader().numStrings << " strings, "; if (fileHeader().magic == Gto::Header::MagicText) { @@ -164,66 +148,67 @@ Reader::descriptionComplete() { if (big) { - if (isSwapped()) cout << "little endian binary\n"; - else cout << "big endian binary\n"; + if (isSwapped()) + cout << "little endian binary\n"; + else + cout << "big endian binary\n"; } else { - if (isSwapped()) cout << "big endian binary\n"; - else cout << "little endian binary\n"; + if (isSwapped()) + cout << "big endian binary\n"; + else + cout << "little endian binary\n"; } } for (Gto::Reader::Properties::const_iterator p = properties().begin(); - p != properties().end(); - ++p) + p != properties().end(); ++p) { outputPropertyHeader(*p); } } - if (outputStrings) outputStringTable(); + if (outputStrings) + outputStringTable(); } -void -Reader::outputStringTable() +void Reader::outputStringTable() { - const StringTable &strings = stringTable(); + const StringTable& strings = stringTable(); - for (size_t i=0; i < strings.size(); i++) + for (size_t i = 0; i < strings.size(); i++) { - if (i && !formatData) cout << ", "; + if (i && !formatData) + cout << ", "; cout << i << ": \"" << strings[i] << "\""; - if (formatData) cout << endl; + if (formatData) + cout << endl; } cout << endl; exit(0); } -Reader::Request -Reader::object(const std::string &name, - const std::string &protocol, - unsigned int version, - const Gto::Reader::ObjectInfo &info) +Reader::Request Reader::object(const std::string& name, + const std::string& protocol, + unsigned int version, + const Gto::Reader::ObjectInfo& info) { return Request(outputData); } -Reader::Request -Reader::component(const std::string &n, - const std::string &i, - const Gto::Reader::ComponentInfo& c) +Reader::Request Reader::component(const std::string& n, const std::string& i, + const Gto::Reader::ComponentInfo& c) { return Request(outputData); } -Reader::Request -Reader::property(const std::string&, - const std::string&, - const Gto::Reader::PropertyInfo &info) +Reader::Request Reader::property(const std::string&, const std::string&, + const Gto::Reader::PropertyInfo& info) { - if (!outputData) return Request(false); + if (!outputData) + return Request(false); if (filtered) { @@ -236,8 +221,7 @@ Reader::property(const std::string&, } } -void -Reader::outputPropertyHeader(const Gto::Reader::PropertyInfo &info) +void Reader::outputPropertyHeader(const Gto::Reader::PropertyInfo& info) { headerOutput(info); @@ -245,42 +229,58 @@ Reader::outputPropertyHeader(const Gto::Reader::PropertyInfo &info) switch (info.type) { - case Gto::Int: type = "int"; break; - case Gto::Float: type = "float"; break; - case Gto::Double: type = "double"; break; - case Gto::Half: type = "half"; break; - case Gto::String: type = "string"; break; - case Gto::Short: type = "short"; break; - case Gto::Byte: type = "byte"; break; - case Gto::Boolean: type = "bool"; break; - default: type = "unknown"; break; + case Gto::Int: + type = "int"; + break; + case Gto::Float: + type = "float"; + break; + case Gto::Double: + type = "double"; + break; + case Gto::Half: + type = "half"; + break; + case Gto::String: + type = "string"; + break; + case Gto::Short: + type = "short"; + break; + case Gto::Byte: + type = "byte"; + break; + case Gto::Boolean: + type = "bool"; + break; + default: + type = "unknown"; + break; } - cout << " property " << type - << "[" << info.dims.x; + cout << " property " << type << "[" << info.dims.x; - if (info.dims.y > 0) cout << "," << info.dims.y; - if (info.dims.z > 0) cout << "," << info.dims.z; - if (info.dims.w > 0) cout << "," << info.dims.w; + if (info.dims.y > 0) + cout << "," << info.dims.y; + if (info.dims.z > 0) + cout << "," << info.dims.z; + if (info.dims.w > 0) + cout << "," << info.dims.w; cout << "]" << "[" << info.size << "]" - << " \"" - << stringFromId(info.name) - << "\""; + << " \"" << stringFromId(info.name) << "\""; if (outputInterp && stringFromId(info.interpretation) != "") { - cout << " interpret as \"" - << stringFromId(info.interpretation) + cout << " interpret as \"" << stringFromId(info.interpretation) << "\" "; } cout << endl; } -void* -Reader::data(const PropertyInfo& info, size_t bytes) +void* Reader::data(const PropertyInfo& info, size_t bytes) { if (bytes) { @@ -291,71 +291,71 @@ Reader::data(const PropertyInfo& info, size_t bytes) { switch (info.type) { - case Gto::Float: - data(info, (float*)0, info.size); - break; - case Gto::Double: - data(info, (double*)0, info.size); - break; - case Gto::Int: - case Gto::String: - data(info, (int*)0, info.size); - break; - case Gto::Short: - data(info, (unsigned short*)0, info.size); - break; - case Gto::Byte: - data(info, (unsigned char*)0, info.size); - break; - case Gto::Boolean: - break; + case Gto::Float: + data(info, (float*)0, info.size); + break; + case Gto::Double: + data(info, (double*)0, info.size); + break; + case Gto::Int: + case Gto::String: + data(info, (int*)0, info.size); + break; + case Gto::Short: + data(info, (unsigned short*)0, info.size); + break; + case Gto::Byte: + data(info, (unsigned char*)0, info.size); + break; + case Gto::Boolean: + break; } } return 0; } -void -Reader::dataRead(const PropertyInfo& info) +void Reader::dataRead(const PropertyInfo& info) { void* buffer = (void*)&m_buffer.front(); switch (info.type) { - case Gto::Float: - data(info, (float*)buffer, info.size); - break; - case Gto::Double: - data(info, (double*)buffer, info.size); - break; - case Gto::Int: - case Gto::String: - data(info, (int*)buffer, info.size); - break; - case Gto::Short: - data(info, (unsigned short*)buffer, info.size); - break; - case Gto::Byte: - data(info, (unsigned char*)buffer, info.size); - break; - case Gto::Boolean: - break; + case Gto::Float: + data(info, (float*)buffer, info.size); + break; + case Gto::Double: + data(info, (double*)buffer, info.size); + break; + case Gto::Int: + case Gto::String: + data(info, (int*)buffer, info.size); + break; + case Gto::Short: + data(info, (unsigned short*)buffer, info.size); + break; + case Gto::Byte: + data(info, (unsigned char*)buffer, info.size); + break; + case Gto::Boolean: + break; } } void Reader::data(const PropertyInfo& info, const float* data, size_t numItems) { - if (!outputData) return; + if (!outputData) + return; cout << "float[" << info.dims.x; - if (info.dims.y > 0) cout << "," << info.dims.y; - if (info.dims.z > 0) cout << "," << info.dims.z; - if (info.dims.w > 0) cout << "," << info.dims.w; - cout << "] " - << stringFromId(info.component->object->name) - << "." << info.component->fullName - << "." << stringFromId(info.name) - << " = "; + if (info.dims.y > 0) + cout << "," << info.dims.y; + if (info.dims.z > 0) + cout << "," << info.dims.z; + if (info.dims.w > 0) + cout << "," << info.dims.w; + cout << "] " << stringFromId(info.component->object->name) << "." + << info.component->fullName << "." << stringFromId(info.name) << " = "; if (formatData) { @@ -366,17 +366,18 @@ void Reader::data(const PropertyInfo& info, const float* data, size_t numItems) cout << "["; } - for (size_t i=0; i < numItems; i++) + for (size_t i = 0; i < numItems; i++) { - if (formatData) cout << " "; + if (formatData) + cout << " "; - if (info.dims.x > 1 ) + if (info.dims.x > 1) { size_t esize = Gto::elementSize(info.dims); cout << " ["; - for( int j = 0; j < esize; ++j ) + for (int j = 0; j < esize; ++j) { - cout << " " << data[(i*esize)+j]; + cout << " " << data[(i * esize) + j]; } cout << " ]"; } @@ -385,7 +386,8 @@ void Reader::data(const PropertyInfo& info, const float* data, size_t numItems) cout << " " << data[i]; } - if (formatData) cout << endl; + if (formatData) + cout << endl; } cout << (formatData ? "" : " ") << "]" << endl; @@ -393,17 +395,18 @@ void Reader::data(const PropertyInfo& info, const float* data, size_t numItems) void Reader::data(const PropertyInfo& info, const double* data, size_t numItems) { - if (!outputData) return; + if (!outputData) + return; cout << "double[" << info.dims.x; - if (info.dims.y > 0) cout << "," << info.dims.y; - if (info.dims.z > 0) cout << "," << info.dims.z; - if (info.dims.w > 0) cout << "," << info.dims.w; - cout << "] " - << stringFromId(info.component->object->name) - << "." << info.component->fullName - << "." << stringFromId(info.name) - << " = "; + if (info.dims.y > 0) + cout << "," << info.dims.y; + if (info.dims.z > 0) + cout << "," << info.dims.z; + if (info.dims.w > 0) + cout << "," << info.dims.w; + cout << "] " << stringFromId(info.component->object->name) << "." + << info.component->fullName << "." << stringFromId(info.name) << " = "; if (formatData) { @@ -414,18 +417,19 @@ void Reader::data(const PropertyInfo& info, const double* data, size_t numItems) cout << "["; } - for (size_t i=0; i < numItems; i++) + for (size_t i = 0; i < numItems; i++) { - if (formatData) cout << " "; - + if (formatData) + cout << " "; + size_t esize = Gto::elementSize(info.dims); - if (esize > 1 ) + if (esize > 1) { cout << " ["; - for( int j = 0; j < esize; ++j ) + for (int j = 0; j < esize; ++j) { - cout << " " << data[(i*esize)+j]; + cout << " " << data[(i * esize) + j]; } cout << " ]"; } @@ -434,7 +438,8 @@ void Reader::data(const PropertyInfo& info, const double* data, size_t numItems) cout << " " << data[i]; } - if (formatData) cout << endl; + if (formatData) + cout << endl; } cout << (formatData ? "" : " ") << "]" << endl; @@ -442,18 +447,20 @@ void Reader::data(const PropertyInfo& info, const double* data, size_t numItems) void Reader::data(const PropertyInfo& info, const int* data, size_t numItems) { - if (!outputData) return; + if (!outputData) + return; if (info.type == Gto::Int) { cout << "int[" << info.dims.x; - if (info.dims.y > 0) cout << "," << info.dims.y; - if (info.dims.z > 0) cout << "," << info.dims.z; - if (info.dims.w > 0) cout << "," << info.dims.w; - cout << "] " - << stringFromId(info.component->object->name) - << "." << info.component->fullName - << "." << stringFromId(info.name) + if (info.dims.y > 0) + cout << "," << info.dims.y; + if (info.dims.z > 0) + cout << "," << info.dims.z; + if (info.dims.w > 0) + cout << "," << info.dims.w; + cout << "] " << stringFromId(info.component->object->name) << "." + << info.component->fullName << "." << stringFromId(info.name) << " = "; if (formatData) @@ -465,18 +472,19 @@ void Reader::data(const PropertyInfo& info, const int* data, size_t numItems) cout << "["; } - for (size_t i=0; i < numItems; i++) + for (size_t i = 0; i < numItems; i++) { - if (formatData) cout << " "; + if (formatData) + cout << " "; size_t esize = Gto::elementSize(info.dims); if (esize > 1) { cout << " ["; - for( int j = 0; j < esize; ++j ) + for (int j = 0; j < esize; ++j) { - cout << " " << data[(i*esize)+j]; + cout << " " << data[(i * esize) + j]; } cout << " ]"; } @@ -485,20 +493,21 @@ void Reader::data(const PropertyInfo& info, const int* data, size_t numItems) cout << " " << data[i]; } - if (formatData) cout << endl; + if (formatData) + cout << endl; } } else { - cout << "string[" - << info.dims.x; - if (info.dims.y > 0) cout << "," << info.dims.y; - if (info.dims.z > 0) cout << "," << info.dims.z; - if (info.dims.w > 0) cout << "," << info.dims.w; - cout << "] " - << stringFromId(info.component->object->name) - << "." << info.component->fullName - << "." << stringFromId(info.name) + cout << "string[" << info.dims.x; + if (info.dims.y > 0) + cout << "," << info.dims.y; + if (info.dims.z > 0) + cout << "," << info.dims.z; + if (info.dims.w > 0) + cout << "," << info.dims.w; + cout << "] " << stringFromId(info.component->object->name) << "." + << info.component->fullName << "." << stringFromId(info.name) << " = "; if (formatData) @@ -510,24 +519,25 @@ void Reader::data(const PropertyInfo& info, const int* data, size_t numItems) cout << "["; } - for (size_t i=0; i < numItems; i++) + for (size_t i = 0; i < numItems; i++) { - if (formatData) cout << " "; + if (formatData) + cout << " "; size_t esize = Gto::elementSize(info.dims); - if( esize > 1 ) + if (esize > 1) { cout << " ["; - for( int j = 0; j < esize; ++j ) + for (int j = 0; j < esize; ++j) { if (numericStrings) { - cout << " " << data[(i*esize)+j]; + cout << " " << data[(i * esize) + j]; } else { - cout << " \"" << stringFromId(data[(i*esize)+j]); + cout << " \"" << stringFromId(data[(i * esize) + j]); cout << "\""; } } @@ -545,29 +555,31 @@ void Reader::data(const PropertyInfo& info, const int* data, size_t numItems) } } - if (formatData) cout << endl; + if (formatData) + cout << endl; } } cout << (formatData ? "" : " ") << "]" << endl; } -void Reader::data(const PropertyInfo& info, - const unsigned short* data, +void Reader::data(const PropertyInfo& info, const unsigned short* data, size_t numItems) { - if (!outputData) return; + if (!outputData) + return; if (info.type == Gto::Short) { cout << "short[" << info.dims.x; - if (info.dims.y > 0) cout << "," << info.dims.y; - if (info.dims.z > 0) cout << "," << info.dims.z; - if (info.dims.w > 0) cout << "," << info.dims.w; - cout << "] " - << stringFromId(info.component->object->name) - << "." << info.component->fullName - << "." << stringFromId(info.name) + if (info.dims.y > 0) + cout << "," << info.dims.y; + if (info.dims.z > 0) + cout << "," << info.dims.z; + if (info.dims.w > 0) + cout << "," << info.dims.w; + cout << "] " << stringFromId(info.component->object->name) << "." + << info.component->fullName << "." << stringFromId(info.name) << " = "; if (formatData) @@ -579,19 +591,19 @@ void Reader::data(const PropertyInfo& info, cout << "["; } - - for (size_t i=0; i < numItems; i++) + for (size_t i = 0; i < numItems; i++) { - if (formatData) cout << " "; + if (formatData) + cout << " "; size_t esize = Gto::elementSize(info.dims); - if( esize > 1 ) + if (esize > 1) { cout << " ["; - for( int j = 0; j < esize; ++j ) + for (int j = 0; j < esize; ++j) { - cout << " " << data[(i*esize)+j]; + cout << " " << data[(i * esize) + j]; } cout << " ]"; } @@ -600,29 +612,31 @@ void Reader::data(const PropertyInfo& info, cout << " " << data[i]; } - if (formatData) cout << endl; + if (formatData) + cout << endl; } } cout << (formatData ? "" : " ") << "]" << endl; } -void Reader::data(const PropertyInfo& info, - const unsigned char* data, +void Reader::data(const PropertyInfo& info, const unsigned char* data, size_t numItems) { - if (!outputData) return; + if (!outputData) + return; if (info.type == Gto::Byte) { cout << "byte[" << info.dims.x; - if (info.dims.y > 0) cout << "," << info.dims.y; - if (info.dims.z > 0) cout << "," << info.dims.z; - if (info.dims.w > 0) cout << "," << info.dims.w; - cout << "] " - << stringFromId(info.component->object->name) - << "." << info.component->fullName - << "." << stringFromId(info.name) + if (info.dims.y > 0) + cout << "," << info.dims.y; + if (info.dims.z > 0) + cout << "," << info.dims.z; + if (info.dims.w > 0) + cout << "," << info.dims.w; + cout << "] " << stringFromId(info.component->object->name) << "." + << info.component->fullName << "." << stringFromId(info.name) << " = "; if (formatData) @@ -636,16 +650,17 @@ void Reader::data(const PropertyInfo& info, size_t esize = Gto::elementSize(info.dims); - for (size_t i=0; i < numItems; i++) + for (size_t i = 0; i < numItems; i++) { - if (formatData) cout << " "; + if (formatData) + cout << " "; - if( esize > 1 ) + if (esize > 1) { cout << " ["; - for( int j = 0; j < esize; ++j ) + for (int j = 0; j < esize; ++j) { - cout << " " << int(data[(i*esize)+j]); + cout << " " << int(data[(i * esize) + j]); } cout << " ]"; } @@ -654,7 +669,8 @@ void Reader::data(const PropertyInfo& info, cout << " " << int(data[i]); } - if (formatData) cout << endl; + if (formatData) + cout << endl; } } @@ -663,7 +679,8 @@ void Reader::data(const PropertyInfo& info, void Reader::data(const PropertyInfo& info, bool) { - if (!outputData) return; + if (!outputData) + return; } //---------------------------------------------------------------------- @@ -673,11 +690,11 @@ void filterData(const std::string& filterExpr, Reader& reader) Gto::Reader::Properties& properties = reader.properties(); Gto::Reader::Objects& objects = reader.objects(); - for (size_t i=0; i < properties.size(); i++) + for (size_t i = 0; i < properties.size(); i++) { - Gto::Reader::PropertyInfo& p = properties[i]; + Gto::Reader::PropertyInfo& p = properties[i]; const Gto::Reader::ComponentInfo* c = p.component; - const Gto::Reader::ObjectInfo* o = c->object; + const Gto::Reader::ObjectInfo* o = c->object; string name; name = reader.stringFromId(o->name); @@ -693,7 +710,7 @@ void filterData(const std::string& filterExpr, Reader& reader) } } - for (size_t i=0; i < objects.size(); i++) + for (size_t i = 0; i < objects.size(); i++) { Gto::Reader::ObjectInfo& p = objects[i]; @@ -715,7 +732,8 @@ void usage() << "-l/--line dump data/strings one per line\n" << "-h/--header header only (default)\n" << "-s/--strings output strings table\n" - << "-n/--numeric-strings output string properties as string numbers\n" + << "-n/--numeric-strings output string properties as string " + "numbers\n" << "-i/--interpretation-strings output interpretation strings\n" << "-f/--filter expr filter shell-like expression\n" << "-r/--readall force data read\n" @@ -725,66 +743,57 @@ void usage() exit(-1); } - -int utf8Main(int argc, char *argv[]) +int utf8Main(int argc, char* argv[]) { - const char *inFile = 0; + const char* inFile = 0; string filterExpr; - for (int i=1; i < argc; i++) + for (int i = 1; i < argc; i++) { - const char *arg = argv[i]; + const char* arg = argv[i]; if (*arg == '-') { - if (!strcmp(arg, "-d") || - !strcmp(arg, "--dump")) + if (!strcmp(arg, "-d") || !strcmp(arg, "--dump")) { - outputData = true; + outputData = true; outputHeader = false; } - else if (!strcmp(arg, "-a") || - !strcmp(arg, "--all")) + else if (!strcmp(arg, "-a") || !strcmp(arg, "--all")) { - outputData = true; + outputData = true; outputHeader = true; outputInterp = true; } - else if (!strcmp(arg, "-h") || - !strcmp(arg, "--header")) + else if (!strcmp(arg, "-h") || !strcmp(arg, "--header")) { - outputData = false; + outputData = false; outputHeader = true; } - else if (!strcmp(arg, "-s") || - !strcmp(arg, "--strings")) + else if (!strcmp(arg, "-s") || !strcmp(arg, "--strings")) { - outputData = false; + outputData = false; outputHeader = false; outputStrings = true; } - else if (!strcmp(arg, "-r") || - !strcmp(arg, "--readall")) + else if (!strcmp(arg, "-r") || !strcmp(arg, "--readall")) { - readAll = true; + readAll = true; } - else if (!strcmp(arg, "-l") || - !strcmp(arg, "--line")) + else if (!strcmp(arg, "-l") || !strcmp(arg, "--line")) { - formatData = true; + formatData = true; } - else if (!strcmp(arg, "-n") || - !strcmp(arg, "--numeric-strings")) + else if (!strcmp(arg, "-n") || !strcmp(arg, "--numeric-strings")) { numericStrings = true; } - else if (!strcmp(arg, "-i") || - !strcmp(arg, "--interpretation-strings")) + else if (!strcmp(arg, "-i") + || !strcmp(arg, "--interpretation-strings")) { outputInterp = true; } - else if (!strcmp(arg, "-f") || - !strcmp(arg, "--filter-expression")) + else if (!strcmp(arg, "-f") || !strcmp(arg, "--filter-expression")) { i++; filterExpr = argv[i]; @@ -809,13 +818,15 @@ int utf8Main(int argc, char *argv[]) } unsigned int mode = 0; - if (!outputData && !readAll) mode |= Gto::Reader::HeaderOnly; + if (!outputData && !readAll) + mode |= Gto::Reader::HeaderOnly; - if (filterExpr != "") mode = Gto::Reader::RandomAccess; + if (filterExpr != "") + mode = Gto::Reader::RandomAccess; Reader reader(mode); - if ( !reader.open(inFile) ) + if (!reader.open(inFile)) { cerr << "Error reading file " << inFile << endl; } diff --git a/src/bin/gtotools/gtoinfo/utf8Main.cpp b/src/bin/gtotools/gtoinfo/utf8Main.cpp index 69e097cc9..7c46f886c 100644 --- a/src/bin/gtotools/gtoinfo/utf8Main.cpp +++ b/src/bin/gtotools/gtoinfo/utf8Main.cpp @@ -1,6 +1,6 @@ // -// Copyright (C) 2023 Autodesk, Inc. All Rights Reserved. -// -// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2023 Autodesk, Inc. All Rights Reserved. // -#include "../../utf8Main.cpp" \ No newline at end of file +// SPDX-License-Identifier: Apache-2.0 +// +#include "../../utf8Main.cpp" diff --git a/src/bin/gtotools/gtomerge/main.cpp b/src/bin/gtotools/gtomerge/main.cpp index 22f004a90..8e867d0a9 100644 --- a/src/bin/gtotools/gtomerge/main.cpp +++ b/src/bin/gtotools/gtomerge/main.cpp @@ -17,29 +17,27 @@ using namespace Gto; using namespace std; - -const char *stripNamePrefix( const std::string &name, const char *prefix ) +const char* stripNamePrefix(const std::string& name, const char* prefix) { - if( ! prefix ) + if (!prefix) { return name.c_str(); } - if( name.substr( 0, strlen( prefix ) ) == prefix ) + if (name.substr(0, strlen(prefix)) == prefix) { return &(name[strlen(prefix)]); } return name.c_str(); } -void -propertyMerge(Component *out, Component *in) +void propertyMerge(Component* out, Component* in) { - for (size_t i=0; i < in->properties.size(); i++) + for (size_t i = 0; i < in->properties.size(); i++) { - Property *p = in->properties[i]; + Property* p = in->properties[i]; bool found = false; - for (size_t q=0; q < out->properties.size(); q++) + for (size_t q = 0; q < out->properties.size(); q++) { if (out->properties[q]->name == p->name) { @@ -57,15 +55,14 @@ propertyMerge(Component *out, Component *in) } } -void -componentMerge(Components& out, Components& in) +void componentMerge(Components& out, Components& in) { - for (size_t i=0; i < in.size(); i++) + for (size_t i = 0; i < in.size(); i++) { - Component *c = in[i]; + Component* c = in[i]; bool found = false; - for (size_t q=0; q < out.size(); q++) + for (size_t q = 0; q < out.size(); q++) { if (out[q]->name == c->name) { @@ -85,21 +82,21 @@ componentMerge(Components& out, Components& in) } } -void -objectMerge(RawDataBase *out, RawDataBase *in, const char *stripPrefix) +void objectMerge(RawDataBase* out, RawDataBase* in, const char* stripPrefix) { - if( stripPrefix ) + if (stripPrefix) { - for (size_t i=0; i < in->objects.size(); i++) + for (size_t i = 0; i < in->objects.size(); i++) { - Object *o = in->objects[i]; + Object* o = in->objects[i]; bool found = false; - std::string mungedNameIn( stripNamePrefix( o->name, stripPrefix ) ); + std::string mungedNameIn(stripNamePrefix(o->name, stripPrefix)); - for (size_t q=0; q < out->objects.size(); q++) + for (size_t q = 0; q < out->objects.size(); q++) { - std::string mungedNameOut( stripNamePrefix( out->objects[q]->name, stripPrefix ) ); + std::string mungedNameOut( + stripNamePrefix(out->objects[q]->name, stripPrefix)); if (mungedNameOut == mungedNameIn) { found = true; @@ -119,12 +116,12 @@ objectMerge(RawDataBase *out, RawDataBase *in, const char *stripPrefix) } else { - for (size_t i=0; i < in->objects.size(); i++) + for (size_t i = 0; i < in->objects.size(); i++) { - Object *o = in->objects[i]; + Object* o = in->objects[i]; bool found = false; - for (size_t q=0; q < out->objects.size(); q++) + for (size_t q = 0; q < out->objects.size(); q++) { if (out->objects[q]->name == o->name) { @@ -153,20 +150,20 @@ void usage() << "-nc force uncompressed GTO" << endl << "-sp PREFIX strip prefix" << endl << endl; - + exit(-1); } -int utf8Main(int argc, char *argv[]) +int utf8Main(int argc, char* argv[]) { vector inputFiles; - char *outFile = NULL; + char* outFile = NULL; RawDataBase outObjects; - char *stripPrefix = NULL; + char* stripPrefix = NULL; int text = 0; int nocompress = 0; - for (int i=1; i < argc; i++) + for (int i = 1; i < argc; i++) { if (!strcmp(argv[i], "-o")) { @@ -211,7 +208,7 @@ int utf8Main(int argc, char *argv[]) usage(); } - for (size_t i=0; i < inputFiles.size(); i++) + for (size_t i = 0; i < inputFiles.size(); i++) { RawDataBaseReader reader; cout << "Reading input file " << inputFiles[i] << "..." << endl; @@ -224,20 +221,21 @@ int utf8Main(int argc, char *argv[]) } else { - RawDataBase *inObjects = reader.dataBase(); + RawDataBase* inObjects = reader.dataBase(); objectMerge(&outObjects, inObjects, stripPrefix); } } RawDataBaseWriter writer; Writer::FileType type = Writer::CompressedGTO; - if (nocompress) type = Writer::BinaryGTO; - if (text) type = Writer::TextGTO; + if (nocompress) + type = Writer::BinaryGTO; + if (text) + type = Writer::TextGTO; if (!writer.write(outFile, outObjects, type)) { - cerr << "ERROR: unable to write file " << outFile - << endl; + cerr << "ERROR: unable to write file " << outFile << endl; exit(-1); } else diff --git a/src/bin/gtotools/gtomerge/utf8Main.cpp b/src/bin/gtotools/gtomerge/utf8Main.cpp index 69e097cc9..7c46f886c 100644 --- a/src/bin/gtotools/gtomerge/utf8Main.cpp +++ b/src/bin/gtotools/gtomerge/utf8Main.cpp @@ -1,6 +1,6 @@ // -// Copyright (C) 2023 Autodesk, Inc. All Rights Reserved. -// -// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2023 Autodesk, Inc. All Rights Reserved. // -#include "../../utf8Main.cpp" \ No newline at end of file +// SPDX-License-Identifier: Apache-2.0 +// +#include "../../utf8Main.cpp" diff --git a/src/bin/imgtools/makeFBIOformats/main.cpp b/src/bin/imgtools/makeFBIOformats/main.cpp index dd5102784..8332485e3 100644 --- a/src/bin/imgtools/makeFBIOformats/main.cpp +++ b/src/bin/imgtools/makeFBIOformats/main.cpp @@ -1,9 +1,9 @@ //****************************************************************************** -// Copyright (c) 2007 Tweak Inc. +// Copyright (c) 2007 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #include "../../utf8Main.h" @@ -21,7 +21,7 @@ using namespace TwkUtil; using namespace Gto; using namespace std; -#ifdef PLATFORM_DARWIN +#ifdef PLATFORM_DARWIN #define EXT_PATTERN "dylib" #endif @@ -47,12 +47,12 @@ int utf8Main(int argc, char** argv) FileNameList files; string dir = argc == 2 ? argv[1] : "."; - + cout << "INFO: looking in " << dir << endl; if (filesInDirectory(pathConform(dir).c_str(), "io_*." EXT_PATTERN, files)) { - for (int i=0; i < files.size(); i++) + for (int i = 0; i < files.size(); i++) { string file = dir; file += "/"; @@ -73,20 +73,20 @@ int utf8Main(int argc, char** argv) Writer writer; string outfile = dir; - if (outfile[outfile.size()-1] != '/') outfile += "/"; + if (outfile[outfile.size() - 1] != '/') + outfile += "/"; outfile += "formats.gto"; outfile = pathConform(outfile); - + if (!writer.open(outfile.c_str(), Writer::CompressedGTO)) { cerr << "ERROR: makeFBIOformats: can't open output file" << endl; return -1; } - + const GenericIO::Plugins& plugs = GenericIO::allPlugins(); - - for (GenericIO::Plugins::const_iterator i = plugs.begin(); - i != plugs.end(); + + for (GenericIO::Plugins::const_iterator i = plugs.begin(); i != plugs.end(); ++i) { @@ -95,7 +95,7 @@ int utf8Main(int argc, char** argv) string fname = prefix(plugin->pluginFile()); writer.beginObject(fname.c_str(), "imageio", 2); - const FrameBufferIO::ImageTypeInfos& infos = + const FrameBufferIO::ImageTypeInfos& infos = plugin->extensionsSupported(); writer.beginComponent(":info"); @@ -103,14 +103,14 @@ int utf8Main(int argc, char** argv) writer.property("sortkey", Gto::String, 1); writer.endComponent(); - for (int q=0; q < infos.size(); q++) + for (int q = 0; q < infos.size(); q++) { const FrameBufferIO::ImageTypeInfo& info = infos[q]; writer.beginComponent(info.extension.c_str()); writer.property("description", Gto::String, 1); writer.property("capabilities", Gto::Int, 1); - writer.property("codecs", Gto::String, + writer.property("codecs", Gto::String, info.compressionSchemes.size(), 2); writer.property("encodeParams", Gto::String, info.encodeParameters.size(), 2); @@ -122,19 +122,19 @@ int utf8Main(int argc, char** argv) writer.intern(plugin->identifier()); writer.intern(plugin->sortKey()); - for (int j=0; j < info.compressionSchemes.size(); j++) + for (int j = 0; j < info.compressionSchemes.size(); j++) { writer.intern(info.compressionSchemes[j].first); writer.intern(info.compressionSchemes[j].second); } - for (int j=0; j < info.encodeParameters.size(); j++) + for (int j = 0; j < info.encodeParameters.size(); j++) { writer.intern(info.encodeParameters[j].first); writer.intern(info.encodeParameters[j].second); } - for (int j=0; j < info.decodeParameters.size(); j++) + for (int j = 0; j < info.decodeParameters.size(); j++) { writer.intern(info.decodeParameters[j].first); writer.intern(info.decodeParameters[j].second); @@ -146,54 +146,59 @@ int utf8Main(int argc, char** argv) writer.beginData(); - for (GenericIO::Plugins::const_iterator i = plugs.begin(); - i != plugs.end(); + for (GenericIO::Plugins::const_iterator i = plugs.begin(); i != plugs.end(); ++i) { FrameBufferIO* plugin = *i; - const FrameBufferIO::ImageTypeInfos& infos = + const FrameBufferIO::ImageTypeInfos& infos = plugin->extensionsSupported(); int id = writer.lookup(plugin->identifier()); - int k = writer.lookup(plugin->sortKey()); + int k = writer.lookup(plugin->sortKey()); writer.propertyData(&id); writer.propertyData(&k); - for (int q=0; q < infos.size(); q++) + for (int q = 0; q < infos.size(); q++) { const FrameBufferIO::ImageTypeInfo& info = infos[q]; - int s = writer.lookup(info.description); + int s = writer.lookup(info.description); vector schemes; vector eparams; vector dparams; writer.propertyData(&s); writer.propertyData(&info.capabilities); - for (int j=0; j < info.compressionSchemes.size(); j++) + for (int j = 0; j < info.compressionSchemes.size(); j++) { - schemes.push_back(writer.lookup(info.compressionSchemes[j].first)); - schemes.push_back(writer.lookup(info.compressionSchemes[j].second)); + schemes.push_back( + writer.lookup(info.compressionSchemes[j].first)); + schemes.push_back( + writer.lookup(info.compressionSchemes[j].second)); } - for (int j=0; j < info.encodeParameters.size(); j++) + for (int j = 0; j < info.encodeParameters.size(); j++) { - eparams.push_back(writer.lookup(info.encodeParameters[j].first)); - eparams.push_back(writer.lookup(info.encodeParameters[j].second)); + eparams.push_back( + writer.lookup(info.encodeParameters[j].first)); + eparams.push_back( + writer.lookup(info.encodeParameters[j].second)); } - for (int j=0; j < info.decodeParameters.size(); j++) + for (int j = 0; j < info.decodeParameters.size(); j++) { - dparams.push_back(writer.lookup(info.decodeParameters[j].first)); - dparams.push_back(writer.lookup(info.decodeParameters[j].second)); + dparams.push_back( + writer.lookup(info.decodeParameters[j].first)); + dparams.push_back( + writer.lookup(info.decodeParameters[j].second)); } - if (schemes.empty()) + if (schemes.empty()) { writer.emptyProperty(); } - else + else { writer.propertyData(&schemes.front()); } @@ -217,7 +222,7 @@ int utf8Main(int argc, char** argv) } } } - + writer.endData(); TwkFB::GenericIO::shutdown(); // Shutdown TwkFB::GenericIO plugins diff --git a/src/bin/imgtools/makeFBIOformats/utf8Main.cpp b/src/bin/imgtools/makeFBIOformats/utf8Main.cpp index 69e097cc9..7c46f886c 100644 --- a/src/bin/imgtools/makeFBIOformats/utf8Main.cpp +++ b/src/bin/imgtools/makeFBIOformats/utf8Main.cpp @@ -1,6 +1,6 @@ // -// Copyright (C) 2023 Autodesk, Inc. All Rights Reserved. -// -// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2023 Autodesk, Inc. All Rights Reserved. // -#include "../../utf8Main.cpp" \ No newline at end of file +// SPDX-License-Identifier: Apache-2.0 +// +#include "../../utf8Main.cpp" diff --git a/src/bin/imgtools/makeMovieIOformats/main.cpp b/src/bin/imgtools/makeMovieIOformats/main.cpp index 15b0c7ab8..a3b89a256 100644 --- a/src/bin/imgtools/makeMovieIOformats/main.cpp +++ b/src/bin/imgtools/makeMovieIOformats/main.cpp @@ -1,29 +1,29 @@ //****************************************************************************** -// Copyright (c) 2007 Tweak Inc. +// Copyright (c) 2007 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #include "../../utf8Main.h" #ifdef _MSC_VER - // - // We are targetting at least XP, (IE no windows95, etc). - // - #define WINVER 0x0501 - #define _WIN32_WINNT 0x0501 - #include - #include - #include - #include - // - // NOTE: win_pthreads, which supplies implement.h, seems - // targetted at an earlier version of windows (pre-XP). If you - // include implement.h here, it won't compile. But as far as I - // can tell, it's not needed, so just leave it out. - // - // #include +// +// We are targetting at least XP, (IE no windows95, etc). +// +#define WINVER 0x0501 +#define _WIN32_WINNT 0x0501 +#include +#include +#include +#include +// +// NOTE: win_pthreads, which supplies implement.h, seems +// targetted at an earlier version of windows (pre-XP). If you +// include implement.h here, it won't compile. But as far as I +// can tell, it's not needed, so just leave it out. +// +// #include #endif #include @@ -39,7 +39,7 @@ using namespace TwkUtil; using namespace Gto; using namespace std; -#ifdef PLATFORM_DARWIN +#ifdef PLATFORM_DARWIN #define EXT_PATTERN "dylib" #endif @@ -64,12 +64,12 @@ int utf8Main(int argc, char** argv) FileNameList files; string dir = argc == 2 ? argv[1] : "."; - + cout << "INFO: looking in " << dir << endl; if (filesInDirectory(pathConform(dir).c_str(), "mio_*." EXT_PATTERN, files)) { - for (int i=0; i < files.size(); i++) + for (int i = 0; i < files.size(); i++) { string file = dir; file += "/"; @@ -91,7 +91,8 @@ int utf8Main(int argc, char** argv) Writer writer; string outfile = dir; - if (outfile[outfile.size()-1] != '/') outfile += "/"; + if (outfile[outfile.size() - 1] != '/') + outfile += "/"; outfile += "movieformats.gto"; outfile = pathConform(outfile); @@ -100,11 +101,10 @@ int utf8Main(int argc, char** argv) cerr << "ERROR: makeMovieIOformats: can't open output file" << endl; return -1; } - + const GenericIO::Plugins& plugs = GenericIO::allPlugins(); - for (GenericIO::Plugins::const_iterator i = plugs.begin(); - i != plugs.end(); + for (GenericIO::Plugins::const_iterator i = plugs.begin(); i != plugs.end(); ++i) { MovieIO* plugin = *i; @@ -112,8 +112,7 @@ int utf8Main(int argc, char** argv) string fname = prefix(plugin->pluginFile()); writer.beginObject(fname.c_str(), "movieio", 2); - const MovieIO::MovieTypeInfos& infos = - plugin->extensionsSupported(); + const MovieIO::MovieTypeInfos& infos = plugin->extensionsSupported(); writer.beginComponent(":info"); writer.property("identifier", Gto::String, 1); @@ -123,7 +122,7 @@ int utf8Main(int argc, char** argv) writer.intern(plugin->identifier()); writer.intern(plugin->sortKey()); - for (int q=0; q < infos.size(); q++) + for (int q = 0; q < infos.size(); q++) { const MovieIO::MovieTypeInfo& info = infos[q]; @@ -131,33 +130,36 @@ int utf8Main(int argc, char** argv) writer.property("description", Gto::String, 1); writer.property("capabilities", Gto::Int, 1); writer.property("video_codecs", Gto::String, info.codecs.size(), 2); - writer.property("audio_codecs", Gto::String, info.audioCodecs.size(), 2); - writer.property("encode_parameters", Gto::String, info.encodeParameters.size(), 3); - writer.property("decode_parameters", Gto::String, info.decodeParameters.size(), 3); + writer.property("audio_codecs", Gto::String, + info.audioCodecs.size(), 2); + writer.property("encode_parameters", Gto::String, + info.encodeParameters.size(), 3); + writer.property("decode_parameters", Gto::String, + info.decodeParameters.size(), 3); writer.endComponent(); writer.intern(info.description); - for (int j=0; j < info.codecs.size(); j++) + for (int j = 0; j < info.codecs.size(); j++) { writer.intern(info.codecs[j].first); writer.intern(info.codecs[j].second); } - for (int j=0; j < info.audioCodecs.size(); j++) + for (int j = 0; j < info.audioCodecs.size(); j++) { writer.intern(info.audioCodecs[j].first); writer.intern(info.audioCodecs[j].second); } - for (int j=0; j < info.encodeParameters.size(); j++) + for (int j = 0; j < info.encodeParameters.size(); j++) { writer.intern(info.encodeParameters[j].name); writer.intern(info.encodeParameters[j].description); writer.intern(info.encodeParameters[j].codec); } - for (int j=0; j < info.decodeParameters.size(); j++) + for (int j = 0; j < info.decodeParameters.size(); j++) { writer.intern(info.decodeParameters[j].name); writer.intern(info.decodeParameters[j].description); @@ -170,25 +172,23 @@ int utf8Main(int argc, char** argv) writer.beginData(); - for (GenericIO::Plugins::const_iterator i = plugs.begin(); - i != plugs.end(); + for (GenericIO::Plugins::const_iterator i = plugs.begin(); i != plugs.end(); ++i) { MovieIO* plugin = *i; - const MovieIO::MovieTypeInfos& infos = - plugin->extensionsSupported(); + const MovieIO::MovieTypeInfos& infos = plugin->extensionsSupported(); int id = writer.lookup(plugin->identifier()); - int k = writer.lookup(plugin->sortKey()); + int k = writer.lookup(plugin->sortKey()); writer.propertyData(&id); writer.propertyData(&k); - for (int q=0; q < infos.size(); q++) + for (int q = 0; q < infos.size(); q++) { const MovieIO::MovieTypeInfo& info = infos[q]; - int s = writer.lookup(info.description); + int s = writer.lookup(info.description); vector vcodecs; vector acodecs; vector eparams; @@ -196,49 +196,61 @@ int utf8Main(int argc, char** argv) writer.propertyData(&s); writer.propertyData(&info.capabilities); - for (int j=0; j < info.codecs.size(); j++) + for (int j = 0; j < info.codecs.size(); j++) { vcodecs.push_back(writer.lookup(info.codecs[j].first)); vcodecs.push_back(writer.lookup(info.codecs[j].second)); } - for (int j=0; j < info.audioCodecs.size(); j++) + for (int j = 0; j < info.audioCodecs.size(); j++) { acodecs.push_back(writer.lookup(info.audioCodecs[j].first)); acodecs.push_back(writer.lookup(info.audioCodecs[j].second)); } - for (int j=0; j < info.audioCodecs.size(); j++) + for (int j = 0; j < info.audioCodecs.size(); j++) { acodecs.push_back(writer.lookup(info.audioCodecs[j].first)); acodecs.push_back(writer.lookup(info.audioCodecs[j].second)); } - for (int j=0; j < info.encodeParameters.size(); j++) + for (int j = 0; j < info.encodeParameters.size(); j++) { eparams.push_back(writer.lookup(info.encodeParameters[j].name)); - eparams.push_back(writer.lookup(info.encodeParameters[j].description)); - eparams.push_back(writer.lookup(info.encodeParameters[j].codec)); + eparams.push_back( + writer.lookup(info.encodeParameters[j].description)); + eparams.push_back( + writer.lookup(info.encodeParameters[j].codec)); } - for (int j=0; j < info.decodeParameters.size(); j++) + for (int j = 0; j < info.decodeParameters.size(); j++) { dparams.push_back(writer.lookup(info.decodeParameters[j].name)); - dparams.push_back(writer.lookup(info.decodeParameters[j].description)); - dparams.push_back(writer.lookup(info.decodeParameters[j].codec)); + dparams.push_back( + writer.lookup(info.decodeParameters[j].description)); + dparams.push_back( + writer.lookup(info.decodeParameters[j].codec)); } - if (vcodecs.empty()) writer.emptyProperty(); - else writer.propertyData(&vcodecs.front()); + if (vcodecs.empty()) + writer.emptyProperty(); + else + writer.propertyData(&vcodecs.front()); - if (acodecs.empty()) writer.emptyProperty(); - else writer.propertyData(&acodecs.front()); + if (acodecs.empty()) + writer.emptyProperty(); + else + writer.propertyData(&acodecs.front()); - if (eparams.empty()) writer.emptyProperty(); - else writer.propertyData(&eparams.front()); + if (eparams.empty()) + writer.emptyProperty(); + else + writer.propertyData(&eparams.front()); - if (dparams.empty()) writer.emptyProperty(); - else writer.propertyData(&dparams.front()); + if (dparams.empty()) + writer.emptyProperty(); + else + writer.propertyData(&dparams.front()); } } diff --git a/src/bin/imgtools/makeMovieIOformats/utf8Main.cpp b/src/bin/imgtools/makeMovieIOformats/utf8Main.cpp index 69e097cc9..7c46f886c 100644 --- a/src/bin/imgtools/makeMovieIOformats/utf8Main.cpp +++ b/src/bin/imgtools/makeMovieIOformats/utf8Main.cpp @@ -1,6 +1,6 @@ // -// Copyright (C) 2023 Autodesk, Inc. All Rights Reserved. -// -// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2023 Autodesk, Inc. All Rights Reserved. // -#include "../../utf8Main.cpp" \ No newline at end of file +// SPDX-License-Identifier: Apache-2.0 +// +#include "../../utf8Main.cpp" diff --git a/src/bin/imgtools/rmsImageDiff/main.cpp b/src/bin/imgtools/rmsImageDiff/main.cpp index 0db691db1..448b59648 100644 --- a/src/bin/imgtools/rmsImageDiff/main.cpp +++ b/src/bin/imgtools/rmsImageDiff/main.cpp @@ -1,7 +1,7 @@ // -// Copyright (C) 2023 Autodesk, Inc. All Rights Reserved. -// -// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2023 Autodesk, Inc. All Rights Reserved. +// +// SPDX-License-Identifier: Apache-2.0 // #include "../../utf8Main.h" @@ -45,35 +45,30 @@ using namespace TwkMath; FrameBuffer* convertBoth(FrameBuffer* inFB, FrameBuffer::DataType t) { if (inFB->isPlanar()) - return copyConvert(inFB,t); - return copyConvertPlane(inFB,t); + return copyConvert(inFB, t); + return copyConvertPlane(inFB, t); } -template -double sumChannels (const T &v) +template double sumChannels(const T& v) { double sum = 0.0; - for (size_t n = 0 ; n < v.dimension(); ++n) + for (size_t n = 0; n < v.dimension(); ++n) { - sum += (double) v[n]; + sum += (double)v[n]; } - + return sum; } template -int computeRMS(const FrameBuffer* a, - const FrameBuffer* b, - bool doFloat, - bool findMax, - bool doCompare, - double dmax) +int computeRMS(const FrameBuffer* a, const FrameBuffer* b, bool doFloat, + bool findMax, bool doCompare, double dmax) { Tdouble sum(0.0); double maxDiff = 0.0; - const double ushort_max = (double) (std::numeric_limits ::max()); + const double ushort_max = (double)(std::numeric_limits::max()); int maxX = -1; int maxY = -1; @@ -85,9 +80,9 @@ int computeRMS(const FrameBuffer* a, Tfloat maxA; Tfloat maxB; - for (int y=0; y < a->height(); y++) + for (int y = 0; y < a->height(); y++) { - for (int x=0; x < a->width(); x++) + for (int x = 0; x < a->width(); x++) { Tfloat ca = a->scanline(y)[x]; Tfloat cb = b->scanline(y)[x]; @@ -107,21 +102,27 @@ int computeRMS(const FrameBuffer* a, maxA = ca; maxB = cb; } - } else if (doCompare) { - for (int c=0; c < a->numChannels(); ++c) - { - if (fabs((double) cd[c]) > dmax) - { - cout << "Pixel difference at (" << x << ", " << y << ") channel[" << c - << "] = " << fabs((double) cd[c]) << " found." << endl; - noMatch = true; - break; - } - } } - if (noMatch) break; + else if (doCompare) + { + for (int c = 0; c < a->numChannels(); ++c) + { + if (fabs((double)cd[c]) > dmax) + { + cout << "Pixel difference at (" << x << ", " << y + << ") channel[" << c + << "] = " << fabs((double)cd[c]) << " found." + << endl; + noMatch = true; + break; + } + } + } + if (noMatch) + break; } - if (noMatch) break; + if (noMatch) + break; } if (doCompare) @@ -140,7 +141,7 @@ int computeRMS(const FrameBuffer* a, sum /= Tdouble(a->height() * a->width()); - for (size_t n = 0 ; n < sum.dimension(); ++n) + for (size_t n = 0; n < sum.dimension(); ++n) { cout << "" << sqrt(sum[n]); } @@ -148,8 +149,8 @@ int computeRMS(const FrameBuffer* a, if (findMax && maxX > -1) { - cout << "max diff at (" << maxX << ", " << maxY << "): " << - maxA << " vs. " << maxB << endl; + cout << "max diff at (" << maxX << ", " << maxY << "): " << maxA + << " vs. " << maxB << endl; } } else @@ -157,9 +158,9 @@ int computeRMS(const FrameBuffer* a, Tunsigned maxA; Tunsigned maxB; - for (int y=0; y < a->height(); y++) + for (int y = 0; y < a->height(); y++) { - for (int x=0; x < a->width(); x++) + for (int x = 0; x < a->width(); x++) { Tunsigned ca = a->scanline(y)[x]; Tunsigned cb = b->scanline(y)[x]; @@ -179,21 +180,27 @@ int computeRMS(const FrameBuffer* a, maxA = ca; maxB = cb; } - } else if (doCompare) { - for (int c=0; c < a->numChannels(); ++c) - { - if (fabs((double) cd[c]) > dmax) - { - cout << "Pixel difference at (" << x << ", " << y << ") channel[" << c - << "] = " << fabs((double) cd[c]) << " found." << endl; - noMatch = true; - break; - } - } } - if (noMatch) break; + else if (doCompare) + { + for (int c = 0; c < a->numChannels(); ++c) + { + if (fabs((double)cd[c]) > dmax) + { + cout << "Pixel difference at (" << x << ", " << y + << ") channel[" << c + << "] = " << fabs((double)cd[c]) << " found." + << endl; + noMatch = true; + break; + } + } + } + if (noMatch) + break; } - if (noMatch) break; + if (noMatch) + break; } if (doCompare) @@ -211,7 +218,7 @@ int computeRMS(const FrameBuffer* a, } sum /= Tdouble(a->height() * a->width()); - for (size_t n = 0 ; n < sum.dimension(); ++n) + for (size_t n = 0; n < sum.dimension(); ++n) { cout << "" << sqrt(sum[n]); } @@ -219,22 +226,24 @@ int computeRMS(const FrameBuffer* a, if (findMax && maxX > -1) { - cout << "max diff at (" << maxX << ", " << maxY << "): " << - maxA << " vs. " << maxB << endl; + cout << "max diff at (" << maxX << ", " << maxY << "): " << maxA + << " vs. " << maxB << endl; } } return 0; } -int utf8Main(int argc, char *argv[]) +int utf8Main(int argc, char* argv[]) { #ifdef PLATFORM_DARWIN - TwkApp::DarwinBundle bundle("RV", MAJOR_VERSION, MINOR_VERSION, REVISION_NUMBER); + TwkApp::DarwinBundle bundle("RV", MAJOR_VERSION, MINOR_VERSION, + REVISION_NUMBER); #else QCoreApplication qapp(argc, argv); - TwkApp::QTBundle bundle("rv", MAJOR_VERSION, MINOR_VERSION, REVISION_NUMBER); - (void) bundle.top(); + TwkApp::QTBundle bundle("rv", MAJOR_VERSION, MINOR_VERSION, + REVISION_NUMBER); + (void)bundle.top(); #endif char* input1 = 0; @@ -243,26 +252,35 @@ int utf8Main(int argc, char *argv[]) bool doFloat = false; bool findMax = false; bool doCompare = false; - double dmax = 0.0; + double dmax = 0.0; // // Parse cmd line args // - - string usage = string("usage: ") + argv[0] + " [-f] [-m] [-cmp] [-dmax ] \n" + - " -f: operate on FLOAT pixels\n" + - " -m: print location and values of pixel with max difference\n" + - " -cmp: perform image comparison (returns exit 1 if not matched)" + - " -dmax: Maximum allow channel error during comparison (default=0.0)"; + + string usage = + string("usage: ") + argv[0] + + " [-f] [-m] [-cmp] [-dmax ] \n" + + " -f: operate on FLOAT pixels\n" + + " -m: print location and values of pixel with max difference\n" + + " -cmp: perform image comparison (returns exit 1 if not matched)" + + " -dmax: Maximum allow channel error during comparison " + "(default=0.0)"; for (int i = 1; i < argc; ++i) { - if (strcmp(argv[i], "-f") == 0) doFloat = true; - else if (strcmp(argv[i], "-m") == 0) findMax = true; - else if (strcmp(argv[i], "-cmp") == 0) doCompare = true; - else if (strcmp(argv[i], "-dmax") == 0 && (i+1 < argc)) dmax = atof(argv[++i]); - else if (!input1) input1 = argv[i]; - else if (!input2) input2 = argv[i]; + if (strcmp(argv[i], "-f") == 0) + doFloat = true; + else if (strcmp(argv[i], "-m") == 0) + findMax = true; + else if (strcmp(argv[i], "-cmp") == 0) + doCompare = true; + else if (strcmp(argv[i], "-dmax") == 0 && (i + 1 < argc)) + dmax = atof(argv[++i]); + else if (!input1) + input1 = argv[i]; + else if (!input2) + input2 = argv[i]; } if (argc < 3 || argc > 8 || !input1 || !input2) { @@ -273,8 +291,9 @@ int utf8Main(int argc, char *argv[]) string in1 = pathConform(input1); string in2 = pathConform(input2); - TwkFB::GenericIO::init(); // Initialize TwkFB::GenericIO plugins statics - TwkMovie::GenericIO::init(); // Initialize TwkMovie::GenericIO plugins statics + TwkFB::GenericIO::init(); // Initialize TwkFB::GenericIO plugins statics + TwkMovie::GenericIO::init(); // Initialize TwkMovie::GenericIO plugins + // statics try { @@ -300,9 +319,9 @@ int utf8Main(int argc, char *argv[]) try { cout << "INFO: reading " << in1 << endl; - GenericIO::readImages(aImages, in1, request); + GenericIO::readImages(aImages, in1, request); cout << "INFO: reading " << in2 << endl; - GenericIO::readImages(bImages, in2, request); + GenericIO::readImages(bImages, in2, request); } catch (exception& exc) { @@ -313,8 +332,9 @@ int utf8Main(int argc, char *argv[]) FrameBuffer* ai = aImages.front(); FrameBuffer* bi = bImages.front(); -// cout << "a -> "; ai->outputInfo(cout); cout << " planar: " << ai->isPlanar() << endl; -// cout << "b -> "; bi->outputInfo(cout); cout << " planar: " << bi->isPlanar() << endl; + // cout << "a -> "; ai->outputInfo(cout); cout << " planar: " << + // ai->isPlanar() << endl; cout << "b -> "; bi->outputInfo(cout); cout << + // " planar: " << bi->isPlanar() << endl; if (ai->isPlanar()) { FrameBuffer* temp = mergePlanes(ai); @@ -326,8 +346,10 @@ int utf8Main(int argc, char *argv[]) bi = temp; } - FrameBuffer* a = convertBoth(ai, (doFloat) ? FrameBuffer::FLOAT : FrameBuffer::USHORT); - FrameBuffer* b = convertBoth(bi, (doFloat) ? FrameBuffer::FLOAT : FrameBuffer::USHORT); + FrameBuffer* a = + convertBoth(ai, (doFloat) ? FrameBuffer::FLOAT : FrameBuffer::USHORT); + FrameBuffer* b = + convertBoth(bi, (doFloat) ? FrameBuffer::FLOAT : FrameBuffer::USHORT); if (a->width() != b->width() || a->height() != b->height()) { @@ -336,7 +358,6 @@ int utf8Main(int argc, char *argv[]) exit(-1); } - if (a->numChannels() != b->numChannels()) { cerr << "ERROR: incompatible images" << endl; @@ -355,50 +376,53 @@ int utf8Main(int argc, char *argv[]) flip(b); } -// cout << "a -> "; a->outputInfo(cout); cout << " planar: " << a->isPlanar() << endl; -// cout << "b -> "; b->outputInfo(cout); cout << " planar: " << b->isPlanar() << endl; - - -// if (a->dataType() != b->dataType()) -// { -// FrameBuffer::DataType t; - -// if (a->dataType() < b->dataType()) -// { -// t = a->dataType(); -// } -// else -// { -// t = b->dataType(); -// } - -// if (a->dataType() != t) a = convertBoth(a, t); -// if (b->dataType() != t) b = convertBoth(b, t); -// } -// + // cout << "a -> "; a->outputInfo(cout); cout << " planar: " << + // a->isPlanar() << endl; cout << "b -> "; b->outputInfo(cout); cout << " + // planar: " << b->isPlanar() << endl; + + // if (a->dataType() != b->dataType()) + // { + // FrameBuffer::DataType t; + + // if (a->dataType() < b->dataType()) + // { + // t = a->dataType(); + // } + // else + // { + // t = b->dataType(); + // } + + // if (a->dataType() != t) a = convertBoth(a, t); + // if (b->dataType() != t) b = convertBoth(b, t); + // } + // int status = 0; - if (a->numChannels() == 1) { - status = computeRMS(a, b, doFloat, findMax, doCompare, dmax); + status = computeRMS(a, b, doFloat, findMax, + doCompare, dmax); } else if (a->numChannels() == 2) { - status = computeRMS(a, b, doFloat, findMax, doCompare, dmax); + status = computeRMS(a, b, doFloat, findMax, + doCompare, dmax); } else if (a->numChannels() == 3) { - status = computeRMS(a, b, doFloat, findMax, doCompare, dmax); + status = computeRMS(a, b, doFloat, findMax, + doCompare, dmax); } else if (a->numChannels() == 4) { - status = computeRMS(a, b, doFloat, findMax, doCompare, dmax); + status = computeRMS(a, b, doFloat, findMax, + doCompare, dmax); } TwkMovie::GenericIO::shutdown(); // Shutdown TwkMovie::GenericIO plugins - TwkFB::GenericIO::shutdown(); // Shutdown TwkFB::GenericIO plugins + TwkFB::GenericIO::shutdown(); // Shutdown TwkFB::GenericIO plugins return 0; } diff --git a/src/bin/imgtools/rmsImageDiff/pool.h b/src/bin/imgtools/rmsImageDiff/pool.h index a32190a0d..5cac353bf 100644 --- a/src/bin/imgtools/rmsImageDiff/pool.h +++ b/src/bin/imgtools/rmsImageDiff/pool.h @@ -1,9 +1,9 @@ //****************************************************************************** -// Copyright (c) 2005 Tweak Inc. +// Copyright (c) 2005 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #ifndef __rv__pool__h__ #define __rv__pool__h__ diff --git a/src/bin/imgtools/rmsImageDiff/utf8Main.cpp b/src/bin/imgtools/rmsImageDiff/utf8Main.cpp index 69e097cc9..7c46f886c 100644 --- a/src/bin/imgtools/rmsImageDiff/utf8Main.cpp +++ b/src/bin/imgtools/rmsImageDiff/utf8Main.cpp @@ -1,6 +1,6 @@ // -// Copyright (C) 2023 Autodesk, Inc. All Rights Reserved. -// -// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2023 Autodesk, Inc. All Rights Reserved. // -#include "../../utf8Main.cpp" \ No newline at end of file +// SPDX-License-Identifier: Apache-2.0 +// +#include "../../utf8Main.cpp" diff --git a/src/bin/imgtools/rvio/UICommands.cpp b/src/bin/imgtools/rvio/UICommands.cpp index 22a26bdf8..aa8c2c754 100644 --- a/src/bin/imgtools/rvio/UICommands.cpp +++ b/src/bin/imgtools/rvio/UICommands.cpp @@ -1,512 +1,324 @@ //****************************************************************************** // Copyright (c) 2001-2005 Tweak Inc. All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #include #include -namespace RVIO { +namespace RVIO +{ + + using namespace TwkApp; + using namespace Mu; + using namespace std; + + void initUICommands(MuLangContext* context) + { + USING_MU_FUNCTION_SYMBOLS; + MuLangContext* c = context; + Symbol* root = context->globalScope(); + Name cname = c->internName("commands"); + Mu::Module* commands = root->findSymbolOfType(cname); + + commands->addSymbols( + new Function(c, "resizeFit", resizeFit, None, Return, "void", End), + + new Function(c, "setViewSize", setViewSize, None, Return, "void", + Parameters, new Param(c, "width", "int"), + new Param(c, "height", "int"), End), + + new Function(c, "popupMenu", popupMenu, None, Return, "void", + Parameters, new Param(c, "event", "Event"), + new Param(c, "menu", "MenuItem[]", Value(Pointer(0))), + End), + + new Function( + c, "popupMenuAtPoint", popupMenuAtPoint, None, Return, "void", + Parameters, new Param(c, "x", "int"), new Param(c, "y", "int"), + new Param(c, "menu", "MenuItem[]", Value(Pointer(0))), End), + + new Function(c, "setWindowTitle", setWindowTitle, None, Return, + "void", Parameters, new Param(c, "title", "string"), + End), + + new Function(c, "center", center, None, Return, "void", End), + + new Function(c, "close", close, None, Return, "void", End), + + new Function(c, "toggleMenuBar", toggleMenuBar, None, Return, + "void", End), + + new Function(c, "isMenuBarVisible", isMenuBarVisible, None, Return, + "bool", End), + + new SymbolicConstant(c, "OneExistingFile", "int", Value(0)), + new SymbolicConstant(c, "ManyExistingFiles", "int", Value(0)), + new SymbolicConstant(c, "ManyExistingFilesAndDirectories", "int", + Value(0)), + new SymbolicConstant(c, "OneFileName", "int", Value(0)), + new SymbolicConstant(c, "OneDirectory", "int", Value(0)), + + new Function(c, "openMediaFileDialog", openMediaFileDialog, None, + Return, "string[]", Parameters, + new Param(c, "associated", "bool"), + new Param(c, "selectType", "int"), + new Param(c, "filter", "string", Value(0)), + new Param(c, "defaultPath", "string", Value(0)), + new Param(c, "label", "string", Value(0)), End), + + new Function(c, "openFileDialog", openFileDialog, None, Return, + "string[]", Parameters, + new Param(c, "associated", "bool"), + new Param(c, "multiple", "bool", Value(false)), + new Param(c, "directory", "bool", Value(false)), + new Param(c, "filter", "string", Value(0)), + new Param(c, "defaultPath", "string", Value(0)), End), + + new Function(c, "saveFileDialog", saveFileDialog, None, Return, + "string", Parameters, + new Param(c, "associated", "bool"), + new Param(c, "filter", "string", Value(0)), + new Param(c, "defaultPath", "string", Value(0)), End), + + new SymbolicConstant(c, "CursorNone", "int", Value(0)), + new SymbolicConstant(c, "CursorArrow", "int", Value(2)), + new SymbolicConstant(c, "CursorDefault", "int", Value(1)), + + new Function(c, "setCursor", setCursor, None, Return, "void", + Parameters, new Param(c, "cursorType", "int"), End), + + new SymbolicConstant(c, "InfoAlert", "int", Value(0)), + new SymbolicConstant(c, "WarningAlert", "int", Value(1)), + new SymbolicConstant(c, "ErrorAlert", "int", Value(2)), + + new Function(c, "stereoSupported", stereoSupported, None, Return, + "bool", End), + + new Function(c, "alertPanel", alertPanel, None, Return, "int", + Parameters, new Param(c, "associated", "bool"), + new Param(c, "type", "int"), + new Param(c, "title", "string"), + new Param(c, "message", "string"), + new Param(c, "button0", "string"), + new Param(c, "button1", "string"), + new Param(c, "button2", "string"), End), + + new Function(c, "watchFile", watchFile, None, Return, "void", + Parameters, new Param(c, "filename", "string"), + new Param(c, "watch", "bool"), End), + + new Function(c, "showConsole", showConsole, None, Return, "void", + End), + + new Function(c, "isConsoleVisible", isConsoleVisible, None, Return, + "bool", End), + // network + + new Function(c, "remoteSendMessage", remoteSendMessage, None, + Return, "void", Parameters, + new Param(c, "message", "string"), + new Param(c, "recipients", "string[]", Value(0)), End), + + new Function(c, "remoteSendEvent", remoteSendEvent, None, Return, + "void", Parameters, new Param(c, "event", "string"), + new Param(c, "target", "string"), + new Param(c, "contents", "string"), + new Param(c, "recipients", "string[]", Value(0)), End), + + new Function(c, "remoteConnections", remoteConnections, None, + Return, "string[]", End), + + new Function(c, "remoteApplications", remoteApplications, None, + Return, "string[]", End), + + new Function(c, "remoteContacts", remoteContacts, None, Return, + "string[]", End), + + new Function(c, "remoteLocalContactName", remoteLocalContactName, + None, Return, "string", End), + + new Function(c, "remoteConnect", remoteConnect, None, Return, + "void", Parameters, new Param(c, "name", "string"), + new Param(c, "host", "string"), + new Param(c, "port", "int", Value(0)), End), + + new Function(c, "remoteDisconnect", remoteDisconnect, None, Return, + "void", Parameters, + new Param(c, "remoteContact", "string"), End), + + new Function(c, "remoteNetwork", remoteNetwork, None, Return, + "void", Parameters, new Param(c, "on", "bool"), End), + + new SymbolicConstant(c, "NetworkStatusOn", "int", Value(1)), + new SymbolicConstant(c, "NetworkStatusOff", "int", Value(0)), + + new Function(c, "remoteNetworkStatus", remoteNetworkStatus, None, + Return, "int", End), -using namespace TwkApp; -using namespace Mu; -using namespace std; + new Function(c, "writeSetting", writeSetting, None, Return, "void", + Parameters, new Param(c, "group", "string"), + new Param(c, "name", "string"), + new Param(c, "value", "SettingsValue"), End), -void initUICommands(MuLangContext* context) -{ - USING_MU_FUNCTION_SYMBOLS; - MuLangContext* c = context; - Symbol* root = context->globalScope(); - Name cname = c->internName("commands"); - Mu::Module* commands = root->findSymbolOfType(cname); - - commands->addSymbols(new Function(c, "resizeFit", resizeFit, None, - Return, "void", - End), - - new Function(c, "setViewSize", setViewSize, None, - Return, "void", - Parameters, - new Param(c, "width", "int"), - new Param(c, "height", "int"), - End), - - new Function(c, "popupMenu", popupMenu, None, - Return, "void", - Parameters, - new Param(c, "event", "Event"), - new Param(c, "menu", "MenuItem[]", Value(Pointer(0))), - End), - - new Function(c, "popupMenuAtPoint", popupMenuAtPoint, None, - Return, "void", - Parameters, - new Param(c, "x", "int"), - new Param(c, "y", "int"), - new Param(c, "menu", "MenuItem[]", Value(Pointer(0))), - End), - - new Function(c, "setWindowTitle", setWindowTitle, None, - Return, "void", - Parameters, - new Param(c, "title", "string"), - End), - - new Function(c, "center", center, None, - Return, "void", - End), - - new Function(c, "close", close, None, - Return, "void", - End), - - new Function(c, "toggleMenuBar", toggleMenuBar, None, - Return, "void", - End), - - new Function(c, "isMenuBarVisible", isMenuBarVisible, None, - Return, "bool", - End), - - new SymbolicConstant(c, "OneExistingFile", "int", Value(0)), - new SymbolicConstant(c, "ManyExistingFiles", "int", Value(0)), - new SymbolicConstant(c, "ManyExistingFilesAndDirectories", "int", Value(0)), - new SymbolicConstant(c, "OneFileName", "int", Value(0)), - new SymbolicConstant(c, "OneDirectory", "int", Value(0)), - - new Function(c, "openMediaFileDialog", openMediaFileDialog, - None, - Return, "string[]", - Parameters, - new Param(c, "associated", "bool"), - new Param(c, "selectType", "int"), - new Param(c, "filter", "string", Value(0)), - new Param(c, "defaultPath", "string", Value(0)), - new Param(c, "label", "string", Value(0)), - End), - - new Function(c, "openFileDialog", openFileDialog, - None, - Return, "string[]", - Parameters, - new Param(c, "associated", "bool"), - new Param(c, "multiple", "bool", Value(false)), - new Param(c, "directory", "bool", Value(false)), - new Param(c, "filter", "string", Value(0)), - new Param(c, "defaultPath", "string", Value(0)), - End), - - new Function(c, "saveFileDialog", saveFileDialog, - None, - Return, "string", - Parameters, - new Param(c, "associated", "bool"), - new Param(c, "filter", "string", Value(0)), - new Param(c, "defaultPath", "string", Value(0)), - End), - - new SymbolicConstant(c, "CursorNone", "int", Value(0)), - new SymbolicConstant(c, "CursorArrow", "int", Value(2)), - new SymbolicConstant(c, "CursorDefault", "int", Value(1)), - - new Function(c, "setCursor", setCursor, None, - Return, "void", - Parameters, - new Param(c, "cursorType", "int"), - End), - - new SymbolicConstant(c, "InfoAlert", "int", Value(0)), - new SymbolicConstant(c, "WarningAlert", "int", Value(1)), - new SymbolicConstant(c, "ErrorAlert", "int", Value(2)), - - new Function(c, "stereoSupported", stereoSupported, None, - Return, "bool", - End), - - new Function(c, "alertPanel", alertPanel, None, - Return, "int", - Parameters, - new Param(c, "associated", "bool"), - new Param(c, "type", "int"), - new Param(c, "title", "string"), - new Param(c, "message", "string"), - new Param(c, "button0", "string"), - new Param(c, "button1", "string"), - new Param(c, "button2", "string"), - End), - - new Function(c, "watchFile", watchFile, None, - Return, "void", - Parameters, - new Param(c, "filename", "string"), - new Param(c, "watch", "bool"), - End), - - new Function(c, "showConsole", showConsole, None, - Return, "void", - End), - - new Function(c, "isConsoleVisible", isConsoleVisible, None, - Return, "bool", - End), - // network - - new Function(c, "remoteSendMessage", remoteSendMessage, None, - Return, "void", - Parameters, - new Param(c, "message", "string"), - new Param(c, "recipients", "string[]", Value(0)), - End), - - new Function(c, "remoteSendEvent", remoteSendEvent, None, - Return, "void", - Parameters, - new Param(c, "event", "string"), - new Param(c, "target", "string"), - new Param(c, "contents", "string"), - new Param(c, "recipients", "string[]", Value(0)), - End), - - new Function(c, "remoteConnections", remoteConnections, None, - Return, "string[]", - End), - - new Function(c, "remoteApplications", remoteApplications, None, - Return, "string[]", - End), - - new Function(c, "remoteContacts", remoteContacts, None, - Return, "string[]", - End), - - new Function(c, "remoteLocalContactName", remoteLocalContactName, None, - Return, "string", - End), - - new Function(c, "remoteConnect", remoteConnect, None, - Return, "void", - Parameters, - new Param(c, "name", "string"), - new Param(c, "host", "string"), - new Param(c, "port", "int", Value(0)), - End), - - new Function(c, "remoteDisconnect", remoteDisconnect, None, - Return, "void", - Parameters, - new Param(c, "remoteContact", "string"), - End), - - new Function(c, "remoteNetwork", remoteNetwork, None, - Return, "void", - Parameters, - new Param(c, "on", "bool"), - End), - - new SymbolicConstant(c, "NetworkStatusOn", "int", Value(1)), - new SymbolicConstant(c, "NetworkStatusOff", "int", Value(0)), - - new Function(c, "remoteNetworkStatus", remoteNetworkStatus, None, - Return, "int", - End), - - new Function(c, "writeSetting", writeSetting, None, - Return, "void", - Parameters, - new Param(c, "group", "string"), - new Param(c, "name", "string"), - new Param(c, "value", "SettingsValue"), - End), - - new Function(c, "readSetting", readSetting, None, - Return, "SettingsValue", - Parameters, - new Param(c, "group", "string"), - new Param(c, "name", "string"), - new Param(c, "defaultValue", "SettingsValue"), - End), - - new Function(c, "httpGet", httpGet, None, - Return, "void", - Parameters, - new Param(c, "url", "string"), - new Param(c, "headers", "[(string,string)]"), - new Param(c, "replyEvent", "string"), - new Param(c, "authenticationEvent", "string", Value(Pointer(0))), - new Param(c, "progressEvent", "string", Value(Pointer(0))), - new Param(c, "ignoreSslErrors", "bool", Value(false)), - End), - - new Function(c, "httpPost", httpPost, None, - Return, "void", - Parameters, - new Param(c, "url", "string"), - new Param(c, "headers", "[(string,string)]"), - new Param(c, "postString", "string"), - new Param(c, "replyEvent", "string"), - new Param(c, "authenticationEvent", "string", Value(Pointer(0))), - new Param(c, "progressEvent", "string", Value(Pointer(0))), - new Param(c, "ignoreSslErrors", "bool", Value(false)), - End), - - new Function(c, "mainWindowWidget", mainWindowWidget, None, - Return, "qt.QMainWindow", - End), - - new Function(c, "networkAccessManager", networkAccessManager, None, - Return, "qt.QNetworkAccessManager", - End), - - new Function(c, "javascriptMuExport", javascriptMuExport, None, - Return, "void", - Parameters, - new Param(c, "frame", "qt.QWebFrame"), - End), - - new Function(c, "sessionFromUrl", sessionFromUrl, None, - Return, "void", - Parameters, - new Param(c, "url", "string"), - End), - - new Function(c, "putUrlOnClipboard", putUrlOnClipboard, None, - Return, "void", - Parameters, - new Param(c, "url", "string"), - new Param(c, "title", "string"), - new Param(c, "doEncode", "bool", Value(true)), - End), - - new Function(c, "myNetworkPort", myNetworkPort, None, - Return, "int", - End), - - new Function(c, "myNetworkHost", myNetworkHost, None, - Return, "string", - End), - - new Function(c, "encodePassword", encodePassword, - None, - Return, "string", - Parameters, - new Param(c, "password", "string"), - End), - - new Function(c, "decodePassword", decodePassword, - None, - Return, "string", - Parameters, - new Param(c, "password", "string"), - End), - - new Function(c, "cacheDir", cacheDir, - None, - Return, "string", - End), - - new Function(c, "openUrl", openUrl, - None, - Return, "void", - Parameters, - new Param(c, "url", "string"), - End), - - EndArguments); -} - -NODE_IMPLEMENTATION(resizeFit, void) -{ -} + new Function(c, "readSetting", readSetting, None, Return, + "SettingsValue", Parameters, + new Param(c, "group", "string"), + new Param(c, "name", "string"), + new Param(c, "defaultValue", "SettingsValue"), End), -NODE_IMPLEMENTATION(setViewSize, void) -{ -} + new Function( + c, "httpGet", httpGet, None, Return, "void", Parameters, + new Param(c, "url", "string"), + new Param(c, "headers", "[(string,string)]"), + new Param(c, "replyEvent", "string"), + new Param(c, "authenticationEvent", "string", + Value(Pointer(0))), + new Param(c, "progressEvent", "string", Value(Pointer(0))), + new Param(c, "ignoreSslErrors", "bool", Value(false)), End), -NODE_IMPLEMENTATION(popupMenu, void) -{ -} + new Function( + c, "httpPost", httpPost, None, Return, "void", Parameters, + new Param(c, "url", "string"), + new Param(c, "headers", "[(string,string)]"), + new Param(c, "postString", "string"), + new Param(c, "replyEvent", "string"), + new Param(c, "authenticationEvent", "string", + Value(Pointer(0))), + new Param(c, "progressEvent", "string", Value(Pointer(0))), + new Param(c, "ignoreSslErrors", "bool", Value(false)), End), -NODE_IMPLEMENTATION(popupMenuAtPoint, void) -{ -} + new Function(c, "mainWindowWidget", mainWindowWidget, None, Return, + "qt.QMainWindow", End), -NODE_IMPLEMENTATION(setWindowTitle, void) -{ -} + new Function(c, "networkAccessManager", networkAccessManager, None, + Return, "qt.QNetworkAccessManager", End), -NODE_IMPLEMENTATION(center, void) -{ -} + new Function(c, "javascriptMuExport", javascriptMuExport, None, + Return, "void", Parameters, + new Param(c, "frame", "qt.QWebFrame"), End), -NODE_IMPLEMENTATION(close, void) -{ -} + new Function(c, "sessionFromUrl", sessionFromUrl, None, Return, + "void", Parameters, new Param(c, "url", "string"), + End), -NODE_IMPLEMENTATION(toggleMenuBar, void) -{ -} + new Function(c, "putUrlOnClipboard", putUrlOnClipboard, None, + Return, "void", Parameters, + new Param(c, "url", "string"), + new Param(c, "title", "string"), + new Param(c, "doEncode", "bool", Value(true)), End), -NODE_IMPLEMENTATION(isMenuBarVisible, bool) -{ - NODE_RETURN(false); -} + new Function(c, "myNetworkPort", myNetworkPort, None, Return, "int", + End), -NODE_IMPLEMENTATION(openMediaFileDialog, Pointer) -{ - NODE_RETURN((Pointer)0); -} + new Function(c, "myNetworkHost", myNetworkHost, None, Return, + "string", End), -NODE_IMPLEMENTATION(openFileDialog, Pointer) -{ - NODE_RETURN((Pointer)0); -} + new Function(c, "encodePassword", encodePassword, None, Return, + "string", Parameters, + new Param(c, "password", "string"), End), -NODE_IMPLEMENTATION(saveFileDialog, Pointer) -{ - NODE_RETURN((Pointer)0); -} + new Function(c, "decodePassword", decodePassword, None, Return, + "string", Parameters, + new Param(c, "password", "string"), End), -NODE_IMPLEMENTATION(setCursor, void) -{ -} + new Function(c, "cacheDir", cacheDir, None, Return, "string", End), -NODE_IMPLEMENTATION(alertPanel, int) -{ - NODE_RETURN(0); -} + new Function(c, "openUrl", openUrl, None, Return, "void", + Parameters, new Param(c, "url", "string"), End), -NODE_IMPLEMENTATION(stereoSupported, bool) -{ - NODE_RETURN(false); -} + EndArguments); + } -NODE_IMPLEMENTATION(watchFile, void) -{ -} + NODE_IMPLEMENTATION(resizeFit, void) {} -NODE_IMPLEMENTATION(showConsole, void) -{ -} + NODE_IMPLEMENTATION(setViewSize, void) {} -NODE_IMPLEMENTATION(isConsoleVisible, bool) -{ - NODE_RETURN(false); -} + NODE_IMPLEMENTATION(popupMenu, void) {} + NODE_IMPLEMENTATION(popupMenuAtPoint, void) {} -NODE_IMPLEMENTATION(remoteSendMessage, void) -{ -} + NODE_IMPLEMENTATION(setWindowTitle, void) {} -NODE_IMPLEMENTATION(remoteSendEvent, void) -{ -} + NODE_IMPLEMENTATION(center, void) {} -NODE_IMPLEMENTATION(remoteConnections, Pointer) -{ - NODE_RETURN(0); -} + NODE_IMPLEMENTATION(close, void) {} -NODE_IMPLEMENTATION(remoteApplications, Pointer) -{ - NODE_RETURN(0); -} + NODE_IMPLEMENTATION(toggleMenuBar, void) {} -NODE_IMPLEMENTATION(remoteContacts, Pointer) -{ - NODE_RETURN(0); -} + NODE_IMPLEMENTATION(isMenuBarVisible, bool) { NODE_RETURN(false); } -NODE_IMPLEMENTATION(remoteLocalContactName, Pointer) -{ - NODE_RETURN(0); -} + NODE_IMPLEMENTATION(openMediaFileDialog, Pointer) + { + NODE_RETURN((Pointer)0); + } -NODE_IMPLEMENTATION(remoteConnect, void) -{ -} + NODE_IMPLEMENTATION(openFileDialog, Pointer) { NODE_RETURN((Pointer)0); } -NODE_IMPLEMENTATION(remoteDisconnect, void) -{ -} + NODE_IMPLEMENTATION(saveFileDialog, Pointer) { NODE_RETURN((Pointer)0); } -NODE_IMPLEMENTATION(remoteNetwork, void) -{ -} + NODE_IMPLEMENTATION(setCursor, void) {} -NODE_IMPLEMENTATION(remoteNetworkStatus, int) -{ - NODE_RETURN(0); -} + NODE_IMPLEMENTATION(alertPanel, int) { NODE_RETURN(0); } -NODE_IMPLEMENTATION(writeSetting, void) -{ -} + NODE_IMPLEMENTATION(stereoSupported, bool) { NODE_RETURN(false); } -NODE_IMPLEMENTATION(readSetting, Pointer) -{ - NODE_RETURN(0); -} + NODE_IMPLEMENTATION(watchFile, void) {} -NODE_DECLARATION(httpGet, void) -{ -} + NODE_IMPLEMENTATION(showConsole, void) {} -NODE_DECLARATION(httpPost, void) -{ -} + NODE_IMPLEMENTATION(isConsoleVisible, bool) { NODE_RETURN(false); } -NODE_DECLARATION(sessionFromUrl, void) -{ -} + NODE_IMPLEMENTATION(remoteSendMessage, void) {} -NODE_DECLARATION(putUrlOnClipboard, void) -{ -} + NODE_IMPLEMENTATION(remoteSendEvent, void) {} -NODE_DECLARATION(myNetworkPort, int) -{ - NODE_RETURN(0); -} + NODE_IMPLEMENTATION(remoteConnections, Pointer) { NODE_RETURN(0); } -NODE_DECLARATION(encodePassword, Mu::Pointer) -{ - NODE_RETURN(0); -} + NODE_IMPLEMENTATION(remoteApplications, Pointer) { NODE_RETURN(0); } -NODE_DECLARATION(decodePassword, Mu::Pointer) -{ - NODE_RETURN(0); -} + NODE_IMPLEMENTATION(remoteContacts, Pointer) { NODE_RETURN(0); } -NODE_DECLARATION(cacheDir, Mu::Pointer) -{ - NODE_RETURN(0); -} + NODE_IMPLEMENTATION(remoteLocalContactName, Pointer) { NODE_RETURN(0); } -NODE_IMPLEMENTATION(openUrl, void) -{ -} + NODE_IMPLEMENTATION(remoteConnect, void) {} -NODE_DECLARATION(mainWindowWidget, Mu::Pointer) -{ - NODE_RETURN(0); -} + NODE_IMPLEMENTATION(remoteDisconnect, void) {} -NODE_DECLARATION(networkAccessManager, Mu::Pointer) -{ - NODE_RETURN(0); -} + NODE_IMPLEMENTATION(remoteNetwork, void) {} -NODE_DECLARATION(javascriptMuExport, void) -{ -} + NODE_IMPLEMENTATION(remoteNetworkStatus, int) { NODE_RETURN(0); } -NODE_IMPLEMENTATION(myNetworkHost, Pointer) -{ - NODE_RETURN(0); -} + NODE_IMPLEMENTATION(writeSetting, void) {} + + NODE_IMPLEMENTATION(readSetting, Pointer) { NODE_RETURN(0); } + + NODE_DECLARATION(httpGet, void) {} + + NODE_DECLARATION(httpPost, void) {} + + NODE_DECLARATION(sessionFromUrl, void) {} + + NODE_DECLARATION(putUrlOnClipboard, void) {} + + NODE_DECLARATION(myNetworkPort, int) { NODE_RETURN(0); } + + NODE_DECLARATION(encodePassword, Mu::Pointer) { NODE_RETURN(0); } + + NODE_DECLARATION(decodePassword, Mu::Pointer) { NODE_RETURN(0); } + + NODE_DECLARATION(cacheDir, Mu::Pointer) { NODE_RETURN(0); } + + NODE_IMPLEMENTATION(openUrl, void) {} + + NODE_DECLARATION(mainWindowWidget, Mu::Pointer) { NODE_RETURN(0); } + + NODE_DECLARATION(networkAccessManager, Mu::Pointer) { NODE_RETURN(0); } + + NODE_DECLARATION(javascriptMuExport, void) {} + + NODE_IMPLEMENTATION(myNetworkHost, Pointer) { NODE_RETURN(0); } -} // End namespace RVIO +} // End namespace RVIO diff --git a/src/bin/imgtools/rvio/UICommands.h b/src/bin/imgtools/rvio/UICommands.h index 9c232186a..b1107d953 100644 --- a/src/bin/imgtools/rvio/UICommands.h +++ b/src/bin/imgtools/rvio/UICommands.h @@ -1,9 +1,9 @@ //****************************************************************************** -// Copyright (c) 2005 Tweak Inc. +// Copyright (c) 2005 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #ifndef __RVIO__UICommands__h__ #define __RVIO__UICommands__h__ @@ -12,54 +12,55 @@ #include #include -namespace RVIO { +namespace RVIO +{ -void initUICommands(Mu::MuLangContext*); + void initUICommands(Mu::MuLangContext*); -NODE_DECLARATION(resizeFit, void); -NODE_DECLARATION(setViewSize, void); -NODE_DECLARATION(popupMenu, void); -NODE_DECLARATION(popupMenuAtPoint, void); -NODE_DECLARATION(setWindowTitle, void); -NODE_DECLARATION(center, void); -NODE_DECLARATION(close, void); -NODE_DECLARATION(toggleMenuBar, void); -NODE_DECLARATION(isMenuBarVisible, bool); -NODE_DECLARATION(openMediaFileDialog, Mu::Pointer); -NODE_DECLARATION(openFileDialog, Mu::Pointer); -NODE_DECLARATION(saveFileDialog, Mu::Pointer); -NODE_DECLARATION(setCursor, void); -NODE_DECLARATION(alertPanel, int); -NODE_DECLARATION(stereoSupported, bool); -NODE_DECLARATION(watchFile, void); -NODE_DECLARATION(showConsole, void); -NODE_DECLARATION(isConsoleVisible, bool); -NODE_DECLARATION(remoteSendMessage, void); -NODE_DECLARATION(remoteSendEvent, void); -NODE_DECLARATION(remoteApplications, Mu::Pointer); -NODE_DECLARATION(remoteConnections, Mu::Pointer); -NODE_DECLARATION(remoteContacts, Mu::Pointer); -NODE_DECLARATION(remoteLocalContactName, Mu::Pointer); -NODE_DECLARATION(remoteConnect, void); -NODE_DECLARATION(remoteDisconnect, void); -NODE_DECLARATION(remoteNetwork, void); -NODE_DECLARATION(remoteNetworkStatus, int); -NODE_DECLARATION(writeSetting, void); -NODE_DECLARATION(readSetting, Mu::Pointer); -NODE_DECLARATION(httpGet, void); -NODE_DECLARATION(httpPost, void); -NODE_DECLARATION(sessionFromUrl, void); -NODE_DECLARATION(putUrlOnClipboard, void); -NODE_DECLARATION(myNetworkPort, int); -NODE_DECLARATION(encodePassword, Mu::Pointer); -NODE_DECLARATION(decodePassword, Mu::Pointer); -NODE_DECLARATION(cacheDir, Mu::Pointer); -NODE_DECLARATION(mainWindowWidget, Mu::Pointer); -NODE_DECLARATION(networkAccessManager, Mu::Pointer); -NODE_DECLARATION(javascriptMuExport, void); -NODE_DECLARATION(openUrl, void); -NODE_DECLARATION(myNetworkHost, Mu::Pointer); + NODE_DECLARATION(resizeFit, void); + NODE_DECLARATION(setViewSize, void); + NODE_DECLARATION(popupMenu, void); + NODE_DECLARATION(popupMenuAtPoint, void); + NODE_DECLARATION(setWindowTitle, void); + NODE_DECLARATION(center, void); + NODE_DECLARATION(close, void); + NODE_DECLARATION(toggleMenuBar, void); + NODE_DECLARATION(isMenuBarVisible, bool); + NODE_DECLARATION(openMediaFileDialog, Mu::Pointer); + NODE_DECLARATION(openFileDialog, Mu::Pointer); + NODE_DECLARATION(saveFileDialog, Mu::Pointer); + NODE_DECLARATION(setCursor, void); + NODE_DECLARATION(alertPanel, int); + NODE_DECLARATION(stereoSupported, bool); + NODE_DECLARATION(watchFile, void); + NODE_DECLARATION(showConsole, void); + NODE_DECLARATION(isConsoleVisible, bool); + NODE_DECLARATION(remoteSendMessage, void); + NODE_DECLARATION(remoteSendEvent, void); + NODE_DECLARATION(remoteApplications, Mu::Pointer); + NODE_DECLARATION(remoteConnections, Mu::Pointer); + NODE_DECLARATION(remoteContacts, Mu::Pointer); + NODE_DECLARATION(remoteLocalContactName, Mu::Pointer); + NODE_DECLARATION(remoteConnect, void); + NODE_DECLARATION(remoteDisconnect, void); + NODE_DECLARATION(remoteNetwork, void); + NODE_DECLARATION(remoteNetworkStatus, int); + NODE_DECLARATION(writeSetting, void); + NODE_DECLARATION(readSetting, Mu::Pointer); + NODE_DECLARATION(httpGet, void); + NODE_DECLARATION(httpPost, void); + NODE_DECLARATION(sessionFromUrl, void); + NODE_DECLARATION(putUrlOnClipboard, void); + NODE_DECLARATION(myNetworkPort, int); + NODE_DECLARATION(encodePassword, Mu::Pointer); + NODE_DECLARATION(decodePassword, Mu::Pointer); + NODE_DECLARATION(cacheDir, Mu::Pointer); + NODE_DECLARATION(mainWindowWidget, Mu::Pointer); + NODE_DECLARATION(networkAccessManager, Mu::Pointer); + NODE_DECLARATION(javascriptMuExport, void); + NODE_DECLARATION(openUrl, void); + NODE_DECLARATION(myNetworkHost, Mu::Pointer); -} // RVIO +} // namespace RVIO #endif // __RV__UICommands__h__ diff --git a/src/bin/imgtools/rvio/main.cpp b/src/bin/imgtools/rvio/main.cpp index d631f1654..72db59c8a 100644 --- a/src/bin/imgtools/rvio/main.cpp +++ b/src/bin/imgtools/rvio/main.cpp @@ -1,8 +1,8 @@ //****************************************************************************** // Copyright (c) 2001-2005 Tweak Inc. All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #include "../../utf8Main.h" @@ -110,7 +110,7 @@ // RVIO third party optional customization #if defined(RVIO_THIRD_PARTY_CUSTOMIZATION) - extern void rvioThirdPartyCustomization(TwkApp::Bundle& bundle, char* licarg); +extern void rvioThirdPartyCustomization(TwkApp::Bundle& bundle, char* licarg); #endif typedef TwkContainer::StringProperty StringProperty; @@ -133,36 +133,24 @@ struct Illuminant }; Illuminant standardIlluminants[] = { - {"A", 0.44757f, 0.40745f }, - {"B", 0.34842f, 0.35161f}, - {"C", 0.31006f, 0.31616f}, - {"D50", 0.34567f, 0.35850f}, - {"D55", 0.33242f, 0.34743f}, - {"D65", 0.31271f, 0.32902f}, - {"D65REC709", 0.3127f, 0.3290f}, - {"D75", 0.29902f, 0.31485f}, - {"E", 1.0f/3.0f, 1.0f/3.0f}, - {"F1", 0.31310f, 0.33727f}, - {"F2", 0.37208f, 0.37529f}, - {"F3", 0.40910f, 0.39430f}, - {"F4", 0.44018f, 0.40329f}, - {"F5", 0.31379f, 0.34531f}, - {"F6", 0.37790f, 0.38835f}, - {"F7", 0.31292f, 0.32933f}, - {"F8", 0.34588f, 0.35875f}, - {"F9", 0.37417f, 0.37281f}, - {"F10", 0.34609f, 0.35986f}, - {"F11", 0.38052f, 0.37713f}, - {"F12", 0.43695f, 0.40441f}, - {NULL, 0, 0} -}; - -int parseInFiles(int argc, char *argv[]) + {"A", 0.44757f, 0.40745f}, {"B", 0.34842f, 0.35161f}, + {"C", 0.31006f, 0.31616f}, {"D50", 0.34567f, 0.35850f}, + {"D55", 0.33242f, 0.34743f}, {"D65", 0.31271f, 0.32902f}, + {"D65REC709", 0.3127f, 0.3290f}, {"D75", 0.29902f, 0.31485f}, + {"E", 1.0f / 3.0f, 1.0f / 3.0f}, {"F1", 0.31310f, 0.33727f}, + {"F2", 0.37208f, 0.37529f}, {"F3", 0.40910f, 0.39430f}, + {"F4", 0.44018f, 0.40329f}, {"F5", 0.31379f, 0.34531f}, + {"F6", 0.37790f, 0.38835f}, {"F7", 0.31292f, 0.32933f}, + {"F8", 0.34588f, 0.35875f}, {"F9", 0.37417f, 0.37281f}, + {"F10", 0.34609f, 0.35986f}, {"F11", 0.38052f, 0.37713f}, + {"F12", 0.43695f, 0.40441f}, {NULL, 0, 0}}; + +int parseInFiles(int argc, char* argv[]) { // cerr << "Application::parseInFiles " << argc << " files" << endl; Rv::Options& opts = Rv::Options::sharedOptions(); - for (int i=0; iname; i++) { @@ -187,89 +175,89 @@ bool findillum(const char* name, float &x, float &y) return false; } -char* filename = 0; -int showFormats = 0; -char* outputFile = 0; -char* licarg = 0; -int lqt_decoder = 0; -int showVersion = 0; -float filegamma = 1.0; -float ingamma = 1.0; -float outgamma = 1.0; -float exposure = 0.0; -float scale = 1.0; -int iomethod = -1; -int iosize = 61440; -int resizex = 0; -int resizey = 0; -int loglin = 0; -int loglinc = 0; -int redloglin = 0; -int redlogfilmlin = 0; -int linlog = 0; -int verbose = 0; -int reallyverbose = 0; -int outbits = 0; -int processFloat = 0; -char* outtype = 0; -int ysamples = 0; -int rysamples = 0; -int bysamples = 0; -int usamples = 0; -int vsamples = 0; -int asamples = 0; -int xsize = 0; -int ysize = 0; -int flipImage = 0; -int flopImage = 0; -int strictlicense = 0; -char* compressor = (char*)""; -char* codec = (char*)""; -char* audioCodec = (char*)""; -float quality = 0.9f; -char* paRatio = (char*)"1:1"; -float pixelAspect = 1.0; -int paNumerator = 1; -int paDenominator = 1; -char* timerange = 0; -int stretch = 0; -char* comment = (char*)""; -char* copyright = (char*)""; -char* initscript = 0; -int err2out = 0; -int inpremult = 0; -int inunpremult = 0; -int outpremult = 0; -int outunpremult = 0; -float audioRate = 0; -int audioChannels = 0; -char* outStereo = (char*)""; -float outfps = 0; -int nosession = 0; -int outhalf = 0; -int out8 = 0; -int leaderFrames = 1; -int outrgb = 0; -char* dlut = 0; -int insrgb = 0; -int in709 = 0; -int outsrgb = 0; -int out709 = 0; -int outaces = 0; -int outlogc = 0; -int outlogcEI = 0; -int outredlog = 0; -int outredlogfilm = 0; -float white0 = -999; -float white1 = -999; -char* illumName = (char*)""; -int outadaptive = 0; -int tio = 0; -int threads = 1; -int wthreads = -1; -int noprerender = 0; +char* filename = 0; +int showFormats = 0; +char* outputFile = 0; +char* licarg = 0; +int lqt_decoder = 0; +int showVersion = 0; +float filegamma = 1.0; +float ingamma = 1.0; +float outgamma = 1.0; +float exposure = 0.0; +float scale = 1.0; +int iomethod = -1; +int iosize = 61440; +int resizex = 0; +int resizey = 0; +int loglin = 0; +int loglinc = 0; +int redloglin = 0; +int redlogfilmlin = 0; +int linlog = 0; +int verbose = 0; +int reallyverbose = 0; +int outbits = 0; +int processFloat = 0; +char* outtype = 0; +int ysamples = 0; +int rysamples = 0; +int bysamples = 0; +int usamples = 0; +int vsamples = 0; +int asamples = 0; +int xsize = 0; +int ysize = 0; +int flipImage = 0; +int flopImage = 0; +int strictlicense = 0; +char* compressor = (char*)""; +char* codec = (char*)""; +char* audioCodec = (char*)""; +float quality = 0.9f; +char* paRatio = (char*)"1:1"; +float pixelAspect = 1.0; +int paNumerator = 1; +int paDenominator = 1; +char* timerange = 0; +int stretch = 0; +char* comment = (char*)""; +char* copyright = (char*)""; +char* initscript = 0; +int err2out = 0; +int inpremult = 0; +int inunpremult = 0; +int outpremult = 0; +int outunpremult = 0; +float audioRate = 0; +int audioChannels = 0; +char* outStereo = (char*)""; +float outfps = 0; +int nosession = 0; +int outhalf = 0; +int out8 = 0; +int leaderFrames = 1; +int outrgb = 0; +char* dlut = 0; +int insrgb = 0; +int in709 = 0; +int outsrgb = 0; +int out709 = 0; +int outaces = 0; +int outlogc = 0; +int outlogcEI = 0; +int outredlog = 0; +int outredlogfilm = 0; +float white0 = -999; +float white1 = -999; +char* illumName = (char*)""; +int outadaptive = 0; +int tio = 0; +int threads = 1; +int wthreads = -1; +int noprerender = 0; char* resampleMethod = (char*)"area"; -char* view = 0; +char* view = 0; static void control_c_handler(int sig) { @@ -277,95 +265,92 @@ static void control_c_handler(int sig) exit(1); } - -vector inputFiles; -vector inchmap; -vector outchmap; -vector > leaderArgs; -vector > tailArgs; -vector > overlayArgs; -vector writerArgs; -float timerwait = 1.0 / 192; +vector inputFiles; +vector inchmap; +vector outchmap; +vector> leaderArgs; +vector> tailArgs; +vector> overlayArgs; +vector writerArgs; +float timerwait = 1.0 / 192; deque outparams; - #ifndef WIN32 -extern "C" { -int GC_pthread_create(pthread_t *new_thread, - const pthread_attr_t *attr, - void *(*start_routine)(void *), void *arg); +extern "C" +{ + int GC_pthread_create(pthread_t* new_thread, const pthread_attr_t* attr, + void* (*start_routine)(void*), void* arg); #ifdef PLATFORM_DARWIN -int GC_pthread_sigmask(int how, const sigset_t *set, sigset_t *oset); + int GC_pthread_sigmask(int how, const sigset_t* set, sigset_t* oset); #endif -int GC_pthread_join(pthread_t thread, void **retval); -int GC_pthread_detach(pthread_t thread); + int GC_pthread_join(pthread_t thread, void** retval); + int GC_pthread_detach(pthread_t thread); } #endif -void -parseParam (string s) +void parseParam(string s) { string::size_type pos = s.find("="); if (pos != string::npos) { - outparams.push_back(TwkUtil::StringPair(s.substr(0, pos), - s.substr(pos+1, string::npos))); + outparams.push_back(TwkUtil::StringPair( + s.substr(0, pos), s.substr(pos + 1, string::npos))); } } -int -parseOutParams(int argc, char *argv[]) +int parseOutParams(int argc, char* argv[]) { - for (int i=0; i args; - for (int i=0; i args; - for (int i=0; iinfo().audioSampleRate; + str << ",audio=sine,amp=0,rate=" << omov->info().audioSampleRate; } str << ".movieproc"; @@ -424,13 +407,14 @@ makeLeaderMovie(MovieWriter::WriteRequest& writeRequest, TwkMovie::MovieInfo info; - info.width = xs; - info.height = ys; - info.uncropWidth = xs; - info.uncropHeight = ys; - info.numChannels = 4; - info.audioSampleRate = omov->hasAudio() ? omov->info().audioSampleRate : 0; - info.audioChannels = omov->info().audioChannels; + info.width = xs; + info.height = ys; + info.uncropWidth = xs; + info.uncropHeight = ys; + info.numChannels = 4; + info.audioSampleRate = + omov->hasAudio() ? omov->info().audioSampleRate : 0; + info.audioChannels = omov->info().audioChannels; mp->open(session, info, info.audioChannels, audioRate); lmov = mp; @@ -446,10 +430,9 @@ makeLeaderMovie(MovieWriter::WriteRequest& writeRequest, return lmov; } -TwkMovie::Movie* -makeOverlayMovie(TwkMovie::Movie* in, - Mu::MuLangContext* context, - Mu::Process* process) +TwkMovie::Movie* makeOverlayMovie(TwkMovie::Movie* in, + Mu::MuLangContext* context, + Mu::Process* process) { if (!overlayArgs.empty()) { @@ -464,8 +447,7 @@ makeOverlayMovie(TwkMovie::Movie* in, return in; } -MovieRV* -makeInputMovie() +MovieRV* makeInputMovie() { Rv::Options& opts = Rv::Options::sharedOptions(); @@ -478,10 +460,10 @@ makeInputMovie() Rv::RvSession* session = new Rv::RvSession(); session->setBatchMode(true); - if (inputFiles.size() == 1 && - extension(inputFiles.front()) == "rv") + if (inputFiles.size() == 1 && extension(inputFiles.front()) == "rv") { - session->read(inputFiles.front().c_str(), IPCore::Session::ReadRequest()); + session->read(inputFiles.front().c_str(), + IPCore::Session::ReadRequest()); } else { @@ -502,7 +484,8 @@ makeInputMovie() if (*outStereo && strcmp(outStereo, "separate")) { vector props; - session->findPropertyOfType(props, "#RVDisplayStereo.stereo.type"); + session->findPropertyOfType( + props, "#RVDisplayStereo.stereo.type"); props.front()->front() = outStereo; } @@ -519,8 +502,10 @@ makeInputMovie() ys = resizey; float aspect = float(size[0]) / float(size[1]); - if (!ys) ys = int(xs / aspect + 0.49f); - else if (!xs) xs = int(ys * aspect + 0.49f); + if (!ys) + ys = int(xs / aspect + 0.49f); + else if (!xs) + xs = int(ys * aspect + 0.49f); } if (xs == 0 || ys == 0) @@ -533,14 +518,13 @@ makeInputMovie() ys = int(float(ys) * scale + 0.49f); TwkMovie::MovieInfo info; - info.width = xs; - info.height = ys; - info.uncropWidth = xs; - info.uncropHeight = ys; - info.numChannels = 4; + info.width = xs; + info.height = ys; + info.uncropWidth = xs; + info.uncropHeight = ys; + info.numChannels = 4; info.audioSampleRate = audioRate; - info.audioChannels = layoutChannels(channelLayouts(audioChannels).front()); - + info.audioChannels = layoutChannels(channelLayouts(audioChannels).front()); if (view && !session->setViewNode(view)) { @@ -555,15 +539,23 @@ makeInputMovie() session->setSessionStateFromNode(session->graph().viewNode()); rvmov->open(session, info, info.audioChannels, audioRate); - if (loglin) Rv::setLogLinOnAll(session->graph(), true, 1); - if (loglinc) Rv::setLogLinOnAll(session->graph(), true, 3); - if (redloglin) Rv::setLogLinOnAll(session->graph(), true, 6); - if (redlogfilmlin) Rv::setLogLinOnAll(session->graph(), true, 7); - if (insrgb) Rv::setSRGBLinOnAll(session->graph(), true); - if (in709) Rv::setRec709LinOnAll(session->graph(), true); - - if (ingamma != 1.0) Rv::setGammaOnAll(session->graph(), ingamma); - if (filegamma != 1.0) Rv::setFileGammaOnAll(session->graph(), filegamma); + if (loglin) + Rv::setLogLinOnAll(session->graph(), true, 1); + if (loglinc) + Rv::setLogLinOnAll(session->graph(), true, 3); + if (redloglin) + Rv::setLogLinOnAll(session->graph(), true, 6); + if (redlogfilmlin) + Rv::setLogLinOnAll(session->graph(), true, 7); + if (insrgb) + Rv::setSRGBLinOnAll(session->graph(), true); + if (in709) + Rv::setRec709LinOnAll(session->graph(), true); + + if (ingamma != 1.0) + Rv::setGammaOnAll(session->graph(), ingamma); + if (filegamma != 1.0) + Rv::setFileGammaOnAll(session->graph(), filegamma); if (exposure != 0.0) { @@ -573,12 +565,14 @@ makeInputMovie() if (flipImage || flopImage) { - Rv::setFlipFlopOnAll(session->graph(), flipImage, true, flopImage, true); + Rv::setFlipFlopOnAll(session->graph(), flipImage, true, flopImage, + true); flipImage = 0; flopImage = 0; } - if (!inchmap.empty()) Rv::setChannelMapOnAll(session->graph(), inchmap); + if (!inchmap.empty()) + Rv::setChannelMapOnAll(session->graph(), inchmap); Rv::fitAllInputs(session->graph(), xs, ys); if (dlut) @@ -623,10 +617,9 @@ makeInputMovie() return rvmov; } -TwkMovie::Movie* -makeFormattedMovie(MovieWriter::WriteRequest& writeRequest, - TwkMovie::Movie* omov, - TwkMovie::Movie* lmov) +TwkMovie::Movie* makeFormattedMovie(MovieWriter::WriteRequest& writeRequest, + TwkMovie::Movie* omov, + TwkMovie::Movie* lmov) { // // Reformatter for the content @@ -639,8 +632,7 @@ makeFormattedMovie(MovieWriter::WriteRequest& writeRequest, { if (!findillum(illumName, white0, white1)) { - cerr << "ERROR: " << illumName - << " is not a standard illuminant" + cerr << "ERROR: " << illumName << " is not a standard illuminant" << endl; exit(-1); } @@ -657,12 +649,16 @@ makeFormattedMovie(MovieWriter::WriteRequest& writeRequest, rmov->setOutputLogCEI(outlogcEI); rmov->setOutputRedLog(outredlog); rmov->setOutputRedLogFilm(outredlogfilm); - if (white0 != -999 && white1 != -999) rmov->setOutputWhite(white0, white1); + if (white0 != -999 && white1 != -999) + rmov->setOutputWhite(white0, white1); rmov->setFlip(flipImage); rmov->setFlop(flopImage); - if (outpremult) rmov->setOutputPremultiply(); - if (outunpremult) rmov->setOutputUnpremultiply(); - if (!outchmap.empty()) rmov->setChannelMap(outchmap); + if (outpremult) + rmov->setOutputPremultiply(); + if (outunpremult) + rmov->setOutputUnpremultiply(); + if (!outchmap.empty()) + rmov->setChannelMap(outchmap); if (rlmov) { @@ -670,11 +666,14 @@ makeFormattedMovie(MovieWriter::WriteRequest& writeRequest, rlmov->setOutputLogSpace(linlog); rlmov->setOutputRedLog(outredlog); rlmov->setOutputRedLogFilm(outredlogfilm); - if (!outchmap.empty()) rlmov->setChannelMap(outchmap); + if (!outchmap.empty()) + rlmov->setChannelMap(outchmap); rlmov->setFlip(flipImage); rlmov->setFlop(flopImage); - if (outpremult) rlmov->setOutputPremultiply(); - if (outunpremult) rlmov->setOutputUnpremultiply(); + if (outpremult) + rlmov->setOutputPremultiply(); + if (outunpremult) + rlmov->setOutputUnpremultiply(); } if (ysamples) @@ -701,24 +700,29 @@ makeFormattedMovie(MovieWriter::WriteRequest& writeRequest, if (outtype && outbits) { - bool fp = !strcmp(outtype, "float") || - !strcmp(outtype, "half") || - !strcmp(outtype, "double"); + bool fp = !strcmp(outtype, "float") || !strcmp(outtype, "half") + || !strcmp(outtype, "double"); if (outbits <= 8) { rmov->setOutputFormat(FrameBuffer::UCHAR); - if (rlmov) rlmov->setOutputFormat(FrameBuffer::UCHAR); + if (rlmov) + rlmov->setOutputFormat(FrameBuffer::UCHAR); } else if (outbits <= 16) { rmov->setOutputFormat(fp ? FrameBuffer::HALF : FrameBuffer::USHORT); - if (rlmov) rlmov->setOutputFormat(fp ? FrameBuffer::HALF : FrameBuffer::USHORT); + if (rlmov) + rlmov->setOutputFormat(fp ? FrameBuffer::HALF + : FrameBuffer::USHORT); } else { - rmov->setOutputFormat(fp ? FrameBuffer::FLOAT : FrameBuffer::USHORT); - if (rlmov) rlmov->setOutputFormat(fp ? FrameBuffer::FLOAT : FrameBuffer::USHORT); + rmov->setOutputFormat(fp ? FrameBuffer::FLOAT + : FrameBuffer::USHORT); + if (rlmov) + rlmov->setOutputFormat(fp ? FrameBuffer::FLOAT + : FrameBuffer::USHORT); } } @@ -733,11 +737,11 @@ makeFormattedMovie(MovieWriter::WriteRequest& writeRequest, { int len = lmov->info().end - lmov->info().start + 1; int fs = lmov->info().start; - int f0 = writeRequest.frames.empty() ? omov->info().start : writeRequest.frames.front(); - int f1 = writeRequest.frames.empty() ? omov->info().end : writeRequest.frames.back(); - LeaderFooterMovie* smov = new LeaderFooterMovie(omov, f0, f1, - lmov, - 0); + int f0 = writeRequest.frames.empty() ? omov->info().start + : writeRequest.frames.front(); + int f1 = writeRequest.frames.empty() ? omov->info().end + : writeRequest.frames.back(); + LeaderFooterMovie* smov = new LeaderFooterMovie(omov, f0, f1, lmov, 0); omov = smov; FrameList lframes; @@ -749,18 +753,15 @@ makeFormattedMovie(MovieWriter::WriteRequest& writeRequest, if (!writeRequest.frames.empty()) { writeRequest.frames.insert(writeRequest.frames.begin(), - lframes.begin(), - lframes.end()); + lframes.begin(), lframes.end()); } } return omov; } -TwkMovie::Movie* -makeMovieTree(MovieWriter::WriteRequest& writeRequest, - Mu::MuLangContext* context, - Mu::Process* process) +TwkMovie::Movie* makeMovieTree(MovieWriter::WriteRequest& writeRequest, + Mu::MuLangContext* context, Mu::Process* process) { MovieRV* reader = makeInputMovie(); @@ -789,7 +790,7 @@ makeMovieTree(MovieWriter::WriteRequest& writeRequest, // largest. // - for (int i=min(fs,fe); i <= max(fs,fe); i+=abs(inc)) + for (int i = min(fs, fe); i <= max(fs, fe); i += abs(inc)) { writeRequest.frames.push_back(i); } @@ -799,40 +800,38 @@ makeMovieTree(MovieWriter::WriteRequest& writeRequest, // Add any overlays, etc // - TwkMovie::Movie* omov = makeOverlayMovie(reader, context, process); - TwkMovie::Movie* lmov = makeLeaderMovie(writeRequest, omov, context, process); + TwkMovie::Movie* omov = makeOverlayMovie(reader, context, process); + TwkMovie::Movie* lmov = + makeLeaderMovie(writeRequest, omov, context, process); TwkMovie::Movie* outmov = makeFormattedMovie(writeRequest, omov, lmov); - //TwkMovie::Movie* outmov = makeFormattedMovie(writeRequest, reader, 0); + // TwkMovie::Movie* outmov = makeFormattedMovie(writeRequest, reader, 0); return outmov; } -string -str(float f) +string str(float f) { ostringstream str; str << f; return str.str(); } -string -str(int i) +string str(int i) { ostringstream str; str << i; return str.str(); } -void -addParam(const string& name, const string& val) +void addParam(const string& name, const string& val) { outparams.push_front(StringPair(name, val)); } -void -addDefaultParams() +void addDefaultParams() { - if (outfps != 0.0) addParam("output/fps", str(outfps)); + if (outfps != 0.0) + addParam("output/fps", str(outfps)); if (outgamma != 1.0) { @@ -840,12 +839,17 @@ addDefaultParams() addParam("output/transfer", TwkFB::ColorSpace::Gamma()); } - if (outsrgb) addParam("output/transfer", TwkFB::ColorSpace::sRGB()); - if (out709) addParam("output/transfer", TwkFB::ColorSpace::Rec709()); + if (outsrgb) + addParam("output/transfer", TwkFB::ColorSpace::sRGB()); + if (out709) + addParam("output/transfer", TwkFB::ColorSpace::Rec709()); if (outlogc) { - if (outlogcEI == 0) addParam("output/transfer", TwkFB::ColorSpace::ArriLogC()); - else addParam("output/transfer", TwkFB::ColorSpace::ArriLogC() + " EI=" + str(outlogcEI)); + if (outlogcEI == 0) + addParam("output/transfer", TwkFB::ColorSpace::ArriLogC()); + else + addParam("output/transfer", + TwkFB::ColorSpace::ArriLogC() + " EI=" + str(outlogcEI)); } if (outaces) @@ -854,7 +858,8 @@ addDefaultParams() addParam("output/transfer", TwkFB::ColorSpace::Linear()); addParam("output/primaries", TwkFB::ColorSpace::ACES()); // NOTE: these go rX,rY,gX,gY,bX,bY,wX,wY - addParam("output/chromaticities", "0.73470,0.26530,0.0,1.0,0.00010,-0.07700,0.32168,0.33767"); + addParam("output/chromaticities", + "0.73470,0.26530,0.0,1.0,0.00010,-0.07700,0.32168,0.33767"); addParam("output/neutral", "0.32168,0.33767"); } @@ -874,8 +879,10 @@ addDefaultParams() addParam("output/transfer", TwkFB::ColorSpace::RedLogFilm()); } - if (outpremult) addParam("output/alpha", "PREMULT"); - else if (outunpremult) addParam("output/alpha", "UNPREMULT"); + if (outpremult) + addParam("output/alpha", "PREMULT"); + else if (outunpremult) + addParam("output/alpha", "UNPREMULT"); if (paNumerator) { @@ -888,8 +895,7 @@ addDefaultParams() } } -bool -parsePA() +bool parsePA() { string pa = paRatio; @@ -905,12 +911,16 @@ parsePA() for (size_t i = 0; i < pa.size(); i++) { char c = pa[i]; - if (c != ':' && c != '.' && (c < '0' || c > '9')) return false; - if (c == '.') dots++; - if (c == ':') colons++; + if (c != ':' && c != '.' && (c < '0' || c > '9')) + return false; + if (c == '.') + dots++; + if (c == ':') + colons++; } - if (dots != 0 && colons != 0) return false; + if (dots != 0 && colons != 0) + return false; // // pull it apart if needed @@ -920,7 +930,7 @@ parsePA() { string::size_type i = pa.find(':'); paNumerator = atoi(pa.substr(0, i).c_str()); - paDenominator = atoi(pa.substr(i+1, pa.size() - i).c_str()); + paDenominator = atoi(pa.substr(i + 1, pa.size() - i).c_str()); } else { @@ -933,13 +943,12 @@ parsePA() return true; } -void -writeSession(string outfile) +void writeSession(string outfile) { if (!(overlayArgs.empty() && leaderArgs.empty())) { - cerr << "WARNING: \"-overlay\" and \"-leader\" " << - "ignored when outputting session" << endl; + cerr << "WARNING: \"-overlay\" and \"-leader\" " + << "ignored when outputting session" << endl; } MovieRV* reader = makeInputMovie(); @@ -969,8 +978,7 @@ void setEnvVar(const string& var, const string& val) //---------------------------------------------------------------------- -int -utf8Main(int argc, char *argv[]) +int utf8Main(int argc, char* argv[]) { setEnvVar("LANG", "C"); setEnvVar("LC_ALL", "C"); @@ -983,46 +991,51 @@ utf8Main(int argc, char *argv[]) // #ifdef RVIO_HW - TwkGLF::FBOVideoDevice* dummyDev = new TwkGLF::FBOVideoDevice(0, 10, 10, false); + TwkGLF::FBOVideoDevice* dummyDev = + new TwkGLF::FBOVideoDevice(0, 10, 10, false); #else - TwkGLF::OSMesaVideoDevice* dummyDev = new TwkGLF::OSMesaVideoDevice(0, 10, 10, true); + TwkGLF::OSMesaVideoDevice* dummyDev = + new TwkGLF::OSMesaVideoDevice(0, 10, 10, true); FrameBuffer* dummyFB = new FrameBuffer(10, 10, 4, FrameBuffer::FLOAT); dummyDev->makeCurrent(dummyFB); #endif IPCore::ImageRenderer::queryGL(); - const char* glVersion =(const char*)glGetString(GL_SHADING_LANGUAGE_VERSION); + const char* glVersion = + (const char*)glGetString(GL_SHADING_LANGUAGE_VERSION); IPCore::Shader::Function::useShadingLanguageVersion(glVersion); - #ifndef PLATFORM_WINDOWS - // - // Check the per-process limit on open file descriptors and - // reset the soft limit to the hard limit. - // - struct rlimit rlim; - getrlimit (RLIMIT_NOFILE, &rlim); - rlim.rlim_cur = rlim.rlim_max; - setrlimit (RLIMIT_NOFILE, &rlim); - #endif +#ifndef PLATFORM_WINDOWS + // + // Check the per-process limit on open file descriptors and + // reset the soft limit to the hard limit. + // + struct rlimit rlim; + getrlimit(RLIMIT_NOFILE, &rlim); + rlim.rlim_cur = rlim.rlim_max; + setrlimit(RLIMIT_NOFILE, &rlim); +#endif #ifdef PTW32_STATIC_LIB pthread_win32_process_attach_np(); pthread_win32_process_attach_np(); #endif - #ifdef PLATFORM_DARWIN QCoreApplication qapp(argc, argv); - TwkApp::DarwinBundle bundle("RV", MAJOR_VERSION, MINOR_VERSION, REVISION_NUMBER); + TwkApp::DarwinBundle bundle("RV", MAJOR_VERSION, MINOR_VERSION, + REVISION_NUMBER); #endif #ifdef PLATFORM_LINUX QCoreApplication qapp(argc, argv); - TwkApp::QTBundle bundle("rv", MAJOR_VERSION, MINOR_VERSION, REVISION_NUMBER); + TwkApp::QTBundle bundle("rv", MAJOR_VERSION, MINOR_VERSION, + REVISION_NUMBER); #endif #ifdef PLATFORM_WINDOWS QApplication qapp(argc, argv); - TwkApp::QTBundle bundle("rv", MAJOR_VERSION, MINOR_VERSION, REVISION_NUMBER); + TwkApp::QTBundle bundle("rv", MAJOR_VERSION, MINOR_VERSION, + REVISION_NUMBER); #endif Rv::Options& opts = Rv::Options::sharedOptions(); @@ -1033,8 +1046,9 @@ utf8Main(int argc, char *argv[]) Imf::staticInitialize(); IPCore::Application::cacheEnvVars(); - TwkFB::GenericIO::init(); // Initialize TwkFB::GenericIO plugins statics - TwkMovie::GenericIO::init(); // Initialize TwkMovie::GenericIO plugins statics + TwkFB::GenericIO::init(); // Initialize TwkFB::GenericIO plugins statics + TwkMovie::GenericIO::init(); // Initialize TwkMovie::GenericIO plugins + // statics IPCore::AudioRenderer::setNoAudio(true); @@ -1046,11 +1060,8 @@ utf8Main(int argc, char *argv[]) // Call the deploy functions // - TWK_DEPLOY_APP_OBJECT dobj(MAJOR_VERSION, - MINOR_VERSION, - REVISION_NUMBER, - argc, argv, - RELEASE_DESCRIPTION, + TWK_DEPLOY_APP_OBJECT dobj(MAJOR_VERSION, MINOR_VERSION, REVISION_NUMBER, + argc, argv, RELEASE_DESCRIPTION, "HEAD=" GIT_HEAD); // @@ -1059,27 +1070,27 @@ utf8Main(int argc, char *argv[]) int sleepTime = 0; - opts.exrInherit = 0; - opts.exrNoOneChannel = 0; + opts.exrInherit = 0; + opts.exrNoOneChannel = 0; opts.exrReadWindowIsDisplayWindow = 0; - opts.exrReadWindow = 1; // DisplayWindow - opts.dpxPixel = (char*)"A2_BGR10"; - opts.cinPixel = (char*)"A2_BGR10"; + opts.exrReadWindow = 1; // DisplayWindow + opts.dpxPixel = (char*)"A2_BGR10"; + opts.cinPixel = (char*)"A2_BGR10"; #ifdef PLATFORM_WINDOWS - opts.exrIOMethod = 2; - opts.dpxIOMethod = 2; - opts.cinIOMethod = 2; - opts.tgaIOMethod = 2; - opts.jpegIOMethod = 2; - opts.tiffIOMethod = 2; + opts.exrIOMethod = 2; + opts.dpxIOMethod = 2; + opts.cinIOMethod = 2; + opts.tgaIOMethod = 2; + opts.jpegIOMethod = 2; + opts.tiffIOMethod = 2; #else - opts.exrIOMethod = 2; - opts.dpxIOMethod = 2; - opts.cinIOMethod = 2; - opts.tgaIOMethod = 2; - opts.jpegIOMethod = 2; - opts.tiffIOMethod = 2; + opts.exrIOMethod = 2; + opts.dpxIOMethod = 2; + opts.cinIOMethod = 2; + opts.tgaIOMethod = 2; + opts.jpegIOMethod = 2; + opts.tiffIOMethod = 2; #endif // @@ -1099,181 +1110,329 @@ utf8Main(int argc, char *argv[]) // Parse cmd line args // - if (arg_parse - (argc, argv, - "", "\nUsage: RVIO (hardware version) movie and image sequence conversion and creation", - "", "", - "", " Make Movie: rvio in.#.tif -o out.mov", - "", " Convert Image: rvio in.tif -o out.jpg", - "", " Convert Image Seq.: rvio in.#.tif -o out.#.jpg", - "", " Movie With Audio: rvio [ in.#.tif in.wav ] -o out.mov", - "", " Movie With LUT: rvio [ -llut log2film.csp in.#.dpx ] -o out.mov", - "", " Rip Movie Range #1: rvio in.mov -t 1000-1200 -o out.mov", - "", " Rip Movie Range #2: rvio in.mov -t 1000-1200 -o out.#.jpg", - "", " Rip Movie Audio: rvio in.mov -o out.wav", - "", " Conform Image: rvio in.tif -outres 512 512 -o out.tif", - "", " Resize Image: rvio in.#.tif -scale 0.25 -o out.#.jpg", - "", " Resize/Stretch: rvio in.#.tif -resize 640 480 -o out.#.jpg", - "", " Resize Keep Aspect: rvio in.#.tif -resize 1920 0 -o out.#.jpg", - "", " Resize Keep Aspt #2: rvio in.#.tif -resize 0 1080 -o out.#.jpg", - "", " Sequence: rvio cut1.#.tif cut2.mov cut3.1-100#.dpx -o out.mov", - "", " Per-Source Arg: rvio [ -pa 2.0 -fps 30 cut1.#.dpx ] cut2.mov -o out.mov", - "", " Stereo Movie File: rvio [ left.mov right.mov ] -outstereo separate -o out.mov", - "", " Stereo Anaglyph: rvio [ left.mov right.mov ] -outstereo anaglyph -o out.mov", - "", " Log Cin/DPX to Movie: rvio -inlog -outsrgb in.#.cin -o out.mov", - "", " Output Log Cin/DPX: rvio -outlog in.#.exr -o out.#.dpx", - "", " OpenEXR 16 Bit Out: rvio in.#.dpx -outhalf -o out.#.exr", - "", " OpenEXR to 8 Bit: rvio in.#.exr -out8 -o out.#.tif", - "", " OpenEXR B44 4:2:0: rvio in.#.exr -outhalf -yryby 1 2 2 -codec B44 -o out.#.exr", - "", " OpenEXR B44A 4:2:0: rvio in.#.exr -outhalf -yrybya 1 2 2 1 -codec B44A -o out.#.exr", - "", " OpenEXR DWAA 4:2:0: rvio in.#.exr -outhalf -yryby 1 2 2 -quality 45 -codec DWAA -o out.#.exr", - "", " OpenEXR DWAB 4:2:0: rvio in.#.exr -outhalf -yrybya 1 2 2 1 -quality 45 -codec DWAB -o out.#.exr", - "", " ACES from PD DPX: rvio in.#.dpx -inlog -outhalf -outaces out.#.aces", - "", " ACES from JPEG: rvio in.#.jpg -insrgb -outhalf -outaces out.#.aces", - "", " Chng White to D75: rvio in.#.exr -outillum D75 -outhalf -o out.#.exr", - "", " Chng White to D75 #2: rvio in.#.exr -outwhite 0.29902 0.31485 -outhalf -o out.#.exr", - "", " TIFF 32 Bit Float: rvio in.#.tif -outformat 32 float -o out.#.tif", - "", " Anamorphic Unsqueeze: rvio [ -pa 2.0 in_2k_full_ap.#.dpx ] -outres 2048 1556/2 -o out_2k.mov", - "", " Camera JPEG to EXR: rvio -insrgb IMG1234.jpg -o out.exr", - "", " Letterbox HD in 1.33: rvio [ -uncrop 1920 1444 0 182 in1080.#.dpx ] -outres 640 480 -o out.mov", - "", " Crop 2.35 of Full Ap: rvio [ -crop 0 342 2047 1213 inFullAp.#.dpx ] -o out.mov", - "", " Multiple CPUs: rvio -v -rthreads 3 in.#.dpx -o out.mov", - "", " Test Throughput: rvio -v in.#.dpx -o out.null", - "", "", - "", "Advanced EXR/ACES Header Attributes Usage:", - "", " Multiple -outparam values can be used.", - "", " Type names: f, i, s, sv -- float, int, string, string vector [N values]", - "", " v2i, v2f, v3i, v3f -- 2D and 3D int and float vectors [2 or 3 values required]", - "", " b2i, b2f -- 2D box float and int [4 values required]", - "", " c -- chromaticities [8 values required]", - "", " Passthrough syntax: -outparams passthrough=REGEX", - "", " Attr creation syntax: -outparams NAME:TYPE=VALUE0[,VALUE1,...]\"", - "", " EXIF attrs: rvio exif.jpg -insrgb -o out.exr -outparams \"passthrough=.*EXIF.*\"", - "", " Create float attr: rvio in.exr -o out.exr -outparams pi:f=3.14", - "", " Create v2i attr: rvio in.exr -o out.exr -outparams myV2iAttr:v2i=1,2", - "", " Create string attr: rvio in.exr -o out.exr -outparams \"myAttr:s=HELLO WORLD\"", - "", " Chromaticies (XYZ): rvio XYZ.tiff -o out.exr -outparams chromaticities:c=1,0,0,1,0,0,.333333,.3333333", - "", " No Color Adaptation: rvio in.exr -o out.aces -outaces -outillum D65REC709", - "", "", - "", "Example Leader/Overlay Usage:", - "", " simpleslate: side-text Field1=Value1 Field2=Value2 ...", - "", " watermark: text opacity", - "", " frameburn: opacity grey font-point-size", - "", " bug: file.tif opacity height", - "", " matte: aspect-ratio opacity", - "", "", - "", " Movie w/Slate: rvio in.#.jpg -o out.mov -leader simpleslate \"FilmCo\" \\", - "", " \"Artist=Jane Q. Artiste\" \"Shot=S01\" \"Show=BlockBuster\" \\", - "", " \"Comments=You said it was too blue so I made it red\"", - "", " Movie w/Watermark: rvio in.#.jpg -o out.mov -overlay watermark \"FilmCo Eyes Only\" .25", - "", " Movie w/Frame Burn: rvio in.#.jpg -o out.mov -overlay frameburn .4 1.0 30.0", - "", " Movie w/Bug: rvio in.#.jpg -o out.mov -overlay bug logo.tif 0.4 128 15 100", - "", " Movie w/Matte: rvio in.#.jpg -o out.mov -overlay matte 2.35 0.8", - "", " Multiple: rvio ... -leader ... -overlay ... -overlay ...", - "", "", - RV_ARG_SEQUENCE_HELP, - "", "", - RV_ARG_SOURCE_OPTIONS(opts), - "", "", - "", "Global arguments", - "", "", - "", ARG_SUBR(parseInFiles), "Input sequence patterns, images, movies, or directories ", - "-o %S", &outputFile, "Output sequence or image", - "-t %S", &timerange, "Output time range (default=input time range)", - "-tio", ARG_FLAG(&tio), "Output time range from view's in/out points", - "-v", ARG_FLAG(&verbose), "Verbose messages", - "-vv", ARG_FLAG(&reallyverbose), "Really Verbose messages", - "-q", ARG_FLAG(&processFloat), "Best quality color conversions (not necessary, slower)", - "-ns", ARG_FLAG(&opts.nukeSequence), "Nuke-style sequences (deprecated and ignored -- no longer needed)", - "-noRanges", ARG_FLAG(&opts.noRanges), "No separate frame ranges (i.e. 1-10 will be considered a file)", \ - "-rthreads %d", &threads, "Number of reader/render threads (default=1)", - "-wthreads %d", &wthreads, "Number of writer threads (limited support for this)", - "-view %S", &view, "View to render (default=defaultSequence or current view in RV file)", - "-noSequence", ARG_FLAG(&opts.noSequence), "Don't contract files into sequences", \ - "-formats", ARG_FLAG(&showFormats), "Show all supported image and movie formats", - "-leader", ARG_SUBR(parseLeader), "Insert leader/slate (can use multiple time)", - "-leaderframes %d", &leaderFrames, "Number of leader frames (default=1)", - "-overlay", ARG_SUBR(parseOverlay), "Visual overlay(s) (can use multiple times)", - "-inlog", ARG_FLAG(&loglin), "Convert input to linear space via Cineon Log->Lin", - "-inredlog", ARG_FLAG(&redloglin), "Convert input to linear space via Red Log->Lin", - "-inredlogfilm", ARG_FLAG(&redlogfilmlin), "Convert input to linear space via Red Log Film->Lin", - "-insrgb", ARG_FLAG(&insrgb), "Convert input to linear space from sRGB space", - "-in709", ARG_FLAG(&in709), "Convert input to linear space from Rec-709 space", - "-ingamma %f", &ingamma, "Convert input using gamma correction", - "-filegamma %f", &filegamma, "Convert input using gamma correction to linear space", - "-inchannelmap", ARG_SUBR(parseInChannels), "map input channels", - "-inpremult", ARG_FLAG(&inpremult), "premultiply alpha and color", - "-inunpremult", ARG_FLAG(&inunpremult), "un-premultiply alpha and color", - "-exposure %f", &exposure, "Apply relative exposure change (in stops)", - "-scale %f", &scale, "Scale input image geometry", - "-resize %d [%d]", &resizex, &resizey, "Resize input image geometry to exact size on input", -// "-resampleMethod %S", &resampleMethod, "Resampling method (area, linear, cubic, nearest, default=%s)", resampleMethod, - "-dlut %S", &dlut, "Apply display LUT", - "-flip", ARG_FLAG(&flipImage), "Flip image (flip vertical) (keep orientation flags the same)", - "-flop", ARG_FLAG(&flopImage), "Flop image (flip horizontal) (keep orientation flags the same)", - "-yryby %d %d %d", &ysamples, &rysamples, &bysamples, "Y RY BY sub-sampled planar output", - "-yrybya %d %d %d %d", &ysamples, &rysamples, &bysamples, &asamples, "Y RY BY A sub-sampled planar output", - "-yuv %d %d %d", &ysamples, &usamples, &vsamples, "Y U V sub-sampled planar output", - "-outparams", ARG_SUBR(&parseOutParams), "Codec specific output parameters", \ - "-outchannelmap", ARG_SUBR(parseOutChannels), "map output channels", - "-outrgb", ARG_FLAG(&outrgb), "same as -outchannelmap R G B", - "-outpremult", ARG_FLAG(&outpremult), "premultiply alpha and color", - "-outunpremult", ARG_FLAG(&outunpremult), "un-premultiply alpha and color", - "-outlog", ARG_FLAG(&linlog), "Convert output to log space via Cineon Lin->Log", - "-outsrgb", ARG_FLAG(&outsrgb), "Convert output to sRGB ColorSpace", - "-out709", ARG_FLAG(&out709), "Convert output to Rec-709 ColorSpace", - "-outredlog", ARG_FLAG(&outredlog), "Convert output to Red Log ColorSpace", - "-outredlogfilm", ARG_FLAG(&outredlogfilm), "Convert output to Red Log Film ColorSpace", - "-outgamma %f", &outgamma, "Apply gamma to output", - "-outstereo", ARG_SUBR(&parseOutStereo), "Output stereo (checker, scanline, anaglyph, left, right, pair, mirror, hsqueezed, vsqueezed, default=separate)", - "-outformat %d %S", &outbits, &outtype, "Output bits and format (e.g. 16 float -or- 8 int)", - "-outhalf", ARG_FLAG(&outhalf), "Same as -outformat 16 float", - "-out8", ARG_FLAG(&out8), "Same as -outformat 8 int", - "-outres %d %d", &xsize, &ysize, "Output resolution", - "-outfps %f", &outfps, "Output FPS", - "-outaces", ARG_FLAG(&outaces), "Output ACES gamut (converts pixels to ACES)", - "-outwhite %f %f", &white0, &white1, "Output white CIE 1931 chromaticity x, y", - "-outillum %S", &illumName, "Output standard illuminant name (A-C, D50, D55, D65, D65REC709, D75 E, F[1-12])", - "-codec %S", &codec, "Output codec (varies with file format)", - "-audiocodec %S", &audioCodec, "Output audio codec (varies with file format)", - "-audiorate %f", &audioRate, "Output audio sample rate (default 48000)", - "-audiochannels %d", &audioChannels, "Output audio channels (default 2)", - "-quality %f", &quality, "Output codec quality 0.0 -> 1.0 (100000 for DWAA/DWAB) (varies w/format and codec default=%g)", quality, - "-outpa %S", &paRatio, "Output pixel aspect ratio (e.g. 1.33 or 16:9, etc. metadata only) default=%s", paRatio, - "-comment %S", &comment, "Ouput comment (movie files, default=\"%s\")", comment, - "-copyright %S", ©right, "Ouput copyright (movie files, default=\"%s\")", copyright, - "-lic %S", &licarg, "Use specific license file (this param is simply ignored for Open RV as it is not required)", - "-debug", ARG_SUBR(&Rv::parseDebugKeyWords), "Debug category", \ - "-version", ARG_FLAG(&showVersion), "Show RVIO version number", - "-iomethod %d [%d]", &iomethod, &iosize, "I/O Method (overrides all) (0=standard, 1=buffered, 2=unbuffered, 3=MemoryMap, 4=AsyncBuffered, 5=AsyncUnbuffered, default=%d) and optional chunk size (default=%d)", iomethod, iosize, \ - "-exrcpus %d", &opts.exrcpus, "EXR thread count (default=%d)", opts.exrcpus, \ - "-exrRGBA", ARG_FLAG(&opts.exrRGBA), "EXR Always read as RGBA (default=false)", \ - "-exrInherit", ARG_FLAG(&opts.exrInherit), "EXR guess channel inheritance (default=false)", \ - "-exrNoOneChannel", ARG_FLAG(&opts.exrNoOneChannel), "EXR never use one channel planar images (default=false)", \ - "-exrIOMethod %d [%d]", &opts.exrIOMethod, &opts.exrIOSize, "EXR I/O Method (0=standard, 1=buffered, 2=unbuffered, 3=MemoryMap, 4=AsyncBuffered, 5=AsyncUnbuffered, default=%d) and optional chunk size (default=%d)", opts.exrIOMethod, opts.exrIOSize, \ - "-exrReadWindowIsDisplayWindow", ARG_FLAG(&opts.exrReadWindowIsDisplayWindow), "EXR read window is display window (default=false)", \ - "-exrReadWindow %d", &opts.exrReadWindow, "EXR Read Window Method (0=Data, 1=Display, 2=Union, 3=Data inside Display, default=%d)", opts.exrReadWindow, \ - "-jpegRGBA", ARG_FLAG(&opts.jpegRGBA), "Make JPEG four channel RGBA on read (default=no, use RGB or YUV)", \ - "-jpegIOMethod %d [%d]", &opts.jpegIOMethod, &opts.jpegIOSize, "JPEG I/O Method (0=standard, 1=buffered, 2=unbuffered, 3=MemoryMap, 4=AsyncBuffered, 5=AsyncUnbuffered, default=%d) and optional chunk size (default=%d)", opts.exrIOMethod, opts.exrIOSize, \ - "-cinpixel %S", &opts.cinPixel, "Cineon pixel storage (default=%s)", opts.cinPixel, \ - "-cinchroma", ARG_FLAG(&opts.cinchroma), "Use Cineon chromaticity values (for default reader only)", \ - "-cinIOMethod %d [%d]", &opts.cinIOMethod, &opts.cinIOSize, "Cineon I/O Method (0=standard, 1=buffered, 2=unbuffered, 3=MemoryMap, 4=AsyncBuffered, 5=AsyncUnbuffered, default=%d) and optional chunk size (default=%d)", opts.cinIOMethod, opts.cinIOSize, \ - "-dpxpixel %S", &opts.dpxPixel, "DPX pixel storage (default=%s)", opts.dpxPixel, \ - "-dpxchroma", ARG_FLAG(&opts.dpxchroma), "Use DPX chromaticity values (for default reader only)", \ - "-dpxIOMethod %d [%d]", &opts.dpxIOMethod, &opts.dpxIOSize, "DPX I/O Method (0=standard, 1=buffered, 2=unbuffered, 3=MemoryMap, 4=AsyncBuffered, 5=AsyncUnbuffered, default=%d) and optional chunk size (default=%d)", opts.dpxIOMethod, opts.dpxIOSize, \ - "-tgaIOMethod %d [%d]", &opts.tgaIOMethod, &opts.tgaIOSize, "TARGA I/O Method (0=standard, 1=buffered, 2=unbuffered, 3=MemoryMap, 4=AsyncBuffered, 5=AsyncUnbuffered, default=%d) and optional chunk size (default=%d)", opts.tgaIOMethod, opts.tgaIOSize, \ - "-tiffIOMethod %d [%d]", &opts.tiffIOMethod, &opts.tiffIOSize, "TIFF I/O Method (0=standard, 1=buffered, 2=unbuffered, 3=MemoryMap, 4=AsyncBuffered, 5=AsyncUnbuffered, default=%d) and optional chunk size (default=%d)", opts.tgaIOMethod, opts.tgaIOSize, \ - "-init %S", &initscript, "Override init script", - "-err-to-out", ARG_FLAG(&err2out), "Output errors to standard output (instead of standard error)", - "-strictlicense", ARG_FLAG(&strictlicense), "Exit rather than consume an RV license if no rvio licenses are available (this param is simply ignored for Open RV as it is not required)", - //"-noprerender", ARG_FLAG(&noprerender), "Turn off prerendering optimization", - "-flags", ARG_SUBR(&Rv::parseMuFlags), "Arbitrary flags (flag, or 'name=value') for Mu", + if (arg_parse( + argc, argv, "", + "\nUsage: RVIO (hardware version) movie and image sequence " + "conversion and creation", + "", "", "", " Make Movie: rvio in.#.tif -o out.mov", "", + " Convert Image: rvio in.tif -o out.jpg", "", + " Convert Image Seq.: rvio in.#.tif -o out.#.jpg", "", + " Movie With Audio: rvio [ in.#.tif in.wav ] -o out.mov", "", + " Movie With LUT: rvio [ -llut log2film.csp in.#.dpx ] -o " + "out.mov", + "", " Rip Movie Range #1: rvio in.mov -t 1000-1200 -o out.mov", + "", " Rip Movie Range #2: rvio in.mov -t 1000-1200 -o out.#.jpg", + "", " Rip Movie Audio: rvio in.mov -o out.wav", "", + " Conform Image: rvio in.tif -outres 512 512 -o out.tif", + "", + " Resize Image: rvio in.#.tif -scale 0.25 -o out.#.jpg", + "", + " Resize/Stretch: rvio in.#.tif -resize 640 480 -o " + "out.#.jpg", + "", + " Resize Keep Aspect: rvio in.#.tif -resize 1920 0 -o out.#.jpg", + "", + " Resize Keep Aspt #2: rvio in.#.tif -resize 0 1080 -o out.#.jpg", + "", + " Sequence: rvio cut1.#.tif cut2.mov cut3.1-100#.dpx " + "-o out.mov", + "", + " Per-Source Arg: rvio [ -pa 2.0 -fps 30 cut1.#.dpx ] " + "cut2.mov -o out.mov", + "", + " Stereo Movie File: rvio [ left.mov right.mov ] -outstereo " + "separate -o out.mov", + "", + " Stereo Anaglyph: rvio [ left.mov right.mov ] -outstereo " + "anaglyph -o out.mov", + "", + " Log Cin/DPX to Movie: rvio -inlog -outsrgb in.#.cin -o out.mov", + "", " Output Log Cin/DPX: rvio -outlog in.#.exr -o out.#.dpx", + "", " OpenEXR 16 Bit Out: rvio in.#.dpx -outhalf -o out.#.exr", + "", " OpenEXR to 8 Bit: rvio in.#.exr -out8 -o out.#.tif", "", + " OpenEXR B44 4:2:0: rvio in.#.exr -outhalf -yryby 1 2 2 " + "-codec B44 -o out.#.exr", + "", + " OpenEXR B44A 4:2:0: rvio in.#.exr -outhalf -yrybya 1 2 2 1 " + "-codec B44A -o out.#.exr", + "", + " OpenEXR DWAA 4:2:0: rvio in.#.exr -outhalf -yryby 1 2 2 " + "-quality 45 -codec DWAA -o out.#.exr", + "", + " OpenEXR DWAB 4:2:0: rvio in.#.exr -outhalf -yrybya 1 2 2 1 " + "-quality 45 -codec DWAB -o out.#.exr", + "", + " ACES from PD DPX: rvio in.#.dpx -inlog -outhalf -outaces " + "out.#.aces", + "", + " ACES from JPEG: rvio in.#.jpg -insrgb -outhalf -outaces " + "out.#.aces", + "", + " Chng White to D75: rvio in.#.exr -outillum D75 -outhalf -o " + "out.#.exr", + "", + " Chng White to D75 #2: rvio in.#.exr -outwhite 0.29902 0.31485 " + "-outhalf -o out.#.exr", + "", + " TIFF 32 Bit Float: rvio in.#.tif -outformat 32 float -o " + "out.#.tif", + "", + " Anamorphic Unsqueeze: rvio [ -pa 2.0 in_2k_full_ap.#.dpx ] " + "-outres 2048 1556/2 -o out_2k.mov", + "", " Camera JPEG to EXR: rvio -insrgb IMG1234.jpg -o out.exr", + "", + " Letterbox HD in 1.33: rvio [ -uncrop 1920 1444 0 182 " + "in1080.#.dpx ] -outres 640 480 -o out.mov", + "", + " Crop 2.35 of Full Ap: rvio [ -crop 0 342 2047 1213 " + "inFullAp.#.dpx ] -o out.mov", + "", + " Multiple CPUs: rvio -v -rthreads 3 in.#.dpx -o out.mov", + "", " Test Throughput: rvio -v in.#.dpx -o out.null", "", "", + "", "Advanced EXR/ACES Header Attributes Usage:", "", + " Multiple -outparam values can be used.", "", + " Type names: f, i, s, sv -- float, int, string, string " + "vector [N values]", + "", + " v2i, v2f, v3i, v3f -- 2D and 3D int and float " + "vectors [2 or 3 values required]", + "", + " b2i, b2f -- 2D box float and int [4 " + "values required]", + "", + " c -- chromaticities [8 values " + "required]", + "", " Passthrough syntax: -outparams passthrough=REGEX", "", + " Attr creation syntax: -outparams " + "NAME:TYPE=VALUE0[,VALUE1,...]\"", + "", + " EXIF attrs: rvio exif.jpg -insrgb -o out.exr " + "-outparams \"passthrough=.*EXIF.*\"", + "", + " Create float attr: rvio in.exr -o out.exr -outparams " + "pi:f=3.14", + "", + " Create v2i attr: rvio in.exr -o out.exr -outparams " + "myV2iAttr:v2i=1,2", + "", + " Create string attr: rvio in.exr -o out.exr -outparams " + "\"myAttr:s=HELLO WORLD\"", + "", + " Chromaticies (XYZ): rvio XYZ.tiff -o out.exr -outparams " + "chromaticities:c=1,0,0,1,0,0,.333333,.3333333", + "", + " No Color Adaptation: rvio in.exr -o out.aces -outaces " + "-outillum D65REC709", + "", "", "", "Example Leader/Overlay Usage:", "", + " simpleslate: side-text Field1=Value1 Field2=Value2 ...", + "", " watermark: text opacity", "", + " frameburn: opacity grey font-point-size", "", + " bug: file.tif opacity height", "", + " matte: aspect-ratio opacity", "", "", "", + " Movie w/Slate: rvio in.#.jpg -o out.mov -leader " + "simpleslate \"FilmCo\" \\", + "", + " \"Artist=Jane Q. Artiste\" " + "\"Shot=S01\" \"Show=BlockBuster\" \\", + "", + " \"Comments=You said it was too blue " + "so I made it red\"", + "", + " Movie w/Watermark: rvio in.#.jpg -o out.mov -overlay " + "watermark \"FilmCo Eyes Only\" .25", + "", + " Movie w/Frame Burn: rvio in.#.jpg -o out.mov -overlay " + "frameburn .4 1.0 30.0", + "", + " Movie w/Bug: rvio in.#.jpg -o out.mov -overlay bug " + "logo.tif 0.4 128 15 100", + "", + " Movie w/Matte: rvio in.#.jpg -o out.mov -overlay matte " + "2.35 0.8", + "", + " Multiple: rvio ... -leader ... -overlay ... " + "-overlay ...", + "", "", RV_ARG_SEQUENCE_HELP, "", "", RV_ARG_SOURCE_OPTIONS(opts), + "", "", "", "Global arguments", "", "", "", ARG_SUBR(parseInFiles), + "Input sequence patterns, images, movies, or directories ", "-o %S", + &outputFile, "Output sequence or image", "-t %S", &timerange, + "Output time range (default=input time range)", "-tio", + ARG_FLAG(&tio), "Output time range from view's in/out points", "-v", + ARG_FLAG(&verbose), "Verbose messages", "-vv", + ARG_FLAG(&reallyverbose), "Really Verbose messages", "-q", + ARG_FLAG(&processFloat), + "Best quality color conversions (not necessary, slower)", "-ns", + ARG_FLAG(&opts.nukeSequence), + "Nuke-style sequences (deprecated and ignored -- no longer needed)", + "-noRanges", ARG_FLAG(&opts.noRanges), + "No separate frame ranges (i.e. 1-10 will be considered a file)", + "-rthreads %d", &threads, + "Number of reader/render threads (default=1)", "-wthreads %d", + &wthreads, "Number of writer threads (limited support for this)", + "-view %S", &view, + "View to render (default=defaultSequence or current view in RV " + "file)", + "-noSequence", ARG_FLAG(&opts.noSequence), + "Don't contract files into sequences", "-formats", + ARG_FLAG(&showFormats), + "Show all supported image and movie formats", "-leader", + ARG_SUBR(parseLeader), + "Insert leader/slate (can use multiple time)", "-leaderframes %d", + &leaderFrames, "Number of leader frames (default=1)", "-overlay", + ARG_SUBR(parseOverlay), + "Visual overlay(s) (can use multiple times)", "-inlog", + ARG_FLAG(&loglin), + "Convert input to linear space via Cineon Log->Lin", "-inredlog", + ARG_FLAG(&redloglin), + "Convert input to linear space via Red Log->Lin", "-inredlogfilm", + ARG_FLAG(&redlogfilmlin), + "Convert input to linear space via Red Log Film->Lin", "-insrgb", + ARG_FLAG(&insrgb), "Convert input to linear space from sRGB space", + "-in709", ARG_FLAG(&in709), + "Convert input to linear space from Rec-709 space", "-ingamma %f", + &ingamma, "Convert input using gamma correction", "-filegamma %f", + &filegamma, "Convert input using gamma correction to linear space", + "-inchannelmap", ARG_SUBR(parseInChannels), "map input channels", + "-inpremult", ARG_FLAG(&inpremult), "premultiply alpha and color", + "-inunpremult", ARG_FLAG(&inunpremult), + "un-premultiply alpha and color", "-exposure %f", &exposure, + "Apply relative exposure change (in stops)", "-scale %f", &scale, + "Scale input image geometry", "-resize %d [%d]", &resizex, &resizey, + "Resize input image geometry to exact size on input", + // "-resampleMethod %S", &resampleMethod, "Resampling method + // (area, linear, cubic, nearest, default=%s)", + // resampleMethod, + "-dlut %S", &dlut, "Apply display LUT", "-flip", + ARG_FLAG(&flipImage), + "Flip image (flip vertical) (keep orientation flags the same)", + "-flop", ARG_FLAG(&flopImage), + "Flop image (flip horizontal) (keep orientation flags the same)", + "-yryby %d %d %d", &ysamples, &rysamples, &bysamples, + "Y RY BY sub-sampled planar output", "-yrybya %d %d %d %d", + &ysamples, &rysamples, &bysamples, &asamples, + "Y RY BY A sub-sampled planar output", "-yuv %d %d %d", &ysamples, + &usamples, &vsamples, "Y U V sub-sampled planar output", + "-outparams", ARG_SUBR(&parseOutParams), + "Codec specific output parameters", "-outchannelmap", + ARG_SUBR(parseOutChannels), "map output channels", "-outrgb", + ARG_FLAG(&outrgb), "same as -outchannelmap R G B", "-outpremult", + ARG_FLAG(&outpremult), "premultiply alpha and color", + "-outunpremult", ARG_FLAG(&outunpremult), + "un-premultiply alpha and color", "-outlog", ARG_FLAG(&linlog), + "Convert output to log space via Cineon Lin->Log", "-outsrgb", + ARG_FLAG(&outsrgb), "Convert output to sRGB ColorSpace", "-out709", + ARG_FLAG(&out709), "Convert output to Rec-709 ColorSpace", + "-outredlog", ARG_FLAG(&outredlog), + "Convert output to Red Log ColorSpace", "-outredlogfilm", + ARG_FLAG(&outredlogfilm), + "Convert output to Red Log Film ColorSpace", "-outgamma %f", + &outgamma, "Apply gamma to output", "-outstereo", + ARG_SUBR(&parseOutStereo), + "Output stereo (checker, scanline, anaglyph, left, right, pair, " + "mirror, hsqueezed, vsqueezed, default=separate)", + "-outformat %d %S", &outbits, &outtype, + "Output bits and format (e.g. 16 float -or- 8 int)", "-outhalf", + ARG_FLAG(&outhalf), "Same as -outformat 16 float", "-out8", + ARG_FLAG(&out8), "Same as -outformat 8 int", "-outres %d %d", + &xsize, &ysize, "Output resolution", "-outfps %f", &outfps, + "Output FPS", "-outaces", ARG_FLAG(&outaces), + "Output ACES gamut (converts pixels to ACES)", "-outwhite %f %f", + &white0, &white1, "Output white CIE 1931 chromaticity x, y", + "-outillum %S", &illumName, + "Output standard illuminant name (A-C, D50, D55, D65, D65REC709, " + "D75 E, F[1-12])", + "-codec %S", &codec, "Output codec (varies with file format)", + "-audiocodec %S", &audioCodec, + "Output audio codec (varies with file format)", "-audiorate %f", + &audioRate, "Output audio sample rate (default 48000)", + "-audiochannels %d", &audioChannels, + "Output audio channels (default 2)", "-quality %f", &quality, + "Output codec quality 0.0 -> 1.0 (100000 for DWAA/DWAB) (varies " + "w/format and codec default=%g)", + quality, "-outpa %S", &paRatio, + "Output pixel aspect ratio (e.g. 1.33 or 16:9, etc. metadata only) " + "default=%s", + paRatio, "-comment %S", &comment, + "Ouput comment (movie files, default=\"%s\")", comment, + "-copyright %S", ©right, + "Ouput copyright (movie files, default=\"%s\")", copyright, + "-lic %S", &licarg, + "Use specific license file (this param is simply ignored for Open " + "RV as it is not required)", + "-debug", ARG_SUBR(&Rv::parseDebugKeyWords), "Debug category", + "-version", ARG_FLAG(&showVersion), "Show RVIO version number", + "-iomethod %d [%d]", &iomethod, &iosize, + "I/O Method (overrides all) (0=standard, 1=buffered, 2=unbuffered, " + "3=MemoryMap, 4=AsyncBuffered, 5=AsyncUnbuffered, default=%d) and " + "optional chunk size (default=%d)", + iomethod, iosize, "-exrcpus %d", &opts.exrcpus, + "EXR thread count (default=%d)", opts.exrcpus, "-exrRGBA", + ARG_FLAG(&opts.exrRGBA), "EXR Always read as RGBA (default=false)", + "-exrInherit", ARG_FLAG(&opts.exrInherit), + "EXR guess channel inheritance (default=false)", "-exrNoOneChannel", + ARG_FLAG(&opts.exrNoOneChannel), + "EXR never use one channel planar images (default=false)", + "-exrIOMethod %d [%d]", &opts.exrIOMethod, &opts.exrIOSize, + "EXR I/O Method (0=standard, 1=buffered, 2=unbuffered, " + "3=MemoryMap, 4=AsyncBuffered, 5=AsyncUnbuffered, default=%d) and " + "optional chunk size (default=%d)", + opts.exrIOMethod, opts.exrIOSize, "-exrReadWindowIsDisplayWindow", + ARG_FLAG(&opts.exrReadWindowIsDisplayWindow), + "EXR read window is display window (default=false)", + "-exrReadWindow %d", &opts.exrReadWindow, + "EXR Read Window Method (0=Data, 1=Display, 2=Union, 3=Data inside " + "Display, default=%d)", + opts.exrReadWindow, "-jpegRGBA", ARG_FLAG(&opts.jpegRGBA), + "Make JPEG four channel RGBA on read (default=no, use RGB or YUV)", + "-jpegIOMethod %d [%d]", &opts.jpegIOMethod, &opts.jpegIOSize, + "JPEG I/O Method (0=standard, 1=buffered, 2=unbuffered, " + "3=MemoryMap, 4=AsyncBuffered, 5=AsyncUnbuffered, default=%d) and " + "optional chunk size (default=%d)", + opts.exrIOMethod, opts.exrIOSize, "-cinpixel %S", &opts.cinPixel, + "Cineon pixel storage (default=%s)", opts.cinPixel, "-cinchroma", + ARG_FLAG(&opts.cinchroma), + "Use Cineon chromaticity values (for default reader only)", + "-cinIOMethod %d [%d]", &opts.cinIOMethod, &opts.cinIOSize, + "Cineon I/O Method (0=standard, 1=buffered, 2=unbuffered, " + "3=MemoryMap, 4=AsyncBuffered, 5=AsyncUnbuffered, default=%d) and " + "optional chunk size (default=%d)", + opts.cinIOMethod, opts.cinIOSize, "-dpxpixel %S", &opts.dpxPixel, + "DPX pixel storage (default=%s)", opts.dpxPixel, "-dpxchroma", + ARG_FLAG(&opts.dpxchroma), + "Use DPX chromaticity values (for default reader only)", + "-dpxIOMethod %d [%d]", &opts.dpxIOMethod, &opts.dpxIOSize, + "DPX I/O Method (0=standard, 1=buffered, 2=unbuffered, " + "3=MemoryMap, 4=AsyncBuffered, 5=AsyncUnbuffered, default=%d) and " + "optional chunk size (default=%d)", + opts.dpxIOMethod, opts.dpxIOSize, "-tgaIOMethod %d [%d]", + &opts.tgaIOMethod, &opts.tgaIOSize, + "TARGA I/O Method (0=standard, 1=buffered, 2=unbuffered, " + "3=MemoryMap, 4=AsyncBuffered, 5=AsyncUnbuffered, default=%d) and " + "optional chunk size (default=%d)", + opts.tgaIOMethod, opts.tgaIOSize, "-tiffIOMethod %d [%d]", + &opts.tiffIOMethod, &opts.tiffIOSize, + "TIFF I/O Method (0=standard, 1=buffered, 2=unbuffered, " + "3=MemoryMap, 4=AsyncBuffered, 5=AsyncUnbuffered, default=%d) and " + "optional chunk size (default=%d)", + opts.tgaIOMethod, opts.tgaIOSize, "-init %S", &initscript, + "Override init script", "-err-to-out", ARG_FLAG(&err2out), + "Output errors to standard output (instead of standard error)", + "-strictlicense", ARG_FLAG(&strictlicense), + "Exit rather than consume an RV license if no rvio licenses are " + "available (this param is simply ignored for Open RV as it is not " + "required)", + //"-noprerender", ARG_FLAG(&noprerender), "Turn off prerendering + // optimization", + "-flags", ARG_SUBR(&Rv::parseMuFlags), + "Arbitrary flags (flag, or 'name=value') for Mu", #if defined(PLATFORM_WINDOWS) && !defined(NDEBUG) - "-sleep %d", &sleepTime, "Sleep (in seconds) before starting to allow attaching debugger", + "-sleep %d", &sleepTime, + "Sleep (in seconds) before starting to allow attaching debugger", #endif - NULL) < 0) + NULL) + < 0) { - exit(-1); + exit(-1); } TwkMovie::MovieWriter::setReallyVerbose(reallyverbose); @@ -1283,7 +1442,8 @@ utf8Main(int argc, char *argv[]) // of reader threads. // - if (wthreads == -1) wthreads = threads; + if (wthreads == -1) + wthreads = threads; opts.delaySessionLoading = 0; @@ -1304,18 +1464,18 @@ utf8Main(int argc, char *argv[]) // iomethod overrides all specific iomethods for backwards compat // - opts.exrIOMethod = iomethod; - opts.dpxIOMethod = iomethod; - opts.cinIOMethod = iomethod; - opts.tgaIOMethod = iomethod; + opts.exrIOMethod = iomethod; + opts.dpxIOMethod = iomethod; + opts.cinIOMethod = iomethod; + opts.tgaIOMethod = iomethod; opts.jpegIOMethod = iomethod; opts.tiffIOMethod = iomethod; - opts.exrIOSize = iosize; - opts.dpxIOSize = iosize; - opts.cinIOSize = iosize; - opts.tgaIOSize = iosize; - opts.jpegIOSize = iosize; - opts.tiffIOSize = iosize; + opts.exrIOSize = iosize; + opts.dpxIOSize = iosize; + opts.cinIOSize = iosize; + opts.tgaIOSize = iosize; + opts.jpegIOSize = iosize; + opts.tiffIOSize = iosize; } opts.exportIOEnvVars(); @@ -1351,12 +1511,13 @@ utf8Main(int argc, char *argv[]) addDefaultParams(); - if (const char *envParams = getenv("RVIO_OUTPARAMS")) + if (const char* envParams = getenv("RVIO_OUTPARAMS")) { string s(envParams); vector params; stl_ext::tokenize(params, s, " "); - for (int i = 0; i < params.size(); ++i) parseParam(params[i]); + for (int i = 0; i < params.size(); ++i) + parseParam(params[i]); } if (!opts.initializeAfterParsing(0)) @@ -1374,20 +1535,29 @@ utf8Main(int argc, char *argv[]) nosession = 0; - if (err2out) cerr.rdbuf(cout.rdbuf()); + if (err2out) + cerr.rdbuf(cout.rdbuf()); if (showVersion) { - cout << MAJOR_VERSION << "." - << MINOR_VERSION << "." - << REVISION_NUMBER << endl; + cout << MAJOR_VERSION << "." << MINOR_VERSION << "." << REVISION_NUMBER + << endl; exit(0); } - if (outhalf) { outbits = 16; outtype = (char*)"float"; } - if (out8) { outbits = 8; outtype = (char*)"int"; } - if (reallyverbose) verbose = 1; + if (outhalf) + { + outbits = 16; + outtype = (char*)"float"; + } + if (out8) + { + outbits = 8; + outtype = (char*)"int"; + } + if (reallyverbose) + verbose = 1; if (outrgb) { @@ -1415,12 +1585,13 @@ utf8Main(int argc, char *argv[]) // Get CPU info and tell the EXR library to use them all // - - if (opts.exrcpus > 1) Imf::setGlobalThreadCount(opts.exrcpus); + if (opts.exrcpus > 1) + Imf::setGlobalThreadCount(opts.exrcpus); string initPath = bundle.rcfile("rviorc", "mu", "RVIO_INIT"); bundle.addPathToEnvVar("OIIO_LIBRARY_PATH", bundle.appPluginPath("OIIO")); - if (initscript) initPath = initscript; + if (initscript) + initPath = initscript; // RVIO third party optional customization #if defined(RVIO_THIRD_PARTY_CUSTOMIZATION) @@ -1434,7 +1605,8 @@ utf8Main(int argc, char *argv[]) } catch (...) { - cerr << "WARNING: a problem occured while loading image plugins." << endl; + cerr << "WARNING: a problem occured while loading image plugins." + << endl; cerr << " some plugins may not have been loaded." << endl; } @@ -1462,10 +1634,10 @@ utf8Main(int argc, char *argv[]) RVIO::initUICommands(TwkApp::muContext()); Rv::initCommands(TwkApp::muContext()); } - catch (const exception &e) + catch (const exception& e) { cerr << "ERROR: during initialization: " << e.what() << endl; - exit( -1 ); + exit(-1); } #ifndef PLATFORM_WINDOWS @@ -1502,7 +1674,7 @@ utf8Main(int argc, char *argv[]) // Mu::MuLangContext* context = TwkApp::muContext(); - Mu::Process* process = TwkApp::muProcess(); + Mu::Process* process = TwkApp::muProcess(); TwkUtil::setThreadName("RVIO Main"); @@ -1522,23 +1694,22 @@ utf8Main(int argc, char *argv[]) FrameBufferIO::ReadRequest readRequest; MovieWriter::WriteRequest writeRequest; - writeRequest.threads = wthreads; - writeRequest.fps = outfps; - writeRequest.compression = codec; - writeRequest.codec = codec; - writeRequest.audioCodec = audioCodec; - writeRequest.quality = quality; - writeRequest.pixelAspect = pixelAspect; - writeRequest.verbose = verbose; - writeRequest.audioChannels = audioChannels; - writeRequest.audioRate = audioRate; - writeRequest.stereo = !strcmp(outStereo, "separate"); - writeRequest.comments = comment; - writeRequest.copyright = copyright; - writeRequest.args = writerArgs; - - copy(outparams.begin(), - outparams.end(), + writeRequest.threads = wthreads; + writeRequest.fps = outfps; + writeRequest.compression = codec; + writeRequest.codec = codec; + writeRequest.audioCodec = audioCodec; + writeRequest.quality = quality; + writeRequest.pixelAspect = pixelAspect; + writeRequest.verbose = verbose; + writeRequest.audioChannels = audioChannels; + writeRequest.audioRate = audioRate; + writeRequest.stereo = !strcmp(outStereo, "separate"); + writeRequest.comments = comment; + writeRequest.copyright = copyright; + writeRequest.args = writerArgs; + + copy(outparams.begin(), outparams.end(), back_inserter(writeRequest.parameters)); if (timerange) @@ -1548,10 +1719,8 @@ utf8Main(int argc, char *argv[]) if (writeRequest.frames.empty()) { - cerr << "ERROR: timerange \"" - << timerange - << "\" expands to nothing" - << endl; + cerr << "ERROR: timerange \"" << timerange + << "\" expands to nothing" << endl; exit(-1); } @@ -1578,28 +1747,28 @@ utf8Main(int argc, char *argv[]) #ifdef WIN32 GC_INIT(); GC_allow_register_threads(); - outmov = new ThreadedMovie(inputMovies, outFrames, 8, 0, threadedMovieInit); + outmov = + new ThreadedMovie(inputMovies, outFrames, 8, 0, threadedMovieInit); #else ThreadedMovie::ThreadAPI threadAPI; threadAPI.create = GC_pthread_create; - threadAPI.join = GC_pthread_join; + threadAPI.join = GC_pthread_join; threadAPI.detach = GC_pthread_detach; - outmov = new ThreadedMovie(inputMovies, outFrames, 8, &threadAPI, threadedMovieInit); + outmov = new ThreadedMovie(inputMovies, outFrames, 8, &threadAPI, + threadedMovieInit); #endif #endif - //assert(inputMovies.size() == 1); - //outmov = inputMovies.front(); + // assert(inputMovies.size() == 1); + // outmov = inputMovies.front(); // // On windows, we need to do this *after* the threaded movie // has been created. Not sure why. // - TwkApp::initWithFile(TwkApp::muContext(), - TwkApp::muProcess(), - TwkApp::muModuleList(), - initPath.c_str()); + TwkApp::initWithFile(TwkApp::muContext(), TwkApp::muProcess(), + TwkApp::muModuleList(), initPath.c_str()); // // Since the sessions we're created earlier (before we @@ -1611,17 +1780,20 @@ utf8Main(int argc, char *argv[]) // for (int i = 0; i < IPCore::App()->documents().size(); ++i) { - if (Rv::RvSession *s = dynamic_cast (IPCore::App()->documents()[i])) + if (Rv::RvSession* s = + dynamic_cast(IPCore::App()->documents()[i])) { s->postInitialize(); // - // We show the user no cache stats, so don't bother to compute them. + // We show the user no cache stats, so don't bother to compute + // them. // s->graph().cache().setCacheStatsDisabled(true); } } - MovieWriter* writer = TwkMovie::GenericIO::movieWriter(pathConform(outfile)); + MovieWriter* writer = + TwkMovie::GenericIO::movieWriter(pathConform(outfile)); if (!writer) { @@ -1649,7 +1821,8 @@ utf8Main(int argc, char *argv[]) if (writeRequest.compression != "") { - cout << "INFO: output compressor " << writeRequest.compression << endl; + cout << "INFO: output compressor " << writeRequest.compression + << endl; } if (writeRequest.codec != "") @@ -1664,10 +1837,8 @@ utf8Main(int argc, char *argv[]) if (writeRequest.timeRangeOverride && timerange) { - cout << "INFO: override time range " << timerange - << ", (" << writeRequest.frames.size() - << " frames)" - << endl; + cout << "INFO: override time range " << timerange << ", (" + << writeRequest.frames.size() << " frames)" << endl; } if (writeRequest.keepPlanar && reallyverbose) @@ -1680,7 +1851,8 @@ utf8Main(int argc, char *argv[]) // Tell the writer to do its business // - if (!writer->write(outmov, outfile, writeRequest)) exit (-2); + if (!writer->write(outmov, outfile, writeRequest)) + exit(-2); // clean up any frame buffers we allocated writing the movie // @@ -1708,9 +1880,8 @@ utf8Main(int argc, char *argv[]) #endif TwkMovie::GenericIO::shutdown(); // Shutdown TwkMovie::GenericIO plugins - TwkFB::GenericIO::shutdown(); // Shutdown TwkFB::GenericIO plugins + TwkFB::GenericIO::shutdown(); // Shutdown TwkFB::GenericIO plugins TwkFB::ThreadPool::shutdown(); return 0; } - diff --git a/src/bin/imgtools/rvio/utf8Main.cpp b/src/bin/imgtools/rvio/utf8Main.cpp index 69e097cc9..7c46f886c 100644 --- a/src/bin/imgtools/rvio/utf8Main.cpp +++ b/src/bin/imgtools/rvio/utf8Main.cpp @@ -1,6 +1,6 @@ // -// Copyright (C) 2023 Autodesk, Inc. All Rights Reserved. -// -// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2023 Autodesk, Inc. All Rights Reserved. // -#include "../../utf8Main.cpp" \ No newline at end of file +// SPDX-License-Identifier: Apache-2.0 +// +#include "../../utf8Main.cpp" diff --git a/src/bin/imgtools/rvls/main.cpp b/src/bin/imgtools/rvls/main.cpp index 6e1ed47fd..7e5f59044 100644 --- a/src/bin/imgtools/rvls/main.cpp +++ b/src/bin/imgtools/rvls/main.cpp @@ -1,9 +1,9 @@ //****************************************************************************** // Copyright (c) 2007 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #include "../../utf8Main.h" @@ -54,9 +54,10 @@ using namespace boost; bool bruteForce = false; vector inputFiles; -int parseInFiles(int argc, char *argv[]) + +int parseInFiles(int argc, char* argv[]) { - for (int i=0; i& parts) if (info.video) { - str << info.width; parts.push_back(str.str()); str.str(""); - str << info.height; parts.push_back(str.str()); str.str(""); + str << info.width; + parts.push_back(str.str()); + str.str(""); + str << info.height; + parts.push_back(str.str()); + str.str(""); int nc = info.numChannels; switch (info.dataType) { - case TwkFB::FrameBuffer::UCHAR: str << "8i"; break; - case TwkFB::FrameBuffer::USHORT: str << "16i"; break; - case TwkFB::FrameBuffer::HALF: str << "16f"; break; - case TwkFB::FrameBuffer::FLOAT: str << "32f"; break; - case TwkFB::FrameBuffer::UINT: str << "32i"; break; - case TwkFB::FrameBuffer::DOUBLE: str << "64i"; break; - case TwkFB::FrameBuffer::PACKED_Cb8_Y8_Cr8_Y8: str << "8i"; - nc = 3; - break; - case TwkFB::FrameBuffer::PACKED_Y8_Cb8_Y8_Cr8: str << "8i"; - nc = 3; - break; - case TwkFB::FrameBuffer::PACKED_R10_G10_B10_X2: - case TwkFB::FrameBuffer::PACKED_X2_B10_G10_R10: - str << "10i"; - nc = 3; - break; - default: - str << info.dataType; + case TwkFB::FrameBuffer::UCHAR: + str << "8i"; + break; + case TwkFB::FrameBuffer::USHORT: + str << "16i"; + break; + case TwkFB::FrameBuffer::HALF: + str << "16f"; + break; + case TwkFB::FrameBuffer::FLOAT: + str << "32f"; + break; + case TwkFB::FrameBuffer::UINT: + str << "32i"; + break; + case TwkFB::FrameBuffer::DOUBLE: + str << "64i"; + break; + case TwkFB::FrameBuffer::PACKED_Cb8_Y8_Cr8_Y8: + str << "8i"; + nc = 3; + break; + case TwkFB::FrameBuffer::PACKED_Y8_Cb8_Y8_Cr8: + str << "8i"; + nc = 3; + break; + case TwkFB::FrameBuffer::PACKED_R10_G10_B10_X2: + case TwkFB::FrameBuffer::PACKED_X2_B10_G10_R10: + str << "10i"; + nc = 3; + break; + default: + str << info.dataType; } - parts.push_back(str.str()); str.str(""); - str << nc; parts.push_back(str.str()); str.str(""); + parts.push_back(str.str()); + str.str(""); + str << nc; + parts.push_back(str.str()); + str.str(""); int nframes = info.end - info.start + 1; if (nframes > 0) { - str << info.fps; parts.push_back(str.str()); str.str(""); - str << nframes; parts.push_back(str.str()); str.str(""); + str << info.fps; + parts.push_back(str.str()); + str.str(""); + str << nframes; + parts.push_back(str.str()); + str.str(""); } else { @@ -139,7 +164,7 @@ void lsLong(const string& seq, vector& parts) } else { - for (int i=0; i < 6; i++) + for (int i = 0; i < 6; i++) parts.push_back(""); } @@ -147,28 +172,32 @@ void lsLong(const string& seq, vector& parts) { if (info.audioChannels.size() == 0) { - str << "-"; parts.push_back(str.str()); str.str(""); + str << "-"; + parts.push_back(str.str()); + str.str(""); } else { - str << info.audioChannels.size(); parts.push_back(str.str()); str.str(""); + str << info.audioChannels.size(); + parts.push_back(str.str()); + str.str(""); } } else { - for (int i=0; i < 1; i++) + for (int i = 0; i < 1; i++) parts.push_back(""); } delete reader; } - else if (seq.substr(0,14) == "RVImageSource|") + else if (seq.substr(0, 14) == "RVImageSource|") { ostringstream str; vector strs; - boost::split(strs,seq,boost::is_any_of("|")); - parts.push_back(strs[3]); // width - parts.push_back(strs[4]); // height + boost::split(strs, seq, boost::is_any_of("|")); + parts.push_back(strs[3]); // width + parts.push_back(strs[4]); // height parts.push_back(strs[8] + ((strs[9] == "0") ? "i" : "f")); // depth+type str << strs[2].size(); // numChannels @@ -184,59 +213,70 @@ void lsLong(const string& seq, vector& parts) str << nframes; frames = str.str(); } - parts.push_back(fps); // fps + parts.push_back(fps); // fps parts.push_back(frames); // frame count // no audio - for (int i=0; i < 1; i++) parts.push_back(""); + for (int i = 0; i < 1; i++) + parts.push_back(""); } parts.push_back(seq); } -string lsAlignedLongOuput(vector >& listing, bool x2=true) +string lsAlignedLongOuput(vector>& listing, bool x2 = true) { ostringstream out; vector spacing; - if (listing.empty()) return ""; + if (listing.empty()) + return ""; spacing.resize(listing.front().size()); - for (int i=0; i < spacing.size(); i++) + for (int i = 0; i < spacing.size(); i++) { - for (int q=1; q < listing.size(); q++) + for (int q = 1; q < listing.size(); q++) { if (listing[q].size() > 1) spacing[i] = max(spacing[i], listing[q][i].size()); } } - for (int i=0; i < spacing.size(); i++) + for (int i = 0; i < spacing.size(); i++) { - for (int q=0; q < listing.size(); q++) + for (int q = 0; q < listing.size(); q++) { if (listing[q].size() > 1) - if (spacing[i] > 0) spacing[i] = max(spacing[i], listing[q][i].size()); + if (spacing[i] > 0) + spacing[i] = max(spacing[i], listing[q][i].size()); } } out << setfill(' '); - for (int q=0; q < listing.size(); q++) + for (int q = 0; q < listing.size(); q++) { const vector& entry = listing[q]; if (entry.size() > 1) { - for (int i=0; i < entry.size(); i++) + for (int i = 0; i < entry.size(); i++) { - if (spacing[i] == 0) continue; - if (i == spacing.size()-1 || i == 1 || i == 3) out << left; - else out << right; - - if (x2 && i == 1 && entry[i] != "") out << " x "; else out << " "; - - if (i == entry.size() - 1) out << entry[i]; - else out << setw(spacing[i]) << entry[i] << setw(0); + if (spacing[i] == 0) + continue; + if (i == spacing.size() - 1 || i == 1 || i == 3) + out << left; + else + out << right; + + if (x2 && i == 1 && entry[i] != "") + out << " x "; + else + out << " "; + + if (i == entry.size() - 1) + out << entry[i]; + else + out << setw(spacing[i]) << entry[i] << setw(0); } out << endl; @@ -246,7 +286,7 @@ string lsAlignedLongOuput(vector >& listing, bool x2=true) return out.str(); } -string lsExtended(const string& seq, bool yaml=false) +string lsExtended(const string& seq, bool yaml = false) { YAML::Emitter out_yaml; out_yaml.SetIndent(4); @@ -269,13 +309,13 @@ string lsExtended(const string& seq, bool yaml=false) const FrameBuffer& fb = minfo.proxy; const FrameBuffer::AttributeVector& attrs = fb.attributes(); - vector > listing; + vector> listing; out_yaml << YAML::Key << "Attributes"; - out_yaml << YAML::Value << YAML::BeginMap; //Attribute Map - for (int i=0; i < attrs.size(); i++) + out_yaml << YAML::Value << YAML::BeginMap; // Attribute Map + for (int i = 0; i < attrs.size(); i++) { - listing.resize(listing.size()+1); + listing.resize(listing.size() + 1); listing.back().resize(2); listing.back()[0] = attrs[i]->name(); @@ -286,29 +326,29 @@ string lsExtended(const string& seq, bool yaml=false) } out_yaml << YAML::EndMap; // Attribute Map End - if (minfo.video) { ostringstream str; - listing.resize(listing.size()+1); + listing.resize(listing.size() + 1); listing.back().resize(2); listing.back()[0] = "Channels"; out_yaml << YAML::Key << "Channels"; - out_yaml << YAML::Value << YAML::BeginSeq; //Channel Sequencce + out_yaml << YAML::Value << YAML::BeginSeq; // Channel Sequencce - for (int i=0; i < minfo.channelInfos.size(); i++) + for (int i = 0; i < minfo.channelInfos.size(); i++) { - if (i) str << ", "; + if (i) + str << ", "; str << minfo.channelInfos[i].name; out_yaml << minfo.channelInfos[i].name; } - out_yaml << YAML::EndSeq; //Channel Sequence End + out_yaml << YAML::EndSeq; // Channel Sequence End listing.back()[1] = str.str(); str.str(""); - listing.resize(listing.size()+1); + listing.resize(listing.size() + 1); listing.back().resize(2); listing.back()[0] = "Resolution"; @@ -316,7 +356,7 @@ string lsExtended(const string& seq, bool yaml=false) str << minfo.numChannels << "ch, "; out_yaml << YAML::Key << "Resolution"; - out_yaml << YAML::Value << YAML::BeginMap; //Resolution Map + out_yaml << YAML::Value << YAML::BeginMap; // Resolution Map out_yaml << YAML::Key << "Width"; out_yaml << YAML::Value << minfo.uncropWidth; @@ -331,70 +371,70 @@ string lsExtended(const string& seq, bool yaml=false) out_yaml << YAML::Value << YAML::BeginMap; // Depth Map switch (minfo.dataType) { - case TwkFB::FrameBuffer::UCHAR: - str << "8 bits/ch"; - out_yaml << YAML::Key << "Bits"; - out_yaml << YAML::Value << 8; - out_yaml << YAML::Key << "Type"; - out_yaml << YAML::Value << "int"; - break; - case TwkFB::FrameBuffer::USHORT: - str << "16 bits/ch"; - out_yaml << YAML::Key << "Bits"; - out_yaml << YAML::Value << 16; - out_yaml << YAML::Key << "Type"; - out_yaml << YAML::Value << "int"; - break; - case TwkFB::FrameBuffer::HALF: - str << "16 bits/ch floating point"; - out_yaml << YAML::Key << "Bits"; - out_yaml << YAML::Value << 16; - out_yaml << YAML::Key << "Type"; - out_yaml << YAML::Value << "float"; - break; - case TwkFB::FrameBuffer::FLOAT: - str << "32 bits/ch floating point"; - out_yaml << YAML::Key << "Bits"; - out_yaml << YAML::Value << 32; - out_yaml << YAML::Key << "Type"; - out_yaml << YAML::Value << "float"; - break; - case TwkFB::FrameBuffer::UINT: - str << "32 bits/ch"; - out_yaml << YAML::Key << "Bits"; - out_yaml << YAML::Value << 32; - out_yaml << YAML::Key << "Type"; - out_yaml << YAML::Value << "int"; - break; - case TwkFB::FrameBuffer::DOUBLE: - str << "64 bits/ch floating point"; - out_yaml << YAML::Key << "Bits"; - out_yaml << YAML::Value << 64; - out_yaml << YAML::Key << "Type"; - out_yaml << YAML::Value << "float"; - break; - case TwkFB::FrameBuffer::PACKED_Cb8_Y8_Cr8_Y8: - case TwkFB::FrameBuffer::PACKED_Y8_Cb8_Y8_Cr8: - str << "8 bits/ch"; - out_yaml << YAML::Key << "Bits"; - out_yaml << YAML::Value << 8; - out_yaml << YAML::Key << "Type"; - out_yaml << YAML::Value << "int"; - break; - case TwkFB::FrameBuffer::PACKED_R10_G10_B10_X2: - case TwkFB::FrameBuffer::PACKED_X2_B10_G10_R10: - str << "10 bits/ch"; - out_yaml << YAML::Key << "Bits"; - out_yaml << YAML::Value << 10; - out_yaml << YAML::Key << "Type"; - out_yaml << YAML::Value << "int"; - break; - default: - str << "?"; - out_yaml << YAML::Key << "Bits"; - out_yaml << YAML::Value << "?"; - out_yaml << YAML::Key << "Type"; - out_yaml << YAML::Value << "?"; + case TwkFB::FrameBuffer::UCHAR: + str << "8 bits/ch"; + out_yaml << YAML::Key << "Bits"; + out_yaml << YAML::Value << 8; + out_yaml << YAML::Key << "Type"; + out_yaml << YAML::Value << "int"; + break; + case TwkFB::FrameBuffer::USHORT: + str << "16 bits/ch"; + out_yaml << YAML::Key << "Bits"; + out_yaml << YAML::Value << 16; + out_yaml << YAML::Key << "Type"; + out_yaml << YAML::Value << "int"; + break; + case TwkFB::FrameBuffer::HALF: + str << "16 bits/ch floating point"; + out_yaml << YAML::Key << "Bits"; + out_yaml << YAML::Value << 16; + out_yaml << YAML::Key << "Type"; + out_yaml << YAML::Value << "float"; + break; + case TwkFB::FrameBuffer::FLOAT: + str << "32 bits/ch floating point"; + out_yaml << YAML::Key << "Bits"; + out_yaml << YAML::Value << 32; + out_yaml << YAML::Key << "Type"; + out_yaml << YAML::Value << "float"; + break; + case TwkFB::FrameBuffer::UINT: + str << "32 bits/ch"; + out_yaml << YAML::Key << "Bits"; + out_yaml << YAML::Value << 32; + out_yaml << YAML::Key << "Type"; + out_yaml << YAML::Value << "int"; + break; + case TwkFB::FrameBuffer::DOUBLE: + str << "64 bits/ch floating point"; + out_yaml << YAML::Key << "Bits"; + out_yaml << YAML::Value << 64; + out_yaml << YAML::Key << "Type"; + out_yaml << YAML::Value << "float"; + break; + case TwkFB::FrameBuffer::PACKED_Cb8_Y8_Cr8_Y8: + case TwkFB::FrameBuffer::PACKED_Y8_Cb8_Y8_Cr8: + str << "8 bits/ch"; + out_yaml << YAML::Key << "Bits"; + out_yaml << YAML::Value << 8; + out_yaml << YAML::Key << "Type"; + out_yaml << YAML::Value << "int"; + break; + case TwkFB::FrameBuffer::PACKED_R10_G10_B10_X2: + case TwkFB::FrameBuffer::PACKED_X2_B10_G10_R10: + str << "10 bits/ch"; + out_yaml << YAML::Key << "Bits"; + out_yaml << YAML::Value << 10; + out_yaml << YAML::Key << "Type"; + out_yaml << YAML::Value << "int"; + break; + default: + str << "?"; + out_yaml << YAML::Key << "Bits"; + out_yaml << YAML::Value << "?"; + out_yaml << YAML::Key << "Type"; + out_yaml << YAML::Value << "?"; } out_yaml << YAML::EndMap; // Depth Map End out_yaml << YAML::EndMap; // Resolution Map End @@ -402,7 +442,6 @@ string lsExtended(const string& seq, bool yaml=false) listing.back()[1] = str.str(); } - reverse(listing.begin(), listing.end()); out << seq << ":" << endl << endl; @@ -411,23 +450,24 @@ string lsExtended(const string& seq, bool yaml=false) delete reader; } - else if (seq.substr(0,14) == "RVImageSource|") + else if (seq.substr(0, 14) == "RVImageSource|") { vector strs; - boost::split(strs,seq,boost::is_any_of("|")); + boost::split(strs, seq, boost::is_any_of("|")); - vector > listing; + vector> listing; ostringstream str; - listing.resize(listing.size()+1); + listing.resize(listing.size() + 1); listing.back().resize(2); listing.back()[0] = "Channels"; out_yaml << YAML::Key << "Channels"; out_yaml << YAML::Value << YAML::BeginSeq; // Channel Sequence - for (int i=0; i < strs[2].size(); i++) + for (int i = 0; i < strs[2].size(); i++) { - if (i) str << ", "; + if (i) + str << ", "; str << strs[2][i]; out_yaml << strs[2][i]; } @@ -437,13 +477,14 @@ string lsExtended(const string& seq, bool yaml=false) listing.back()[1] = str.str(); str.str(""); - listing.resize(listing.size()+1); + listing.resize(listing.size() + 1); listing.back().resize(2); listing.back()[0] = "Resolution"; str << strs[3] << " x " << strs[4] << ", "; str << strs[2].size() << "ch, "; - str << strs[8] << " bits/ch" << ((strs[9] == "0") ? "" : " floating point"); + str << strs[8] << " bits/ch" + << ((strs[9] == "0") ? "" : " floating point"); out_yaml << YAML::Key << "Resolution"; out_yaml << YAML::Value << YAML::BeginMap; // Resolution Map @@ -467,7 +508,6 @@ string lsExtended(const string& seq, bool yaml=false) out_yaml << YAML::EndMap; // End Depth Map out_yaml << YAML::EndMap; // End Resolution Map - listing.back()[1] = str.str(); reverse(listing.begin(), listing.end()); @@ -490,30 +530,34 @@ vector readSession(string path) string thispath; GTOReader reader = new GTOReader(); GTOReader::Containers nodes = reader.read(path.c_str()); - for (int n=0; n < nodes.size(); n++) + for (int n = 0; n < nodes.size(); n++) { if (nodes[n]->protocol() == "RVFileSource") { PropertyContainer::Components comps = nodes[n]->components(); - for (int c=0; c < comps.size(); c++) + for (int c = 0; c < comps.size(); c++) { - if (comps[c]->name() != "media") continue; + if (comps[c]->name() != "media") + continue; Component::Container props = comps[c]->properties(); - for (int p=0; p < props.size(); p++) + for (int p = 0; p < props.size(); p++) { - if (props[p]->name() != "movie") continue; + if (props[p]->name() != "movie") + continue; vector movs; string movs_string = props[p]->valueAsString(); split(movs, movs_string, is_any_of(string(" "))); - for (int m=0; m < movs.size(); m++) + for (int m = 0; m < movs.size(); m++) { thispath = movs[m]; - if (movs[m].size() > 13 && movs[m].substr(0, 14) == "${RV_PATHSWAP_") + if (movs[m].size() > 13 + && movs[m].substr(0, 14) == "${RV_PATHSWAP_") { int endpos = movs[m].find("}"); - if (endpos == string::npos) continue; + if (endpos == string::npos) + continue; string envvar = movs[m].substr(2, endpos - 2); char* pathswap = getenv(envvar.c_str()); if (pathswap != NULL) @@ -530,44 +574,54 @@ vector readSession(string path) { ostringstream imgsrc; string name = "", channels = ""; - int uncropWidth = 0, uncropHeight = 0, - start = 0, end = 0, inc = 0, + int uncropWidth = 0, uncropHeight = 0, start = 0, end = 0, inc = 0, bitsPerChannel = 0, isFloat = 0; float pixelAspect = 0.0, fps = 0.0; PropertyContainer::Components comps = nodes[n]->components(); - for (int c=0; c < comps.size(); c++) + for (int c = 0; c < comps.size(); c++) { - if (comps[c]->name() != "media" && comps[c]->name() != "image") continue; + if (comps[c]->name() != "media" && comps[c]->name() != "image") + continue; Component::Container props = comps[c]->properties(); - for (int p=0; p < props.size(); p++) + for (int p = 0; p < props.size(); p++) { string pName = props[p]->name(); - if (pName == "name") name = props[p]->valueAsString(); - else if (pName == "channels") channels = props[p]->valueAsString(); - else if (pName == "uncropWidth") uncropWidth = reinterpret_cast(props[p])->front(); - else if (pName == "uncropHeight") uncropHeight = reinterpret_cast(props[p])->front(); - else if (pName == "start") start = reinterpret_cast(props[p])->front(); - else if (pName == "end") end = reinterpret_cast(props[p])->front(); - else if (pName == "inc") inc = reinterpret_cast(props[p])->front(); - else if (pName == "bitsPerChannel") bitsPerChannel = reinterpret_cast(props[p])->front(); - else if (pName == "float") isFloat = reinterpret_cast(props[p])->front(); - else if (pName == "pixelAspect") pixelAspect = reinterpret_cast(props[p])->front(); - else if (pName == "fps") fps = reinterpret_cast(props[p])->front(); + if (pName == "name") + name = props[p]->valueAsString(); + else if (pName == "channels") + channels = props[p]->valueAsString(); + else if (pName == "uncropWidth") + uncropWidth = + reinterpret_cast(props[p])->front(); + else if (pName == "uncropHeight") + uncropHeight = + reinterpret_cast(props[p])->front(); + else if (pName == "start") + start = + reinterpret_cast(props[p])->front(); + else if (pName == "end") + end = reinterpret_cast(props[p])->front(); + else if (pName == "inc") + inc = reinterpret_cast(props[p])->front(); + else if (pName == "bitsPerChannel") + bitsPerChannel = + reinterpret_cast(props[p])->front(); + else if (pName == "float") + isFloat = + reinterpret_cast(props[p])->front(); + else if (pName == "pixelAspect") + pixelAspect = + reinterpret_cast(props[p])->front(); + else if (pName == "fps") + fps = + reinterpret_cast(props[p])->front(); } } - imgsrc << "RVImageSource|" - << name << "|" - << channels << "|" - << uncropWidth << "|" - << uncropHeight << "|" - << start << "|" - << end << "|" - << inc << "|" - << bitsPerChannel << "|" - << isFloat << "|" - << pixelAspect << "|" - << fps << "|"; + imgsrc << "RVImageSource|" << name << "|" << channels << "|" + << uncropWidth << "|" << uncropHeight << "|" << start << "|" + << end << "|" << inc << "|" << bitsPerChannel << "|" + << isFloat << "|" << pixelAspect << "|" << fps << "|"; thispath = imgsrc.str(); imgsrc.str(""); @@ -583,55 +637,56 @@ int utf8Main(int argc, char** argv) const QCoreApplication qapp(argc, argv); #ifdef PLATFORM_DARWIN - TwkApp::DarwinBundle bundle("RV", MAJOR_VERSION, MINOR_VERSION, REVISION_NUMBER); + TwkApp::DarwinBundle bundle("RV", MAJOR_VERSION, MINOR_VERSION, + REVISION_NUMBER); #else - TwkApp::QTBundle bundle("rv", MAJOR_VERSION, MINOR_VERSION, REVISION_NUMBER); - (void) bundle.top(); + TwkApp::QTBundle bundle("rv", MAJOR_VERSION, MINOR_VERSION, + REVISION_NUMBER); + (void)bundle.top(); #endif - int showVersion = 0; - int a = 0; - int s = 0; - int b = 0; - int minseq = 3; - int nr = 0; - int l = 0; - int x = 0; - int ns = 0; - int showFormats = 0; - int yaml = 0; + int showVersion = 0; + int a = 0; + int s = 0; + int b = 0; + int minseq = 3; + int nr = 0; + int l = 0; + int x = 0; + int ns = 0; + int showFormats = 0; + int yaml = 0; char* debugString = 0; - char* outputFile = 0; + char* outputFile = 0; // // Call the deploy functions // - TWK_DEPLOY_APP_OBJECT dobj(MAJOR_VERSION, - MINOR_VERSION, - REVISION_NUMBER, - argc, argv, - RELEASE_DESCRIPTION, + TWK_DEPLOY_APP_OBJECT dobj(MAJOR_VERSION, MINOR_VERSION, REVISION_NUMBER, + argc, argv, RELEASE_DESCRIPTION, "HEAD=" GIT_HEAD); - if (arg_parse - (argc, argv, - "", "\nUsage: rvls list movies and image sequences\n", - "", ARG_SUBR(parseInFiles), "Input sequence patterns, images, movies, or directories ", - "-a", ARG_FLAG(&a), "Show hidden files", - "-s", ARG_FLAG(&s), "Show sequences only (no non-sequence member files)", - "-l", ARG_FLAG(&l), "Show long listing", - "-x", ARG_FLAG(&x), "Show extended attributes and image structure", - "-b", ARG_FLAG(&b), "Use brute force if no reader found", - "-o %S", &outputFile, "Output log file. Results will be printed to stdout by default", - "-nr", ARG_FLAG(&nr), "Do not show frame ranges", - "-ns", ARG_FLAG(&ns), "Do not infer sequences (list each file separately)", - "-min %d", &minseq, "Minimum number of files considered a sequence (default=%d)", minseq, - "-formats", ARG_FLAG(&showFormats), "List image/movie formats", - "-yaml", ARG_FLAG(&yaml), "Output in YAML format. (-x only)", - "-version", ARG_FLAG(&showVersion), "Show rvls version number", - "-debug %S", &debugString, "Debug category (only 'plugins' for now)", - NULL) < 0) + if (arg_parse( + argc, argv, "", "\nUsage: rvls list movies and image sequences\n", + "", ARG_SUBR(parseInFiles), + "Input sequence patterns, images, movies, or directories ", "-a", + ARG_FLAG(&a), "Show hidden files", "-s", ARG_FLAG(&s), + "Show sequences only (no non-sequence member files)", "-l", + ARG_FLAG(&l), "Show long listing", "-x", ARG_FLAG(&x), + "Show extended attributes and image structure", "-b", ARG_FLAG(&b), + "Use brute force if no reader found", "-o %S", &outputFile, + "Output log file. Results will be printed to stdout by default", + "-nr", ARG_FLAG(&nr), "Do not show frame ranges", "-ns", + ARG_FLAG(&ns), "Do not infer sequences (list each file separately)", + "-min %d", &minseq, + "Minimum number of files considered a sequence (default=%d)", + minseq, "-formats", ARG_FLAG(&showFormats), + "List image/movie formats", "-yaml", ARG_FLAG(&yaml), + "Output in YAML format. (-x only)", "-version", + ARG_FLAG(&showVersion), "Show rvls version number", "-debug %S", + &debugString, "Debug category (only 'plugins' for now)", NULL) + < 0) { exit(-1); } @@ -644,17 +699,16 @@ int utf8Main(int argc, char** argv) { debugSwitches(debugString); } - catch (const std::exception &e) + catch (const std::exception& e) { cerr << "ERROR: during initialization: " << e.what() << endl; - exit( -1 ); + exit(-1); } if (showVersion) { - cout << MAJOR_VERSION << "." - << MINOR_VERSION << "." - << REVISION_NUMBER << endl; + cout << MAJOR_VERSION << "." << MINOR_VERSION << "." << REVISION_NUMBER + << endl; exit(0); } @@ -669,7 +723,8 @@ int utf8Main(int argc, char** argv) } catch (...) { - cerr << "WARNING: a problem occured while loading image plugins." << endl; + cerr << "WARNING: a problem occured while loading image plugins." + << endl; cerr << " some plugins may not have been loaded." << endl; } @@ -683,7 +738,7 @@ int utf8Main(int argc, char** argv) TwkApp::initMu(nullptr); TwkApp::initPython(); } - catch (const std::exception &e) + catch (const std::exception& e) { cerr << "ERROR: during initialization: " << e.what() << '\n'; exit(-1); @@ -706,27 +761,30 @@ int utf8Main(int argc, char** argv) { vector allfiles; - for (int i=0; i < inputFiles.size(); i++) + for (int i = 0; i < inputFiles.size(); i++) { string path = inputFiles[i]; if (isDirectory(path.c_str())) { - if (path[path.size()-1] != '/') path.append("/"); + if (path[path.size() - 1] != '/') + path.append("/"); vector files; if (filesInDirectory(path.c_str(), files)) { - for (int q=0; q < files.size(); q++) + for (int q = 0; q < files.size(); q++) { - if (files[q].size() && files[q][0] == '.' && !a) continue; + if (files[q].size() && files[q][0] == '.' && !a) + continue; string file = path; file += files[q]; allfiles.push_back(file); } } } - else if (path.size() > 2 && path.substr(path.size() - 3, path.size() - 1) == ".rv") + else if (path.size() > 2 + && path.substr(path.size() - 3, path.size() - 1) == ".rv") { allfiles = readSession(path); } @@ -744,20 +802,16 @@ int utf8Main(int argc, char** argv) } else { - SequencePredicate sPred = (bruteForce) ? - AnySequencePredicate : GlobalExtensionPredicate; - seqs = sequencesInFileList(allfiles, - sPred, - nonmatching, - showranges, + SequencePredicate sPred = + (bruteForce) ? AnySequencePredicate : GlobalExtensionPredicate; + seqs = sequencesInFileList(allfiles, sPred, nonmatching, showranges, minseq); } std::sort(seqs.begin(), seqs.end()); - if (l) { - vector > listing(seqs.size()+1); + vector> listing(seqs.size() + 1); listing.front().push_back("w"); listing.front().push_back("h"); listing.front().push_back("typ"); @@ -767,16 +821,16 @@ int utf8Main(int argc, char** argv) listing.front().push_back("#ach"); listing.front().push_back("file"); - for (int i=0; i < seqs.size(); i++) + for (int i = 0; i < seqs.size(); i++) { - lsLong(seqs[i], listing[i+1]); + lsLong(seqs[i], listing[i + 1]); } out << lsAlignedLongOuput(listing); } else if (x) { - for (int i=0; i < seqs.size(); i++) + for (int i = 0; i < seqs.size(); i++) { out << lsExtended(seqs[i], yaml); } diff --git a/src/bin/imgtools/rvls/utf8Main.cpp b/src/bin/imgtools/rvls/utf8Main.cpp index 69e097cc9..7c46f886c 100644 --- a/src/bin/imgtools/rvls/utf8Main.cpp +++ b/src/bin/imgtools/rvls/utf8Main.cpp @@ -1,6 +1,6 @@ // -// Copyright (C) 2023 Autodesk, Inc. All Rights Reserved. -// -// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2023 Autodesk, Inc. All Rights Reserved. // -#include "../../utf8Main.cpp" \ No newline at end of file +// SPDX-License-Identifier: Apache-2.0 +// +#include "../../utf8Main.cpp" diff --git a/src/bin/mu/mu-interp/main.cpp b/src/bin/mu/mu-interp/main.cpp index d27310c66..3a3a7dd59 100644 --- a/src/bin/mu/mu-interp/main.cpp +++ b/src/bin/mu/mu-interp/main.cpp @@ -1,7 +1,7 @@ // // Copyright (c) 2001 Jim Hourihan // -// SPDX-License-Identifier: Apache-2.0 +// SPDX-License-Identifier: Apache-2.0 // #include #include @@ -53,7 +53,6 @@ #define RUSAGE_SELF 0 #endif - using namespace std; using namespace Mu; typedef Mu::SymbolTable::SymbolHashTable HT; @@ -67,11 +66,11 @@ int why = 0; int debug = 0; int compile = 0; -GenericMachine* machine=0; -MuLangContext* context=0; -MuLangLanguage* language=0; -Process* process=0; -Thread* gThread=0; +GenericMachine* machine = 0; +MuLangContext* context = 0; +MuLangLanguage* language = 0; +Process* process = 0; +Thread* gThread = 0; #if 0 #ifdef MU_USE_BOEHM_COLLECTOR @@ -95,26 +94,26 @@ seconds(timeval start, timeval end) //---------------------------------------------------------------------- -void -dumpSymbols(Symbol *s, int depth) +void dumpSymbols(Symbol* s, int depth) { - for (int i=0; ioutput(cout); cout << endl; if (s->symbolTable()) { - HT& table = s->symbolTable()->hashTable(); - - for (HT::Iterator it(table); it; ++it) - { - cout << it.index() << ":"; - for (Symbol *ss = (*it); ss; ss = ss->nextOverload()) - { - dumpSymbols(ss,depth+1); - } - } + HT& table = s->symbolTable()->hashTable(); + + for (HT::Iterator it(table); it; ++it) + { + cout << it.index() << ":"; + for (Symbol* ss = (*it); ss; ss = ss->nextOverload()) + { + dumpSymbols(ss, depth + 1); + } + } } } @@ -124,12 +123,11 @@ dumpSymbols(Symbol *s, int depth) extern "C" void ptw32_processInitialize(void); #endif -int -main(int argc, char **argv) +int main(int argc, char** argv) { -//#ifdef PLATFORM_WINDOWS - //ptw32_processInitialize(); -//#endif + // #ifdef PLATFORM_WINDOWS + // ptw32_processInitialize(); + // #endif char* inFile = 0; char* printFunc = 0; @@ -145,45 +143,45 @@ main(int argc, char **argv) GarbageCollector::init(); - if (arg_parse - (argc, argv, - "", "Usage: %s [options]", argv[0], - "[%S]", &inFile, "input .mu source file", - "-print", ARG_FLAG(&print), "print parse tree in lispy form", - "-printFunc %S", &printFunc, "print function in lispy form", - "-stdin", ARG_FLAG(&noninteractive), "non interactive mode", - "-no-readline", ARG_FLAG(&noReadline), "don't use readline library", - "-why", ARG_FLAG(&why), "verbose function choice information", - "-debug", ARG_FLAG(&debug), "include debug information", - "-symbols", ARG_FLAG(&symbols), "output root symbol table", - "-compile", ARG_FLAG(&compile), "compile muc files on demand", - "-noeval", ARG_FLAG(&noeval), "don't evaluate", - "-notruncate", ARG_FLAG(¬runcate), "don't truncate long output", - "-no-gc", ARG_FLAG(&disableGC), "turn off garbage collector", - "-usage", ARG_FLAG(&usage), "show usage", - "-name", ARG_FLAG(&streamName), "name to use for error reporting", - "-main", ARG_FLAG(&callmain), "call the main() function if it exists", - NULL) < 0) + if (arg_parse( + argc, argv, "", "Usage: %s [options]", argv[0], "[%S]", &inFile, + "input .mu source file", "-print", ARG_FLAG(&print), + "print parse tree in lispy form", "-printFunc %S", &printFunc, + "print function in lispy form", "-stdin", ARG_FLAG(&noninteractive), + "non interactive mode", "-no-readline", ARG_FLAG(&noReadline), + "don't use readline library", "-why", ARG_FLAG(&why), + "verbose function choice information", "-debug", ARG_FLAG(&debug), + "include debug information", "-symbols", ARG_FLAG(&symbols), + "output root symbol table", "-compile", ARG_FLAG(&compile), + "compile muc files on demand", "-noeval", ARG_FLAG(&noeval), + "don't evaluate", "-notruncate", ARG_FLAG(¬runcate), + "don't truncate long output", "-no-gc", ARG_FLAG(&disableGC), + "turn off garbage collector", "-usage", ARG_FLAG(&usage), + "show usage", "-name", ARG_FLAG(&streamName), + "name to use for error reporting", "-main", ARG_FLAG(&callmain), + "call the main() function if it exists", NULL) + < 0) { - exit( 0 ); + exit(0); } - machine = new GenericMachine(); - context = new MuLangContext("basic","main"); + machine = new GenericMachine(); + context = new MuLangContext("basic", "main"); language = new MuLangLanguage(); - process = new Process(context); + process = new Process(context); - if (disableGC) GarbageCollector::disable(); + if (disableGC) + GarbageCollector::disable(); Module::setCompileOnDemand(compile == 1, compile == 1); #ifdef LINKED_MODULES - Module* autodoc = new Mu::AutoDocModule(context, "autodoc"); - Module* io = new Mu::IOModule(context, "io"); - Module* image = new Mu::ImageModule(context, "image"); - Module* sys = new Mu::SystemModule(context, "system"); - Module* enc = new Mu::SystemModule(context, "encoding"); - Module* qt = new Mu::qtModule(context, "qt"); + Module* autodoc = new Mu::AutoDocModule(context, "autodoc"); + Module* io = new Mu::IOModule(context, "io"); + Module* image = new Mu::ImageModule(context, "image"); + Module* sys = new Mu::SystemModule(context, "system"); + Module* enc = new Mu::SystemModule(context, "encoding"); + Module* qt = new Mu::qtModule(context, "qt"); context->globalScope()->addSymbol(autodoc); context->globalScope()->addSymbol(image); @@ -196,7 +194,7 @@ main(int argc, char **argv) context->verbose(why ? true : false); context->debugging(debug ? true : false); gThread = process->newApplicationThread(); - + if (!noninteractive && !inFile) { InteractiveSession session; @@ -240,40 +238,38 @@ main(int argc, char **argv) cerr << "ERROR: Uncaught exception" << endl; exit(-1); } - + if (symbols) { - cout << "SYMBOLS\n" << flush; - cout << "-------\n" << flush; - dumpSymbols(context->globalScope(),0); - cout << endl << flush; + cout << "SYMBOLS\n" << flush; + cout << "-------\n" << flush; + dumpSymbols(context->globalScope(), 0); + cout << endl << flush; } if (process->rootNode()) { - if (print) - { - cout << "\nNODE TREE\n" << flush; - NodePrinter printer(process->rootNode(), cout, - NodePrinter::Lispy); - printer.traverse(); + if (print) + { + cout << "\nNODE TREE\n" << flush; + NodePrinter printer(process->rootNode(), cout, NodePrinter::Lispy); + printer.traverse(); cout << endl; - } + } - #if 0 getrusage(RUSAGE_SELF, &start_usage); #endif - if (!noeval) - { - Value v = process->evaluate(gThread); + if (!noeval) + { + Value v = process->evaluate(gThread); - if (const Type *type = gThread->returnValueType()) + if (const Type* type = gThread->returnValueType()) { if (!type->isTypePattern()) { - //type->output(cout); + // type->output(cout); cout << "result"; cout << " => "; type->outputValue(cout, v, notruncate != 0); @@ -284,19 +280,21 @@ main(int argc, char **argv) { cout << "=> Unknown return type and value" << endl; } - } + } } if (printFunc) { - QualifiedName n = context->internName(printFunc); + QualifiedName n = context->internName(printFunc); - if (const Symbol *sym = - context->globalScope()->findSymbolByQualifiedName(n, false)) + if (const Symbol* sym = + context->globalScope()->findSymbolByQualifiedName(n, false)) { - for (const Symbol *s = sym->firstOverload(); s; s = s->nextOverload()) + for (const Symbol* s = sym->firstOverload(); s; + s = s->nextOverload()) { - if (const Mu::Function *f = dynamic_cast(s)) + if (const Mu::Function* f = + dynamic_cast(s)) { cout << "Function: " << f->name() << " "; @@ -319,33 +317,34 @@ main(int argc, char **argv) if (callmain) { - if (Name n = context->lookupName("main")) - { - if (Mu::Function *f = - context->globalScope()->findSymbolOfType(n)) - { - StringType *stype = context->globalScope()-> - findSymbolOfType(context->lookupName("string")); - - DynamicArrayType *arrayType = - static_cast(context->arrayType(stype, 1, 0)); - DynamicArray *array = new DynamicArray(arrayType, 1); - - array->resize(argc); - - for (int i=0; i < argc; i++) - { - StringType::String *s = stype->allocate(argv[i]); - array->element(i) = s; - } - - cout << "RUNNING MAIN:\n"; - - Mu::Function::ArgumentVector vargs; - vargs.push_back(Value(array)); - process->call(gThread, f, vargs); - } - } + if (Name n = context->lookupName("main")) + { + if (Mu::Function* f = + context->globalScope()->findSymbolOfType(n)) + { + StringType* stype = + context->globalScope()->findSymbolOfType( + context->lookupName("string")); + + DynamicArrayType* arrayType = static_cast( + context->arrayType(stype, 1, 0)); + DynamicArray* array = new DynamicArray(arrayType, 1); + + array->resize(argc); + + for (int i = 0; i < argc; i++) + { + StringType::String* s = stype->allocate(argv[i]); + array->element(i) = s; + } + + cout << "RUNNING MAIN:\n"; + + Mu::Function::ArgumentVector vargs; + vargs.push_back(Value(array)); + process->call(gThread, f, vargs); + } + } } #if 0 @@ -369,7 +368,5 @@ main(int argc, char **argv) } #endif - return 0; } - diff --git a/src/bin/mu/mu-interp/test/ack.cpp b/src/bin/mu/mu-interp/test/ack.cpp index 3c08eb58b..7a4032860 100644 --- a/src/bin/mu/mu-interp/test/ack.cpp +++ b/src/bin/mu/mu-interp/test/ack.cpp @@ -1,14 +1,15 @@ // -// Copyright (C) 2023 Autodesk, Inc. All Rights Reserved. -// -// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2023 Autodesk, Inc. All Rights Reserved. +// +// SPDX-License-Identifier: Apache-2.0 // #include using namespace std; -int ack (int m, int n) +int ack(int m, int n) { - return m == 0 ? (n+1) : (n == 0 ? ack(m-1, 1) : ack(m-1, ack(m, n-1))); + return m == 0 ? (n + 1) + : (n == 0 ? ack(m - 1, 1) : ack(m - 1, ack(m, n - 1))); } int main(int argc, const char** argv) diff --git a/src/bin/nsapps/RV/main.cpp b/src/bin/nsapps/RV/main.cpp index a66c6b2b5..7bf65d072 100644 --- a/src/bin/nsapps/RV/main.cpp +++ b/src/bin/nsapps/RV/main.cpp @@ -1,8 +1,8 @@ //****************************************************************************** // Copyright (c) 2008 Tweak Software. All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #include #include @@ -71,7 +71,7 @@ extern const char* rv_mac_aqua; // RV third party optional customization #if defined(RV_THIRD_PARTY_CUSTOMIZATION) - extern void rvThirdPartyCustomization(TwkApp::Bundle& bundle, char* licarg); +extern void rvThirdPartyCustomization(TwkApp::Bundle& bundle, char* licarg); #endif // @@ -81,9 +81,9 @@ extern const char* rv_mac_aqua; #if MAJOR_VERSION == 99 #if NDEBUG -//#error ********* NO VERSION INFORMATION *********** +// #error ********* NO VERSION INFORMATION *********** #else -#warning ********* NO VERSION INFORMATION *********** +#warning********* NO VERSION INFORMATION *********** #endif #endif @@ -100,26 +100,24 @@ static void control_c_handler(int sig) exit(1); } -static int rtPeriod = 240; +static int rtPeriod = 240; static int rtComputation = 720; -static int rtConstraint = 360; +static int rtConstraint = 360; static int rtPreemptable = 1; - -static int -set_realtime(int period, int computation, int constraint) +static int set_realtime(int period, int computation, int constraint) { struct thread_time_constraint_policy ttcpolicy; - ttcpolicy.period=period; // HZ/160 - ttcpolicy.computation=computation; // HZ/3300; - ttcpolicy.constraint=constraint; // HZ/2200; - ttcpolicy.preemptible=1; + ttcpolicy.period = period; // HZ/160 + ttcpolicy.computation = computation; // HZ/3300; + ttcpolicy.constraint = constraint; // HZ/2200; + ttcpolicy.preemptible = 1; - if (thread_policy_set(mach_thread_self(), - THREAD_TIME_CONSTRAINT_POLICY, + if (thread_policy_set(mach_thread_self(), THREAD_TIME_CONSTRAINT_POLICY, (thread_policy_t)&ttcpolicy, - THREAD_TIME_CONSTRAINT_POLICY_COUNT) != KERN_SUCCESS) + THREAD_TIME_CONSTRAINT_POLICY_COUNT) + != KERN_SUCCESS) { return 0; } @@ -130,13 +128,13 @@ set_realtime(int period, int computation, int constraint) void thread_priority_init() { struct thread_time_constraint_policy ttcpolicy; - int ret, bus_speed, mib [2] = { CTL_HW, HW_BUS_FREQ }; + int ret, bus_speed, mib[2] = {CTL_HW, HW_BUS_FREQ}; size_t len; len = sizeof(bus_speed); #if !defined(__aarch64__) - int ret2 = sysctl (mib, 2, &bus_speed, &len, NULL, 0); + int ret2 = sysctl(mib, 2, &bus_speed, &len, NULL, 0); if (ret2 < 0) { cout << "ERROR: unable to get system bus frequency: " << ret2 << endl; @@ -171,15 +169,13 @@ void thread_priority_init() // // - ttcpolicy.period = bus_speed / rtPeriod; + ttcpolicy.period = bus_speed / rtPeriod; ttcpolicy.computation = bus_speed / rtComputation; - ttcpolicy.constraint = bus_speed / rtConstraint; + ttcpolicy.constraint = bus_speed / rtConstraint; ttcpolicy.preemptible = rtPreemptable != 0; - if (thread_policy_set(mach_thread_self(), - THREAD_TIME_CONSTRAINT_POLICY, - (int *)&ttcpolicy, - THREAD_TIME_CONSTRAINT_POLICY_COUNT) + if (thread_policy_set(mach_thread_self(), THREAD_TIME_CONSTRAINT_POLICY, + (int*)&ttcpolicy, THREAD_TIME_CONSTRAINT_POLICY_COUNT) != KERN_SUCCESS) { cout << "INFO: running without real-time scheduling" << endl; @@ -187,8 +183,7 @@ void thread_priority_init() else { cout << "INFO: real-time thread priorities set (bus=" - << (bus_speed/1000) << "kHz)" - << endl; + << (bus_speed / 1000) << "kHz)" << endl; } } @@ -207,17 +202,17 @@ string scarfFile(const string& fileName) static string qtver; -static int gc_filter (const char* name, void* ptr, size_t size) +static int gc_filter(const char* name, void* ptr, size_t size) { string s(name); - if (s.find("/Library/Frameworks/") != string::npos || - s.find("/System/Library/Frameworks/") != string::npos || - s.find("/usr/lib/") != string::npos || - s.find("imageformats/libq") != string::npos || - s.find(qtver) != string::npos) + if (s.find("/Library/Frameworks/") != string::npos + || s.find("/System/Library/Frameworks/") != string::npos + || s.find("/usr/lib/") != string::npos + || s.find("imageformats/libq") != string::npos + || s.find(qtver) != string::npos) { - //cout << "SKIPPING: " << name << endl; + // cout << "SKIPPING: " << name << endl; return 0; } else @@ -226,18 +221,20 @@ static int gc_filter (const char* name, void* ptr, size_t size) } } -int main(int argc, char *argv[]) +int main(int argc, char* argv[]) { if (!getenv("HOME")) { - cerr << "ERROR: $HOME is not set in the environment and is required." << endl; + cerr << "ERROR: $HOME is not set in the environment and is required." + << endl; exit(-1); } // - // As of OSX 10.7, interesting settings of the locale can cause crashes in apple core code. + // As of OSX 10.7, interesting settings of the locale can cause crashes in + // apple core code. // - if(getenv("LANG")) + if (getenv("LANG")) { std::string originalLocale = getenv("LANG"); setenv("ORIGINALLOCAL", originalLocale.c_str(), 1); @@ -246,19 +243,22 @@ int main(int argc, char *argv[]) { setenv("ORIGINALLOCAL", "en", 1); } - setenv ("LANG", "C", 1); - setenv ("LC_ALL", "C", 1); + setenv("LANG", "C", 1); + setenv("LC_ALL", "C", 1); // Qt 5.12.1 specific - // Disable Qt Quick hardware rendering because QwebEngineView conflicts with QGLWidget - setenv( "QT_QUICK_BACKEND", "software", 0 /* changeFlag : Do not change the existing value */); + // Disable Qt Quick hardware rendering because QwebEngineView conflicts with + // QGLWidget + setenv("QT_QUICK_BACKEND", "software", + 0 /* changeFlag : Do not change the existing value */); // Qt 5.12.1 specific // Prevent Mac from automatically scaling app pixel coordinates in OpenGL - setenv("QT_MAC_WANTS_BEST_RESOLUTION_OPENGL_SURFACE", "0", 0); /* changeFlag : Do not change the existing value */ + setenv("QT_MAC_WANTS_BEST_RESOLUTION_OPENGL_SURFACE", "0", + 0); /* changeFlag : Do not change the existing value */ - // Prevent usage of native sibling widgets on Mac. This attribute can be removed - // if GLView is changed to inherit from QOpenGLWidget. + // Prevent usage of native sibling widgets on Mac. This attribute can be + // removed if GLView is changed to inherit from QOpenGLWidget. QApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings); const bool noHighDPISupport = getenv("RV_QT_HDPI_SUPPORT") == nullptr; @@ -273,25 +273,28 @@ int main(int argc, char *argv[]) } const char* pythonPath = getenv("PYTHONPATH"); - if (pythonPath) pythonPath = strdup(pythonPath); - - #ifndef PLATFORM_WINDOWS - // - // Check the per-process limit on open file descriptors and - // reset the soft limit to the hard limit. - // - struct rlimit rlim; - getrlimit (RLIMIT_NOFILE, &rlim); - rlim_t target = rlim.rlim_max; - if (OPEN_MAX < rlim.rlim_max) target = OPEN_MAX; - rlim.rlim_cur = target; - setrlimit (RLIMIT_NOFILE, &rlim); - getrlimit (RLIMIT_NOFILE, &rlim); - if (rlim.rlim_cur < target) - { - cerr << "WARNING: unable to increase open file limit above " << rlim.rlim_cur << endl; - } - #endif + if (pythonPath) + pythonPath = strdup(pythonPath); + +#ifndef PLATFORM_WINDOWS + // + // Check the per-process limit on open file descriptors and + // reset the soft limit to the hard limit. + // + struct rlimit rlim; + getrlimit(RLIMIT_NOFILE, &rlim); + rlim_t target = rlim.rlim_max; + if (OPEN_MAX < rlim.rlim_max) + target = OPEN_MAX; + rlim.rlim_cur = target; + setrlimit(RLIMIT_NOFILE, &rlim); + getrlimit(RLIMIT_NOFILE, &rlim); + if (rlim.rlim_cur < target) + { + cerr << "WARNING: unable to increase open file limit above " + << rlim.rlim_cur << endl; + } +#endif { string qt(QT_VERSION_STR); @@ -306,13 +309,12 @@ int main(int argc, char *argv[]) string altPrefsPath; for (size_t i = 0; i < argc; i++) { - if (i < argc-1 && !strcmp(argv[i], "-prefsPath")) altPrefsPath = argv[i+1]; + if (i < argc - 1 && !strcmp(argv[i], "-prefsPath")) + altPrefsPath = argv[i + 1]; } - Rv::RvApplication::initializeQSettings (altPrefsPath); + Rv::RvApplication::initializeQSettings(altPrefsPath); - TwkApp::DarwinBundle bundle("RV", - MAJOR_VERSION, - MINOR_VERSION, + TwkApp::DarwinBundle bundle("RV", MAJOR_VERSION, MINOR_VERSION, REVISION_NUMBER, true /*register rvlink protocol handler*/); @@ -322,15 +324,16 @@ int main(int argc, char *argv[]) // Expand any rvlink urls in argv // - vector newArgv; + vector newArgv; for (int i = 0; i < argc; ++i) { - if (0 == strncmp ("rvlink://", argv[i], 9)) + if (0 == strncmp("rvlink://", argv[i], 9)) { - Rv::RvApplication::parseURL (argv[i], newArgv); + Rv::RvApplication::parseURL(argv[i], newArgv); } - else newArgv.push_back (argv[i]); + else + newArgv.push_back(argv[i]); } argv = &(newArgv[0]); argc = newArgv.size(); @@ -340,25 +343,28 @@ int main(int argc, char *argv[]) for (size_t i = 0; i < argc; i++) { - if (!strcmp(argv[i], "-noPrefs")) noPrefs = true; - else if (!strcmp(argv[i], "-resetPrefs")) resetPrefs = true; + if (!strcmp(argv[i], "-noPrefs")) + noPrefs = true; + else if (!strcmp(argv[i], "-resetPrefs")) + resetPrefs = true; else if (!strcmp(argv[i], "-bakeURL")) { - string url = Rv::RvApplication::bakeCommandLineURL (argc, argv); + string url = Rv::RvApplication::bakeCommandLineURL(argc, argv); cerr << "Baked URL: " << url << endl; exit(0); } else if (!strcmp(argv[i], "-encodeURL")) { - string url = Rv::RvApplication::encodeCommandLineURL (argc, argv); + string url = Rv::RvApplication::encodeCommandLineURL(argc, argv); cerr << "Encoded URL: " << url << endl; exit(0); } else if (!strcmp(argv[i], "-registerHandler")) { bundle.registerHandler(); - cerr << "INFO: registering '" << argv[0] << "' as default rvlink protocol handler." << endl; + cerr << "INFO: registering '" << argv[0] + << "' as default rvlink protocol handler." << endl; exit(0); } } @@ -368,9 +374,12 @@ int main(int argc, char *argv[]) // Rv::Options& opts = Rv::Options::sharedOptions(); - if (resetPrefs) Rv::RvPreferences::resetPreferencesFile(); - if (!noPrefs) Rv::RvPreferences::loadSettingsIntoOptions(opts); - else Rv::PackageManager::setIgnorePrefs(true); + if (resetPrefs) + Rv::RvPreferences::resetPreferencesFile(); + if (!noPrefs) + Rv::RvPreferences::loadSettingsIntoOptions(opts); + else + Rv::PackageManager::setIgnorePrefs(true); Rv::Options::manglePerSourceArgs(argv, argc); Rv::Options prefOpts = opts; @@ -382,12 +391,12 @@ int main(int argc, char *argv[]) // // Required by the Live Review RV plugin React component's scroll bars - std::vector arguments( argv, argv + argc ); + std::vector arguments(argv, argv + argc); static char enableOverlayScrollbar[] = "--enable-features=OverlayScrollbar"; - arguments.emplace_back( enableOverlayScrollbar ); - argc = static_cast( arguments.size() ); + arguments.emplace_back(enableOverlayScrollbar); + argc = static_cast(arguments.size()); argv = &arguments[0]; -; + ; // // Initialze IMF library for multi-threading @@ -397,16 +406,14 @@ int main(int argc, char *argv[]) // Call the deploy functions // - TWK_DEPLOY_APP_OBJECT dobj(MAJOR_VERSION, - MINOR_VERSION, - REVISION_NUMBER, - argc, argv, - RELEASE_DESCRIPTION, + TWK_DEPLOY_APP_OBJECT dobj(MAJOR_VERSION, MINOR_VERSION, REVISION_NUMBER, + argc, argv, RELEASE_DESCRIPTION, "HEAD=" GIT_HEAD); Imf::staticInitialize(); - TwkFB::GenericIO::init(); // Initialize TwkFB::GenericIO plugins statics - TwkMovie::GenericIO::init(); // Initialize TwkMovie::GenericIO plugins statics + TwkFB::GenericIO::init(); // Initialize TwkFB::GenericIO plugins statics + TwkMovie::GenericIO::init(); // Initialize TwkMovie::GenericIO plugins + // statics // // We handle the '--help' flag by changing it to '-help' for @@ -427,28 +434,32 @@ int main(int argc, char *argv[]) IPCore::Application::cacheEnvVars(); - int strictlicense = 0; - int registerHandler = 0; - char *prefsPath; - int sleepTime = 0; - - if (arg_parse - (nargv.size(), &nargv.front(), - "", "", - RV_ARG_EXAMPLES, - "", "", - RV_ARG_SEQUENCE_HELP, - "", "", - RV_ARG_SOURCE_OPTIONS(opts), - "", "", - "", ARG_SUBR(Rv::RvApplication::parseInFiles), "Input sequence patterns, images, movies, or directories ", - RV_ARG_PARSE_OPTIONS(opts), - "-strictlicense", ARG_FLAG(&strictlicense), "Exit rather than consume an RV license if no rvsolo licenses are available", - "-prefsPath %S", &prefsPath, "Alternate path to preferences directory", - "-registerHandler", ARG_FLAG(®isterHandler), "Register this executable as the default rvlink protocol handler (OS X only)", - "-rt %d %d %d %d", &rtPeriod, &rtComputation, &rtConstraint, &rtPreemptable, "Real time parameters (default=%d %d %d %d)", rtPeriod, rtComputation, rtConstraint, rtPreemptable, - "-sleep %d", &sleepTime, "Sleep (in seconds) before starting to allow attaching debugger", - NULL) < 0) + int strictlicense = 0; + int registerHandler = 0; + char* prefsPath; + int sleepTime = 0; + + if (arg_parse( + nargv.size(), &nargv.front(), "", "", RV_ARG_EXAMPLES, "", "", + RV_ARG_SEQUENCE_HELP, "", "", RV_ARG_SOURCE_OPTIONS(opts), "", "", + "", ARG_SUBR(Rv::RvApplication::parseInFiles), + "Input sequence patterns, images, movies, or directories ", + RV_ARG_PARSE_OPTIONS(opts), "-strictlicense", + ARG_FLAG(&strictlicense), + "Exit rather than consume an RV license if no rvsolo licenses are " + "available", + "-prefsPath %S", &prefsPath, + "Alternate path to preferences directory", "-registerHandler", + ARG_FLAG(®isterHandler), + "Register this executable as the default rvlink protocol handler " + "(OS X only)", + "-rt %d %d %d %d", &rtPeriod, &rtComputation, &rtConstraint, + &rtPreemptable, "Real time parameters (default=%d %d %d %d)", + rtPeriod, rtComputation, rtConstraint, rtPreemptable, "-sleep %d", + &sleepTime, + "Sleep (in seconds) before starting to allow attaching debugger", + NULL) + < 0) { exit(-1); } @@ -456,13 +467,14 @@ int main(int argc, char *argv[]) if (sleepTime > 0) { cout << "INFO: sleeping " << sleepTime << " seconds" << endl; - std::this_thread::sleep_for( std::chrono::seconds( sleepTime ) ); + std::this_thread::sleep_for(std::chrono::seconds(sleepTime)); cout << "INFO: continuing after sleep" << endl; } if (opts.showVersion) { - cout << MAJOR_VERSION << "." << MINOR_VERSION << "." << REVISION_NUMBER << endl; + cout << MAJOR_VERSION << "." << MINOR_VERSION << "." << REVISION_NUMBER + << endl; exit(0); } @@ -498,8 +510,8 @@ int main(int argc, char *argv[]) else { Imf::setGlobalThreadCount(TwkUtil::SystemInfo::numCPUs() > 1 - ? (TwkUtil::SystemInfo::numCPUs()-1) - : 1); + ? (TwkUtil::SystemInfo::numCPUs() - 1) + : 1); } // @@ -510,30 +522,31 @@ int main(int argc, char *argv[]) QTranslator* translator = new QTranslator(); QLocale locale = QLocale(getenv("ORIGINALLOCAL")); - if (translator->load(locale, QLatin1String("i18n"), "_",QLatin1String(":/translations"))) { + if (translator->load(locale, QLatin1String("i18n"), "_", + QLatin1String(":/translations"))) + { app->installTranslator(translator); } +#ifdef PLATFORM_DARWIN + // + // As of Qt 4.7, the qt.conf file in Contents/Resources no longer + // seems to get Qt to look in our plugins dir. As a result plugins + // can be loaded from /Developer, etc, and chaos ensues. The below + // seems to do the trick. + // + QDir dir(QCoreApplication::applicationDirPath()); + dir.cdUp(); + dir.cd("PlugIns"); + dir.cd("Qt"); + QCoreApplication::addLibraryPath(dir.absolutePath()); - #ifdef PLATFORM_DARWIN - // - // As of Qt 4.7, the qt.conf file in Contents/Resources no longer - // seems to get Qt to look in our plugins dir. As a result plugins - // can be loaded from /Developer, etc, and chaos ensues. The below - // seems to do the trick. - // - QDir dir(QCoreApplication::applicationDirPath()); - dir.cdUp(); - dir.cd("PlugIns"); - dir.cd("Qt"); - QCoreApplication::addLibraryPath(dir.absolutePath()); - - dir.cdUp(); - dir.cdUp(); - dir.cd("MacOS"); - QCoreApplication::removeLibraryPath(dir.absolutePath()); - QCoreApplication::removeLibraryPath("/Developer/Applications/Qt/plugins"); - #endif + dir.cdUp(); + dir.cdUp(); + dir.cd("MacOS"); + QCoreApplication::removeLibraryPath(dir.absolutePath()); + QCoreApplication::removeLibraryPath("/Developer/Applications/Qt/plugins"); +#endif Rv::RvApplication* rvapp = new Rv::RvApplication(argc, argv); app->installEventFilter(rvapp); @@ -551,21 +564,30 @@ int main(int argc, char *argv[]) // 5) ./rvrc.mu // - if (getenv("RV_APP_RVIO")) bundle.setEnvVar("RV_APP_RVIO_SET_BY_USER", "true"); - else bundle.setEnvVar("RV_APP_RVIO", bundle.executableFile("rvio")); + if (getenv("RV_APP_RVIO")) + bundle.setEnvVar("RV_APP_RVIO_SET_BY_USER", "true"); + else + bundle.setEnvVar("RV_APP_RVIO", bundle.executableFile("rvio")); bundle.setEnvVar("RV_APP_RV", bundle.executableFile("RV")); bundle.setEnvVar("RV_APP_RV_SHORT_NAME", "RV"); bundle.setEnvVar("RV_APP_MANUAL", bundle.resource("rv_manual", "pdf")); - bundle.setEnvVar("RV_APP_MANUAL_HTML", bundle.resource("rv_manual", "html")); - bundle.setEnvVar("RV_APP_SDI_MANUAL", bundle.resource("rvsdi_manual", "pdf")); - bundle.setEnvVar("RV_APP_SDI_MANUAL_HTML", bundle.resource("rvsdi_manual", "html")); - bundle.setEnvVar("RV_APP_REFERENCE_MANUAL", bundle.resource("rv_reference", "pdf")); - bundle.setEnvVar("RV_APP_REFERENCE_MANUAL_HTML", bundle.resource("rv_reference", "html")); + bundle.setEnvVar("RV_APP_MANUAL_HTML", + bundle.resource("rv_manual", "html")); + bundle.setEnvVar("RV_APP_SDI_MANUAL", + bundle.resource("rvsdi_manual", "pdf")); + bundle.setEnvVar("RV_APP_SDI_MANUAL_HTML", + bundle.resource("rvsdi_manual", "html")); + bundle.setEnvVar("RV_APP_REFERENCE_MANUAL", + bundle.resource("rv_reference", "pdf")); + bundle.setEnvVar("RV_APP_REFERENCE_MANUAL_HTML", + bundle.resource("rv_reference", "html")); bundle.setEnvVar("RV_APP_MU_MANUAL", bundle.resource("mu", "pdf")); bundle.setEnvVar("RV_APP_GTO_REFERENCE", bundle.resource("gto", "pdf")); - bundle.setEnvVar("RV_APP_RELEASE_NOTES", bundle.resource("rv_release_notes", "html")); - bundle.setEnvVar("RV_APP_LICENSES_NOTES", bundle.resource("rv_client_licenses", "html")); + bundle.setEnvVar("RV_APP_RELEASE_NOTES", + bundle.resource("rv_release_notes", "html")); + bundle.setEnvVar("RV_APP_LICENSES_NOTES", + bundle.resource("rv_client_licenses", "html")); bundle.addPathToEnvVar("OIIO_LIBRARY_PATH", bundle.appPluginPath("OIIO")); // @@ -584,13 +606,14 @@ int main(int argc, char *argv[]) try { - //TwkFB::GenericIO::loadPlugins("TWK_FB_PLUGIN_PATH"); + // TwkFB::GenericIO::loadPlugins("TWK_FB_PLUGIN_PATH"); TwkFB::loadProxyPlugins("TWK_FB_PLUGIN_PATH"); TwkMovie::loadProxyPlugins("TWK_MOVIE_PLUGIN_PATH"); } catch (...) { - cerr << "WARNING: a problem occured while loading image plugins." << endl; + cerr << "WARNING: a problem occured while loading image plugins." + << endl; cerr << " some plugins may not have been loaded." << endl; } @@ -607,7 +630,8 @@ int main(int argc, char *argv[]) // QT starts here // - if (!getenv("RV_DARK")) bundle.setEnvVar("RV_DARK", "", true); + if (!getenv("RV_DARK")) + bundle.setEnvVar("RV_DARK", "", true); QString csstext; @@ -618,9 +642,7 @@ int main(int argc, char *argv[]) } else { - csstext = QString(rv_mac_dark) - .arg(opts.fontSize1) - .arg(opts.fontSize2); + csstext = QString(rv_mac_dark).arg(opts.fontSize1).arg(opts.fontSize2); } if (!opts.qtstyle || !strcmp(opts.qtstyle, "RV")) @@ -643,18 +665,17 @@ int main(int argc, char *argv[]) exit(-1); } - TwkApp::initWithFile(TwkApp::muContext(), - TwkApp::muProcess(), - TwkApp::muModuleList(), - muInitFile.c_str()); + TwkApp::initWithFile(TwkApp::muContext(), TwkApp::muProcess(), + TwkApp::muModuleList(), muInitFile.c_str()); - TwkApp::pyInitWithFile(pyInitFile.c_str(), Rv::pyRvAppCommands(), Rv::pyUICommands()); + TwkApp::pyInitWithFile(pyInitFile.c_str(), Rv::pyRvAppCommands(), + Rv::pyUICommands()); } - catch (const exception &e) + catch (const exception& e) { cerr << "ERROR: during initialization: " << e.what() << endl; rvapp->console()->processLastTextBuffer(); - exit( -1 ); + exit(-1); } rvapp->console()->processTextBuffer(); @@ -682,16 +703,16 @@ int main(int argc, char *argv[]) { try { - #ifdef PLATFORM_DARWIN - // - // As of Qt 4.7, they have moved their event handler registration deep - // into the event loop so it's not possible to override it. Turns out - // that if we set this attribute at exactly this moment, it prevents the - // handler registration overriding without any other bad effects. We - // hope. XXX - // - QCoreApplication::setAttribute (Qt::AA_DontUseNativeMenuBar, false); - #endif +#ifdef PLATFORM_DARWIN + // + // As of Qt 4.7, they have moved their event handler registration + // deep into the event loop so it's not possible to override it. + // Turns out that if we set this attribute at exactly this moment, + // it prevents the handler registration overriding without any + // other bad effects. We hope. XXX + // + QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuBar, false); +#endif rval = app->exec(); } catch (TwkExc::Exception& exc) @@ -699,10 +720,9 @@ int main(int argc, char *argv[]) cerr << exc; exit(-1); } - catch (const exception &e) + catch (const exception& e) { - cerr << "ERROR: Unhandled exception during execution: " - << e.what() + cerr << "ERROR: Unhandled exception during execution: " << e.what() << endl; exit(-1); @@ -715,8 +735,8 @@ int main(int argc, char *argv[]) } TwkMovie::GenericIO::shutdown(); // Shutdown TwkMovie::GenericIO plugins - TwkFB::GenericIO::shutdown(); // Shutdown TwkFB::GenericIO plugins - TwkFB::ThreadPool::shutdown(); // Shutdown TwkFB ThreadPool + TwkFB::GenericIO::shutdown(); // Shutdown TwkFB::GenericIO plugins + TwkFB::ThreadPool::shutdown(); // Shutdown TwkFB ThreadPool TwkGLF::UninitPBOPools(); diff --git a/src/bin/python/py-interp/main.cpp b/src/bin/python/py-interp/main.cpp index 3af13e818..11ccb75b5 100644 --- a/src/bin/python/py-interp/main.cpp +++ b/src/bin/python/py-interp/main.cpp @@ -1,7 +1,7 @@ // -// Copyright (C) 2023 Autodesk, Inc. All Rights Reserved. -// -// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2023 Autodesk, Inc. All Rights Reserved. +// +// SPDX-License-Identifier: Apache-2.0 // /* Minimal main program -- everything is loaded from the library */ @@ -21,43 +21,49 @@ using namespace std; using namespace TwkApp; #ifdef PLATFORM_DARWIN -DarwinBundle bundle("python", BUNDLE_MAJOR_VERSION, BUNDLE_MINOR_VERSION, BUNDLE_REVISION_NUMBER); +DarwinBundle bundle("python", BUNDLE_MAJOR_VERSION, BUNDLE_MINOR_VERSION, + BUNDLE_REVISION_NUMBER); #else -QTBundle bundle("python", BUNDLE_MAJOR_VERSION, BUNDLE_MINOR_VERSION, BUNDLE_REVISION_NUMBER); +QTBundle bundle("python", BUNDLE_MAJOR_VERSION, BUNDLE_MINOR_VERSION, + BUNDLE_REVISION_NUMBER); #endif -int -main(int argc, char **argv) +int main(int argc, char** argv) { - //Sleep(10 * 1000); + // Sleep(10 * 1000); QApplication app(argc, argv); #ifndef PLATFORM_DARWIN bundle.initializeAfterQApplication(); // cause init() to be called #endif - Py_SetProgramName( Py_DecodeLocale( argv[0], nullptr ) ); - // Current issue: sys.path doesn't hold the site-packages path and thus py-interp cannot import modules. - // This is the same as calling py-interp with -S since this disables site.py on init which is the symptom of the current issue. + Py_SetProgramName(Py_DecodeLocale(argv[0], nullptr)); + // Current issue: sys.path doesn't hold the site-packages path and thus + // py-interp cannot import modules. This is the same as calling py-interp + // with -S since this disables site.py on init which is the symptom of the + // current issue. // Py_InitializeEx(1); // Note about Py_Initilialize: - // See here for issue about calling Py_Initialize and Py_Main after: https://bugs.python.org/issue34008 - // See here for which functions are allowed to be called before Py_Initialize: https://docs.python.org/3/c-api/init.html#pre-init-safe - // And we can infer, based on the previous 2 links, that it also safe for Py_Main (since it calls Py_Initialize itself) + // See here for issue about calling Py_Initialize and Py_Main after: + // https://bugs.python.org/issue34008 See here for which functions are + // allowed to be called before Py_Initialize: + // https://docs.python.org/3/c-api/init.html#pre-init-safe And we can infer, + // based on the previous 2 links, that it also safe for Py_Main (since it + // calls Py_Initialize itself) static wchar_t delim = L'\0'; wchar_t** w_argv = new wchar_t*[argc + 1]; w_argv[argc] = &delim; - for(int i = 0; i < argc; ++i) + for (int i = 0; i < argc; ++i) { - w_argv[i] = Py_DecodeLocale(argv[i], nullptr); + w_argv[i] = Py_DecodeLocale(argv[i], nullptr); } - // PySys_SetArgvEx is deprecated in 3.11 (and using PySys_SetArgvEx without Py_Initialize crashes on make) - // PySys_SetArgvEx( argc, w_argv, 0 ); + // PySys_SetArgvEx is deprecated in 3.11 (and using PySys_SetArgvEx without + // Py_Initialize crashes on make) PySys_SetArgvEx( argc, w_argv, 0 ); PyConfig config; PyConfig_InitPythonConfig(&config); @@ -65,8 +71,10 @@ main(int argc, char **argv) // config.safe_path is new in 3.11 // config.safe_path = 0; - // Not calling Py_InitializeFromConfig(&config); since it's the same problem than Py_Initialize - // Argv is still passed; you can repro (cause the same problem) the current issue by calling py-interp with -S i.e.: "./py-interp -S" + // Not calling Py_InitializeFromConfig(&config); since it's the same problem + // than Py_Initialize Argv is still passed; you can repro (cause the same + // problem) the current issue by calling py-interp with -S i.e.: + // "./py-interp -S" #ifdef PLATFORM_WINDOWS // diff --git a/src/bin/utf8Main.cpp b/src/bin/utf8Main.cpp index 64a268b56..447f8cd85 100644 --- a/src/bin/utf8Main.cpp +++ b/src/bin/utf8Main.cpp @@ -6,46 +6,43 @@ // //*****************************************************************************/ -#if defined( _WIN32 ) +#if defined(_WIN32) #include #include #endif +int utf8Main(int argc, char* argv[]); -int utf8Main( int argc, char* argv[] ); - -#if defined( _WIN32 ) +#if defined(_WIN32) int wmain(int argc, wchar_t* wargv[]) { - // converts UCS2 arguements to utf-8 charset - char ** argv = new char * [argc]; - for (int argn = 0; argn < argc; argn++) - { - int sizeNeeded = WideCharToMultiByte(CP_UTF8, 0, wargv[argn], -1, NULL, 0, NULL, NULL); - if (sizeNeeded > 0 ) + // converts UCS2 arguements to utf-8 charset + char** argv = new char*[argc]; + for (int argn = 0; argn < argc; argn++) { - char * strTo = new char [sizeNeeded]; - WideCharToMultiByte(CP_UTF8, 0, wargv[argn], -1, strTo, sizeNeeded, NULL, NULL); - argv[argn] = strTo; + int sizeNeeded = WideCharToMultiByte(CP_UTF8, 0, wargv[argn], -1, NULL, + 0, NULL, NULL); + if (sizeNeeded > 0) + { + char* strTo = new char[sizeNeeded]; + WideCharToMultiByte(CP_UTF8, 0, wargv[argn], -1, strTo, sizeNeeded, + NULL, NULL); + argv[argn] = strTo; + } + else + argv[argn] = nullptr; } - else - argv[argn] = nullptr; - } - - int result = utf8Main(argc, argv); - - for (int argn = 0; argn < argc; argn++) - delete [] argv[argn]; - - delete [] argv; - - return result; + + int result = utf8Main(argc, argv); + + for (int argn = 0; argn < argc; argn++) + delete[] argv[argn]; + + delete[] argv; + + return result; } #else -int main(int argc, char* argv[]) -{ - return utf8Main(argc, argv); -} +int main(int argc, char* argv[]) { return utf8Main(argc, argv); } #endif - diff --git a/src/bin/utf8Main.h b/src/bin/utf8Main.h index 31f4a4b09..cd9b3d5dd 100644 --- a/src/bin/utf8Main.h +++ b/src/bin/utf8Main.h @@ -6,4 +6,4 @@ // //*****************************************************************************/ -int utf8Main( int argc, char* argv[] ); +int utf8Main(int argc, char* argv[]); diff --git a/src/bin/utf8WinMain.cpp b/src/bin/utf8WinMain.cpp index 4c030d9d0..d3c3eb7c0 100644 --- a/src/bin/utf8WinMain.cpp +++ b/src/bin/utf8WinMain.cpp @@ -6,55 +6,54 @@ // //*****************************************************************************/ -#if defined( _WIN32 ) +#if defined(_WIN32) #include #include #endif +int utf8Main(int argc, char* argv[]); -int utf8Main( int argc, char* argv[] ); - -#if defined( _WIN32 ) +#if defined(_WIN32) int wmain(int argc, wchar_t* wargv[]) { - // converts UCS2 arguements to utf-8 charset - char ** argv = new char * [argc]; - for (int argn = 0; argn < argc; argn++) - { - int sizeNeeded = WideCharToMultiByte(CP_UTF8, 0, wargv[argn], -1, NULL, 0, NULL, NULL); - if (sizeNeeded > 0 ) + // converts UCS2 arguements to utf-8 charset + char** argv = new char*[argc]; + for (int argn = 0; argn < argc; argn++) { - char * strTo = new char [sizeNeeded]; - WideCharToMultiByte(CP_UTF8, 0, wargv[argn], -1, strTo, sizeNeeded, NULL, NULL); - argv[argn] = strTo; + int sizeNeeded = WideCharToMultiByte(CP_UTF8, 0, wargv[argn], -1, NULL, + 0, NULL, NULL); + if (sizeNeeded > 0) + { + char* strTo = new char[sizeNeeded]; + WideCharToMultiByte(CP_UTF8, 0, wargv[argn], -1, strTo, sizeNeeded, + NULL, NULL); + argv[argn] = strTo; + } + else + argv[argn] = nullptr; } - else - argv[argn] = nullptr; - } - - int result = utf8Main(argc, argv); - - for (int argn = 0; argn < argc; argn++) - delete [] argv[argn]; - - delete [] argv; - - return result; + + int result = utf8Main(argc, argv); + + for (int argn = 0; argn < argc; argn++) + delete[] argv[argn]; + + delete[] argv; + + return result; } -extern "C" int APIENTRY WinMain(HINSTANCE /*hInstance*/, HINSTANCE /*hPrevInstance*/, LPSTR /*cmdParamarg*/, int /* cmdShow */) +extern "C" int APIENTRY WinMain(HINSTANCE /*hInstance*/, + HINSTANCE /*hPrevInstance*/, + LPSTR /*cmdParamarg*/, int /* cmdShow */) { - int argc; - wchar_t **argvW = CommandLineToArgvW(GetCommandLineW(), &argc); - if (!argvW) - return -1; - return wmain(argc, argvW); + int argc; + wchar_t** argvW = CommandLineToArgvW(GetCommandLineW(), &argc); + if (!argvW) + return -1; + return wmain(argc, argvW); } #else -int main(int argc, char* argv[]) -{ - return utf8Main(argc, argv); -} +int main(int argc, char* argv[]) { return utf8Main(argc, argv); } #endif - diff --git a/src/lib/app/DarwinBundle/DarwinBundle/DarwinBundle.h b/src/lib/app/DarwinBundle/DarwinBundle/DarwinBundle.h index fa932c164..b7bc27bf5 100644 --- a/src/lib/app/DarwinBundle/DarwinBundle/DarwinBundle.h +++ b/src/lib/app/DarwinBundle/DarwinBundle/DarwinBundle.h @@ -1,115 +1,116 @@ //****************************************************************************** -// Copyright (c) 2007 Tweak Inc. +// Copyright (c) 2007 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #ifndef __DarwinBundle__DarwinBundle__h__ #define __DarwinBundle__DarwinBundle__h__ #include -namespace TwkApp { - -// -// DarwinBundle implements the TwkApp::Bundle API for an NSApp. It -// basically calls the underlying NSBundle functions. -// -// This class will also create and AutoRelease pool. So if you make -// this on the stack in main it will provide ObjC memory management -// for you. -// -// If the bundle is created as sandboxed the security bookmark -// functions will return actual values. -// - -struct BundlePaths; - -class DarwinBundle : public Bundle +namespace TwkApp { - public: - DarwinBundle(const FileName& AppName, - size_t majorVersion, - size_t minorVersion, - size_t revisionNumber, - bool protocolHandler = false, - bool sandboxed = false, - bool inheritedSandbox = false); - - virtual ~DarwinBundle(); - - // - // DarwinBundle API - // - - PathVector fileInSupportPath(const FileName& name); // - // Resource path, as in NSBundle call + // DarwinBundle implements the TwkApp::Bundle API for an NSApp. It + // basically calls the underlying NSBundle functions. // - - Path resourcePath(); - - Path builtInPluginPath(); - - // - // This is a helper function which gets rid of the -psn argument - // that the open command adds to the argument list. nargv - // contains the filtered arguments. - // - - static void removePSN(int &argc, char* argv[], std::vector& nargv); - + // This class will also create and AutoRelease pool. So if you make + // this on the stack in main it will provide ObjC memory management + // for you. // - // Bundle API + // If the bundle is created as sandboxed the security bookmark + // functions will return actual values. // - virtual Path userHome(); - virtual Path userMovies(); - virtual Path userMusic(); - virtual Path userPictures(); - virtual Path top(); - virtual Path executableFile(const FileName& name); - virtual Path application(const FileName& name); - virtual PathVector supportPath(); - virtual Path rcfile(const FileName& rcfileName, - const FileName& type, - const EnvVar& rcenv); - virtual Path userPluginPath(const DirName& pluginType); - virtual PathVector pluginPath(const DirName& pluginType); - virtual PathVector scriptPath(const DirName& scriptType); - virtual Path appPluginPath(const DirName& pluginType); - virtual Path appScriptPath(const DirName& scriptType); - virtual Path userCacheDir(); - virtual Path resource(const FileName& name, const FileName& type); - virtual PathVector licenseFiles(const FileName& licFileName, + struct BundlePaths; + + class DarwinBundle : public Bundle + { + public: + DarwinBundle(const FileName& AppName, size_t majorVersion, + size_t minorVersion, size_t revisionNumber, + bool protocolHandler = false, bool sandboxed = false, + bool inheritedSandbox = false); + + virtual ~DarwinBundle(); + + // + // DarwinBundle API + // + + PathVector fileInSupportPath(const FileName& name); + + // + // Resource path, as in NSBundle call + // + + Path resourcePath(); + + Path builtInPluginPath(); + + // + // This is a helper function which gets rid of the -psn argument + // that the open command adds to the argument list. nargv + // contains the filtered arguments. + // + + static void removePSN(int& argc, char* argv[], + std::vector& nargv); + + // + // Bundle API + // + + virtual Path userHome(); + virtual Path userMovies(); + virtual Path userMusic(); + virtual Path userPictures(); + virtual Path top(); + virtual Path executableFile(const FileName& name); + virtual Path application(const FileName& name); + virtual PathVector supportPath(); + virtual Path rcfile(const FileName& rcfileName, const FileName& type, + const EnvVar& rcenv); + virtual Path userPluginPath(const DirName& pluginType); + virtual PathVector pluginPath(const DirName& pluginType); + virtual PathVector scriptPath(const DirName& scriptType); + virtual Path appPluginPath(const DirName& pluginType); + virtual Path appScriptPath(const DirName& scriptType); + virtual Path userCacheDir(); + virtual Path resource(const FileName& name, const FileName& type); + virtual PathVector licenseFiles(const FileName& licFileName, + const FileName& type); + virtual Path defaultLicense(const FileName& licFileName, const FileName& type); - virtual Path defaultLicense(const FileName& licFileName, - const FileName& type); - virtual void setEnvVar(const EnvVar& name, const Path& value, bool force=false); - virtual void addPathToEnvVar(const EnvVar& name, const PathVector& value); - virtual void addPathToEnvVar(const EnvVar& name, const Path& value, bool toHead=false); - virtual FileName crashLogFile(); - virtual Path crashLogDirectory(); - - virtual FileAccessPermission permissionForFileAccess(const Path&, bool readonly) const; - virtual AccessObject beginFileAccessWithPermission(const FileAccessPermission&) const; - virtual void endFileAccessWithPermission(AccessObject) const; - - // - // Register this executable as the default rvlink protocol - // handler. - // - - void registerHandler(); - - private: - BundlePaths* m_bundle; - std::string m_userSupportPath; -}; - - -} // TwkApp + virtual void setEnvVar(const EnvVar& name, const Path& value, + bool force = false); + virtual void addPathToEnvVar(const EnvVar& name, + const PathVector& value); + virtual void addPathToEnvVar(const EnvVar& name, const Path& value, + bool toHead = false); + virtual FileName crashLogFile(); + virtual Path crashLogDirectory(); + + virtual FileAccessPermission + permissionForFileAccess(const Path&, bool readonly) const; + virtual AccessObject + beginFileAccessWithPermission(const FileAccessPermission&) const; + virtual void endFileAccessWithPermission(AccessObject) const; + + // + // Register this executable as the default rvlink protocol + // handler. + // + + void registerHandler(); + + private: + BundlePaths* m_bundle; + std::string m_userSupportPath; + }; + +} // namespace TwkApp #endif // __DarwinBundle__DarwinBundle__h__ - diff --git a/src/lib/app/MuTwkApp/CommandsModule.cpp b/src/lib/app/MuTwkApp/CommandsModule.cpp index 209e1193a..ea51ab66b 100644 --- a/src/lib/app/MuTwkApp/CommandsModule.cpp +++ b/src/lib/app/MuTwkApp/CommandsModule.cpp @@ -1,9 +1,9 @@ //****************************************************************************** -// Copyright (c) 2005 Tweak Inc. +// Copyright (c) 2005 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #include #include @@ -38,592 +38,464 @@ #include #include -namespace TwkApp { -using namespace TwkApp; -using namespace Mu; -using namespace std; -using namespace TwkUtil; -typedef StringType::String String; -CommandsModule::CommandsModule(Context* c, const char* name) : Module(c, name) +namespace TwkApp { + using namespace TwkApp; + using namespace Mu; + using namespace std; + using namespace TwkUtil; + typedef StringType::String String; -} - -CommandsModule::~CommandsModule() -{ -} - -void -CommandsModule::load() -{ - USING_MU_FUNCTION_SYMBOLS; - typedef ParameterVariable Param; - - // - // Force the existance of the types we're going to use - // - - - MuLangContext* context = (MuLangContext*)globalModule()->context(); - const Type* stringType = context->stringType(); - const Type* floatType = context->floatType(); - const Type* intType = context->intType(); - const Type* vec2fType = context->vec2fType(); - Context* c = context; - - Context::TypeVector types; - types.push_back(context->stringType()); - types.push_back(context->intType()); - context->tupleType(types); - - context->arrayType(floatType, 1, 0); // float[] - context->arrayType(floatType, 2, 4, 4); // float[4,4] - context->arrayType(intType, 1, 0); // int[] - context->arrayType(stringType, 1, 0); // string[] - context->arrayType(vec2fType, 1, 0); - context->functionType("(void;Event)"); - - types.clear(); - types.push_back(stringType); - types.push_back(stringType); - - context->listType(stringType); - context->arrayType(context->tupleType(types), 1, 0); - - globalScope()->addSymbols( new MenuItem(c, "MenuItem", 0), - EndArguments ); - - addSymbols(new SymbolicConstant(c, "NeutralMenuState", "int", Value(0)), - new SymbolicConstant(c, "UncheckedMenuState", "int", Value(1)), - new SymbolicConstant(c, "CheckedMenuState", "int", Value(2)), - new SymbolicConstant(c, "MixedStateMenuState", "int", Value(3)), - new SymbolicConstant(c, "DisabledMenuState", "int", Value(-1)), - - new Function(c, "eval", CommandsModule::eval, None, - Parameters, - new Param(c, "text", "string"), - Return, "string", - End), - - new Function(c, "undo", CommandsModule::undo, None, - Return, "void", - End), - - new Function(c, "redo", CommandsModule::redo, None, - Return, "void", - End), - - new Function(c, "clearHistory", CommandsModule::clearHistory, None, - Return, "void", - End), - - new Function(c, "beginCompoundCommand", - CommandsModule::beginCompoundCommand, None, - Parameters, - new ParameterVariable(c, "name", "string"), - Return, "void", - End), - - new Function(c, "endCompoundCommand", - CommandsModule::endCompoundCommand, None, - Return, "void", - End), - - new Function(c, "undoHistory", CommandsModule::undoHistory, None, - Return, "string[]", - End), - - new Function(c, "redoHistory", CommandsModule::redoHistory, None, - Return, "string[]", - End), - - new Function(c, "activateMode", CommandsModule::activateMode, - None, - Return, "void", - Parameters, - new Param(c, "name", "string"), - End), - - new Function(c, "isModeActive", CommandsModule::isModeActive, - None, - Return, "bool", - Parameters, - new Param(c, "name", "string"), - End), - - new Function(c, "activeModes", CommandsModule::activeModes, - None, - Return, "[string]", - End), - - new Function(c, "deactivateMode", CommandsModule::deactivateMode, - None, - Return, "void", - Parameters, - new Param(c, "name", "string"), - End), - - new Function(c, "defineMinorMode", CommandsModule::defineMinorMode, - None, - Return, "void", - Parameters, - new Param(c, "name", "string"), - new Param(c, "sortKey", "string", Value(Pointer(0))), - new Param(c, "order", "int", Value(0)), - End), - - new Function(c, "bindingDocumentation", CommandsModule::bindDoc, None, - Return, "string", - Parameters, - new Param(c, "eventName", "string"), - new Param(c, "modeName", "string", Value()), - new Param(c, "tableName", "string", Value()), - End), - - new Function(c, "bindings", CommandsModule::bindings, None, - Return, "(string,string)[]", - End), - - new Function(c, "bind", CommandsModule::bind, None, - Return, "void", - Parameters, - new Param(c, "modeName", "string"), - new Param(c, "tableName", "string"), - new Param(c, "eventName", "string"), - new Param(c, "func", "(void;Event)"), - new Param(c, "description", "string", Value()), - End), - - new Function(c, "bindRegex", CommandsModule::bindRegex, None, - Return, "void", - Parameters, - new Param(c, "modeName", "string"), - new Param(c, "tableName", "string"), - new Param(c, "eventPattern", "string"), - new Param(c, "func", "(void;Event)"), - new Param(c, "description", "string", Value()), - End), - - new Function(c, "unbind", CommandsModule::unbind, None, - Return, "void", - Parameters, - new Param(c, "modeName", "string"), - new Param(c, "tableName", "string"), - new Param(c, "eventName", "string"), - End), - - new Function(c, "unbindRegex", CommandsModule::unbindRegex, None, - Return, "void", - Parameters, - new Param(c, "modeName", "string"), - new Param(c, "tableName", "string"), - new Param(c, "eventName", "string"), - End), - - new Function(c, "setEventTableBBox", CommandsModule::setTableBBox, None, - Return, "void", - Parameters, - new Param(c, "modeName", "string"), - new Param(c, "tableName", "string"), - new Param(c, "min", "vector float[2]"), - new Param(c, "max", "vector float[2]"), - End), - - new Function(c, "defineModeMenu", - CommandsModule::defineModeMenu, None, - Return, "void", - Parameters, - new Param(c, "mode", "string"), - new Param(c, "menu", "MenuItem[]"), - new Param(c, "strict", "bool", Value(false)), - End), - - // new Function(c, "isComputationInProgress", - // CommandsModule::isComputationInProgress, None, - // Return, "bool", - // End), - - // new Function(c, "computationMessage", - // CommandsModule::computationMessage, None, - // Return, "string", - // End), - - // new Function(c, "computationProgress", - // CommandsModule::computationProgress, None, - // Return, "float", - // End), - - // new Function(c, "computationElapsedTime", - // CommandsModule::computationElapsedTime, None, - // Return, "float", - // End), - - new Function(c, "pushEventTable", - CommandsModule::pushEventTable, None, - Return, "void", - Parameters, - new Param(c, "table", "string"), - End), - - new Function(c, "popEventTable", - CommandsModule::popEventTable, None, - Return, "void", - End), - - new Function(c, "popEventTable", - CommandsModule::popNamedEventTable, None, - Return, "void", - Parameters, - new Param(c, "table", "string"), - End), - - new Function(c, "activeEventTables", - CommandsModule::activeEventTables, None, - Return, "[string]", - End), - - new Function(c, "contractSequences", - CommandsModule::contractSeq, None, - Return, "string[]", - Parameters, - new Param(c, "files", "string[]"), - End), - - new Function(c, "sequenceOfFile", - CommandsModule::sequenceOfFile, None, - Return, "(string,int)", - Parameters, - new Param(c, "file", "string"), - End), - - EndArguments); -} - -static Document* currentDocument() -{ - if (Document* d = Document::eventDocument()) - { - return d; - } - else + CommandsModule::CommandsModule(Context* c, const char* name) + : Module(c, name) { - return Document::activeDocument(); } -} -static void throwBadArgumentException(const Mu::Node& node, - Mu::Thread& thread, - std::string msg) -{ - ostringstream str; - const Mu::MuLangContext* context = - static_cast(thread.context()); - ExceptionType::Exception *e = - new ExceptionType::Exception(context->exceptionType()); - str << "in " << node.symbol()->fullyQualifiedName() << ": " << msg; - e->string() += str.str().c_str(); - thread.setException(e); - BadArgumentException exc; - exc.message() = e->string(); - throw exc; -} - - -NODE_IMPLEMENTATION(CommandsModule::eval, Pointer) -{ - Process* p = NODE_THREAD.process(); - const String *text = NODE_ARG_OBJECT(0, StringType::String); - const StringType* stype = - static_cast(NODE_THIS.type()); - MuLangContext* c = static_cast(p->context()); - Context::ModuleList modules; - String* s = stype->allocate(muEval(c, p, modules, text->c_str(), "commands.eval")); - NODE_RETURN(s); -} - -NODE_IMPLEMENTATION(CommandsModule::undo, void) -{ - Document *d = currentDocument(); - d->undoCommand(); -} - -NODE_IMPLEMENTATION(CommandsModule::redo, void) -{ - Document *d = currentDocument(); - d->redoCommand(); -} + CommandsModule::~CommandsModule() {} -NODE_IMPLEMENTATION(CommandsModule::clearHistory, void) -{ - Document *d = currentDocument(); - d->clearHistory(); -} + void CommandsModule::load() + { + USING_MU_FUNCTION_SYMBOLS; + typedef ParameterVariable Param; -NODE_IMPLEMENTATION(CommandsModule::beginCompoundCommand, void) -{ - String *name = NODE_ARG_OBJECT(0, StringType::String); - Document *d = currentDocument(); - d->beginCompoundCommand(name->c_str()); -} + // + // Force the existance of the types we're going to use + // -NODE_IMPLEMENTATION(CommandsModule::endCompoundCommand, void) -{ - Document *d = currentDocument(); - d->endCompoundCommand(); -} + MuLangContext* context = (MuLangContext*)globalModule()->context(); + const Type* stringType = context->stringType(); + const Type* floatType = context->floatType(); + const Type* intType = context->intType(); + const Type* vec2fType = context->vec2fType(); + Context* c = context; + + Context::TypeVector types; + types.push_back(context->stringType()); + types.push_back(context->intType()); + context->tupleType(types); + + context->arrayType(floatType, 1, 0); // float[] + context->arrayType(floatType, 2, 4, 4); // float[4,4] + context->arrayType(intType, 1, 0); // int[] + context->arrayType(stringType, 1, 0); // string[] + context->arrayType(vec2fType, 1, 0); + context->functionType("(void;Event)"); + + types.clear(); + types.push_back(stringType); + types.push_back(stringType); + + context->listType(stringType); + context->arrayType(context->tupleType(types), 1, 0); + + globalScope()->addSymbols(new MenuItem(c, "MenuItem", 0), EndArguments); + + addSymbols( + new SymbolicConstant(c, "NeutralMenuState", "int", Value(0)), + new SymbolicConstant(c, "UncheckedMenuState", "int", Value(1)), + new SymbolicConstant(c, "CheckedMenuState", "int", Value(2)), + new SymbolicConstant(c, "MixedStateMenuState", "int", Value(3)), + new SymbolicConstant(c, "DisabledMenuState", "int", Value(-1)), + + new Function(c, "eval", CommandsModule::eval, None, Parameters, + new Param(c, "text", "string"), Return, "string", End), + + new Function(c, "undo", CommandsModule::undo, None, Return, "void", + End), + + new Function(c, "redo", CommandsModule::redo, None, Return, "void", + End), + + new Function(c, "clearHistory", CommandsModule::clearHistory, None, + Return, "void", End), + + new Function(c, "beginCompoundCommand", + CommandsModule::beginCompoundCommand, None, Parameters, + new ParameterVariable(c, "name", "string"), Return, + "void", End), + + new Function(c, "endCompoundCommand", + CommandsModule::endCompoundCommand, None, Return, + "void", End), + + new Function(c, "undoHistory", CommandsModule::undoHistory, None, + Return, "string[]", End), + + new Function(c, "redoHistory", CommandsModule::redoHistory, None, + Return, "string[]", End), + + new Function(c, "activateMode", CommandsModule::activateMode, None, + Return, "void", Parameters, + new Param(c, "name", "string"), End), + + new Function(c, "isModeActive", CommandsModule::isModeActive, None, + Return, "bool", Parameters, + new Param(c, "name", "string"), End), + + new Function(c, "activeModes", CommandsModule::activeModes, None, + Return, "[string]", End), + + new Function(c, "deactivateMode", CommandsModule::deactivateMode, + None, Return, "void", Parameters, + new Param(c, "name", "string"), End), + + new Function(c, "defineMinorMode", CommandsModule::defineMinorMode, + None, Return, "void", Parameters, + new Param(c, "name", "string"), + new Param(c, "sortKey", "string", Value(Pointer(0))), + new Param(c, "order", "int", Value(0)), End), + + new Function(c, "bindingDocumentation", CommandsModule::bindDoc, + None, Return, "string", Parameters, + new Param(c, "eventName", "string"), + new Param(c, "modeName", "string", Value()), + new Param(c, "tableName", "string", Value()), End), + + new Function(c, "bindings", CommandsModule::bindings, None, Return, + "(string,string)[]", End), + + new Function(c, "bind", CommandsModule::bind, None, Return, "void", + Parameters, new Param(c, "modeName", "string"), + new Param(c, "tableName", "string"), + new Param(c, "eventName", "string"), + new Param(c, "func", "(void;Event)"), + new Param(c, "description", "string", Value()), End), + + new Function(c, "bindRegex", CommandsModule::bindRegex, None, + Return, "void", Parameters, + new Param(c, "modeName", "string"), + new Param(c, "tableName", "string"), + new Param(c, "eventPattern", "string"), + new Param(c, "func", "(void;Event)"), + new Param(c, "description", "string", Value()), End), + + new Function(c, "unbind", CommandsModule::unbind, None, Return, + "void", Parameters, new Param(c, "modeName", "string"), + new Param(c, "tableName", "string"), + new Param(c, "eventName", "string"), End), + + new Function(c, "unbindRegex", CommandsModule::unbindRegex, None, + Return, "void", Parameters, + new Param(c, "modeName", "string"), + new Param(c, "tableName", "string"), + new Param(c, "eventName", "string"), End), + + new Function(c, "setEventTableBBox", CommandsModule::setTableBBox, + None, Return, "void", Parameters, + new Param(c, "modeName", "string"), + new Param(c, "tableName", "string"), + new Param(c, "min", "vector float[2]"), + new Param(c, "max", "vector float[2]"), End), + + new Function(c, "defineModeMenu", CommandsModule::defineModeMenu, + None, Return, "void", Parameters, + new Param(c, "mode", "string"), + new Param(c, "menu", "MenuItem[]"), + new Param(c, "strict", "bool", Value(false)), End), + + // new Function(c, "isComputationInProgress", + // CommandsModule::isComputationInProgress, None, + // Return, "bool", + // End), + + // new Function(c, "computationMessage", + // CommandsModule::computationMessage, None, + // Return, "string", + // End), + + // new Function(c, "computationProgress", + // CommandsModule::computationProgress, None, + // Return, "float", + // End), + + // new Function(c, "computationElapsedTime", + // CommandsModule::computationElapsedTime, None, + // Return, "float", + // End), + + new Function(c, "pushEventTable", CommandsModule::pushEventTable, + None, Return, "void", Parameters, + new Param(c, "table", "string"), End), + + new Function(c, "popEventTable", CommandsModule::popEventTable, + None, Return, "void", End), + + new Function(c, "popEventTable", CommandsModule::popNamedEventTable, + None, Return, "void", Parameters, + new Param(c, "table", "string"), End), + + new Function(c, "activeEventTables", + CommandsModule::activeEventTables, None, Return, + "[string]", End), + + new Function(c, "contractSequences", CommandsModule::contractSeq, + None, Return, "string[]", Parameters, + new Param(c, "files", "string[]"), End), + + new Function(c, "sequenceOfFile", CommandsModule::sequenceOfFile, + None, Return, "(string,int)", Parameters, + new Param(c, "file", "string"), End), + + EndArguments); + } -NODE_IMPLEMENTATION(CommandsModule::readFile, void) -{ - const String *name = NODE_ARG_OBJECT(0, StringType::String); - bool import = NODE_ARG(1, bool); + static Document* currentDocument() + { + if (Document* d = Document::eventDocument()) + { + return d; + } + else + { + return Document::activeDocument(); + } + } - if (Document *d = currentDocument()) + static void throwBadArgumentException(const Mu::Node& node, + Mu::Thread& thread, std::string msg) { - Document::ReadRequest request; - request.setOption("append", import); - d->read(name->c_str(), request); + ostringstream str; + const Mu::MuLangContext* context = + static_cast(thread.context()); + ExceptionType::Exception* e = + new ExceptionType::Exception(context->exceptionType()); + str << "in " << node.symbol()->fullyQualifiedName() << ": " << msg; + e->string() += str.str().c_str(); + thread.setException(e); + BadArgumentException exc; + exc.message() = e->string(); + throw exc; } -} -NODE_IMPLEMENTATION(CommandsModule::writeFile, void) -{ - String* name = NODE_ARG_OBJECT(0, StringType::String); - const bool partial = NODE_ARG(1, bool); + NODE_IMPLEMENTATION(CommandsModule::eval, Pointer) + { + Process* p = NODE_THREAD.process(); + const String* text = NODE_ARG_OBJECT(0, StringType::String); + const StringType* stype = + static_cast(NODE_THIS.type()); + MuLangContext* c = static_cast(p->context()); + Context::ModuleList modules; + String* s = stype->allocate( + muEval(c, p, modules, text->c_str(), "commands.eval")); + NODE_RETURN(s); + } - if (Document *d = currentDocument()) + NODE_IMPLEMENTATION(CommandsModule::undo, void) { - Document::WriteRequest request; - request.setOption("partial", partial); - d->write(name->c_str(), request); + Document* d = currentDocument(); + d->undoCommand(); } -} -namespace { + NODE_IMPLEMENTATION(CommandsModule::redo, void) + { + Document* d = currentDocument(); + d->redoCommand(); + } -void -compileHistoryDescriptions(const TwkApp::CommandHistory* history, - bool undo, - vector& array, - size_t indent = 0) -{ - const TwkApp::CommandStack& stack = undo ? history->undoStack() : history->redoStack(); + NODE_IMPLEMENTATION(CommandsModule::clearHistory, void) + { + Document* d = currentDocument(); + d->clearHistory(); + } - for (int i=0; i < stack.size(); i++) + NODE_IMPLEMENTATION(CommandsModule::beginCompoundCommand, void) { - const TwkApp::Command* c = stack[i]; - - ostringstream str; + String* name = NODE_ARG_OBJECT(0, StringType::String); + Document* d = currentDocument(); + d->beginCompoundCommand(name->c_str()); + } - for (size_t q = 0; q < indent; q++) str << "."; - str << c->description() << " (" << c->name() << ")"; + NODE_IMPLEMENTATION(CommandsModule::endCompoundCommand, void) + { + Document* d = currentDocument(); + d->endCompoundCommand(); + } - array.push_back(str.str()); + NODE_IMPLEMENTATION(CommandsModule::readFile, void) + { + const String* name = NODE_ARG_OBJECT(0, StringType::String); + bool import = NODE_ARG(1, bool); - if (const TwkApp::CompoundCommand* cc = - dynamic_cast(stack[i])) + if (Document* d = currentDocument()) { - compileHistoryDescriptions(cc, undo, array, indent+1); + Document::ReadRequest request; + request.setOption("append", import); + d->read(name->c_str(), request); } } -} -} + NODE_IMPLEMENTATION(CommandsModule::writeFile, void) + { + String* name = NODE_ARG_OBJECT(0, StringType::String); + const bool partial = NODE_ARG(1, bool); -NODE_IMPLEMENTATION(CommandsModule::undoHistory, Mu::Pointer) -{ - Process *p = NODE_THREAD.process(); - Document *d = currentDocument(); + if (Document* d = currentDocument()) + { + Document::WriteRequest request; + request.setOption("partial", partial); + d->write(name->c_str(), request); + } + } - const Mu::DynamicArrayType* atype = - static_cast(NODE_THIS.type()); - const Mu::StringType* stype = - static_cast(atype->elementType()); + namespace + { - DynamicArray *array = new DynamicArray(atype, 1); + void compileHistoryDescriptions(const TwkApp::CommandHistory* history, + bool undo, vector& array, + size_t indent = 0) + { + const TwkApp::CommandStack& stack = + undo ? history->undoStack() : history->redoStack(); - vector desc; - compileHistoryDescriptions(d, true, desc); - array->resize(desc.size()); + for (int i = 0; i < stack.size(); i++) + { + const TwkApp::Command* c = stack[i]; - for (int i=0; i < desc.size(); i++) - { - array->element(i) = stype->allocate(desc[i]); - } + ostringstream str; - NODE_RETURN(array); -} + for (size_t q = 0; q < indent; q++) + str << "."; + str << c->description() << " (" << c->name() << ")"; -NODE_IMPLEMENTATION(CommandsModule::redoHistory, Mu::Pointer) -{ - Process *p = NODE_THREAD.process(); - Document *d = currentDocument(); + array.push_back(str.str()); - const Mu::DynamicArrayType* atype = - static_cast(NODE_THIS.type()); - const Mu::StringType* stype = - static_cast(atype->elementType()); + if (const TwkApp::CompoundCommand* cc = + dynamic_cast(stack[i])) + { + compileHistoryDescriptions(cc, undo, array, indent + 1); + } + } + } - DynamicArray *array = new DynamicArray(atype, 1); - const TwkApp::CommandStack& redoStack = d->redoStack(); - array->resize(redoStack.size()); + } // namespace - for (int i=0; i < redoStack.size(); i++) + NODE_IMPLEMENTATION(CommandsModule::undoHistory, Mu::Pointer) { - const TwkApp::Command* c = redoStack[i]; - array->element(i) = stype->allocate(c->description()); - } + Process* p = NODE_THREAD.process(); + Document* d = currentDocument(); - NODE_RETURN(array); -} + const Mu::DynamicArrayType* atype = + static_cast(NODE_THIS.type()); + const Mu::StringType* stype = + static_cast(atype->elementType()); -NODE_IMPLEMENTATION(CommandsModule::defineMinorMode, void) -{ - Process* p = NODE_THREAD.process(); - Document* d = currentDocument(); - String* modeName = NODE_ARG_OBJECT(0, StringType::String); - String* sortKey = NODE_ARG_OBJECT(1, StringType::String); - int order = NODE_ARG(2, int); - - MinorMode* mode = new MinorMode(modeName->c_str(), d); - mode->setOrder(order); - if (sortKey) mode->setSortKey(sortKey->c_str()); - d->addMode(mode); -} - -NODE_IMPLEMENTATION(CommandsModule::activateMode, void) -{ - Process* p = NODE_THREAD.process(); - Document* d = currentDocument(); - String* modeName = NODE_ARG_OBJECT(0, StringType::String); - - if (!modeName) - throwBadArgumentException(NODE_THIS, NODE_THREAD, "Nil argument to function"); + DynamicArray* array = new DynamicArray(atype, 1); - d->activateMode(modeName->c_str()); -} + vector desc; + compileHistoryDescriptions(d, true, desc); + array->resize(desc.size()); -NODE_IMPLEMENTATION(CommandsModule::isModeActive, bool) -{ - Process* p = NODE_THREAD.process(); - Document* d = currentDocument(); - bool b = false; + for (int i = 0; i < desc.size(); i++) + { + array->element(i) = stype->allocate(desc[i]); + } - if (String* modeName = NODE_ARG_OBJECT(0, StringType::String)) - { - b = d->isModeActive(modeName->c_str()); - } - else - { - throwBadArgumentException(NODE_THIS, NODE_THREAD, "Nil argument to function"); + NODE_RETURN(array); } - NODE_RETURN(b); -} - - -NODE_IMPLEMENTATION(CommandsModule::deactivateMode, void) -{ - Process* p = NODE_THREAD.process(); - Document* d = currentDocument(); - String* modeName = NODE_ARG_OBJECT(0, StringType::String); - d->deactivateMode(modeName->c_str()); -} - -NODE_IMPLEMENTATION(CommandsModule::bind, void) -{ - Process *p = NODE_THREAD.process(); - Document *d = currentDocument(); + NODE_IMPLEMENTATION(CommandsModule::redoHistory, Mu::Pointer) + { + Process* p = NODE_THREAD.process(); + Document* d = currentDocument(); - String* modeName = NODE_ARG_OBJECT(0, StringType::String); - String* tableName = NODE_ARG_OBJECT(1, StringType::String); - String* eventName = NODE_ARG_OBJECT(2, StringType::String); - FunctionObject* obj = NODE_ARG_OBJECT(3, FunctionObject); - String* docstring = NODE_ARG_OBJECT(4, StringType::String); + const Mu::DynamicArrayType* atype = + static_cast(NODE_THIS.type()); + const Mu::StringType* stype = + static_cast(atype->elementType()); - string doc = docstring ? docstring->c_str() : ""; + DynamicArray* array = new DynamicArray(atype, 1); + const TwkApp::CommandStack& redoStack = d->redoStack(); + array->resize(redoStack.size()); - if (Mode* mode = d->findModeByName(modeName->c_str())) - { - EventTable* table = mode->findTableByName(tableName->c_str()); - - if (!table) + for (int i = 0; i < redoStack.size(); i++) { - table = new EventTable(tableName->c_str()); - mode->addEventTable(table); + const TwkApp::Command* c = redoStack[i]; + array->element(i) = stype->allocate(c->description()); } - MuFuncAction* action = new MuFuncAction(obj, doc); - table->bind(eventName->c_str(), action); - // - // currentDocument has a copy of this table, so invalidate - // that copy. - // - d->invalidateEventTables(); + NODE_RETURN(array); } - else + + NODE_IMPLEMENTATION(CommandsModule::defineMinorMode, void) { - string msg = "No mode named " + string(modeName->c_str()); - throwBadArgumentException(NODE_THIS, NODE_THREAD, msg); + Process* p = NODE_THREAD.process(); + Document* d = currentDocument(); + String* modeName = NODE_ARG_OBJECT(0, StringType::String); + String* sortKey = NODE_ARG_OBJECT(1, StringType::String); + int order = NODE_ARG(2, int); + + MinorMode* mode = new MinorMode(modeName->c_str(), d); + mode->setOrder(order); + if (sortKey) + mode->setSortKey(sortKey->c_str()); + d->addMode(mode); } -} -NODE_IMPLEMENTATION(CommandsModule::bindRegex, void) -{ - Process *p = NODE_THREAD.process(); - Document *d = currentDocument(); + NODE_IMPLEMENTATION(CommandsModule::activateMode, void) + { + Process* p = NODE_THREAD.process(); + Document* d = currentDocument(); + String* modeName = NODE_ARG_OBJECT(0, StringType::String); - String* modeName = NODE_ARG_OBJECT(0, StringType::String); - String* tableName = NODE_ARG_OBJECT(1, StringType::String); - String* eventRegex = NODE_ARG_OBJECT(2, StringType::String); - FunctionObject* obj = NODE_ARG_OBJECT(3, FunctionObject); - String* docstring = NODE_ARG_OBJECT(4, StringType::String); + if (!modeName) + throwBadArgumentException(NODE_THIS, NODE_THREAD, + "Nil argument to function"); - string doc = docstring ? docstring->c_str() : ""; + d->activateMode(modeName->c_str()); + } - if (Mode* mode = d->findModeByName(modeName->c_str())) + NODE_IMPLEMENTATION(CommandsModule::isModeActive, bool) { - EventTable* table = mode->findTableByName(tableName->c_str()); + Process* p = NODE_THREAD.process(); + Document* d = currentDocument(); + bool b = false; - if (!table) + if (String* modeName = NODE_ARG_OBJECT(0, StringType::String)) + { + b = d->isModeActive(modeName->c_str()); + } + else { - table = new EventTable(tableName->c_str()); - mode->addEventTable(table); + throwBadArgumentException(NODE_THIS, NODE_THREAD, + "Nil argument to function"); } - MuFuncAction* action = new MuFuncAction(obj, doc); - table->bindRegex(eventRegex->c_str(), action); - // - // currentDocument has a copy of this table, so invalidate - // that copy. - // - d->invalidateEventTables(); + NODE_RETURN(b); } - else + + NODE_IMPLEMENTATION(CommandsModule::deactivateMode, void) { - string msg = "No mode named " + string(modeName->c_str()); - throwBadArgumentException(NODE_THIS, NODE_THREAD, msg); + Process* p = NODE_THREAD.process(); + Document* d = currentDocument(); + String* modeName = NODE_ARG_OBJECT(0, StringType::String); + d->deactivateMode(modeName->c_str()); } -} -NODE_IMPLEMENTATION(CommandsModule::unbind, void) -{ - Process *p = NODE_THREAD.process(); - Document *d = currentDocument(); + NODE_IMPLEMENTATION(CommandsModule::bind, void) + { + Process* p = NODE_THREAD.process(); + Document* d = currentDocument(); - String* modeName = NODE_ARG_OBJECT(0, StringType::String); - String* tableName = NODE_ARG_OBJECT(1, StringType::String); - String* eventName = NODE_ARG_OBJECT(2, StringType::String); + String* modeName = NODE_ARG_OBJECT(0, StringType::String); + String* tableName = NODE_ARG_OBJECT(1, StringType::String); + String* eventName = NODE_ARG_OBJECT(2, StringType::String); + FunctionObject* obj = NODE_ARG_OBJECT(3, FunctionObject); + String* docstring = NODE_ARG_OBJECT(4, StringType::String); - if (!modeName || !tableName || !eventName) - { - throwBadArgumentException(NODE_THIS, NODE_THREAD, "Nil argument to function"); - } + string doc = docstring ? docstring->c_str() : ""; - if (Mode* mode = d->findModeByName(modeName->c_str())) - { - if (EventTable* table = mode->findTableByName(tableName->c_str())) + if (Mode* mode = d->findModeByName(modeName->c_str())) { - table->unbind(eventName->c_str()); + EventTable* table = mode->findTableByName(tableName->c_str()); + + if (!table) + { + table = new EventTable(tableName->c_str()); + mode->addEventTable(table); + } + + MuFuncAction* action = new MuFuncAction(obj, doc); + table->bind(eventName->c_str(), action); // // currentDocument has a copy of this table, so invalidate // that copy. @@ -632,36 +504,36 @@ NODE_IMPLEMENTATION(CommandsModule::unbind, void) } else { - string msg = "No table named " + string(tableName->c_str()); + string msg = "No mode named " + string(modeName->c_str()); throwBadArgumentException(NODE_THIS, NODE_THREAD, msg); } } - else - { - string msg = "No mode named " + string(modeName->c_str()); - throwBadArgumentException(NODE_THIS, NODE_THREAD, msg); - } -} -NODE_IMPLEMENTATION(CommandsModule::unbindRegex, void) -{ - Process *p = NODE_THREAD.process(); - Document *d = currentDocument(); + NODE_IMPLEMENTATION(CommandsModule::bindRegex, void) + { + Process* p = NODE_THREAD.process(); + Document* d = currentDocument(); - String* modeName = NODE_ARG_OBJECT(0, StringType::String); - String* tableName = NODE_ARG_OBJECT(1, StringType::String); - String* eventName = NODE_ARG_OBJECT(2, StringType::String); + String* modeName = NODE_ARG_OBJECT(0, StringType::String); + String* tableName = NODE_ARG_OBJECT(1, StringType::String); + String* eventRegex = NODE_ARG_OBJECT(2, StringType::String); + FunctionObject* obj = NODE_ARG_OBJECT(3, FunctionObject); + String* docstring = NODE_ARG_OBJECT(4, StringType::String); - if (!modeName || !tableName || !eventName) - { - throwBadArgumentException(NODE_THIS, NODE_THREAD, "Nil argument to function"); - } + string doc = docstring ? docstring->c_str() : ""; - if (Mode* mode = d->findModeByName(modeName->c_str())) - { - if (EventTable* table = mode->findTableByName(tableName->c_str())) + if (Mode* mode = d->findModeByName(modeName->c_str())) { - table->unbindRegex(eventName->c_str()); + EventTable* table = mode->findTableByName(tableName->c_str()); + + if (!table) + { + table = new EventTable(tableName->c_str()); + mode->addEventTable(table); + } + + MuFuncAction* action = new MuFuncAction(obj, doc); + table->bindRegex(eventRegex->c_str(), action); // // currentDocument has a copy of this table, so invalidate // that copy. @@ -670,93 +542,79 @@ NODE_IMPLEMENTATION(CommandsModule::unbindRegex, void) } else { - string msg = "No table named " + string(tableName->c_str()); + string msg = "No mode named " + string(modeName->c_str()); throwBadArgumentException(NODE_THIS, NODE_THREAD, msg); } } - else - { - string msg = "No mode named " + string(modeName->c_str()); - throwBadArgumentException(NODE_THIS, NODE_THREAD, msg); - } -} - -NODE_IMPLEMENTATION(CommandsModule::bindings, Mu::Pointer) -{ - Process *p = NODE_THREAD.process(); - Document *d = currentDocument(); - const Mu::MuLangContext* c = - static_cast(NODE_THREAD.context()); - const DynamicArrayType* atype = (const DynamicArrayType*)NODE_THIS.type(); - const Class* ttype = (const Class*)atype->elementType(); - DynamicArray *array = new DynamicArray(atype, 1); - - struct StringTuple + NODE_IMPLEMENTATION(CommandsModule::unbind, void) { - String* a; - String* b; - }; + Process* p = NODE_THREAD.process(); + Document* d = currentDocument(); - const Document::EventTableStack& stack = d->eventTableStack(); - - for (int i = stack.size() - 1; i >= 0; i--) - { - const EventTable* table = stack[i]; - typedef EventTable::BindingMap::const_iterator iter; - typedef EventTable::BindingMap::value_type vtype; + String* modeName = NODE_ARG_OBJECT(0, StringType::String); + String* tableName = NODE_ARG_OBJECT(1, StringType::String); + String* eventName = NODE_ARG_OBJECT(2, StringType::String); - for (iter i = table->begin(); i != table->end(); ++i) + if (!modeName || !tableName || !eventName) { + throwBadArgumentException(NODE_THIS, NODE_THREAD, + "Nil argument to function"); + } - String* name = c->stringType()->allocate(i->first); - String* doc = c->stringType()->allocate(i->second->docString()); - - ClassInstance* tuple = ClassInstance::allocate(ttype); - StringTuple* st = reinterpret_cast(tuple->structure()); - - st->a = name; - st->b = doc; - - array->resize(array->size() + 1); - array->element(array->size()-1) = tuple; + if (Mode* mode = d->findModeByName(modeName->c_str())) + { + if (EventTable* table = mode->findTableByName(tableName->c_str())) + { + table->unbind(eventName->c_str()); + // + // currentDocument has a copy of this table, so invalidate + // that copy. + // + d->invalidateEventTables(); + } + else + { + string msg = "No table named " + string(tableName->c_str()); + throwBadArgumentException(NODE_THIS, NODE_THREAD, msg); + } + } + else + { + string msg = "No mode named " + string(modeName->c_str()); + throwBadArgumentException(NODE_THIS, NODE_THREAD, msg); } } - NODE_RETURN(array); -} + NODE_IMPLEMENTATION(CommandsModule::unbindRegex, void) + { + Process* p = NODE_THREAD.process(); + Document* d = currentDocument(); -NODE_IMPLEMENTATION(CommandsModule::bindDoc, Mu::Pointer) -{ - Process *p = NODE_THREAD.process(); - Document *d = currentDocument(); - const Mu::MuLangContext* c = - static_cast(NODE_THREAD.context()); + String* modeName = NODE_ARG_OBJECT(0, StringType::String); + String* tableName = NODE_ARG_OBJECT(1, StringType::String); + String* eventName = NODE_ARG_OBJECT(2, StringType::String); - String* eventName = NODE_ARG_OBJECT(0, StringType::String); - String* modeName = NODE_ARG_OBJECT(1, StringType::String); - String* tableName = NODE_ARG_OBJECT(2, StringType::String); + if (!modeName || !tableName || !eventName) + { + throwBadArgumentException(NODE_THIS, NODE_THREAD, + "Nil argument to function"); + } - if (modeName && tableName) - { if (Mode* mode = d->findModeByName(modeName->c_str())) { - const EventTable* table = mode->findTableByName(tableName->c_str()); - - if (!table) + if (EventTable* table = mode->findTableByName(tableName->c_str())) { - string msg = "No table named " + string(tableName->c_str()); - throwBadArgumentException(NODE_THIS, NODE_THREAD, msg); - } - - if (const Action* action = table->query(eventName->c_str())) - { - String* doc = c->stringType()->allocate(action->docString()); - NODE_RETURN(doc); + table->unbindRegex(eventName->c_str()); + // + // currentDocument has a copy of this table, so invalidate + // that copy. + // + d->invalidateEventTables(); } else { - string msg = "Not bound: " + string(eventName->c_str()); + string msg = "No table named " + string(tableName->c_str()); throwBadArgumentException(NODE_THIS, NODE_THREAD, msg); } } @@ -766,89 +624,151 @@ NODE_IMPLEMENTATION(CommandsModule::bindDoc, Mu::Pointer) throwBadArgumentException(NODE_THIS, NODE_THREAD, msg); } } - else + + NODE_IMPLEMENTATION(CommandsModule::bindings, Mu::Pointer) { + Process* p = NODE_THREAD.process(); + Document* d = currentDocument(); + const Mu::MuLangContext* c = + static_cast(NODE_THREAD.context()); + + const DynamicArrayType* atype = + (const DynamicArrayType*)NODE_THIS.type(); + const Class* ttype = (const Class*)atype->elementType(); + DynamicArray* array = new DynamicArray(atype, 1); + + struct StringTuple + { + String* a; + String* b; + }; + const Document::EventTableStack& stack = d->eventTableStack(); for (int i = stack.size() - 1; i >= 0; i--) { const EventTable* table = stack[i]; + typedef EventTable::BindingMap::const_iterator iter; + typedef EventTable::BindingMap::value_type vtype; - if (const Action* action = table->query(eventName->c_str())) + for (iter i = table->begin(); i != table->end(); ++i) { - String* doc = c->stringType()->allocate(action->docString()); - NODE_RETURN(doc); + + String* name = c->stringType()->allocate(i->first); + String* doc = c->stringType()->allocate(i->second->docString()); + + ClassInstance* tuple = ClassInstance::allocate(ttype); + StringTuple* st = + reinterpret_cast(tuple->structure()); + + st->a = name; + st->b = doc; + + array->resize(array->size() + 1); + array->element(array->size() - 1) = tuple; } } - } - NODE_RETURN(0); -} + NODE_RETURN(array); + } -NODE_IMPLEMENTATION(CommandsModule::setTableBBox, void) -{ - Process* p = NODE_THREAD.process(); - Document* d = currentDocument(); - String* modeName = NODE_ARG_OBJECT(0, StringType::String); - String* tableName = NODE_ARG_OBJECT(1, StringType::String); - Vector2f min = NODE_ARG(2, Vector2f); - Vector2f max = NODE_ARG(3, Vector2f); - - TwkMath::Box2i bbox; - bbox.min.x = int(min[0]); - bbox.min.y = int(min[1]); - bbox.max.x = int(max[0]); - bbox.max.y = int(max[1]); - - if (Mode* mode = d->findModeByName(modeName->c_str())) + NODE_IMPLEMENTATION(CommandsModule::bindDoc, Mu::Pointer) { - EventTable* table = mode->findTableByName(tableName->c_str()); + Process* p = NODE_THREAD.process(); + Document* d = currentDocument(); + const Mu::MuLangContext* c = + static_cast(NODE_THREAD.context()); + + String* eventName = NODE_ARG_OBJECT(0, StringType::String); + String* modeName = NODE_ARG_OBJECT(1, StringType::String); + String* tableName = NODE_ARG_OBJECT(2, StringType::String); - if (!table) + if (modeName && tableName) { - table = new EventTable(tableName->c_str()); - mode->addEventTable(table); + if (Mode* mode = d->findModeByName(modeName->c_str())) + { + const EventTable* table = + mode->findTableByName(tableName->c_str()); + + if (!table) + { + string msg = "No table named " + string(tableName->c_str()); + throwBadArgumentException(NODE_THIS, NODE_THREAD, msg); + } + + if (const Action* action = table->query(eventName->c_str())) + { + String* doc = + c->stringType()->allocate(action->docString()); + NODE_RETURN(doc); + } + else + { + string msg = "Not bound: " + string(eventName->c_str()); + throwBadArgumentException(NODE_THIS, NODE_THREAD, msg); + } + } + else + { + string msg = "No mode named " + string(modeName->c_str()); + throwBadArgumentException(NODE_THIS, NODE_THREAD, msg); + } } + else + { + const Document::EventTableStack& stack = d->eventTableStack(); - TwkMath::Box2i old = table->bbox(); - if (old != bbox) - { - table->setBBox(bbox); - // - // currentDocument has a copy of this table, so invalidate - // that copy. - // - d->invalidateEventTables(); + for (int i = stack.size() - 1; i >= 0; i--) + { + const EventTable* table = stack[i]; + + if (const Action* action = table->query(eventName->c_str())) + { + String* doc = + c->stringType()->allocate(action->docString()); + NODE_RETURN(doc); + } + } } - } - else - { - string msg = "No mode named " + string(modeName->c_str()); - throwBadArgumentException(NODE_THIS, NODE_THREAD, msg); - } -} -NODE_IMPLEMENTATION(CommandsModule::defineModeMenu, void) -{ - StringType::String* modeName = NODE_ARG_OBJECT(0, StringType::String); - DynamicArray* array = NODE_ARG_OBJECT(1, DynamicArray); - bool strict = NODE_ARG(2 ,bool); + NODE_RETURN(0); + } - if (array) + NODE_IMPLEMENTATION(CommandsModule::setTableBBox, void) { - Document* d = currentDocument(); - Menu* menu = createTwkAppMenu("Main", array); + Process* p = NODE_THREAD.process(); + Document* d = currentDocument(); + String* modeName = NODE_ARG_OBJECT(0, StringType::String); + String* tableName = NODE_ARG_OBJECT(1, StringType::String); + Vector2f min = NODE_ARG(2, Vector2f); + Vector2f max = NODE_ARG(3, Vector2f); + + TwkMath::Box2i bbox; + bbox.min.x = int(min[0]); + bbox.min.y = int(min[1]); + bbox.max.x = int(max[0]); + bbox.max.y = int(max[1]); - if (Mode* m = d->findModeByName(modeName->c_str())) + if (Mode* mode = d->findModeByName(modeName->c_str())) { - if (strict) m->setMenu(menu); - else m->merge(menu); + EventTable* table = mode->findTableByName(tableName->c_str()); - // - // If we are re-defining an existing menu, we need to invalidate - // the old menu. - // - d->invalidateMenu(); + if (!table) + { + table = new EventTable(tableName->c_str()); + mode->addEventTable(table); + } + + TwkMath::Box2i old = table->bbox(); + if (old != bbox) + { + table->setBBox(bbox); + // + // currentDocument has a copy of this table, so invalidate + // that copy. + // + d->invalidateEventTables(); + } } else { @@ -856,171 +776,210 @@ NODE_IMPLEMENTATION(CommandsModule::defineModeMenu, void) throwBadArgumentException(NODE_THIS, NODE_THREAD, msg); } } -} - -// NODE_IMPLEMENTATION(CommandsModule::isComputationInProgress, bool) -// { -// NODE_RETURN(Interrupt::isWorking()); -// } - -// NODE_IMPLEMENTATION(CommandsModule::computationMessage, Mu::Pointer) -// { -// Process *p = NODE_THREAD.process(); -// const Mu::StringType* stype = -// static_cast(NODE_THIS.type()); - -// if (!Interrupt::isWorking()) -// { -// string msg = "computation not in progress: invalid call"; -// throwBadArgumentException(NODE_THIS, NODE_THREAD, msg); -// } - -// String* s = stype->allocate(Interrupt::currentComputation().message); -// NODE_RETURN(s); -// } - -// NODE_IMPLEMENTATION(CommandsModule::computationProgress, float) -// { -// if (!Interrupt::isWorking()) -// { -// string msg = "computation not in progress: invalid call"; -// throwBadArgumentException(NODE_THIS, NODE_THREAD, msg); -// } - -// NODE_RETURN(Interrupt::currentComputation().percentDone); -// } - -// NODE_IMPLEMENTATION(CommandsModule::computationElapsedTime, float) -// { -// if (!Interrupt::isWorking()) -// { -// string msg = "computation not in progress: invalid call"; -// throwBadArgumentException(NODE_THIS, NODE_THREAD, msg); -// } - -// NODE_RETURN(Interrupt::currentComputation().timer.elapsed()); -// } - -NODE_IMPLEMENTATION(CommandsModule::pushEventTable, void) -{ - String* name = NODE_ARG_OBJECT(0, StringType::String); - Document* d = currentDocument(); - d->pushTable(name->c_str()); -} -NODE_IMPLEMENTATION(CommandsModule::popEventTable, void) -{ - Document* d = currentDocument(); - d->popTable(); -} + NODE_IMPLEMENTATION(CommandsModule::defineModeMenu, void) + { + StringType::String* modeName = NODE_ARG_OBJECT(0, StringType::String); + DynamicArray* array = NODE_ARG_OBJECT(1, DynamicArray); + bool strict = NODE_ARG(2, bool); -NODE_IMPLEMENTATION(CommandsModule::popNamedEventTable, void) -{ - String* name = NODE_ARG_OBJECT(0, StringType::String); - Document* d = currentDocument(); - d->popTable(name->c_str()); -} + if (array) + { + Document* d = currentDocument(); + Menu* menu = createTwkAppMenu("Main", array); -NODE_IMPLEMENTATION(CommandsModule::activeEventTables, Mu::Pointer) -{ - Document* d = currentDocument(); - const Document::EventTableStack& tables = d->eventTableStack(); + if (Mode* m = d->findModeByName(modeName->c_str())) + { + if (strict) + m->setMenu(menu); + else + m->merge(menu); + + // + // If we are re-defining an existing menu, we need to + // invalidate the old menu. + // + d->invalidateMenu(); + } + else + { + string msg = "No mode named " + string(modeName->c_str()); + throwBadArgumentException(NODE_THIS, NODE_THREAD, msg); + } + } + } - Process *p = NODE_THREAD.process(); - const ListType* ltype = static_cast(NODE_THIS.type()); - const Mu::StringType* stype = - static_cast(ltype->elementType()); - Mu::List list(p, ltype); + // NODE_IMPLEMENTATION(CommandsModule::isComputationInProgress, bool) + // { + // NODE_RETURN(Interrupt::isWorking()); + // } + + // NODE_IMPLEMENTATION(CommandsModule::computationMessage, Mu::Pointer) + // { + // Process *p = NODE_THREAD.process(); + // const Mu::StringType* stype = + // static_cast(NODE_THIS.type()); + + // if (!Interrupt::isWorking()) + // { + // string msg = "computation not in progress: invalid call"; + // throwBadArgumentException(NODE_THIS, NODE_THREAD, msg); + // } + + // String* s = stype->allocate(Interrupt::currentComputation().message); + // NODE_RETURN(s); + // } + + // NODE_IMPLEMENTATION(CommandsModule::computationProgress, float) + // { + // if (!Interrupt::isWorking()) + // { + // string msg = "computation not in progress: invalid call"; + // throwBadArgumentException(NODE_THIS, NODE_THREAD, msg); + // } + + // NODE_RETURN(Interrupt::currentComputation().percentDone); + // } + + // NODE_IMPLEMENTATION(CommandsModule::computationElapsedTime, float) + // { + // if (!Interrupt::isWorking()) + // { + // string msg = "computation not in progress: invalid call"; + // throwBadArgumentException(NODE_THIS, NODE_THREAD, msg); + // } + + // NODE_RETURN(Interrupt::currentComputation().timer.elapsed()); + // } + + NODE_IMPLEMENTATION(CommandsModule::pushEventTable, void) + { + String* name = NODE_ARG_OBJECT(0, StringType::String); + Document* d = currentDocument(); + d->pushTable(name->c_str()); + } - for (int i=0; i < tables.size(); i++) + NODE_IMPLEMENTATION(CommandsModule::popEventTable, void) { - StringType::String* str = stype->allocate(tables[i]->name()); - list.append(str); + Document* d = currentDocument(); + d->popTable(); } - NODE_RETURN(list.head()); -} + NODE_IMPLEMENTATION(CommandsModule::popNamedEventTable, void) + { + String* name = NODE_ARG_OBJECT(0, StringType::String); + Document* d = currentDocument(); + d->popTable(name->c_str()); + } -NODE_IMPLEMENTATION(CommandsModule::contractSeq, Pointer) -{ - Process* p = NODE_THREAD.process(); - const DynamicArrayType* atype = static_cast(NODE_THIS.type()); - const StringType* stype = static_cast(atype->elementType()); - DynamicArray* inArray = NODE_ARG_OBJECT(0, DynamicArray); + NODE_IMPLEMENTATION(CommandsModule::activeEventTables, Mu::Pointer) + { + Document* d = currentDocument(); + const Document::EventTableStack& tables = d->eventTableStack(); - if (!inArray) - throwBadArgumentException(NODE_THIS, NODE_THREAD, "Nil argument to function"); + Process* p = NODE_THREAD.process(); + const ListType* ltype = static_cast(NODE_THIS.type()); + const Mu::StringType* stype = + static_cast(ltype->elementType()); + Mu::List list(p, ltype); - if (!inArray->size()) NODE_RETURN(inArray); + for (int i = 0; i < tables.size(); i++) + { + StringType::String* str = stype->allocate(tables[i]->name()); + list.append(str); + } - DynamicArray* outArray = new DynamicArray(atype, 1); - FileNameList files(inArray->size()); + NODE_RETURN(list.head()); + } - for (int i=0; i < files.size(); i++) + NODE_IMPLEMENTATION(CommandsModule::contractSeq, Pointer) { - files[i] = inArray->element(i)->c_str(); - } + Process* p = NODE_THREAD.process(); + const DynamicArrayType* atype = + static_cast(NODE_THIS.type()); + const StringType* stype = + static_cast(atype->elementType()); + DynamicArray* inArray = NODE_ARG_OBJECT(0, DynamicArray); - SequenceNameList seqlist = sequencesInFileList(files, GlobalExtensionPredicate); + if (!inArray) + throwBadArgumentException(NODE_THIS, NODE_THREAD, + "Nil argument to function"); - outArray->resize(seqlist.size()); + if (!inArray->size()) + NODE_RETURN(inArray); - for (int i=0; i < seqlist.size(); i++) - { - outArray->element(i) = stype->allocate(seqlist[i]); - } + DynamicArray* outArray = new DynamicArray(atype, 1); + FileNameList files(inArray->size()); - NODE_RETURN(outArray); -} + for (int i = 0; i < files.size(); i++) + { + files[i] = inArray->element(i)->c_str(); + } -NODE_IMPLEMENTATION(CommandsModule::activeModes, Pointer) -{ - Process* p = NODE_THREAD.process(); - const Mu::MuLangContext* c = - static_cast(NODE_THREAD.context()); + SequenceNameList seqlist = + sequencesInFileList(files, GlobalExtensionPredicate); - const Mu::ListType* listType = static_cast(NODE_THIS.type()); - const StringType* stype = static_cast(listType->elementType()); - Document* d = currentDocument(); + outArray->resize(seqlist.size()); - List list(p, listType); - list.append(stype->allocate(d->majorMode()->name())); + for (int i = 0; i < seqlist.size(); i++) + { + outArray->element(i) = + stype->allocate(seqlist[i]); + } - const Document::MinorModes& minorModes = d->minorModes(); + NODE_RETURN(outArray); + } - for (Document::MinorModes::const_iterator i = minorModes.begin(); - i != minorModes.end(); - ++i) + NODE_IMPLEMENTATION(CommandsModule::activeModes, Pointer) { - const MinorMode* m = *i; - list.append(stype->allocate(m->name())); - } + Process* p = NODE_THREAD.process(); + const Mu::MuLangContext* c = + static_cast(NODE_THREAD.context()); - NODE_RETURN(list.head()); -} + const Mu::ListType* listType = + static_cast(NODE_THIS.type()); + const StringType* stype = + static_cast(listType->elementType()); + Document* d = currentDocument(); -NODE_IMPLEMENTATION(CommandsModule::sequenceOfFile, Pointer) -{ - Process* p = NODE_THREAD.process(); - String* file = NODE_ARG_OBJECT(0, StringType::String); - const StringType* stype = static_cast(file->type()); - const Class* ttype = static_cast(NODE_THIS.type()); + List list(p, listType); + list.append(stype->allocate(d->majorMode()->name())); + + const Document::MinorModes& minorModes = d->minorModes(); + + for (Document::MinorModes::const_iterator i = minorModes.begin(); + i != minorModes.end(); ++i) + { + const MinorMode* m = *i; + list.append(stype->allocate(m->name())); + } + + NODE_RETURN(list.head()); + } - struct PatTuple + NODE_IMPLEMENTATION(CommandsModule::sequenceOfFile, Pointer) { - StringType::String* file; - int frame; - }; - - string filename = file->c_str(); - PatternFramePair pp = TwkUtil::sequenceOfFile(filename, GlobalExtensionPredicate); - - ClassInstance* tuple = ClassInstance::allocate(ttype); - PatTuple* pt = reinterpret_cast(tuple->structure()); - pt->file = stype->allocate(pp.first); - pt->frame = pp.second; - - NODE_RETURN(tuple); -} - -} // MuTwkApp + Process* p = NODE_THREAD.process(); + String* file = NODE_ARG_OBJECT(0, StringType::String); + const StringType* stype = static_cast(file->type()); + const Class* ttype = static_cast(NODE_THIS.type()); + + struct PatTuple + { + StringType::String* file; + int frame; + }; + + string filename = file->c_str(); + PatternFramePair pp = + TwkUtil::sequenceOfFile(filename, GlobalExtensionPredicate); + + ClassInstance* tuple = ClassInstance::allocate(ttype); + PatTuple* pt = reinterpret_cast(tuple->structure()); + pt->file = stype->allocate(pp.first); + pt->frame = pp.second; + + NODE_RETURN(tuple); + } + +} // namespace TwkApp diff --git a/src/lib/app/MuTwkApp/EventType.cpp b/src/lib/app/MuTwkApp/EventType.cpp index e7321150a..d184deb47 100644 --- a/src/lib/app/MuTwkApp/EventType.cpp +++ b/src/lib/app/MuTwkApp/EventType.cpp @@ -1,9 +1,9 @@ //****************************************************************************** -// Copyright (c) 2004 Tweak Inc. +// Copyright (c) 2004 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #include @@ -32,964 +32,929 @@ #include #include -namespace TwkApp { -using namespace Mu; -using namespace std; -typedef StringType::String String; - -//---------------------------------------------------------------------- - -EventType::EventInstance::EventInstance(const Class *c) : ClassInstance(c), - event(0), - document(0) +namespace TwkApp { -} + using namespace Mu; + using namespace std; + typedef StringType::String String; -//---------------------------------------------------------------------- + //---------------------------------------------------------------------- + EventType::EventInstance::EventInstance(const Class* c) + : ClassInstance(c) + , event(0) + , document(0) + { + } -EventType::EventType(Context* c, Class *super) : Class(c, "Event", super) -{ -} + //---------------------------------------------------------------------- -EventType::~EventType() {} + EventType::EventType(Context* c, Class* super) + : Class(c, "Event", super) + { + } -Object* -EventType::newObject() const -{ - return new EventInstance(this); -} + EventType::~EventType() {} -void -EventType::deleteObject(Object *obj) const -{ - delete static_cast(obj); -} + Object* EventType::newObject() const { return new EventInstance(this); } -void -EventType::outputValue(ostream &o, const Value &value, bool full) const -{ - ValueOutputState state(o, full); - outputValueRecursive(o, ValuePointer(&value._Pointer), state); -} - -void -EventType::outputValueRecursive(ostream &o, - const ValuePointer vp, - ValueOutputState& state) const -{ - EventInstance *i = *reinterpret_cast(vp); + void EventType::deleteObject(Object* obj) const + { + delete static_cast(obj); + } - if (i) + void EventType::outputValue(ostream& o, const Value& value, bool full) const { - o << "event) o << "\"" << *i->event << "\""; - else o << "nil"; + void EventType::outputValueRecursive(ostream& o, const ValuePointer vp, + ValueOutputState& state) const + { + EventInstance* i = *reinterpret_cast(vp); + + if (i) + { + o << ""; + if (i->event) + o << "\"" << *i->event << "\""; + else + o << "nil"; + + o << ">"; + } + else + { + o << "nil"; + } } - else + + void EventType::load() { - o << "nil"; - } -} + USING_MU_FUNCTION_SYMBOLS; -void -EventType::load() -{ - USING_MU_FUNCTION_SYMBOLS; - - Symbol *s = scope(); - MuLangContext* context = - (MuLangContext*)globalModule()->context(); - Context* c = context; + Symbol* s = scope(); + MuLangContext* context = (MuLangContext*)globalModule()->context(); + Context* c = context; - string tname = "Event"; - string rname = tname + "&"; + string tname = "Event"; + string rname = tname + "&"; - const char* tn = tname.c_str(); - const char* rn = rname.c_str(); - - s->addSymbols( new ReferenceType(c, "Event&", this), + const char* tn = tname.c_str(); + const char* rn = rname.c_str(); - new Function(c, "Event", BaseFunctions::dereference, Cast, - Return, tn, - Args, rn, End), - - EndArguments); - - globalScope()->addSymbols( - - new Function(c, "print", EventType::print, None, - Return, "void", - Args, tn, End), - - new Function(c, "=", BaseFunctions::assign, AsOp, - Return, rn, - Args, rn, tn, End), - - EndArguments); - - addSymbols( new Function(c, "pointer", EventType::pointer, None, - Return, "vector float[2]", - Args, tn, End), - - new Function(c, "relativePointer", - EventType::relativePointer, None, - Return, "vector float[2]", - Args, tn, End), - - new Function(c, "reference", EventType::reference, None, - Return, "vector float[2]", - Args, tn, End), - - new Function(c, "domain", EventType::domain, None, - Return, "vector float[2]", - Args, tn, End), - - new Function(c, "subDomain", EventType::subDomain, None, - Return, "vector float[2]", - Args, tn, End), - - new Function(c, "domainVerticalFlip", EventType::domainVerticalFlip, None, - Return, "bool", - Args, tn, End), - - new Function(c, "buttons", EventType::buttons, None, - Return, "int", - Args, tn, End), - - new Function(c, "modifiers", EventType::modifiers, None, - Return, "int", - Args, tn, End), - - new Function(c, "key", EventType::key, None, - Return, "int", - Args, tn, End), - - new Function(c, "name", EventType::name, None, - Return, "string", - Args, tn, End), - - new Function(c, "contents", EventType::contents, None, - Return, "string", - Args, tn, End), - - new Function(c, "contentsArray", EventType::contentsArray, None, - Return, "string[]", - Args, tn, End), - - new Function(c, "returnContents", EventType::returnContents, None, - Return, "string", - Args, tn, End), - - new Function(c, "dataContents", EventType::dataContents, None, - Return, "byte[]", - Args, tn, End), - - new Function(c, "sender", EventType::sender, None, - Return, "string", - Args, tn, End), - - new Function(c, "contentType", EventType::contentType, None, - Return, "int", - Args, tn, End), - - new Function(c, "contentMimeType", EventType::contentMimeType, None, - Return, "string", - Args, tn, End), - - new Function(c, "timeStamp", EventType::timeStamp, None, - Return, "float", - Args, tn, End), - - new Function(c, "reject", EventType::reject, None, - Return, "void", - Args, tn, End), - - new Function(c, "setReturnContent", EventType::setReturnContent, - None, - Return, "void", - Args, tn, "string", End), - - new Function(c, "pressure", EventType::pressure, - None, - Return, "float", - Args, tn, End), - - new Function(c, "tangentialPressure", EventType::tangentialPressure, - None, - Return, "float", - Args, tn, End), - - new Function(c, "rotation", EventType::rotation, - None, - Return, "float", - Args, tn, End), - - new Function(c, "xTilt", EventType::xTilt, - None, - Return, "int", - Args, tn, End), - - new Function(c, "yTilt", EventType::yTilt, - None, - Return, "int", - Args, tn, End), - - new Function(c, "activationTime", EventType::activationTime, - None, - Return, "float", - Args, tn, End), - - new SymbolicConstant(c, "None", "int", Value(int(0))), - new SymbolicConstant(c, "Shift", "int", Value(int(1 << 0))), - new SymbolicConstant(c, "Control", "int", Value(int(1 << 1))), - new SymbolicConstant(c, "Alt", "int", Value(int(1 << 2))), - new SymbolicConstant(c, "Meta", "int", Value(int(1 << 3))), - new SymbolicConstant(c, "Super", "int", Value(int(1 << 4))), - new SymbolicConstant(c, "CapLock", "int", Value(int(1 << 5))), - new SymbolicConstant(c, "NumLock", "int", Value(int(1 << 6))), - new SymbolicConstant(c, "ScrollLock", "int", Value(int(1 << 7))), - - new SymbolicConstant(c, "Button1", "int", Value(1 << 0)), - new SymbolicConstant(c, "Button2", "int", Value(1 << 1)), - new SymbolicConstant(c, "Button3", "int", Value(1 << 2)), - - new SymbolicConstant(c, "UnknownObject", "int", Value(-1)), - new SymbolicConstant(c, "BadObject", "int", Value(0)), - new SymbolicConstant(c, "FileObject", "int", Value(1)), - new SymbolicConstant(c, "URLObject", "int", Value(2)), - new SymbolicConstant(c, "TextObject", "int", Value(3)), - - EndArguments ); -} - -static void throwBadArgumentException(const Mu::Node& node, - Mu::Thread& thread, - std::string msg) -{ - ostringstream str; - const Mu::MuLangContext* context = - static_cast(thread.context()); - ExceptionType::Exception *e = - new ExceptionType::Exception(context->exceptionType()); - str << "in " << node.symbol()->fullyQualifiedName() << ": " << msg; - e->string() += str.str().c_str(); - thread.setException(e); - throw BadArgumentException(thread, e); -} - -NODE_IMPLEMENTATION(EventType::print, void) -{ - EventInstance *i = NODE_ARG_OBJECT(0, EventInstance); + s->addSymbols(new ReferenceType(c, "Event&", this), - if (i) - { - i->type()->outputValue(cout, Value(i)); - } - else - { - throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil argument"); - } -} + new Function(c, "Event", BaseFunctions::dereference, Cast, + Return, tn, Args, rn, End), -NODE_IMPLEMENTATION(EventType::name, Pointer) -{ - Process* p = NODE_THREAD.process(); - EventInstance *i = NODE_ARG_OBJECT(0, EventInstance); - const StringType* stype = - static_cast(NODE_THIS.type()); + EndArguments); - if (i) - { - NODE_RETURN(stype->allocate(i->event->name())); - } - else - { - throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil argument"); - NODE_RETURN(0); - } -} + globalScope()->addSymbols( -NODE_IMPLEMENTATION(EventType::contentType, int) -{ - Process* p = NODE_THREAD.process(); - EventInstance *i = NODE_ARG_OBJECT(0, EventInstance); + new Function(c, "print", EventType::print, None, Return, "void", + Args, tn, End), - if (!i) - { - throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil argument"); - } + new Function(c, "=", BaseFunctions::assign, AsOp, Return, rn, Args, + rn, tn, End), - int rval = 0; + EndArguments); - if (const DragDropEvent* de = - dynamic_cast(i->event)) - { - switch (de->contentType()) - { - case DragDropEvent::File: rval = 1; break; - case DragDropEvent::URL: rval = 2; break; - case DragDropEvent::Text: rval = 3; break; - default: rval = -1; break; - } - } - else - { - throwBadArgumentException(NODE_THIS, NODE_THREAD, "bad event type"); - } + addSymbols( + new Function(c, "pointer", EventType::pointer, None, Return, + "vector float[2]", Args, tn, End), - NODE_RETURN(rval); -} + new Function(c, "relativePointer", EventType::relativePointer, None, + Return, "vector float[2]", Args, tn, End), -NODE_IMPLEMENTATION(EventType::contentMimeType, Pointer) -{ - EventInstance *i = NODE_ARG_OBJECT(0, EventInstance); - const StringType* stype = static_cast(NODE_THIS.type()); - String* s = 0; + new Function(c, "reference", EventType::reference, None, Return, + "vector float[2]", Args, tn, End), - if (!i) - { - throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil argument"); - } + new Function(c, "domain", EventType::domain, None, Return, + "vector float[2]", Args, tn, End), - if (const RawDataEvent* e = - dynamic_cast(i->event)) - { - s = stype->allocate(e->contentType()); - } - else if (const GenericStringEvent* e = - dynamic_cast(i->event)) - { - s = stype->allocate("text/plain"); - } - else - { - throwBadArgumentException(NODE_THIS, NODE_THREAD, "mime type not applicable"); - } + new Function(c, "subDomain", EventType::subDomain, None, Return, + "vector float[2]", Args, tn, End), - NODE_RETURN(s); -} + new Function(c, "domainVerticalFlip", EventType::domainVerticalFlip, + None, Return, "bool", Args, tn, End), -NODE_IMPLEMENTATION(EventType::contents, Pointer) -{ - Process* p = NODE_THREAD.process(); - EventInstance *i = NODE_ARG_OBJECT(0, EventInstance); - - if (!i) - { - throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil argument"); - } + new Function(c, "buttons", EventType::buttons, None, Return, "int", + Args, tn, End), - const StringType* stype = - static_cast(NODE_THIS.type()); + new Function(c, "modifiers", EventType::modifiers, None, Return, + "int", Args, tn, End), - String* s = 0; + new Function(c, "key", EventType::key, None, Return, "int", Args, + tn, End), - if (const DragDropEvent* de = - dynamic_cast(i->event)) - { - s = stype->allocate(de->stringContent()); + new Function(c, "name", EventType::name, None, Return, "string", + Args, tn, End), + + new Function(c, "contents", EventType::contents, None, Return, + "string", Args, tn, End), + + new Function(c, "contentsArray", EventType::contentsArray, None, + Return, "string[]", Args, tn, End), + + new Function(c, "returnContents", EventType::returnContents, None, + Return, "string", Args, tn, End), + + new Function(c, "dataContents", EventType::dataContents, None, + Return, "byte[]", Args, tn, End), + + new Function(c, "sender", EventType::sender, None, Return, "string", + Args, tn, End), + + new Function(c, "contentType", EventType::contentType, None, Return, + "int", Args, tn, End), + + new Function(c, "contentMimeType", EventType::contentMimeType, None, + Return, "string", Args, tn, End), + + new Function(c, "timeStamp", EventType::timeStamp, None, Return, + "float", Args, tn, End), + + new Function(c, "reject", EventType::reject, None, Return, "void", + Args, tn, End), + + new Function(c, "setReturnContent", EventType::setReturnContent, + None, Return, "void", Args, tn, "string", End), + + new Function(c, "pressure", EventType::pressure, None, Return, + "float", Args, tn, End), + + new Function(c, "tangentialPressure", EventType::tangentialPressure, + None, Return, "float", Args, tn, End), + + new Function(c, "rotation", EventType::rotation, None, Return, + "float", Args, tn, End), + + new Function(c, "xTilt", EventType::xTilt, None, Return, "int", + Args, tn, End), + + new Function(c, "yTilt", EventType::yTilt, None, Return, "int", + Args, tn, End), + + new Function(c, "activationTime", EventType::activationTime, None, + Return, "float", Args, tn, End), + + new SymbolicConstant(c, "None", "int", Value(int(0))), + new SymbolicConstant(c, "Shift", "int", Value(int(1 << 0))), + new SymbolicConstant(c, "Control", "int", Value(int(1 << 1))), + new SymbolicConstant(c, "Alt", "int", Value(int(1 << 2))), + new SymbolicConstant(c, "Meta", "int", Value(int(1 << 3))), + new SymbolicConstant(c, "Super", "int", Value(int(1 << 4))), + new SymbolicConstant(c, "CapLock", "int", Value(int(1 << 5))), + new SymbolicConstant(c, "NumLock", "int", Value(int(1 << 6))), + new SymbolicConstant(c, "ScrollLock", "int", Value(int(1 << 7))), + + new SymbolicConstant(c, "Button1", "int", Value(1 << 0)), + new SymbolicConstant(c, "Button2", "int", Value(1 << 1)), + new SymbolicConstant(c, "Button3", "int", Value(1 << 2)), + + new SymbolicConstant(c, "UnknownObject", "int", Value(-1)), + new SymbolicConstant(c, "BadObject", "int", Value(0)), + new SymbolicConstant(c, "FileObject", "int", Value(1)), + new SymbolicConstant(c, "URLObject", "int", Value(2)), + new SymbolicConstant(c, "TextObject", "int", Value(3)), + + EndArguments); } - else if (const GenericStringEvent* e = - dynamic_cast(i->event)) + + static void throwBadArgumentException(const Mu::Node& node, + Mu::Thread& thread, std::string msg) { - s = stype->allocate(e->stringContent()); + ostringstream str; + const Mu::MuLangContext* context = + static_cast(thread.context()); + ExceptionType::Exception* e = + new ExceptionType::Exception(context->exceptionType()); + str << "in " << node.symbol()->fullyQualifiedName() << ": " << msg; + e->string() += str.str().c_str(); + thread.setException(e); + throw BadArgumentException(thread, e); } - else if (const RawDataEvent* e = - dynamic_cast(i->event)) + + NODE_IMPLEMENTATION(EventType::print, void) { - if (e->utf8()) + EventInstance* i = NODE_ARG_OBJECT(0, EventInstance); + + if (i) { - s = stype->allocate(e->utf8()); + i->type()->outputValue(cout, Value(i)); } else { - throwBadArgumentException(NODE_THIS, NODE_THREAD, "event not text"); + throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil argument"); } } - else if (const RenderEvent* re = - dynamic_cast(i->event)) - { - s = stype->allocate(re->stringContent()); - } - else - { - throwBadArgumentException(NODE_THIS, NODE_THREAD, "bad event type"); - } - - NODE_RETURN(s); -} -NODE_IMPLEMENTATION(EventType::contentsArray, Pointer) -{ - Process* p = NODE_THREAD.process(); - MuLangContext* c = static_cast(p->context()); - EventInstance *i = NODE_ARG_OBJECT(0, EventInstance); - - if (!i) + NODE_IMPLEMENTATION(EventType::name, Pointer) { - throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil argument"); - } + Process* p = NODE_THREAD.process(); + EventInstance* i = NODE_ARG_OBJECT(0, EventInstance); + const StringType* stype = + static_cast(NODE_THIS.type()); - const DynamicArrayType* atype = - static_cast(NODE_THIS.type()); - DynamicArray* array = new DynamicArray(atype, 1); + if (i) + { + NODE_RETURN(stype->allocate(i->event->name())); + } + else + { + throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil argument"); + NODE_RETURN(0); + } + } - if (const GenericStringEvent* e = - dynamic_cast(i->event)) + NODE_IMPLEMENTATION(EventType::contentType, int) { - const Event::StringVector& v = e->stringContentVector(); - const size_t n = v.size(); + Process* p = NODE_THREAD.process(); + EventInstance* i = NODE_ARG_OBJECT(0, EventInstance); - if (n == 0) + if (!i) { - array->resize(1); - array->element(0) = c->stringType()->allocate(e->stringContent()); + throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil argument"); } - else - { - array->resize(n); - for (size_t q = 0; q < n; q++) + int rval = 0; + + if (const DragDropEvent* de = + dynamic_cast(i->event)) + { + switch (de->contentType()) { - array->element(q) = c->stringType()->allocate(v[q]); + case DragDropEvent::File: + rval = 1; + break; + case DragDropEvent::URL: + rval = 2; + break; + case DragDropEvent::Text: + rval = 3; + break; + default: + rval = -1; + break; } } - } - else - { - throwBadArgumentException(NODE_THIS, NODE_THREAD, "bad event type"); - } + else + { + throwBadArgumentException(NODE_THIS, NODE_THREAD, "bad event type"); + } - NODE_RETURN(array); -} + NODE_RETURN(rval); + } -NODE_IMPLEMENTATION(EventType::returnContents, Pointer) -{ - Process* p = NODE_THREAD.process(); - EventInstance *i = NODE_ARG_OBJECT(0, EventInstance); - - if (!i) + NODE_IMPLEMENTATION(EventType::contentMimeType, Pointer) { - throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil argument"); - } + EventInstance* i = NODE_ARG_OBJECT(0, EventInstance); + const StringType* stype = + static_cast(NODE_THIS.type()); + String* s = 0; - const StringType* stype = - static_cast(NODE_THIS.type()); + if (!i) + { + throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil argument"); + } - String* s = 0; + if (const RawDataEvent* e = dynamic_cast(i->event)) + { + s = stype->allocate(e->contentType()); + } + else if (const GenericStringEvent* e = + dynamic_cast(i->event)) + { + s = stype->allocate("text/plain"); + } + else + { + throwBadArgumentException(NODE_THIS, NODE_THREAD, + "mime type not applicable"); + } - if (const GenericStringEvent* e = - dynamic_cast(i->event)) - { - s = stype->allocate(e->returnContent()); + NODE_RETURN(s); } - NODE_RETURN(s); -} - -NODE_IMPLEMENTATION(EventType::dataContents, Pointer) -{ - EventInstance *inst = NODE_ARG_OBJECT(0, EventInstance); - DynamicArrayType* type = (DynamicArrayType*)NODE_THIS.type(); - DynamicArray *array = new DynamicArray(type, 1); - - if (!inst) + NODE_IMPLEMENTATION(EventType::contents, Pointer) { - throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil argument"); - } + Process* p = NODE_THREAD.process(); + EventInstance* i = NODE_ARG_OBJECT(0, EventInstance); - if (const RawDataEvent* e = dynamic_cast(inst->event)) - { - int sz = e->rawDataSize(); - array->resize(sz); - for (int i = 0; i < sz; ++i) array->element(i) = e->rawData()[i]; - } - else - { - throwBadArgumentException(NODE_THIS, NODE_THREAD, "bad event type"); - } + if (!i) + { + throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil argument"); + } - NODE_RETURN(array); -} + const StringType* stype = + static_cast(NODE_THIS.type()); -NODE_IMPLEMENTATION(EventType::interp, Pointer) -{ - EventInstance *inst = NODE_ARG_OBJECT(0, EventInstance); - const StringType* stype = static_cast(NODE_THIS.type()); - String* s = 0; + String* s = 0; - if (!inst) - { - throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil argument"); - } + if (const DragDropEvent* de = + dynamic_cast(i->event)) + { + s = stype->allocate(de->stringContent()); + } + else if (const GenericStringEvent* e = + dynamic_cast(i->event)) + { + s = stype->allocate(e->stringContent()); + } + else if (const RawDataEvent* e = + dynamic_cast(i->event)) + { + if (e->utf8()) + { + s = stype->allocate(e->utf8()); + } + else + { + throwBadArgumentException(NODE_THIS, NODE_THREAD, + "event not text"); + } + } + else if (const RenderEvent* re = + dynamic_cast(i->event)) + { + s = stype->allocate(re->stringContent()); + } + else + { + throwBadArgumentException(NODE_THIS, NODE_THREAD, "bad event type"); + } - if (const RawDataEvent* e = dynamic_cast(inst->event)) - { - s = stype->allocate(e->contentType()); - } - else - { - throwBadArgumentException(NODE_THIS, NODE_THREAD, "interp not applicable"); + NODE_RETURN(s); } - NODE_RETURN(s); -} - -NODE_IMPLEMENTATION(EventType::sender, Pointer) -{ - Process* p = NODE_THREAD.process(); - EventInstance *i = NODE_ARG_OBJECT(0, EventInstance); - const StringType* stype = - static_cast(NODE_THIS.type()); - - if (!i) + NODE_IMPLEMENTATION(EventType::contentsArray, Pointer) { - throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil argument"); - } + Process* p = NODE_THREAD.process(); + MuLangContext* c = static_cast(p->context()); + EventInstance* i = NODE_ARG_OBJECT(0, EventInstance); - String* s = 0; + if (!i) + { + throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil argument"); + } - if (const GenericStringEvent* e = - dynamic_cast(i->event)) - { - s = stype->allocate(e->senderName()); - } - else - if (const RawDataEvent* e = - dynamic_cast(i->event)) - { - s = stype->allocate(e->senderName()); - } - else - { - throwBadArgumentException(NODE_THIS, NODE_THREAD, "bad event type"); - } + const DynamicArrayType* atype = + static_cast(NODE_THIS.type()); + DynamicArray* array = new DynamicArray(atype, 1); + if (const GenericStringEvent* e = + dynamic_cast(i->event)) + { + const Event::StringVector& v = e->stringContentVector(); + const size_t n = v.size(); - NODE_RETURN(s); -} + if (n == 0) + { + array->resize(1); + array->element(0) = + c->stringType()->allocate(e->stringContent()); + } + else + { + array->resize(n); -NODE_IMPLEMENTATION(EventType::key, int) -{ - EventInstance *e = NODE_ARG_OBJECT(0, EventInstance); - int k; + for (size_t q = 0; q < n; q++) + { + array->element(q) = + c->stringType()->allocate(v[q]); + } + } + } + else + { + throwBadArgumentException(NODE_THIS, NODE_THREAD, "bad event type"); + } - if (!e) - { - throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil argument"); + NODE_RETURN(array); } - if (const KeyEvent* ke = - dynamic_cast(e->event)) - { - k = ke->key(); - } - else + NODE_IMPLEMENTATION(EventType::returnContents, Pointer) { - throwBadArgumentException(NODE_THIS, NODE_THREAD, "bad event type"); - } - - NODE_RETURN(k); -} + Process* p = NODE_THREAD.process(); + EventInstance* i = NODE_ARG_OBJECT(0, EventInstance); -NODE_IMPLEMENTATION(EventType::pointer, Vector2f) -{ - EventInstance* e = NODE_ARG_OBJECT(0, EventInstance); - Vector2f v; + if (!i) + { + throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil argument"); + } - if (!e) - { - throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil argument"); - } + const StringType* stype = + static_cast(NODE_THIS.type()); - if (const TabletEvent* te = - dynamic_cast(e->event)) - { - v[0] = te->gx(); - v[1] = te->gy(); - } - else if (const PointerEvent* pe = - dynamic_cast(e->event)) - { - v[0] = pe->x(); - v[1] = pe->y(); - } - else - { - throwBadArgumentException(NODE_THIS, NODE_THREAD, "bad event type"); - } + String* s = 0; - return v; -} + if (const GenericStringEvent* e = + dynamic_cast(i->event)) + { + s = stype->allocate(e->returnContent()); + } -NODE_IMPLEMENTATION(EventType::relativePointer, Vector2f) -{ - EventInstance* e = NODE_ARG_OBJECT(0, EventInstance); - Vector2f v; - if (!e) - { - throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil argument"); + NODE_RETURN(s); } - if (const TabletEvent* te = - dynamic_cast(e->event)) + NODE_IMPLEMENTATION(EventType::dataContents, Pointer) { - v[0] = te->gx(); - v[1] = te->gy(); + EventInstance* inst = NODE_ARG_OBJECT(0, EventInstance); + DynamicArrayType* type = (DynamicArrayType*)NODE_THIS.type(); + DynamicArray* array = new DynamicArray(type, 1); - if (te->eventTable()) + if (!inst) { - v[0] -= te->eventTable()->bbox().min.x; - v[1] -= te->eventTable()->bbox().min.y; + throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil argument"); } - } - else if (const PointerEvent* pe = - dynamic_cast(e->event)) - { - v[0] = pe->x(); - v[1] = pe->y(); - if (pe->eventTable()) + if (const RawDataEvent* e = + dynamic_cast(inst->event)) { - v[0] -= pe->eventTable()->bbox().min.x; - v[1] -= pe->eventTable()->bbox().min.y; + int sz = e->rawDataSize(); + array->resize(sz); + for (int i = 0; i < sz; ++i) + array->element(i) = e->rawData()[i]; } + else + { + throwBadArgumentException(NODE_THIS, NODE_THREAD, "bad event type"); + } + + NODE_RETURN(array); } - else + + NODE_IMPLEMENTATION(EventType::interp, Pointer) { - throwBadArgumentException(NODE_THIS, NODE_THREAD, "bad event type"); - } + EventInstance* inst = NODE_ARG_OBJECT(0, EventInstance); + const StringType* stype = + static_cast(NODE_THIS.type()); + String* s = 0; - return v; -} + if (!inst) + { + throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil argument"); + } -NODE_IMPLEMENTATION(EventType::reference, Vector2f) -{ - EventInstance* e = NODE_ARG_OBJECT(0, EventInstance); - Vector2f v; + if (const RawDataEvent* e = + dynamic_cast(inst->event)) + { + s = stype->allocate(e->contentType()); + } + else + { + throwBadArgumentException(NODE_THIS, NODE_THREAD, + "interp not applicable"); + } - if (!e) - { - throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil argument"); + NODE_RETURN(s); } - if (const PointerEvent* pe = - dynamic_cast(e->event)) - { - v[0] = pe->startX(); - v[1] = pe->startY(); - } - else + NODE_IMPLEMENTATION(EventType::sender, Pointer) { - throwBadArgumentException(NODE_THIS, NODE_THREAD, "bad event type"); - } + Process* p = NODE_THREAD.process(); + EventInstance* i = NODE_ARG_OBJECT(0, EventInstance); + const StringType* stype = + static_cast(NODE_THIS.type()); - return v; -} + if (!i) + { + throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil argument"); + } -NODE_IMPLEMENTATION(EventType::domain, Vector2f) -{ - EventInstance* e = NODE_ARG_OBJECT(0, EventInstance); - Vector2f v; + String* s = 0; - if (!e) - { - throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil argument"); - } + if (const GenericStringEvent* e = + dynamic_cast(i->event)) + { + s = stype->allocate(e->senderName()); + } + else if (const RawDataEvent* e = + dynamic_cast(i->event)) + { + s = stype->allocate(e->senderName()); + } + else + { + throwBadArgumentException(NODE_THIS, NODE_THREAD, "bad event type"); + } - if (const PointerEvent* pe = - dynamic_cast(e->event)) - { - v[0] = pe->w(); - v[1] = pe->h(); + NODE_RETURN(s); } - else if (const RenderEvent* re = - dynamic_cast(e->event)) - { - v[0] = re->w(); - v[1] = re->h(); - } - else + + NODE_IMPLEMENTATION(EventType::key, int) { - throwBadArgumentException(NODE_THIS, NODE_THREAD, "bad event type"); - } + EventInstance* e = NODE_ARG_OBJECT(0, EventInstance); + int k; - return v; -} + if (!e) + { + throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil argument"); + } -NODE_IMPLEMENTATION(EventType::subDomain, Vector2f) -{ - EventInstance* e = NODE_ARG_OBJECT(0, EventInstance); - Vector2f v; + if (const KeyEvent* ke = dynamic_cast(e->event)) + { + k = ke->key(); + } + else + { + throwBadArgumentException(NODE_THIS, NODE_THREAD, "bad event type"); + } - if (!e) - { - throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil argument"); + NODE_RETURN(k); } - if (const PointerEvent* pe = - dynamic_cast(e->event)) + NODE_IMPLEMENTATION(EventType::pointer, Vector2f) { - v[0] = pe->w(); - v[1] = pe->h(); - } - else if (const RenderEvent* re = - dynamic_cast(e->event)) - { - v[0] = re->w(); - v[1] = re->h(); - } - else - { - throwBadArgumentException(NODE_THIS, NODE_THREAD, "bad event type"); - } + EventInstance* e = NODE_ARG_OBJECT(0, EventInstance); + Vector2f v; - if (e->event->eventTable()) - { - v[0] = e->event->eventTable()->bbox().size().x; - v[1] = e->event->eventTable()->bbox().size().y; - } + if (!e) + { + throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil argument"); + } - return v; -} + if (const TabletEvent* te = dynamic_cast(e->event)) + { + v[0] = te->gx(); + v[1] = te->gy(); + } + else if (const PointerEvent* pe = + dynamic_cast(e->event)) + { + v[0] = pe->x(); + v[1] = pe->y(); + } + else + { + throwBadArgumentException(NODE_THIS, NODE_THREAD, "bad event type"); + } -NODE_IMPLEMENTATION(EventType::domainVerticalFlip, bool) -{ - EventInstance* e = NODE_ARG_OBJECT(0, EventInstance); - Vector2f v; + return v; + } - if (e) + NODE_IMPLEMENTATION(EventType::relativePointer, Vector2f) { - if (const RenderEvent* re = dynamic_cast(e->event)) + EventInstance* e = NODE_ARG_OBJECT(0, EventInstance); + Vector2f v; + if (!e) { - if (re->device()) + throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil argument"); + } + + if (const TabletEvent* te = dynamic_cast(e->event)) + { + v[0] = te->gx(); + v[1] = te->gy(); + + if (te->eventTable()) { - NODE_RETURN(re->device()->capabilities() & VideoDevice::FlippedImage); + v[0] -= te->eventTable()->bbox().min.x; + v[1] -= te->eventTable()->bbox().min.y; } - else + } + else if (const PointerEvent* pe = + dynamic_cast(e->event)) + { + v[0] = pe->x(); + v[1] = pe->y(); + + if (pe->eventTable()) { - throwBadArgumentException(NODE_THIS, NODE_THREAD, "RenderEvent has unset device"); + v[0] -= pe->eventTable()->bbox().min.x; + v[1] -= pe->eventTable()->bbox().min.y; } } else { - throwBadArgumentException(NODE_THIS, NODE_THREAD, "event is not a RenderEvent"); + throwBadArgumentException(NODE_THIS, NODE_THREAD, "bad event type"); } + + return v; } - NODE_RETURN(false); -} + NODE_IMPLEMENTATION(EventType::reference, Vector2f) + { + EventInstance* e = NODE_ARG_OBJECT(0, EventInstance); + Vector2f v; + if (!e) + { + throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil argument"); + } -NODE_IMPLEMENTATION(EventType::buttons, int) -{ - EventInstance* e = NODE_ARG_OBJECT(0, EventInstance); - int b; + if (const PointerEvent* pe = + dynamic_cast(e->event)) + { + v[0] = pe->startX(); + v[1] = pe->startY(); + } + else + { + throwBadArgumentException(NODE_THIS, NODE_THREAD, "bad event type"); + } - if (!e) - { - throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil argument"); + return v; } - if (const PointerEvent* pe = - dynamic_cast(e->event)) - { - b = pe->buttonStates(); - } - else + NODE_IMPLEMENTATION(EventType::domain, Vector2f) { - throwBadArgumentException(NODE_THIS, NODE_THREAD, "bad event type"); - } + EventInstance* e = NODE_ARG_OBJECT(0, EventInstance); + Vector2f v; - return b; -} + if (!e) + { + throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil argument"); + } -NODE_IMPLEMENTATION(EventType::modifiers, int) -{ - EventInstance* e = NODE_ARG_OBJECT(0, EventInstance); - int b; + if (const PointerEvent* pe = + dynamic_cast(e->event)) + { + v[0] = pe->w(); + v[1] = pe->h(); + } + else if (const RenderEvent* re = + dynamic_cast(e->event)) + { + v[0] = re->w(); + v[1] = re->h(); + } + else + { + throwBadArgumentException(NODE_THIS, NODE_THREAD, "bad event type"); + } - if (!e) - { - throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil argument"); + return v; } - if (const ModifierEvent* pe = - dynamic_cast(e->event)) - { - b = pe->modifiers(); - } - else + NODE_IMPLEMENTATION(EventType::subDomain, Vector2f) { - throwBadArgumentException(NODE_THIS, NODE_THREAD, "bad event type"); - } + EventInstance* e = NODE_ARG_OBJECT(0, EventInstance); + Vector2f v; - return b; -} + if (!e) + { + throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil argument"); + } -NODE_IMPLEMENTATION(EventType::timeStamp, float) -{ - EventInstance* e = NODE_ARG_OBJECT(0, EventInstance); - if (!e) - { - throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil argument"); - } - NODE_RETURN(float(e->event->timeStamp())); -} + if (const PointerEvent* pe = + dynamic_cast(e->event)) + { + v[0] = pe->w(); + v[1] = pe->h(); + } + else if (const RenderEvent* re = + dynamic_cast(e->event)) + { + v[0] = re->w(); + v[1] = re->h(); + } + else + { + throwBadArgumentException(NODE_THIS, NODE_THREAD, "bad event type"); + } -NODE_IMPLEMENTATION(EventType::reject, void) -{ - EventInstance* e = NODE_ARG_OBJECT(0, EventInstance); - if (!e) - { - throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil argument"); - } - e->event->handled = false; -} + if (e->event->eventTable()) + { + v[0] = e->event->eventTable()->bbox().size().x; + v[1] = e->event->eventTable()->bbox().size().y; + } -NODE_IMPLEMENTATION(EventType::setReturnContent, void) -{ - EventInstance* e = NODE_ARG_OBJECT(0, EventInstance); - String* s = NODE_ARG_OBJECT(1, String); - if (!e) - { - throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil argument"); + return v; } - if (const GenericStringEvent* se = - dynamic_cast(e->event)) + NODE_IMPLEMENTATION(EventType::domainVerticalFlip, bool) { - se->setReturnContent(s->c_str()); - } - else - if (const RawDataEvent* rde = - dynamic_cast(e->event)) - { - rde->setReturnContent(s->c_str()); - } - else - { - throwBadArgumentException(NODE_THIS, NODE_THREAD, "bad event type"); - } -} + EventInstance* e = NODE_ARG_OBJECT(0, EventInstance); + Vector2f v; -NODE_IMPLEMENTATION(EventType::pressure, float) -{ - EventInstance* e = NODE_ARG_OBJECT(0, EventInstance); - if (!e) - { - throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil argument"); - } + if (e) + { + if (const RenderEvent* re = + dynamic_cast(e->event)) + { + if (re->device()) + { + NODE_RETURN(re->device()->capabilities() + & VideoDevice::FlippedImage); + } + else + { + throwBadArgumentException(NODE_THIS, NODE_THREAD, + "RenderEvent has unset device"); + } + } + else + { + throwBadArgumentException(NODE_THIS, NODE_THREAD, + "event is not a RenderEvent"); + } + } - if (const TabletEvent* te = - dynamic_cast(e->event)) - { - NODE_RETURN(float(te->pressure())); + NODE_RETURN(false); } - else - { - NODE_RETURN(1.0f); - } -} -NODE_IMPLEMENTATION(EventType::tangentialPressure, float) -{ - EventInstance* e = NODE_ARG_OBJECT(0, EventInstance); - if (!e) + NODE_IMPLEMENTATION(EventType::buttons, int) { - throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil argument"); - } + EventInstance* e = NODE_ARG_OBJECT(0, EventInstance); + int b; - if (const TabletEvent* te = - dynamic_cast(e->event)) - { - NODE_RETURN(float(te->tangentialPressure())); - } - else - { - NODE_RETURN(1.0f); - } -} + if (!e) + { + throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil argument"); + } -NODE_IMPLEMENTATION(EventType::rotation, float) -{ - EventInstance* e = NODE_ARG_OBJECT(0, EventInstance); - if (!e) - { - throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil argument"); - } + if (const PointerEvent* pe = + dynamic_cast(e->event)) + { + b = pe->buttonStates(); + } + else + { + throwBadArgumentException(NODE_THIS, NODE_THREAD, "bad event type"); + } - if (const TabletEvent* te = - dynamic_cast(e->event)) - { - NODE_RETURN(float(te->rotation())); + return b; } - else + + NODE_IMPLEMENTATION(EventType::modifiers, int) { - NODE_RETURN(0.0f); + EventInstance* e = NODE_ARG_OBJECT(0, EventInstance); + int b; + + if (!e) + { + throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil argument"); + } + + if (const ModifierEvent* pe = + dynamic_cast(e->event)) + { + b = pe->modifiers(); + } + else + { + throwBadArgumentException(NODE_THIS, NODE_THREAD, "bad event type"); + } + + return b; } -} -NODE_IMPLEMENTATION(EventType::xTilt, int) -{ - EventInstance* e = NODE_ARG_OBJECT(0, EventInstance); - if (!e) + NODE_IMPLEMENTATION(EventType::timeStamp, float) { - throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil argument"); + EventInstance* e = NODE_ARG_OBJECT(0, EventInstance); + if (!e) + { + throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil argument"); + } + NODE_RETURN(float(e->event->timeStamp())); } - if (const TabletEvent* te = - dynamic_cast(e->event)) + NODE_IMPLEMENTATION(EventType::reject, void) { - NODE_RETURN(int(te->xTilt())); + EventInstance* e = NODE_ARG_OBJECT(0, EventInstance); + if (!e) + { + throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil argument"); + } + e->event->handled = false; } - else + + NODE_IMPLEMENTATION(EventType::setReturnContent, void) { - NODE_RETURN(int(0)); + EventInstance* e = NODE_ARG_OBJECT(0, EventInstance); + String* s = NODE_ARG_OBJECT(1, String); + if (!e) + { + throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil argument"); + } + + if (const GenericStringEvent* se = + dynamic_cast(e->event)) + { + se->setReturnContent(s->c_str()); + } + else if (const RawDataEvent* rde = + dynamic_cast(e->event)) + { + rde->setReturnContent(s->c_str()); + } + else + { + throwBadArgumentException(NODE_THIS, NODE_THREAD, "bad event type"); + } } -} -NODE_IMPLEMENTATION(EventType::yTilt, int) -{ - EventInstance* e = NODE_ARG_OBJECT(0, EventInstance); - if (!e) + NODE_IMPLEMENTATION(EventType::pressure, float) { - throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil argument"); + EventInstance* e = NODE_ARG_OBJECT(0, EventInstance); + if (!e) + { + throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil argument"); + } + + if (const TabletEvent* te = dynamic_cast(e->event)) + { + NODE_RETURN(float(te->pressure())); + } + else + { + NODE_RETURN(1.0f); + } } - if (const TabletEvent* te = - dynamic_cast(e->event)) + NODE_IMPLEMENTATION(EventType::tangentialPressure, float) { - NODE_RETURN(int(te->yTilt())); + EventInstance* e = NODE_ARG_OBJECT(0, EventInstance); + if (!e) + { + throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil argument"); + } + + if (const TabletEvent* te = dynamic_cast(e->event)) + { + NODE_RETURN(float(te->tangentialPressure())); + } + else + { + NODE_RETURN(1.0f); + } } - else + + NODE_IMPLEMENTATION(EventType::rotation, float) { - NODE_RETURN(int(0)); + EventInstance* e = NODE_ARG_OBJECT(0, EventInstance); + if (!e) + { + throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil argument"); + } + + if (const TabletEvent* te = dynamic_cast(e->event)) + { + NODE_RETURN(float(te->rotation())); + } + else + { + NODE_RETURN(0.0f); + } } -} -NODE_IMPLEMENTATION(EventType::activationTime, float) -{ - EventInstance* e = NODE_ARG_OBJECT(0, EventInstance); - if (!e) + NODE_IMPLEMENTATION(EventType::xTilt, int) { - throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil argument"); + EventInstance* e = NODE_ARG_OBJECT(0, EventInstance); + if (!e) + { + throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil argument"); + } + + if (const TabletEvent* te = dynamic_cast(e->event)) + { + NODE_RETURN(int(te->xTilt())); + } + else + { + NODE_RETURN(int(0)); + } } - if (const PointerButtonPressEvent* pe = - dynamic_cast(e->event)) + NODE_IMPLEMENTATION(EventType::yTilt, int) { - NODE_RETURN(float(pe->activationTime())); + EventInstance* e = NODE_ARG_OBJECT(0, EventInstance); + if (!e) + { + throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil argument"); + } + + if (const TabletEvent* te = dynamic_cast(e->event)) + { + NODE_RETURN(int(te->yTilt())); + } + else + { + NODE_RETURN(int(0)); + } } - else + + NODE_IMPLEMENTATION(EventType::activationTime, float) { - NODE_RETURN(0.0f); - } -} + EventInstance* e = NODE_ARG_OBJECT(0, EventInstance); + if (!e) + { + throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil argument"); + } + if (const PointerButtonPressEvent* pe = + dynamic_cast(e->event)) + { + NODE_RETURN(float(pe->activationTime())); + } + else + { + NODE_RETURN(0.0f); + } + } } // namespace TwkApp diff --git a/src/lib/app/MuTwkApp/FunctionAction.cpp b/src/lib/app/MuTwkApp/FunctionAction.cpp index 8fe4e736c..c4d069202 100644 --- a/src/lib/app/MuTwkApp/FunctionAction.cpp +++ b/src/lib/app/MuTwkApp/FunctionAction.cpp @@ -1,9 +1,9 @@ //****************************************************************************** -// Copyright (c) 2005 Tweak Inc. +// Copyright (c) 2005 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #include #include @@ -17,101 +17,92 @@ #include #include -namespace TwkApp { -using namespace std; - -MuFuncAction::MuFuncAction(Mu::FunctionObject* obj) - : Action() -{ - m_exception = false; - m_func = obj; - m_func->retainExternal(); -} - -MuFuncAction::MuFuncAction(Mu::FunctionObject* obj, const string& doc) - : Action(doc) +namespace TwkApp { - m_func = obj; - m_exception = false; - m_func->retainExternal(); -} + using namespace std; -MuFuncAction::~MuFuncAction() -{ - m_func->releaseExternal(); -} + MuFuncAction::MuFuncAction(Mu::FunctionObject* obj) + : Action() + { + m_exception = false; + m_func = obj; + m_func->retainExternal(); + } -void -MuFuncAction::execute(Document* d, const Event& event) const -{ - HOP_PROF_FUNC(); + MuFuncAction::MuFuncAction(Mu::FunctionObject* obj, const string& doc) + : Action(doc) + { + m_func = obj; + m_exception = false; + m_func->retainExternal(); + } - const EventType* etype = static_cast - (m_func->function()->argType(0)); - Mu::Process* p = muProcess(); + MuFuncAction::~MuFuncAction() { m_func->releaseExternal(); } - EventType::EventInstance* e = - new EventType::EventInstance(etype); - e->event = &event; - event.handled = true; // the user can call reject() - e->document = d; + void MuFuncAction::execute(Document* d, const Event& event) const + { + HOP_PROF_FUNC(); - Mu::Function::ArgumentVector args(1); - args.back() = Mu::Value(e); - - Mu::FunctionObject* preservedFunc = m_func; - ostringstream preservedFuncName; - m_func->function()->output(preservedFuncName); + const EventType* etype = + static_cast(m_func->function()->argType(0)); + Mu::Process* p = muProcess(); - muAppThread()->call(m_func->function(), args, false); + EventType::EventInstance* e = new EventType::EventInstance(etype); + e->event = &event; + event.handled = true; // the user can call reject() + e->document = d; - if (muAppThread()->uncaughtException() && !m_exception) - { - cerr << "ERROR: event = " - << event.name() - << endl; + Mu::Function::ArgumentVector args(1); + args.back() = Mu::Value(e); - if (m_func != preservedFunc || !m_func || !(m_func->function())) - { - cerr << "ERROR: event handler function object corrupted!" << endl; - } + Mu::FunctionObject* preservedFunc = m_func; + ostringstream preservedFuncName; + m_func->function()->output(preservedFuncName); - cerr << "ERROR: function = " << preservedFuncName.str() << endl; + muAppThread()->call(m_func->function(), args, false); - if (const Mu::Object* o = muAppThread()->exception()) + if (muAppThread()->uncaughtException() && !m_exception) { - cerr << "ERROR: Exception Value: "; - o->type()->outputValue(cerr, (Mu::ValuePointer)&o); - cerr << endl; + cerr << "ERROR: event = " << event.name() << endl; - if (o->type() == muContext()->exceptionType() && - muContext()->debugging()) + if (m_func != preservedFunc || !m_func || !(m_func->function())) { - const Mu::ExceptionType::Exception* exc = - static_cast(o); + cerr << "ERROR: event handler function object corrupted!" + << endl; + } + + cerr << "ERROR: function = " << preservedFuncName.str() << endl; - cerr << "Backtrace:" << endl << exc->backtraceAsString() << endl; + if (const Mu::Object* o = muAppThread()->exception()) + { + cerr << "ERROR: Exception Value: "; + o->type()->outputValue(cerr, (Mu::ValuePointer)&o); + cerr << endl; + + if (o->type() == muContext()->exceptionType() + && muContext()->debugging()) + { + const Mu::ExceptionType::Exception* exc = + static_cast(o); + + cerr << "Backtrace:" << endl + << exc->backtraceAsString() << endl; + } } - } - m_exception = true; - } - else - { - //m_exception = false; + m_exception = true; + } + else + { + // m_exception = false; + } } -} -bool -MuFuncAction::error() const -{ - return m_exception; -} + bool MuFuncAction::error() const { return m_exception; } -Action* -MuFuncAction::copy() const -{ - return new MuFuncAction(m_func, docString()); -} + Action* MuFuncAction::copy() const + { + return new MuFuncAction(m_func, docString()); + } -} // TwkApp +} // namespace TwkApp diff --git a/src/lib/app/MuTwkApp/MenuItem.cpp b/src/lib/app/MuTwkApp/MenuItem.cpp index 506a9e883..935bbbbed 100644 --- a/src/lib/app/MuTwkApp/MenuItem.cpp +++ b/src/lib/app/MuTwkApp/MenuItem.cpp @@ -1,9 +1,9 @@ //****************************************************************************** -// Copyright (c) 2003 Tweak Inc. +// Copyright (c) 2003 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #include #include @@ -18,143 +18,135 @@ #include #include -namespace TwkApp { -using namespace Mu; -using namespace std; - -//---------------------------------------------------------------------- - - -MenuItem::MenuItem(Context* c, const char* name, Class *super) : Class(c, name, super) +namespace TwkApp { -} + using namespace Mu; + using namespace std; -MenuItem::~MenuItem() {} + //---------------------------------------------------------------------- -void -MenuItem::load() -{ - USING_MU_FUNCTION_SYMBOLS; + MenuItem::MenuItem(Context* c, const char* name, Class* super) + : Class(c, name, super) + { + } - Symbol *s = scope(); - MuLangContext* context = (MuLangContext*)globalModule()->context(); - Context* c = context; + MenuItem::~MenuItem() {} - const char* className = "MenuItem"; - const char* refName = "MenuItem&"; + void MenuItem::load() + { + USING_MU_FUNCTION_SYMBOLS; - string tname = s->name().c_str(); - tname += "."; - tname += className; - //string tname = "widget"; + Symbol* s = scope(); + MuLangContext* context = (MuLangContext*)globalModule()->context(); + Context* c = context; - string rname = tname + "&"; + const char* className = "MenuItem"; + const char* refName = "MenuItem&"; - const char* tn = tname.c_str(); - const char* rn = rname.c_str(); + string tname = s->name().c_str(); + tname += "."; + tname += className; + // string tname = "widget"; - const char* mi = "MenuItem[]"; - const char* ft = "(void;Event)"; - const char* bft = "(int;)"; + string rname = tname + "&"; - s->addSymbols( new ReferenceType(c, refName, this), + const char* tn = tname.c_str(); + const char* rn = rname.c_str(); - new Function(c, className, BaseFunctions::dereference, Cast, - Return, tn, - Args, rn, End), + const char* mi = "MenuItem[]"; + const char* ft = "(void;Event)"; + const char* bft = "(int;)"; - EndArguments); + s->addSymbols(new ReferenceType(c, refName, this), - globalScope()->addSymbols( + new Function(c, className, BaseFunctions::dereference, + Cast, Return, tn, Args, rn, End), - new Function(c, "=", BaseFunctions::assign, AsOp, - Return, rn, - Args, rn, tn, End), + EndArguments); - EndArguments); + globalScope()->addSymbols( - // - // Layout of struct - // + new Function(c, "=", BaseFunctions::assign, AsOp, Return, rn, Args, + rn, tn, End), - context->functionType(ft); - context->functionType(bft); - context->arrayType(this, 1, 0); - - addSymbols( new MemberVariable(c, "label", "string"), - new MemberVariable(c, "actionHook", ft), - new MemberVariable(c, "key", "string"), - new MemberVariable(c, "stateHook", bft), - new MemberVariable(c, "subMenu", mi), + EndArguments); - new Function(c, "__allocate", BaseFunctions::classAllocate, Function::None, - Function::Return, tn, - Function::End), + // + // Layout of struct + // - new Function(c, className, MenuItem::construct, None, - Return, tn, - Parameters, - new ParameterVariable(c, "this", tn), - new ParameterVariable(c, "label", "string"), - new ParameterVariable(c, "actionHook", ft), - new ParameterVariable(c, "key", "string", Value(Pointer(0))), - new ParameterVariable(c, "stateHook", bft, Value(Pointer(0))), - new ParameterVariable(c, "subMenu", mi, Value(Pointer(0))), - End), + context->functionType(ft); + context->functionType(bft); + context->arrayType(this, 1, 0); - new Function(c, className, MenuItem::construct2, None, - Return, tn, - Parameters, - new ParameterVariable(c, "this", tn), - new ParameterVariable(c, "label", "string"), - new ParameterVariable(c, "subMenu", mi), - End), + addSymbols( + new MemberVariable(c, "label", "string"), + new MemberVariable(c, "actionHook", ft), + new MemberVariable(c, "key", "string"), + new MemberVariable(c, "stateHook", bft), + new MemberVariable(c, "subMenu", mi), - EndArguments ); + new Function(c, "__allocate", BaseFunctions::classAllocate, + Function::None, Function::Return, tn, Function::End), -} + new Function( + c, className, MenuItem::construct, None, Return, tn, Parameters, + new ParameterVariable(c, "this", tn), + new ParameterVariable(c, "label", "string"), + new ParameterVariable(c, "actionHook", ft), + new ParameterVariable(c, "key", "string", Value(Pointer(0))), + new ParameterVariable(c, "stateHook", bft, Value(Pointer(0))), + new ParameterVariable(c, "subMenu", mi, Value(Pointer(0))), + End), + new Function(c, className, MenuItem::construct2, None, Return, tn, + Parameters, new ParameterVariable(c, "this", tn), + new ParameterVariable(c, "label", "string"), + new ParameterVariable(c, "subMenu", mi), End), -NODE_IMPLEMENTATION(MenuItem::construct, Pointer) -{ - Process *p = NODE_THREAD.process(); - const Class *c = static_cast(NODE_THIS.type()); + EndArguments); + } - ClassInstance *o = NODE_ARG_OBJECT(0, ClassInstance); - StringType::String* label = NODE_ARG_OBJECT(1, StringType::String); - FunctionObject* fobj = NODE_ARG_OBJECT(2, FunctionObject); - StringType::String* key = NODE_ARG_OBJECT(3, StringType::String); - FunctionObject* sobj = NODE_ARG_OBJECT(4, FunctionObject); - DynamicArray* array = NODE_ARG_OBJECT(5, DynamicArray); + NODE_IMPLEMENTATION(MenuItem::construct, Pointer) + { + Process* p = NODE_THREAD.process(); + const Class* c = static_cast(NODE_THIS.type()); - Struct* s = o->data(); + ClassInstance* o = NODE_ARG_OBJECT(0, ClassInstance); + StringType::String* label = NODE_ARG_OBJECT(1, StringType::String); + FunctionObject* fobj = NODE_ARG_OBJECT(2, FunctionObject); + StringType::String* key = NODE_ARG_OBJECT(3, StringType::String); + FunctionObject* sobj = NODE_ARG_OBJECT(4, FunctionObject); + DynamicArray* array = NODE_ARG_OBJECT(5, DynamicArray); - s->label = label; - s->key = key; - s->actionCB = fobj; - s->stateCB = sobj; - s->subMenu = array; + Struct* s = o->data(); - NODE_RETURN(Pointer(o)); -} + s->label = label; + s->key = key; + s->actionCB = fobj; + s->stateCB = sobj; + s->subMenu = array; -NODE_IMPLEMENTATION(MenuItem::construct2, Pointer) -{ - Process *p = NODE_THREAD.process(); - const Class *c = static_cast(NODE_THIS.type()); + NODE_RETURN(Pointer(o)); + } + + NODE_IMPLEMENTATION(MenuItem::construct2, Pointer) + { + Process* p = NODE_THREAD.process(); + const Class* c = static_cast(NODE_THIS.type()); - ClassInstance *o = NODE_ARG_OBJECT(0, ClassInstance); - StringType::String* label = NODE_ARG_OBJECT(1, StringType::String); - DynamicArray* array = NODE_ARG_OBJECT(2, DynamicArray); - Struct* s = o->data(); + ClassInstance* o = NODE_ARG_OBJECT(0, ClassInstance); + StringType::String* label = NODE_ARG_OBJECT(1, StringType::String); + DynamicArray* array = NODE_ARG_OBJECT(2, DynamicArray); + Struct* s = o->data(); - s->label = label; - s->key = 0; - s->actionCB = 0; - s->stateCB = 0; - s->subMenu = array; + s->label = label; + s->key = 0; + s->actionCB = 0; + s->stateCB = 0; + s->subMenu = array; - NODE_RETURN(Pointer(o)); -} + NODE_RETURN(Pointer(o)); + } -} // TwkApp +} // namespace TwkApp diff --git a/src/lib/app/MuTwkApp/MenuState.cpp b/src/lib/app/MuTwkApp/MenuState.cpp index 964ff4805..f28fcba3f 100644 --- a/src/lib/app/MuTwkApp/MenuState.cpp +++ b/src/lib/app/MuTwkApp/MenuState.cpp @@ -1,9 +1,9 @@ //****************************************************************************** -// Copyright (c) 2005 Tweak Inc. +// Copyright (c) 2005 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #include @@ -15,72 +15,70 @@ #include #include -namespace TwkApp { -using namespace std; - -MuStateFunc::MuStateFunc(Mu::FunctionObject* obj) : m_func(obj), m_exception(false) +namespace TwkApp { - m_func->retainExternal(); -} + using namespace std; -MuStateFunc::~MuStateFunc() -{ - m_func->releaseExternal(); - m_func = 0; -} + MuStateFunc::MuStateFunc(Mu::FunctionObject* obj) + : m_func(obj) + , m_exception(false) + { + m_func->retainExternal(); + } -int -MuStateFunc::state() -{ - assert(m_func); - Mu::Process* p = muProcess(); - Mu::Function::ArgumentVector args; - const Mu::Function* F = m_func->function(); - Value v = muAppThread()->call(F, args, false); + MuStateFunc::~MuStateFunc() + { + m_func->releaseExternal(); + m_func = 0; + } - if (muAppThread()->uncaughtException() && !m_exception) + int MuStateFunc::state() { - cerr << "ERROR: while evaluating function: "; - Value v(m_func); - m_func->type()->outputValue(cerr, v); - cerr << endl; + assert(m_func); + Mu::Process* p = muProcess(); + Mu::Function::ArgumentVector args; + const Mu::Function* F = m_func->function(); + Value v = muAppThread()->call(F, args, false); - if (const Mu::Object* e = muAppThread()->exception()) + if (muAppThread()->uncaughtException() && !m_exception) { - cerr << "ERROR: Exception Value: "; - e->type()->outputValue(cerr, (ValuePointer)&e); + cerr << "ERROR: while evaluating function: "; + Value v(m_func); + m_func->type()->outputValue(cerr, v); cerr << endl; - if (e->type() == muContext()->exceptionType() && - muContext()->debugging()) + if (const Mu::Object* e = muAppThread()->exception()) { - const Mu::ExceptionType::Exception* exc = - static_cast(e); + cerr << "ERROR: Exception Value: "; + e->type()->outputValue(cerr, (ValuePointer)&e); + cerr << endl; - cerr << "Backtrace:" << endl << exc->backtraceAsString() << endl; + if (e->type() == muContext()->exceptionType() + && muContext()->debugging()) + { + const Mu::ExceptionType::Exception* exc = + static_cast(e); + + cerr << "Backtrace:" << endl + << exc->backtraceAsString() << endl; + } } + + m_exception = true; + } + else + { + // m_exception = false; } - m_exception = true; - } - else - { - //m_exception = false; + return v._int; } - return v._int; -} + bool MuStateFunc::error() const { return m_exception; } -bool -MuStateFunc::error() const -{ - return m_exception; -} - -Menu::StateFunc* -MuStateFunc::copy() const -{ - return new MuStateFunc(m_func); -} + Menu::StateFunc* MuStateFunc::copy() const + { + return new MuStateFunc(m_func); + } -} // TwkApp +} // namespace TwkApp diff --git a/src/lib/app/MuTwkApp/MuInterface.cpp b/src/lib/app/MuTwkApp/MuInterface.cpp index c848d3253..b846e3e3a 100644 --- a/src/lib/app/MuTwkApp/MuInterface.cpp +++ b/src/lib/app/MuTwkApp/MuInterface.cpp @@ -1,9 +1,9 @@ //****************************************************************************** -// Copyright (c) 2005 Tweak Inc. +// Copyright (c) 2005 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #include #include @@ -60,10 +60,10 @@ GenericMachine* g_machine = 0; // static Context::ModuleList g_modules; -static MuLangContext* g_context = 0; -static MuLangLanguage* g_language = 0; -static Process* g_process = 0; -static Thread* g_appThread = 0; +static MuLangContext* g_context = 0; +static MuLangLanguage* g_language = 0; +static Process* g_process = 0; +static Thread* g_appThread = 0; // // This should to be a container searchable by the GC @@ -71,507 +71,467 @@ static Thread* g_appThread = 0; struct ThreadMapEntry { - pthread_t posixThread; - Thread* muThread; + pthread_t posixThread; + Thread* muThread; }; typedef Mu::STLVector::Type ThreadMap; static ThreadMap threadmap; -extern const char *mu_commands; - -namespace TwkApp { +extern const char* mu_commands; -static bool debugging = false; - -CallEnv::CallEnv(Document* d) : Mu::CallEnvironment(), _doc(d) +namespace TwkApp { -} -CallEnv::~CallEnv() -{ -} + static bool debugging = false; -const Value -CallEnv::call(const Function* F, Function::ArgumentVector& args) const -{ - if (_doc) + CallEnv::CallEnv(Document* d) + : Mu::CallEnvironment() + , _doc(d) { - Document* current = Document::activeDocument(); - if (current != _doc) _doc->makeActive(); - const Value v = muProcess()->call(muAppThread(), F, args); - if (current != _doc) current->makeActive(); - return v; } - else - { - return Value(Pointer(0)); - } -} -const Value -CallEnv::callMethodByName(const char* Fname, Function::ArgumentVector& args) const -{ - if (_doc) + CallEnv::~CallEnv() {} + + const Value CallEnv::call(const Function* F, + Function::ArgumentVector& args) const { - Document* current = Document::activeDocument(); - if (current != _doc) _doc->makeActive(); - const Value v = muAppThread()->callMethodByName(Fname, args, false); - if (current != _doc) current->makeActive(); - return v; + if (_doc) + { + Document* current = Document::activeDocument(); + if (current != _doc) + _doc->makeActive(); + const Value v = muProcess()->call(muAppThread(), F, args); + if (current != _doc) + current->makeActive(); + return v; + } + else + { + return Value(Pointer(0)); + } } - else + + const Value CallEnv::callMethodByName(const char* Fname, + Function::ArgumentVector& args) const { - return Value(Pointer(0)); + if (_doc) + { + Document* current = Document::activeDocument(); + if (current != _doc) + _doc->makeActive(); + const Value v = muAppThread()->callMethodByName(Fname, args, false); + if (current != _doc) + current->makeActive(); + return v; + } + else + { + return Value(Pointer(0)); + } } -} -const Context* -CallEnv::context() const -{ - return muContext(); -} + const Context* CallEnv::context() const { return muContext(); } -//---------------------------------------------------------------------- + //---------------------------------------------------------------------- -void -setDebugging(bool b) -{ - debugging = true; - if (g_context) g_context->debugging(true); -} + void setDebugging(bool b) + { + debugging = true; + if (g_context) + g_context->debugging(true); + } -void -setCompileOnDemand(bool b) -{ - Module::setCompileOnDemand(b, b); // sets both mud and muc output -} + void setCompileOnDemand(bool b) + { + Module::setCompileOnDemand(b, b); // sets both mud and muc output + } -void -setDebugMUC(bool b) -{ - Module::setDebugArchive(b); -} + void setDebugMUC(bool b) { Module::setDebugArchive(b); } -bool -isDebuggingOn() -{ - return g_context ? g_context->debugging() : debugging; -} + bool isDebuggingOn() + { + return g_context ? g_context->debugging() : debugging; + } -Context::ModuleList& -muModuleList() -{ - return g_modules; -} + Context::ModuleList& muModuleList() { return g_modules; } -Mu::MuLangContext* -muContext() -{ - return g_context; -} + Mu::MuLangContext* muContext() { return g_context; } -Mu::Process* -muProcess() -{ - return g_process; -} + Mu::Process* muProcess() { return g_process; } -Mu::Thread* -muAppThread() -{ - for (int i=0; i < threadmap.size(); i++) + Mu::Thread* muAppThread() { - if (pthread_equal(threadmap[i].posixThread, pthread_self())) + for (int i = 0; i < threadmap.size(); i++) { - return threadmap[i].muThread; + if (pthread_equal(threadmap[i].posixThread, pthread_self())) + { + return threadmap[i].muThread; + } } - } - ThreadMapEntry entry; - entry.posixThread = pthread_self(); - entry.muThread = muProcess()->newApplicationThread(); - threadmap.push_back(entry); - return entry.muThread; -} + ThreadMapEntry entry; + entry.posixThread = pthread_self(); + entry.muThread = muProcess()->newApplicationThread(); + threadmap.push_back(entry); + return entry.muThread; + } -// alternative to readline + // alternative to readline -const char* -getline(const char *prompt) -{ - static char buffer[1024]; - size_t max_size = 1024; + const char* getline(const char* prompt) + { + static char buffer[1024]; + size_t max_size = 1024; - cout << prompt << flush; + cout << prompt << flush; - int i = 0; + int i = 0; - for (;i < max_size; i++) - { - if (!cin.eof() && !cin.fail()) + for (; i < max_size; i++) { - char c; - cin.get(c); - if (c == '\n') + if (!cin.eof() && !cin.fail()) { - buffer[i] = 0; - return buffer; + char c; + cin.get(c); + if (c == '\n') + { + buffer[i] = 0; + return buffer; + } + else + { + buffer[i] = c; + } } else { - buffer[i] = c; + break; } } + + if (i) + { + if (i != max_size) + i--; + return buffer; + } else { - break; + return 0; } } - if (i) - { - if (i != max_size) i--; - return buffer; - } - else - { - return 0; - } -} - + //---------------------------------------------------------------------- -//---------------------------------------------------------------------- - -std::string -muEval(MuLangContext* context, - Process* process, - const Context::ModuleList& modules, - const char* line, - const char* contextName, - bool showType) -{ - ostringstream str; - - if (*line) + std::string muEval(MuLangContext* context, Process* process, + const Context::ModuleList& modules, const char* line, + const char* contextName, bool showType) { - try + ostringstream str; + + if (*line) { - Mu::TypedValue value = context->evalText(line, - contextName, - process, - modules); + try + { + Mu::TypedValue value = + context->evalText(line, contextName, process, modules); - if (value._type && value._type != context->voidType()) + if (value._type && value._type != context->voidType()) + { + if (showType) + { + value._type->output(str); + str << " => "; + } + + value._type->outputValue(str, value._value); + } + } + catch (Mu::TypedValue value) { - if (showType) + if (Mu::ExceptionType::Exception* e = + (Mu::ExceptionType::Exception*)value._value._Pointer) { - value._type->output(str); - str << " => "; + str << "ERROR: " << e->string() << endl; + cerr << e->backtraceAsString() << endl; } - - value._type->outputValue(str, value._value); } - } - catch (Mu::TypedValue value) - { - if (Mu::ExceptionType::Exception* e = - (Mu::ExceptionType::Exception*) value._value._Pointer) + catch (std::exception& e) { - str << "ERROR: " << e->string() << endl; - cerr << e->backtraceAsString() << endl; + cout << "ERROR: uncaught exception: " << e.what() << endl; } } - catch (std::exception& e) - { - cout << "ERROR: uncaught exception: " << e.what() << endl; - } - } - - return str.str(); -} -std::string -muEvalStringExpr(MuLangContext* context, - Process* process, - const Context::ModuleList& modules, - const char* line, - const char* contextName) -{ - ostringstream str; + return str.str(); + } - if (*line) + std::string muEvalStringExpr(MuLangContext* context, Process* process, + const Context::ModuleList& modules, + const char* line, const char* contextName) { - try + ostringstream str; + + if (*line) { - Mu::TypedValue value = context->evalText(line, - contextName, - process, - modules); + try + { + Mu::TypedValue value = + context->evalText(line, contextName, process, modules); - if (value._type && value._type == context->stringType()) + if (value._type && value._type == context->stringType()) + { + StringType::String* s = + reinterpret_cast( + value._value._Pointer); + str << s->c_str(); + } + } + catch (Mu::TypedValue value) { - StringType::String* s = reinterpret_cast(value._value._Pointer); - str << s->c_str(); + if (Mu::ExceptionType::Exception* e = + (Mu::ExceptionType::Exception*)value._value._Pointer) + { + str << "ERROR: " << e->string() << endl; + cerr << e->backtraceAsString() << endl; + } } - } - catch (Mu::TypedValue value) - { - if (Mu::ExceptionType::Exception* e = - (Mu::ExceptionType::Exception*) value._value._Pointer) + catch (std::exception& e) { - str << "ERROR: " << e->string() << endl; - cerr << e->backtraceAsString() << endl; + cout << "ERROR: uncaught exception: " << e.what() << endl; } } - catch (std::exception& e) - { - cout << "ERROR: uncaught exception: " << e.what() << endl; - } - } - - return str.str(); -} -void -cli() -{ - cout << "Type `help()' for a list of commands." << endl; - cout << "or `help(\"name of command\")' for help on a specific command." << endl; + return str.str(); + } - while (1) + void cli() { - const char *line; - line = getline("rv> "); + cout << "Type `help()' for a list of commands." << endl; + cout << "or `help(\"name of command\")' for help on a specific command." + << endl; - if (!line) exit(0); - if (!*line) continue; + while (1) + { + const char* line; + line = getline("rv> "); - //add_history(line); + if (!line) + exit(0); + if (!*line) + continue; - string command = line; - command += ";"; + // add_history(line); - try - { - Mu::TypedValue value = g_context->evalText(command.c_str(), "input", - g_process, - g_modules); + string command = line; + command += ";"; - if (value._type && value._type != g_context->voidType()) + try { - value._type->output(cout); - cout << " => "; - value._type->outputValue(cout, value._value); - cout << endl << flush; + Mu::TypedValue value = g_context->evalText( + command.c_str(), "input", g_process, g_modules); + + if (value._type && value._type != g_context->voidType()) + { + value._type->output(cout); + cout << " => "; + value._type->outputValue(cout, value._value); + cout << endl << flush; + } } - } - catch (Mu::TypedValue value) - { - if (Mu::ExceptionType::Exception* e = - (Mu::ExceptionType::Exception*) value._value._Pointer) + catch (Mu::TypedValue value) { - cout << "ERROR: " << e->string() << endl; - cerr << e->backtraceAsString() << endl; + if (Mu::ExceptionType::Exception* e = + (Mu::ExceptionType::Exception*)value._value._Pointer) + { + cout << "ERROR: " << e->string() << endl; + cerr << e->backtraceAsString() << endl; + } + } + catch (std::exception& e) + { + cout << "ERROR: uncaught exception: " << e.what() << endl; } - } - catch (std::exception& e) - { - cout << "ERROR: uncaught exception: " << e.what() << endl; } } -} - -void -batch(MuLangContext* context, - Process* process, - const Context::ModuleList& modules, - const char *filename) -{ - NodeAssembler as(context, process); - for (int i=0; i < modules.size(); i++) + void batch(MuLangContext* context, Process* process, + const Context::ModuleList& modules, const char* filename) { - as.pushScope((Module*)modules[i], false); - } - - ifstream in(UNICODE_C_STR(filename)); - context->setInput(in); + NodeAssembler as(context, process); - if (Process *p = Parse(filename, &as)) - { - if (p->rootNode()) + for (int i = 0; i < modules.size(); i++) { - Thread* thread = muAppThread(); - Value v = p->evaluate(thread); + as.pushScope((Module*)modules[i], false); + } + + ifstream in(UNICODE_C_STR(filename)); + context->setInput(in); - if (thread->uncaughtException()) + if (Process* p = Parse(filename, &as)) + { + if (p->rootNode()) { - if (Mu::ExceptionType::Exception* e = - (Mu::ExceptionType::Exception*) thread->exception()) + Thread* thread = muAppThread(); + Value v = p->evaluate(thread); + if (thread->uncaughtException()) { - cerr << "ERROR: " << e->string() << endl; - cerr << e->backtraceAsString() << endl; - } + if (Mu::ExceptionType::Exception* e = + (Mu::ExceptionType::Exception*)thread->exception()) + + { + cerr << "ERROR: " << e->string() << endl; + cerr << e->backtraceAsString() << endl; + } - exit(-1); + exit(-1); + } } } + else + { + exit(-1); + } } - else - { - exit(-1); - } -} -MuLangContext* -newMuContext(const char* batchFile, GCFilterFunc gc_filter, Context::ModuleList& modules) -{ + MuLangContext* newMuContext(const char* batchFile, GCFilterFunc gc_filter, + Context::ModuleList& modules) + { #ifdef PLATFORM_DARWIN - GarbageCollector::init(); - if (gc_filter != 0) GC_register_has_static_roots_callback(gc_filter); + GarbageCollector::init(); + if (gc_filter != 0) + GC_register_has_static_roots_callback(gc_filter); #endif - if (!g_machine) g_machine = new GenericMachine(); - if (!g_language) g_language = new MuLangLanguage; - - MuLangContext* context = new MuLangContext( batchFile ? "batch" : "cli", - batchFile ? batchFile : "input" ); - - context->debugging(debugging); - - // Module* autodoc = new Mu::AutoDocModule(context, "autodoc"); - // Module* io = new Mu::IOModule(context, "io"); - // Module* sys = new Mu::SystemModule(context, "system"); - // Module* img = new Mu::ImageModule(context, "image"); - // Module* enc = new Mu::EncodingModule(context, "encoding"); - // Module* lin = new Mu::MathLinearModule(context, "math_linear"); - Module* commands = new CommandsModule(context, "commands"); - - context->globalScope()->addSymbol(new EventType(context)); - context->globalScope()->addSymbol(new SettingsValueType(context)); - // context->globalScope()->addSymbol(autodoc); - // context->globalScope()->addSymbol(io); - // context->globalScope()->addSymbol(sys); - // context->globalScope()->addSymbol(img); - // context->globalScope()->addSymbol(enc); - // context->globalScope()->addSymbol(lin); - context->globalScope()->addSymbol(commands); - - modules.push_back(commands); - //modules.push_back(autodoc); - //modules.push_back(io); - modules.push_back(context->mathModule()); - modules.push_back(context->mathUtilModule()); - - return context; -} - -void -initMu(const char* batchFile, GCFilterFunc gc_filter) -{ - if (!g_context) - { - g_context = newMuContext(batchFile, gc_filter, g_modules); + if (!g_machine) + g_machine = new GenericMachine(); + if (!g_language) + g_language = new MuLangLanguage; + + MuLangContext* context = new MuLangContext( + batchFile ? "batch" : "cli", batchFile ? batchFile : "input"); + + context->debugging(debugging); + + // Module* autodoc = new Mu::AutoDocModule(context, "autodoc"); + // Module* io = new Mu::IOModule(context, "io"); + // Module* sys = new Mu::SystemModule(context, "system"); + // Module* img = new Mu::ImageModule(context, "image"); + // Module* enc = new Mu::EncodingModule(context, "encoding"); + // Module* lin = new Mu::MathLinearModule(context, "math_linear"); + Module* commands = new CommandsModule(context, "commands"); + + context->globalScope()->addSymbol(new EventType(context)); + context->globalScope()->addSymbol(new SettingsValueType(context)); + // context->globalScope()->addSymbol(autodoc); + // context->globalScope()->addSymbol(io); + // context->globalScope()->addSymbol(sys); + // context->globalScope()->addSymbol(img); + // context->globalScope()->addSymbol(enc); + // context->globalScope()->addSymbol(lin); + context->globalScope()->addSymbol(commands); + + modules.push_back(commands); + // modules.push_back(autodoc); + // modules.push_back(io); + modules.push_back(context->mathModule()); + modules.push_back(context->mathUtilModule()); + + return context; } - if (!g_process) - { - g_process = new Process(g_context); - } - - if (!g_appThread) + void initMu(const char* batchFile, GCFilterFunc gc_filter) { - g_appThread = muAppThread(); - } -} + if (!g_context) + { + g_context = newMuContext(batchFile, gc_filter, g_modules); + } -void -initWithString(MuLangContext* context, - Process* process, - const Context::ModuleList& modules, - const char* p) -{ - try - { - //Timer t; - context->evalText(p, "initWithString", process, modules); - //cout << "EVAL: " << t.elapsed() << " seconds" << endl; + if (!g_process) + { + g_process = new Process(g_context); + } + + if (!g_appThread) + { + g_appThread = muAppThread(); + } } - catch (StreamOpenFailureException) + + void initWithString(MuLangContext* context, Process* process, + const Context::ModuleList& modules, const char* p) { - // Not an error if no file exists + try + { + // Timer t; + context->evalText(p, "initWithString", process, modules); + // cout << "EVAL: " << t.elapsed() << " seconds" << endl; + } + catch (StreamOpenFailureException) + { + // Not an error if no file exists + } } -} -void -initWithFile(MuLangContext* context, - Process* process, - const Context::ModuleList& modules, - const char* file) -{ - try + void initWithFile(MuLangContext* context, Process* process, + const Context::ModuleList& modules, const char* file) { - //Timer t; - context->evalFile(file, process, modules); - //cout << "EVAL: " << t.elapsed() << " seconds" << endl; + try + { + // Timer t; + context->evalFile(file, process, modules); + // cout << "EVAL: " << t.elapsed() << " seconds" << endl; + } + catch (StreamOpenFailureException) + { + // Not an error if no file exists + } } - catch (StreamOpenFailureException) + + void initRc(MuLangContext* context, Process* process, + const Context::ModuleList& modules, const char* rcfile) { - // Not an error if no file exists + ostringstream str; + str << getenv("HOME") << rcfile; + initWithFile(context, process, modules, str.str().c_str()); } -} - -void -initRc(MuLangContext* context, - Process* process, - const Context::ModuleList& modules, - const char* rcfile) -{ - ostringstream str; - str << getenv("HOME") << rcfile; - initWithFile(context, process, modules, str.str().c_str()); -} -Menu* -createTwkAppMenu(const std::string& name, DynamicArray* array) -{ - size_t size = array->size(); - Menu* menu = new Menu(name); - - for (int q=0; q < size; q++) + Menu* createTwkAppMenu(const std::string& name, DynamicArray* array) { - if (ClassInstance* i = array->element(q)) - { - MenuItem::Struct* s = i->data(); - Menu* subMenu = 0; + size_t size = array->size(); + Menu* menu = new Menu(name); - if (s->subMenu) + for (int q = 0; q < size; q++) + { + if (ClassInstance* i = array->element(q)) { - subMenu = createTwkAppMenu(s->label->c_str(), s->subMenu); - } + MenuItem::Struct* s = i->data(); + Menu* subMenu = 0; - MuFuncAction* action = s->actionCB ? new MuFuncAction(s->actionCB) : 0; - MuStateFunc* sfunc = s->stateCB ? new MuStateFunc(s->stateCB) : 0; + if (s->subMenu) + { + subMenu = createTwkAppMenu(s->label->c_str(), s->subMenu); + } - menu->addItem(new Menu::Item(s->label->c_str(), - action, - s->key ? s->key->c_str() : "", - sfunc, - subMenu)); - } - } + MuFuncAction* action = + s->actionCB ? new MuFuncAction(s->actionCB) : 0; + MuStateFunc* sfunc = + s->stateCB ? new MuStateFunc(s->stateCB) : 0; - return menu; -} + menu->addItem(new Menu::Item(s->label->c_str(), action, + s->key ? s->key->c_str() : "", + sfunc, subMenu)); + } + } -void -runMuInterative() -{ - InteractiveSession session; - session.run(muContext(), muProcess(), muAppThread()); -} + return menu; + } + void runMuInterative() + { + InteractiveSession session; + session.run(muContext(), muProcess(), muAppThread()); + } -} +} // namespace TwkApp diff --git a/src/lib/app/MuTwkApp/MuTwkApp/CommandsModule.h b/src/lib/app/MuTwkApp/MuTwkApp/CommandsModule.h index e928217c1..751fc7259 100644 --- a/src/lib/app/MuTwkApp/MuTwkApp/CommandsModule.h +++ b/src/lib/app/MuTwkApp/MuTwkApp/CommandsModule.h @@ -1,9 +1,9 @@ //****************************************************************************** -// Copyright (c) 2005 Tweak Inc. +// Copyright (c) 2005 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #ifndef __MuTwkApp__CommandsModule__h__ #define __MuTwkApp__CommandsModule__h__ @@ -11,56 +11,55 @@ #include #include -namespace TwkApp { - -class CommandsModule : public Mu::Module +namespace TwkApp { -public: - CommandsModule(Mu::Context* c, const char *name); - virtual ~CommandsModule(); - - virtual void load(); - static NODE_DECLARATION(eval, Mu::Pointer); + class CommandsModule : public Mu::Module + { + public: + CommandsModule(Mu::Context* c, const char* name); + virtual ~CommandsModule(); - static NODE_DECLARATION(undo, void); - static NODE_DECLARATION(redo, void); - static NODE_DECLARATION(clearHistory, void); - static NODE_DECLARATION(undoHistory, Mu::Pointer); - static NODE_DECLARATION(redoHistory, Mu::Pointer); - static NODE_DECLARATION(beginCompoundCommand, void); - static NODE_DECLARATION(endCompoundCommand, void); - static NODE_DECLARATION(readFile, void); - static NODE_DECLARATION(writeFile, void); - static NODE_DECLARATION(defineMinorMode, void); - static NODE_DECLARATION(activateMode, void); - static NODE_DECLARATION(isModeActive, bool); - static NODE_DECLARATION(deactivateMode, void); - static NODE_DECLARATION(bindDoc, Mu::Pointer); - static NODE_DECLARATION(bindings, Mu::Pointer); - static NODE_DECLARATION(bind, void); - static NODE_DECLARATION(bindRegex, void); - static NODE_DECLARATION(unbind, void); - static NODE_DECLARATION(unbindRegex, void); - static NODE_DECLARATION(setTableBBox, void); - static NODE_DECLARATION(pushEventTable, void); - static NODE_DECLARATION(popEventTable, void); - static NODE_DECLARATION(popNamedEventTable, void); - static NODE_DECLARATION(activeEventTables, Mu::Pointer); + virtual void load(); - static NODE_DECLARATION(defineModeMenu, void); - // static NODE_DECLARATION(isComputationInProgress, bool); - // static NODE_DECLARATION(computationMessage, Mu::Pointer); - // static NODE_DECLARATION(computationProgress, float); - // static NODE_DECLARATION(computationElapsedTime, float); - static NODE_DECLARATION(contractSeq, Mu::Pointer); + static NODE_DECLARATION(eval, Mu::Pointer); - static NODE_DECLARATION(activeModes, Mu::Pointer); - static NODE_DECLARATION(sequenceOfFile, Mu::Pointer); -}; + static NODE_DECLARATION(undo, void); + static NODE_DECLARATION(redo, void); + static NODE_DECLARATION(clearHistory, void); + static NODE_DECLARATION(undoHistory, Mu::Pointer); + static NODE_DECLARATION(redoHistory, Mu::Pointer); + static NODE_DECLARATION(beginCompoundCommand, void); + static NODE_DECLARATION(endCompoundCommand, void); + static NODE_DECLARATION(readFile, void); + static NODE_DECLARATION(writeFile, void); + static NODE_DECLARATION(defineMinorMode, void); + static NODE_DECLARATION(activateMode, void); + static NODE_DECLARATION(isModeActive, bool); + static NODE_DECLARATION(deactivateMode, void); + static NODE_DECLARATION(bindDoc, Mu::Pointer); + static NODE_DECLARATION(bindings, Mu::Pointer); + static NODE_DECLARATION(bind, void); + static NODE_DECLARATION(bindRegex, void); + static NODE_DECLARATION(unbind, void); + static NODE_DECLARATION(unbindRegex, void); + static NODE_DECLARATION(setTableBBox, void); + static NODE_DECLARATION(pushEventTable, void); + static NODE_DECLARATION(popEventTable, void); + static NODE_DECLARATION(popNamedEventTable, void); + static NODE_DECLARATION(activeEventTables, Mu::Pointer); + static NODE_DECLARATION(defineModeMenu, void); + // static NODE_DECLARATION(isComputationInProgress, bool); + // static NODE_DECLARATION(computationMessage, Mu::Pointer); + // static NODE_DECLARATION(computationProgress, float); + // static NODE_DECLARATION(computationElapsedTime, float); + static NODE_DECLARATION(contractSeq, Mu::Pointer); + static NODE_DECLARATION(activeModes, Mu::Pointer); + static NODE_DECLARATION(sequenceOfFile, Mu::Pointer); + }; -} // TwkApp +} // namespace TwkApp #endif // __MuTwkApp__CommandsModule__h__ diff --git a/src/lib/app/MuTwkApp/MuTwkApp/EventType.h b/src/lib/app/MuTwkApp/MuTwkApp/EventType.h index eaee7f5b4..0e603711e 100644 --- a/src/lib/app/MuTwkApp/MuTwkApp/EventType.h +++ b/src/lib/app/MuTwkApp/MuTwkApp/EventType.h @@ -1,9 +1,9 @@ //****************************************************************************** -// Copyright (c) 2004 Tweak Inc. +// Copyright (c) 2004 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #ifndef __TwkApp__EventType__h__ #define __TwkApp__EventType__h__ @@ -12,71 +12,73 @@ #include #include -namespace TwkApp { -class Document; -class Event; - -class EventType : public Mu::Class +namespace TwkApp { - public: - EventType(Mu::Context*, Mu::Class *super=0); - ~EventType(); + class Document; + class Event; - class EventInstance : public Mu::ClassInstance + class EventType : public Mu::Class { - public: - EventInstance(const Mu::Class*); + public: + EventType(Mu::Context*, Mu::Class* super = 0); + ~EventType(); - const Event* event; - const Document* document; - protected: - friend class EventType; - }; + class EventInstance : public Mu::ClassInstance + { + public: + EventInstance(const Mu::Class*); + + const Event* event; + const Document* document; - // - // API - // + protected: + friend class EventType; + }; - virtual Mu::Object* newObject() const; - virtual void deleteObject(Mu::Object*) const; - virtual void outputValue(std::ostream&, const Mu::Value&, bool full=false) const; - virtual void outputValueRecursive(std::ostream&, - const Mu::ValuePointer, - Mu::Type::ValueOutputState&) const; - virtual void load(); + // + // API + // - static NODE_DECLARATION(print, void); - static NODE_DECLARATION(pointer, Mu::Vector2f); - static NODE_DECLARATION(relativePointer, Mu::Vector2f); - static NODE_DECLARATION(reference, Mu::Vector2f); - static NODE_DECLARATION(domainVerticalFlip, bool); - static NODE_DECLARATION(domain, Mu::Vector2f); - static NODE_DECLARATION(subDomain, Mu::Vector2f); - static NODE_DECLARATION(buttons, int); - static NODE_DECLARATION(modifiers, int); - static NODE_DECLARATION(name, Mu::Pointer); - static NODE_DECLARATION(key, int); - static NODE_DECLARATION(dataContents, Mu::Pointer); - static NODE_DECLARATION(interp, Mu::Pointer); - static NODE_DECLARATION(contents, Mu::Pointer); - static NODE_DECLARATION(contentsArray, Mu::Pointer); - static NODE_DECLARATION(returnContents, Mu::Pointer); - static NODE_DECLARATION(contentType, int); - static NODE_DECLARATION(contentMimeType, Mu::Pointer); - static NODE_DECLARATION(timeStamp, float); - static NODE_DECLARATION(reject, void); - static NODE_DECLARATION(setReturnContent, void); - static NODE_DECLARATION(sender, Mu::Pointer); - static NODE_DECLARATION(pressure, float); - static NODE_DECLARATION(tangentialPressure, float); - static NODE_DECLARATION(rotation, float); - static NODE_DECLARATION(xTilt, int); - static NODE_DECLARATION(yTilt, int); - static NODE_DECLARATION(activationTime, float); + virtual Mu::Object* newObject() const; + virtual void deleteObject(Mu::Object*) const; + virtual void outputValue(std::ostream&, const Mu::Value&, + bool full = false) const; + virtual void outputValueRecursive(std::ostream&, const Mu::ValuePointer, + Mu::Type::ValueOutputState&) const; + virtual void load(); -private: -}; + static NODE_DECLARATION(print, void); + static NODE_DECLARATION(pointer, Mu::Vector2f); + static NODE_DECLARATION(relativePointer, Mu::Vector2f); + static NODE_DECLARATION(reference, Mu::Vector2f); + static NODE_DECLARATION(domainVerticalFlip, bool); + static NODE_DECLARATION(domain, Mu::Vector2f); + static NODE_DECLARATION(subDomain, Mu::Vector2f); + static NODE_DECLARATION(buttons, int); + static NODE_DECLARATION(modifiers, int); + static NODE_DECLARATION(name, Mu::Pointer); + static NODE_DECLARATION(key, int); + static NODE_DECLARATION(dataContents, Mu::Pointer); + static NODE_DECLARATION(interp, Mu::Pointer); + static NODE_DECLARATION(contents, Mu::Pointer); + static NODE_DECLARATION(contentsArray, Mu::Pointer); + static NODE_DECLARATION(returnContents, Mu::Pointer); + static NODE_DECLARATION(contentType, int); + static NODE_DECLARATION(contentMimeType, Mu::Pointer); + static NODE_DECLARATION(timeStamp, float); + static NODE_DECLARATION(reject, void); + static NODE_DECLARATION(setReturnContent, void); + static NODE_DECLARATION(sender, Mu::Pointer); + static NODE_DECLARATION(pressure, float); + static NODE_DECLARATION(tangentialPressure, float); + static NODE_DECLARATION(rotation, float); + static NODE_DECLARATION(xTilt, int); + static NODE_DECLARATION(yTilt, int); + static NODE_DECLARATION(activationTime, float); + + private: + }; -} // TwkApp +} // namespace TwkApp #endif // __TwkApp__EventType__h__ diff --git a/src/lib/app/MuTwkApp/MuTwkApp/FunctionAction.h b/src/lib/app/MuTwkApp/MuTwkApp/FunctionAction.h index 8abb0238b..1896e8702 100644 --- a/src/lib/app/MuTwkApp/MuTwkApp/FunctionAction.h +++ b/src/lib/app/MuTwkApp/MuTwkApp/FunctionAction.h @@ -1,38 +1,39 @@ //****************************************************************************** -// Copyright (c) 2005 Tweak Inc. +// Copyright (c) 2005 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #ifndef __MuTwkApp__FunctionAction__h__ #define __MuTwkApp__FunctionAction__h__ #include #include -namespace TwkApp { +namespace TwkApp +{ -// -// An action which holds a function object and executes on demand. -// + // + // An action which holds a function object and executes on demand. + // -class MuFuncAction : public Action -{ - public: - MuFuncAction(Mu::FunctionObject*); - MuFuncAction(Mu::FunctionObject*, const std::string& docstring); - virtual ~MuFuncAction(); - virtual void execute(Document*, const Event&) const; - virtual Action* copy() const; - virtual bool error() const; + class MuFuncAction : public Action + { + public: + MuFuncAction(Mu::FunctionObject*); + MuFuncAction(Mu::FunctionObject*, const std::string& docstring); + virtual ~MuFuncAction(); + virtual void execute(Document*, const Event&) const; + virtual Action* copy() const; + virtual bool error() const; - Mu::FunctionObject* fobj() const { return m_func; } + Mu::FunctionObject* fobj() const { return m_func; } - private: - Mu::FunctionObject* m_func; - mutable bool m_exception; -}; + private: + Mu::FunctionObject* m_func; + mutable bool m_exception; + }; -} // TwkApp +} // namespace TwkApp #endif // __MuTwkApp__FunctionAction__h__ diff --git a/src/lib/app/MuTwkApp/MuTwkApp/MenuItem.h b/src/lib/app/MuTwkApp/MuTwkApp/MenuItem.h index 791c4f208..f34b343e8 100644 --- a/src/lib/app/MuTwkApp/MuTwkApp/MenuItem.h +++ b/src/lib/app/MuTwkApp/MuTwkApp/MenuItem.h @@ -1,9 +1,9 @@ //****************************************************************************** -// Copyright (c) 2003 Tweak Inc. +// Copyright (c) 2003 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #ifndef __MuTwkApp__MenuItem__h__ #define __MuTwkApp__MenuItem__h__ @@ -14,50 +14,51 @@ #include #include -namespace TwkApp { -using namespace Mu; - -// -// MenuItem is the base of class hierarchy for UI. -// - -class MenuItem : public Class +namespace TwkApp { -public: + using namespace Mu; + // - // ClassInstance Structure + // MenuItem is the base of class hierarchy for UI. // - struct Struct + class MenuItem : public Class { - StringType::String* label; - FunctionObject* actionCB; - StringType::String* key; - FunctionObject* stateCB; - DynamicArray* subMenu; - }; + public: + // + // ClassInstance Structure + // - // - // Constructors - // + struct Struct + { + StringType::String* label; + FunctionObject* actionCB; + StringType::String* key; + FunctionObject* stateCB; + DynamicArray* subMenu; + }; - MenuItem(Context* c, const char* name, Class *super=0); - ~MenuItem(); + // + // Constructors + // - // - // Symbol API - // + MenuItem(Context* c, const char* name, Class* super = 0); + ~MenuItem(); - virtual void load(); + // + // Symbol API + // - // - // Constant - // + virtual void load(); - static NODE_DECLARATION(construct, Pointer); - static NODE_DECLARATION(construct2, Pointer); -}; + // + // Constant + // + + static NODE_DECLARATION(construct, Pointer); + static NODE_DECLARATION(construct2, Pointer); + }; -} // TwkApp +} // namespace TwkApp #endif // __MuTwkApp__MenuItem__h__ diff --git a/src/lib/app/MuTwkApp/MuTwkApp/MenuState.h b/src/lib/app/MuTwkApp/MuTwkApp/MenuState.h index 8d9c44404..b49a8aafa 100644 --- a/src/lib/app/MuTwkApp/MuTwkApp/MenuState.h +++ b/src/lib/app/MuTwkApp/MuTwkApp/MenuState.h @@ -1,34 +1,34 @@ //****************************************************************************** -// Copyright (c) 2005 Tweak Inc. +// Copyright (c) 2005 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #ifndef __MuTwkApp__MenuState__h__ #define __MuTwkApp__MenuState__h__ #include #include -namespace TwkApp { - -class MuStateFunc : public Menu::StateFunc +namespace TwkApp { -public: - MuStateFunc(Mu::FunctionObject*); - virtual ~MuStateFunc(); - virtual int state(); - virtual Menu::StateFunc* copy() const; - virtual bool error() const; - - bool exceptionOccuredLastTime() const { return m_exception; } -private: - Mu::FunctionObject* m_func; - bool m_exception; -}; + class MuStateFunc : public Menu::StateFunc + { + public: + MuStateFunc(Mu::FunctionObject*); + virtual ~MuStateFunc(); + virtual int state(); + virtual Menu::StateFunc* copy() const; + virtual bool error() const; + + bool exceptionOccuredLastTime() const { return m_exception; } + private: + Mu::FunctionObject* m_func; + bool m_exception; + }; -} // TwkApp +} // namespace TwkApp #endif // __MuTwkApp__MenuState__h__ diff --git a/src/lib/app/MuTwkApp/MuTwkApp/MuInterface.h b/src/lib/app/MuTwkApp/MuTwkApp/MuInterface.h index 0e3a18ec1..c3e7f84c6 100644 --- a/src/lib/app/MuTwkApp/MuTwkApp/MuInterface.h +++ b/src/lib/app/MuTwkApp/MuTwkApp/MuInterface.h @@ -1,9 +1,9 @@ //****************************************************************************** -// Copyright (c) 2005 Tweak Inc. +// Copyright (c) 2005 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #ifndef __MuTwkApp__MuInterface__h__ #define __MuTwkApp__MuInterface__h__ @@ -11,84 +11,78 @@ #include #include -namespace TwkApp { -class Menu; -class Document; - -class CallEnv : public Mu::CallEnvironment +namespace TwkApp { - public: - CallEnv(Document* d); - virtual ~CallEnv(); - virtual const Mu::Value call(const Mu::Function*, Mu::Function::ArgumentVector&) const; - virtual const Mu::Value callMethodByName(const char*, Mu::Function::ArgumentVector&) const; - virtual const Mu::Context* context() const; - void invalidate() { _doc = 0; } - private: - Document* _doc; -}; - -Mu::Context::ModuleList& muModuleList(); -Mu::MuLangContext* muContext(); -Mu::Process* muProcess(); -Mu::Thread* muAppThread(); - -typedef int (*GCFilterFunc)(const char*, void*, size_t); - -void setDebugging(bool); -void setCompileOnDemand(bool); -void setDebugMUC(bool); -bool isDebuggingOn(); - -std::string muEval(Mu::MuLangContext*, - Mu::Process*, - const Mu::Context::ModuleList& modules, - const char* line, - const char* contextName="eval", - bool showType = true); - -std::string muEvalStringExpr(Mu::MuLangContext*, - Mu::Process*, - const Mu::Context::ModuleList& modules, - const char* line, - const char* contextName="eval"); -void cli(); - -void batch(Mu::MuLangContext*, - Mu::Process*, - const Mu::Context::ModuleList&, - const char* filename); - -void initMu(const char* batchfile, GCFilterFunc F = 0); - -void initWithFile(Mu::MuLangContext*, - Mu::Process*, - const Mu::Context::ModuleList&, - const char* filename); - -void initWithString(Mu::MuLangContext*, - Mu::Process*, - const Mu::Context::ModuleList&, - const char* buffer); - -void initRc(Mu::MuLangContext*, - Mu::Process*, - const Mu::Context::ModuleList&, - const char* rcfile); - -TwkApp::Menu* createTwkAppMenu(const std::string& name, Mu::DynamicArray* array); + class Menu; + class Document; -// -// For multi-threaded, etc, you can create a unique app context for -// each thread by calling this. batchfile and gc_filter can be 0 -// + class CallEnv : public Mu::CallEnvironment + { + public: + CallEnv(Document* d); + virtual ~CallEnv(); + virtual const Mu::Value call(const Mu::Function*, + Mu::Function::ArgumentVector&) const; + virtual const Mu::Value + callMethodByName(const char*, Mu::Function::ArgumentVector&) const; + virtual const Mu::Context* context() const; + + void invalidate() { _doc = 0; } + + private: + Document* _doc; + }; + + Mu::Context::ModuleList& muModuleList(); + Mu::MuLangContext* muContext(); + Mu::Process* muProcess(); + Mu::Thread* muAppThread(); + + typedef int (*GCFilterFunc)(const char*, void*, size_t); + + void setDebugging(bool); + void setCompileOnDemand(bool); + void setDebugMUC(bool); + bool isDebuggingOn(); + + std::string muEval(Mu::MuLangContext*, Mu::Process*, + const Mu::Context::ModuleList& modules, const char* line, + const char* contextName = "eval", bool showType = true); + + std::string muEvalStringExpr(Mu::MuLangContext*, Mu::Process*, + const Mu::Context::ModuleList& modules, + const char* line, + const char* contextName = "eval"); + void cli(); + + void batch(Mu::MuLangContext*, Mu::Process*, const Mu::Context::ModuleList&, + const char* filename); + + void initMu(const char* batchfile, GCFilterFunc F = 0); + + void initWithFile(Mu::MuLangContext*, Mu::Process*, + const Mu::Context::ModuleList&, const char* filename); + + void initWithString(Mu::MuLangContext*, Mu::Process*, + const Mu::Context::ModuleList&, const char* buffer); + + void initRc(Mu::MuLangContext*, Mu::Process*, + const Mu::Context::ModuleList&, const char* rcfile); + + TwkApp::Menu* createTwkAppMenu(const std::string& name, + Mu::DynamicArray* array); + + // + // For multi-threaded, etc, you can create a unique app context for + // each thread by calling this. batchfile and gc_filter can be 0 + // -Mu::MuLangContext* newMuContext(const char* batchFile, - GCFilterFunc gc_filter, - Mu::Context::ModuleList& modules); + Mu::MuLangContext* newMuContext(const char* batchFile, + GCFilterFunc gc_filter, + Mu::Context::ModuleList& modules); -void runMuInterative(); + void runMuInterative(); -} +} // namespace TwkApp #endif // __MuTwkApp__MuInterface__h__ diff --git a/src/lib/app/MuTwkApp/MuTwkApp/SettingsValueType.h b/src/lib/app/MuTwkApp/MuTwkApp/SettingsValueType.h index 5d3ff59b7..5940b7017 100644 --- a/src/lib/app/MuTwkApp/MuTwkApp/SettingsValueType.h +++ b/src/lib/app/MuTwkApp/MuTwkApp/SettingsValueType.h @@ -1,65 +1,77 @@ // -// Copyright (c) 2009 Tweak Software. +// Copyright (c) 2009 Tweak Software. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// // #ifndef __TwkApp__SettingsValueType__h__ #define __TwkApp__SettingsValueType__h__ #include #include -namespace Mu { -class VariantInstance; +namespace Mu +{ + class VariantInstance; } -namespace TwkApp { +namespace TwkApp +{ + class SettingsValueType : public Mu::VariantType + { + public: + enum ValueType + { + NoType, + FloatType, + IntType, + BoolType, + StringType, + StringArrayType, + FloatArrayType, + IntArrayType + }; -class SettingsValueType : public Mu::VariantType -{ - public: - - enum ValueType - { - NoType, - FloatType, - IntType, - BoolType, - StringType, - StringArrayType, - FloatArrayType, - IntArrayType - }; + SettingsValueType(Mu::Context*); + virtual ~SettingsValueType(); - SettingsValueType(Mu::Context*); - virtual ~SettingsValueType(); + virtual void load(); - virtual void load(); + static NODE_DECLARATION(defaultConstructor, Mu::Pointer); - static NODE_DECLARATION(defaultConstructor, Mu::Pointer); + ValueType valueType(Mu::VariantInstance*) const; - ValueType valueType(Mu::VariantInstance*) const; + const Mu::VariantTagType* boolType() const { return _boolType; } - const Mu::VariantTagType* boolType() const { return _boolType; } - const Mu::VariantTagType* intType() const { return _intType; } - const Mu::VariantTagType* floatType() const { return _floatType; } - const Mu::VariantTagType* stringType() const { return _stringType; } - const Mu::VariantTagType* stringArrayType() const { return _stringArrayType; } - const Mu::VariantTagType* floatArrayType() const { return _floatArrayType; } - const Mu::VariantTagType* intArrayType() const { return _intArrayType; } + const Mu::VariantTagType* intType() const { return _intType; } - private: - Mu::VariantTagType* _boolType; - Mu::VariantTagType* _intType; - Mu::VariantTagType* _floatType; - Mu::VariantTagType* _stringType; - Mu::VariantTagType* _intArrayType; - Mu::VariantTagType* _stringArrayType; - Mu::VariantTagType* _floatArrayType; -}; + const Mu::VariantTagType* floatType() const { return _floatType; } + + const Mu::VariantTagType* stringType() const { return _stringType; } + + const Mu::VariantTagType* stringArrayType() const + { + return _stringArrayType; + } + + const Mu::VariantTagType* floatArrayType() const + { + return _floatArrayType; + } + + const Mu::VariantTagType* intArrayType() const { return _intArrayType; } + + private: + Mu::VariantTagType* _boolType; + Mu::VariantTagType* _intType; + Mu::VariantTagType* _floatType; + Mu::VariantTagType* _stringType; + Mu::VariantTagType* _intArrayType; + Mu::VariantTagType* _stringArrayType; + Mu::VariantTagType* _floatArrayType; + }; -} // TwkApp +} // namespace TwkApp #endif // __TwkApp__SettingsValueType__h__ diff --git a/src/lib/app/MuTwkApp/SettingsValueType.cpp b/src/lib/app/MuTwkApp/SettingsValueType.cpp index 699c68b2a..dd9d938dd 100644 --- a/src/lib/app/MuTwkApp/SettingsValueType.cpp +++ b/src/lib/app/MuTwkApp/SettingsValueType.cpp @@ -1,9 +1,9 @@ // -// Copyright (c) 2009 Tweak Software. +// Copyright (c) 2009 Tweak Software. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// // #include #include @@ -16,42 +16,46 @@ #include #include -namespace TwkApp { -using namespace std; -using namespace Mu; +namespace TwkApp +{ + using namespace std; + using namespace Mu; -SettingsValueType::SettingsValueType(Context* c) : VariantType(c, "SettingsValue") {} -SettingsValueType::~SettingsValueType() {} + SettingsValueType::SettingsValueType(Context* c) + : VariantType(c, "SettingsValue") + { + } -void -SettingsValueType::load() -{ - USING_MU_FUNCTION_SYMBOLS; + SettingsValueType::~SettingsValueType() {} + + void SettingsValueType::load() + { + USING_MU_FUNCTION_SYMBOLS; - MuLangContext* context = (MuLangContext*)globalModule()->context(); - Context* c = context; - context->arrayType(context->floatType(), 1, 0); - context->arrayType(context->intType(), 1, 0); - context->arrayType(context->stringType(), 1, 0); + MuLangContext* context = (MuLangContext*)globalModule()->context(); + Context* c = context; + context->arrayType(context->floatType(), 1, 0); + context->arrayType(context->intType(), 1, 0); + context->arrayType(context->stringType(), 1, 0); - _floatType = new VariantTagType(c, "Float", "float"); - _intType = new VariantTagType(c, "Int", "int"); - _stringType = new VariantTagType(c, "String", "string"); - _boolType = new VariantTagType(c, "Bool", "bool"); - _floatArrayType = new VariantTagType(c, "FloatArray", "float[]"); - _intArrayType = new VariantTagType(c, "IntArray", "int[]"); - _stringArrayType = new VariantTagType(c, "StringArray", "string[]"); + _floatType = new VariantTagType(c, "Float", "float"); + _intType = new VariantTagType(c, "Int", "int"); + _stringType = new VariantTagType(c, "String", "string"); + _boolType = new VariantTagType(c, "Bool", "bool"); + _floatArrayType = new VariantTagType(c, "FloatArray", "float[]"); + _intArrayType = new VariantTagType(c, "IntArray", "int[]"); + _stringArrayType = new VariantTagType(c, "StringArray", "string[]"); - addSymbols(_floatType, _intType, _stringType, _boolType, - _floatArrayType, _intArrayType, _stringArrayType, - EndArguments); + addSymbols(_floatType, _intType, _stringType, _boolType, + _floatArrayType, _intArrayType, _stringArrayType, + EndArguments); - String rtname = name().c_str(); - rtname += "&"; - ReferenceType* rt = new ReferenceType(c, rtname.c_str(), this); - scope()->addSymbol(rt); + String rtname = name().c_str(); + rtname += "&"; + ReferenceType* rt = new ReferenceType(c, rtname.c_str(), this); + scope()->addSymbol(rt); - const char* tn = fullyQualifiedName().c_str(); + const char* tn = fullyQualifiedName().c_str(); #if 0 for (int i=0 i < constructors.size(); i++) @@ -69,45 +73,49 @@ SettingsValueType::load() } #endif - Function* OpAs = new Function(c, "=", - BaseFunctions::assign, - Function::MemberOperator | Function::Operator, - Function::Return, - rt->fullyQualifiedName().c_str(), - Function::Args, - rt->fullyQualifiedName().c_str(), - tn, - Function::End); + Function* OpAs = new Function( + c, "=", BaseFunctions::assign, + Function::MemberOperator | Function::Operator, Function::Return, + rt->fullyQualifiedName().c_str(), Function::Args, + rt->fullyQualifiedName().c_str(), tn, Function::End); + + globalScope()->addSymbol(OpAs); + } - globalScope()->addSymbol(OpAs); -} + NODE_IMPLEMENTATION(SettingsValueType::defaultConstructor, Pointer) + { + // + // Tricky -- get the scope of the constructor symbol -- that's + // the tag type. + // -NODE_IMPLEMENTATION(SettingsValueType::defaultConstructor, Pointer) -{ - // - // Tricky -- get the scope of the constructor symbol -- that's - // the tag type. - // + const VariantTagType* t = + static_cast(NODE_THIS.symbol()->scope()); - const VariantTagType* t = - static_cast(NODE_THIS.symbol()->scope()); + NODE_RETURN(VariantInstance::allocate(t)); + } - NODE_RETURN(VariantInstance::allocate(t)); -} + SettingsValueType::ValueType + SettingsValueType::valueType(VariantInstance* vobj) const + { + const VariantTagType* tt = + static_cast(vobj->type()); + + if (tt == _stringType) + return StringType; + else if (tt == _intType) + return IntType; + else if (tt == _boolType) + return BoolType; + else if (tt == _floatType) + return FloatType; + else if (tt == _stringArrayType) + return StringArrayType; + else if (tt == _floatArrayType) + return FloatArrayType; + else if (tt == _intArrayType) + return IntArrayType; + return NoType; + } -SettingsValueType::ValueType -SettingsValueType::valueType(VariantInstance* vobj) const -{ - const VariantTagType* tt = static_cast(vobj->type()); - - if (tt == _stringType) return StringType; - else if (tt == _intType) return IntType; - else if (tt == _boolType) return BoolType; - else if (tt == _floatType) return FloatType; - else if (tt == _stringArrayType) return StringArrayType; - else if (tt == _floatArrayType) return FloatArrayType; - else if (tt == _intArrayType) return IntArrayType; - return NoType; -} - -} // TwkApp +} // namespace TwkApp diff --git a/src/lib/app/PyMediaLibrary/PyMediaLibrary.cpp b/src/lib/app/PyMediaLibrary/PyMediaLibrary.cpp index bb37724f1..06b69c83b 100644 --- a/src/lib/app/PyMediaLibrary/PyMediaLibrary.cpp +++ b/src/lib/app/PyMediaLibrary/PyMediaLibrary.cpp @@ -9,66 +9,58 @@ namespace TwkMediaLibrary { - PyMediaLibrary::PyMediaLibrary( const std::string& appName ) - : Library( "py-media-library", appName ), m_root( new PyRootNode( this ) ) - { - } - - PyMediaLibrary::~PyMediaLibrary() - { - delete m_root; - } + PyMediaLibrary::PyMediaLibrary(const std::string& appName) + : Library("py-media-library", appName) + , m_root(new PyRootNode(this)) + { + } - const Node* PyMediaLibrary::rootNode() const - { - return m_root; - } + PyMediaLibrary::~PyMediaLibrary() { delete m_root; } - size_t PyMediaLibrary::numNodeTypeNames() const - { - return 2; - } + const Node* PyMediaLibrary::rootNode() const { return m_root; } - std::string PyMediaLibrary::nodeTypeName( size_t i ) const - { - return nameFromPyNodeType( PyNodeType( PyNoType + i + 1 ) ); - } + size_t PyMediaLibrary::numNodeTypeNames() const { return 2; } - const NodeAPI* PyMediaLibrary::nodeAPI( const Node* innode ) const - { - if( const auto* node = dynamic_cast( innode ) ) + std::string PyMediaLibrary::nodeTypeName(size_t i) const { - return node; + return nameFromPyNodeType(PyNodeType(PyNoType + i + 1)); } - return nullptr; - } - - bool PyMediaLibrary::isLibraryMediaURL( const URL& inURL ) const - { - if( const auto* root = dynamic_cast( rootNode() ) ) + const NodeAPI* PyMediaLibrary::nodeAPI(const Node* innode) const { - return root->isLibraryMediaURL( inURL ); + if (const auto* node = dynamic_cast(innode)) + { + return node; + } + + return nullptr; } - return false; - } + bool PyMediaLibrary::isLibraryMediaURL(const URL& inURL) const + { + if (const auto* root = dynamic_cast(rootNode())) + { + return root->isLibraryMediaURL(inURL); + } - NodeVector PyMediaLibrary::associatedNodes( const URL& inURL ) const - { - NodeVector nodes; + return false; + } - if( const auto* root = dynamic_cast( rootNode() ) ) + NodeVector PyMediaLibrary::associatedNodes(const URL& inURL) const { - const MediaNodeVector mediaNodes = root->mediaNodesForURL( inURL ); + NodeVector nodes; - for( const auto* mediaNode : mediaNodes ) - { - nodes.push_back( mediaNode ); - } - } + if (const auto* root = dynamic_cast(rootNode())) + { + const MediaNodeVector mediaNodes = root->mediaNodesForURL(inURL); - return nodes; - } + for (const auto* mediaNode : mediaNodes) + { + nodes.push_back(mediaNode); + } + } + + return nodes; + } -} // namespace TwkMediaLibrary +} // namespace TwkMediaLibrary diff --git a/src/lib/app/PyMediaLibrary/PyMediaLibrary/PyMediaLibrary.h b/src/lib/app/PyMediaLibrary/PyMediaLibrary/PyMediaLibrary.h index a13eb00ce..b87bf9690 100644 --- a/src/lib/app/PyMediaLibrary/PyMediaLibrary/PyMediaLibrary.h +++ b/src/lib/app/PyMediaLibrary/PyMediaLibrary/PyMediaLibrary.h @@ -14,29 +14,29 @@ namespace TwkMediaLibrary { - class PyRootNode; - class PyMediaNode; + class PyRootNode; + class PyMediaNode; - class PyMediaLibrary : public Library - { - public: - using StreamingURLNodeMap = std::map; + class PyMediaLibrary : public Library + { + public: + using StreamingURLNodeMap = std::map; - explicit PyMediaLibrary( const std::string& appName ); - virtual ~PyMediaLibrary(); + explicit PyMediaLibrary(const std::string& appName); + virtual ~PyMediaLibrary(); - size_t numNodeTypeNames() const override; - std::string nodeTypeName( size_t ) const override; + size_t numNodeTypeNames() const override; + std::string nodeTypeName(size_t) const override; - bool isLibraryMediaURL( const URL& ) const override; + bool isLibraryMediaURL(const URL&) const override; - const Node* rootNode() const override; + const Node* rootNode() const override; - NodeVector associatedNodes( const URL& url ) const override; - const NodeAPI* nodeAPI( const Node* ) const override; + NodeVector associatedNodes(const URL& url) const override; + const NodeAPI* nodeAPI(const Node*) const override; - private: - PyRootNode* m_root; - }; + private: + PyRootNode* m_root; + }; -} // namespace TwkMediaLibrary +} // namespace TwkMediaLibrary diff --git a/src/lib/app/PyMediaLibrary/PyMediaLibrary/PyMediaNode.h b/src/lib/app/PyMediaLibrary/PyMediaLibrary/PyMediaNode.h index 9e23dabac..aecf1ee98 100644 --- a/src/lib/app/PyMediaLibrary/PyMediaLibrary/PyMediaNode.h +++ b/src/lib/app/PyMediaLibrary/PyMediaLibrary/PyMediaNode.h @@ -17,27 +17,29 @@ namespace TwkMediaLibrary { - using Plugin = PyObject*; - - class PyMediaLibrary; - - class PyMediaNode : public PyNode, public MediaAPI - { - public: - PyMediaNode( Library* lib, URL url, PyNode* parent, Plugin plugin, - std::string pluginName ); - virtual ~PyMediaNode(); - virtual const Node* node() const; - URL mediaURL() const override; - bool isStreaming() const override; - bool isRedirecting() const override; - const Node* baseMediaNode() const override; - HTTPCookieVector httpCookies() const override; - HTTPHeaderVector httpHeaders() const override; - URL httpRedirection() const override; - - private: - const URL m_url; - PyObject* m_plugin; - }; -} // namespace TwkMediaLibrary \ No newline at end of file + using Plugin = PyObject*; + + class PyMediaLibrary; + + class PyMediaNode + : public PyNode + , public MediaAPI + { + public: + PyMediaNode(Library* lib, URL url, PyNode* parent, Plugin plugin, + std::string pluginName); + virtual ~PyMediaNode(); + virtual const Node* node() const; + URL mediaURL() const override; + bool isStreaming() const override; + bool isRedirecting() const override; + const Node* baseMediaNode() const override; + HTTPCookieVector httpCookies() const override; + HTTPHeaderVector httpHeaders() const override; + URL httpRedirection() const override; + + private: + const URL m_url; + PyObject* m_plugin; + }; +} // namespace TwkMediaLibrary diff --git a/src/lib/app/PyMediaLibrary/PyMediaLibrary/PyNode.h b/src/lib/app/PyMediaLibrary/PyMediaLibrary/PyNode.h index c183420e0..c3c8e2aa4 100644 --- a/src/lib/app/PyMediaLibrary/PyMediaLibrary/PyNode.h +++ b/src/lib/app/PyMediaLibrary/PyMediaLibrary/PyNode.h @@ -13,47 +13,47 @@ namespace TwkMediaLibrary { - class PyMediaLibrary; - - enum PyNodeType - { - PyNoType = 0, - PyRootType, - PyMediaType - }; - - std::string nameFromPyNodeType( PyNodeType t ); - - class PyNode : public Node - { - public: - using PyNodeVector = std::vector; - using NodeAPIVector = std::vector; - - const Node* parent() const override; - size_t numChildren() const override; - const Node* child( size_t index ) const override; - - std::string name() const override; - std::string typeName() const override; - - protected: - explicit PyNode( Library*, PyNode* parent = nullptr, std::string name = "", - PyNodeType type = PyNoType ); - virtual ~PyNode() = default; - - void addChild( PyNode* ); - void setName( const std::string& ) override; - - friend class PyMediaLibrary; - - private: - PyNodeType m_type; - std::string m_name; - PyNode* m_parent; - PyNodeVector m_children; - NodeAPIVector m_apiVector; - URL m_mediaURL; - }; - -} // namespace TwkMediaLibrary \ No newline at end of file + class PyMediaLibrary; + + enum PyNodeType + { + PyNoType = 0, + PyRootType, + PyMediaType + }; + + std::string nameFromPyNodeType(PyNodeType t); + + class PyNode : public Node + { + public: + using PyNodeVector = std::vector; + using NodeAPIVector = std::vector; + + const Node* parent() const override; + size_t numChildren() const override; + const Node* child(size_t index) const override; + + std::string name() const override; + std::string typeName() const override; + + protected: + explicit PyNode(Library*, PyNode* parent = nullptr, + std::string name = "", PyNodeType type = PyNoType); + virtual ~PyNode() = default; + + void addChild(PyNode*); + void setName(const std::string&) override; + + friend class PyMediaLibrary; + + private: + PyNodeType m_type; + std::string m_name; + PyNode* m_parent; + PyNodeVector m_children; + NodeAPIVector m_apiVector; + URL m_mediaURL; + }; + +} // namespace TwkMediaLibrary diff --git a/src/lib/app/PyMediaLibrary/PyMediaLibrary/PyRootNode.h b/src/lib/app/PyMediaLibrary/PyMediaLibrary/PyRootNode.h index 7ac0a6e77..6efb182b0 100644 --- a/src/lib/app/PyMediaLibrary/PyMediaLibrary/PyRootNode.h +++ b/src/lib/app/PyMediaLibrary/PyMediaLibrary/PyRootNode.h @@ -19,17 +19,17 @@ namespace TwkMediaLibrary { - class PyMediaNode; + class PyMediaNode; - using MediaNodeVector = std::vector; + using MediaNodeVector = std::vector; - class PyRootNode : public PyNode - { - public: - PyRootNode( Library* lib ); - virtual ~PyRootNode(); + class PyRootNode : public PyNode + { + public: + PyRootNode(Library* lib); + virtual ~PyRootNode(); - bool isLibraryMediaURL( const URL& ) const; - MediaNodeVector mediaNodesForURL( const URL& ) const; - }; -} // namespace TwkMediaLibrary \ No newline at end of file + bool isLibraryMediaURL(const URL&) const; + MediaNodeVector mediaNodesForURL(const URL&) const; + }; +} // namespace TwkMediaLibrary diff --git a/src/lib/app/PyMediaLibrary/PyMediaNode.cpp b/src/lib/app/PyMediaLibrary/PyMediaNode.cpp index 8dc20dd66..439b13a81 100644 --- a/src/lib/app/PyMediaLibrary/PyMediaNode.cpp +++ b/src/lib/app/PyMediaLibrary/PyMediaNode.cpp @@ -17,191 +17,187 @@ namespace TwkMediaLibrary { - PyMediaNode::PyMediaNode( Library* lib, URL url, PyNode* parent, - Plugin plugin, std::string pluginName ) - : PyNode( lib, parent, std::move( pluginName ), PyNodeType::PyMediaType ), - MediaAPI(), - m_url( std::move( url ) ), - m_plugin( plugin ) - { - Py_XINCREF( m_plugin ); - } - - PyMediaNode::~PyMediaNode() - { - Py_XDECREF( m_plugin ); - } - - const Node* PyMediaNode::node() const - { - return this; - } - - URL PyMediaNode::mediaURL() const - { - return m_url; - } - - bool PyMediaNode::isStreaming() const - { - PyLockObject lock; - - PyObject* ret = - PyObject_CallMethod( m_plugin, "is_streaming", "s", m_url.c_str() ); - - if( ret == nullptr ) + PyMediaNode::PyMediaNode(Library* lib, URL url, PyNode* parent, + Plugin plugin, std::string pluginName) + : PyNode(lib, parent, std::move(pluginName), PyNodeType::PyMediaType) + , MediaAPI() + , m_url(std::move(url)) + , m_plugin(plugin) { - PyErr_Print(); - return false; + Py_XINCREF(m_plugin); } - return PyObject_IsTrue( ret ); - } + PyMediaNode::~PyMediaNode() { Py_XDECREF(m_plugin); } - bool PyMediaNode::isRedirecting() const - { - PyLockObject lock; + const Node* PyMediaNode::node() const { return this; } - PyObject* ret = - PyObject_CallMethod( m_plugin, "is_redirecting", "s", m_url.c_str() ); + URL PyMediaNode::mediaURL() const { return m_url; } - if( ret == nullptr ) + bool PyMediaNode::isStreaming() const { - PyErr_Print(); - return false; - } - - return PyObject_IsTrue( ret ); - } - const Node* PyMediaNode::baseMediaNode() const - { - return this; - } + PyLockObject lock; - HTTPCookieVector PyMediaNode::httpCookies() const - { - PyLockObject lock; + PyObject* ret = + PyObject_CallMethod(m_plugin, "is_streaming", "s", m_url.c_str()); - HTTPCookieVector cookies; + if (ret == nullptr) + { + PyErr_Print(); + return false; + } - PyObject* ret = - PyObject_CallMethod( m_plugin, "get_http_cookies", "s", m_url.c_str() ); - if( ret == nullptr ) - { - PyErr_Print(); + return PyObject_IsTrue(ret); } - if( PyIter_Check( ret ) ) + bool PyMediaNode::isRedirecting() const { - PyObject* cookieDict; - while( ( cookieDict = PyIter_Next( ret ) ) ) - { - if( PyDict_Check( cookieDict ) ) + PyLockObject lock; + + PyObject* ret = + PyObject_CallMethod(m_plugin, "is_redirecting", "s", m_url.c_str()); + + if (ret == nullptr) { - // PyDict_GetItemString returns a borrowed reference, no need - PyObject* nameObj = PyDict_GetItemString( cookieDict, "name" ); - PyObject* valueObj = PyDict_GetItemString( cookieDict, "value" ); - PyObject* domainObj = PyDict_GetItemString( cookieDict, "domain" ); - PyObject* pathObj = PyDict_GetItemString( cookieDict, "path" ); - - std::string name = - nameObj != nullptr ? PyUnicode_AsUTF8( nameObj ) : ""; - std::string value = - valueObj != nullptr ? PyUnicode_AsUTF8( valueObj ) : ""; - std::string domain = - domainObj != nullptr ? PyUnicode_AsUTF8( domainObj ) : ""; - std::string path = - pathObj != nullptr ? PyUnicode_AsUTF8( pathObj ) : ""; - - cookies.emplace_back( domain, path, name, value ); - - - // PyDict_GetItemString returns a borrowed reference, no need to - // decref - - // Py_XDECREF(keyObj); - // Py_XDECREF(valueObj); - // Py_XDECREF(domainObj); - // Py_XDECREF(pathObj); + PyErr_Print(); + return false; } - Py_XDECREF( cookieDict ); - } - - if( PyErr_Occurred() ) - { - PyErr_Print(); - } + return PyObject_IsTrue(ret); } - Py_XDECREF( ret ); + const Node* PyMediaNode::baseMediaNode() const { return this; } - return cookies; - } + HTTPCookieVector PyMediaNode::httpCookies() const + { + PyLockObject lock; - HTTPHeaderVector PyMediaNode::httpHeaders() const - { - PyLockObject lock; + HTTPCookieVector cookies; - HTTPHeaderVector headers; + PyObject* ret = PyObject_CallMethod(m_plugin, "get_http_cookies", "s", + m_url.c_str()); + if (ret == nullptr) + { + PyErr_Print(); + } - PyObject* ret = - PyObject_CallMethod( m_plugin, "get_http_headers", "s", m_url.c_str() ); - if( ret == nullptr ) - { - PyErr_Print(); + if (PyIter_Check(ret)) + { + PyObject* cookieDict; + while ((cookieDict = PyIter_Next(ret))) + { + if (PyDict_Check(cookieDict)) + { + // PyDict_GetItemString returns a borrowed reference, no + // need + PyObject* nameObj = + PyDict_GetItemString(cookieDict, "name"); + PyObject* valueObj = + PyDict_GetItemString(cookieDict, "value"); + PyObject* domainObj = + PyDict_GetItemString(cookieDict, "domain"); + PyObject* pathObj = + PyDict_GetItemString(cookieDict, "path"); + + std::string name = + nameObj != nullptr ? PyUnicode_AsUTF8(nameObj) : ""; + std::string value = + valueObj != nullptr ? PyUnicode_AsUTF8(valueObj) : ""; + std::string domain = + domainObj != nullptr ? PyUnicode_AsUTF8(domainObj) : ""; + std::string path = + pathObj != nullptr ? PyUnicode_AsUTF8(pathObj) : ""; + + cookies.emplace_back(domain, path, name, value); + + // PyDict_GetItemString returns a borrowed reference, no + // need to decref + + // Py_XDECREF(keyObj); + // Py_XDECREF(valueObj); + // Py_XDECREF(domainObj); + // Py_XDECREF(pathObj); + } + + Py_XDECREF(cookieDict); + } + + if (PyErr_Occurred()) + { + PyErr_Print(); + } + } + + Py_XDECREF(ret); + + return cookies; } - if( PyIter_Check( ret ) ) + HTTPHeaderVector PyMediaNode::httpHeaders() const { - PyObject* cookieDict; - while( ( cookieDict = PyIter_Next( ret ) ) ) - { - if( PyDict_Check( cookieDict ) ) + PyLockObject lock; + + HTTPHeaderVector headers; + + PyObject* ret = PyObject_CallMethod(m_plugin, "get_http_headers", "s", + m_url.c_str()); + if (ret == nullptr) { - // PyDict_GetItemString returns a borrowed reference, no need - PyObject* nameObj = PyDict_GetItemString( cookieDict, "name" ); - PyObject* valueObj = PyDict_GetItemString( cookieDict, "value" ); - - std::string name = - nameObj != nullptr ? PyUnicode_AsUTF8( nameObj ) : ""; - std::string value = - valueObj != nullptr ? PyUnicode_AsUTF8( valueObj ) : ""; - - headers.emplace_back( name, value ); - - // PyDict_GetItemString returns a borrowed reference, no need to - // decref - // - // Py_XDECREF(nameObj); - // Py_XDECREF(valueObj); + PyErr_Print(); } - Py_XDECREF( cookieDict ); - } - } + if (PyIter_Check(ret)) + { + PyObject* cookieDict; + while ((cookieDict = PyIter_Next(ret))) + { + if (PyDict_Check(cookieDict)) + { + // PyDict_GetItemString returns a borrowed reference, no + // need + PyObject* nameObj = + PyDict_GetItemString(cookieDict, "name"); + PyObject* valueObj = + PyDict_GetItemString(cookieDict, "value"); + + std::string name = + nameObj != nullptr ? PyUnicode_AsUTF8(nameObj) : ""; + std::string value = + valueObj != nullptr ? PyUnicode_AsUTF8(valueObj) : ""; + + headers.emplace_back(name, value); + + // PyDict_GetItemString returns a borrowed reference, no + // need to decref + // + // Py_XDECREF(nameObj); + // Py_XDECREF(valueObj); + } + + Py_XDECREF(cookieDict); + } + } - return headers; - } + return headers; + } - URL PyMediaNode::httpRedirection() const - { - PyLockObject lock; + URL PyMediaNode::httpRedirection() const + { + PyLockObject lock; - PyObject* ret = PyObject_CallMethod( m_plugin, "get_http_redirection", "s", - m_url.c_str() ); + PyObject* ret = PyObject_CallMethod(m_plugin, "get_http_redirection", + "s", m_url.c_str()); - if( ret == nullptr ) - { - PyErr_Print(); - return mediaURL(); - } + if (ret == nullptr) + { + PyErr_Print(); + return mediaURL(); + } - std::string redirection = PyUnicode_AsUTF8( ret ); + std::string redirection = PyUnicode_AsUTF8(ret); - Py_XDECREF( ret ); + Py_XDECREF(ret); - return redirection; - } + return redirection; + } -} // namespace TwkMediaLibrary \ No newline at end of file +} // namespace TwkMediaLibrary diff --git a/src/lib/app/PyMediaLibrary/PyNode.cpp b/src/lib/app/PyMediaLibrary/PyNode.cpp index 4362a8ad9..385187758 100644 --- a/src/lib/app/PyMediaLibrary/PyNode.cpp +++ b/src/lib/app/PyMediaLibrary/PyNode.cpp @@ -11,67 +11,50 @@ namespace TwkMediaLibrary { - class PyMediaLibrary; + class PyMediaLibrary; - std::string nameFromPyNodeType( PyNodeType t ) - { - switch( t ) + std::string nameFromPyNodeType(PyNodeType t) { - default: - case PyNoType: - return "PyNoType"; - case PyMediaType: - return "PyMediaType"; - case PyRootType: - return "PyRootType"; + switch (t) + { + default: + case PyNoType: + return "PyNoType"; + case PyMediaType: + return "PyMediaType"; + case PyRootType: + return "PyRootType"; + } + + return ""; } - return ""; - } - - PyNode::PyNode( Library* lib, PyNode* parent, std::string name, - PyNodeType type ) - : Node( lib ), - m_type( type ), - m_name( std::move( name ) ), - m_parent( parent ) - { - if( m_parent ) m_parent->addChild( this ); - } + PyNode::PyNode(Library* lib, PyNode* parent, std::string name, + PyNodeType type) + : Node(lib) + , m_type(type) + , m_name(std::move(name)) + , m_parent(parent) + { + if (m_parent) + m_parent->addChild(this); + } - void PyNode::addChild( PyNode* child ) - { - m_children.push_back( child ); - } + void PyNode::addChild(PyNode* child) { m_children.push_back(child); } - std::string PyNode::typeName() const - { - return nameFromPyNodeType( m_type ); - } + std::string PyNode::typeName() const { return nameFromPyNodeType(m_type); } - std::string PyNode::name() const - { - return m_name; - } + std::string PyNode::name() const { return m_name; } - const Node* PyNode::parent() const - { - return m_parent; - } + const Node* PyNode::parent() const { return m_parent; } - size_t PyNode::numChildren() const - { - return m_children.size(); - } + size_t PyNode::numChildren() const { return m_children.size(); } - const Node* PyNode::child( size_t index ) const - { - return index < m_children.size() ? m_children[index] : nullptr; - } + const Node* PyNode::child(size_t index) const + { + return index < m_children.size() ? m_children[index] : nullptr; + } - void PyNode::setName( const std::string& n ) - { - m_name = n; - } + void PyNode::setName(const std::string& n) { m_name = n; } -} // namespace TwkMediaLibrary \ No newline at end of file +} // namespace TwkMediaLibrary diff --git a/src/lib/app/PyMediaLibrary/PyRootNode.cpp b/src/lib/app/PyMediaLibrary/PyRootNode.cpp index de9d17ac6..e0518662d 100644 --- a/src/lib/app/PyMediaLibrary/PyRootNode.cpp +++ b/src/lib/app/PyMediaLibrary/PyRootNode.cpp @@ -19,191 +19,190 @@ namespace { - static ENVVAR_BOOL( evUseMediaLibraryPlugins, "RV_USE_MEDIA_LIBRARY_PLUGINS", - true ); - - constexpr std::array PLUGIN_FUNCTIONS = { - { - { "is_plugin_enabled" }, - { "is_library_media_url" }, - { "is_streaming" }, - { "is_redirecting" }, - { "get_http_cookies" }, - { "get_http_headers" }, - { "get_http_redirection" } - } - }; - - using Plugin = PyObject*; - using PluginVector = std::vector>; - - PluginVector plugins; - bool pluginsLoaded = !evUseMediaLibraryPlugins.getValue(); - - void loadPlugins() - { - const char* pluginPathsEnv = getenv( "TWK_MEDIA_LIBRARY_PLUGIN_PATH" ); - if( pluginPathsEnv == nullptr ) - { - return; - } + static ENVVAR_BOOL(evUseMediaLibraryPlugins, "RV_USE_MEDIA_LIBRARY_PLUGINS", + true); - std::set pluginNames; - PyLockObject lock; + constexpr std::array PLUGIN_FUNCTIONS = { + {{"is_plugin_enabled"}, + {"is_library_media_url"}, + {"is_streaming"}, + {"is_redirecting"}, + {"get_http_cookies"}, + {"get_http_headers"}, + {"get_http_redirection"}}}; - const TwkUtil::FileNameList pluginPackages = - TwkUtil::findInPath( ".*", pluginPathsEnv ); - - for( const auto& pluginPackage : pluginPackages ) - { - const TwkUtil::FileNameList pluginFiles = - TwkUtil::findInPath( ".*\\.py", pluginPackage ); + using Plugin = PyObject*; + using PluginVector = std::vector>; - for( const auto& pluginFile : pluginFiles ) - { - const std::string pluginImportPath = - TwkUtil::basename( TwkUtil::dirname( pluginFile ) ) + "." + - TwkUtil::prefix( pluginFile ); + PluginVector plugins; + bool pluginsLoaded = !evUseMediaLibraryPlugins.getValue(); - if( pluginNames.find( pluginImportPath ) != pluginNames.end() ) + void loadPlugins() + { + const char* pluginPathsEnv = getenv("TWK_MEDIA_LIBRARY_PLUGIN_PATH"); + if (pluginPathsEnv == nullptr) { - std::cerr << "Plug-In " << pluginImportPath << " (" << pluginFile - << ") already loaded with the same name. Skipped." - << std::endl; - continue; + return; } - std::cout << "Importing MediaLibrary Plug-In: " << pluginImportPath - << std::endl; + std::set pluginNames; + PyLockObject lock; + + const TwkUtil::FileNameList pluginPackages = + TwkUtil::findInPath(".*", pluginPathsEnv); - Plugin pluginObj = PyImport_ImportModule( pluginImportPath.c_str() ); - if( pluginObj ) + for (const auto& pluginPackage : pluginPackages) { - bool valid = true; - for( const auto& func : PLUGIN_FUNCTIONS ) - { - valid &= PyObject_HasAttrString( pluginObj, func.data() ); + const TwkUtil::FileNameList pluginFiles = + TwkUtil::findInPath(".*\\.py", pluginPackage); - if( !valid ) + for (const auto& pluginFile : pluginFiles) { - std::cerr << "Plug-In " << pluginImportPath << "(" << pluginFile - << ") does not have " << func.data() - << " function. Skipped." << std::endl; - break; + const std::string pluginImportPath = + TwkUtil::basename(TwkUtil::dirname(pluginFile)) + "." + + TwkUtil::prefix(pluginFile); + + if (pluginNames.find(pluginImportPath) != pluginNames.end()) + { + std::cerr << "Plug-In " << pluginImportPath << " (" + << pluginFile + << ") already loaded with the same name. Skipped." + << std::endl; + continue; + } + + std::cout << "Importing MediaLibrary Plug-In: " + << pluginImportPath << std::endl; + + Plugin pluginObj = + PyImport_ImportModule(pluginImportPath.c_str()); + if (pluginObj) + { + bool valid = true; + for (const auto& func : PLUGIN_FUNCTIONS) + { + valid &= PyObject_HasAttrString(pluginObj, func.data()); + + if (!valid) + { + std::cerr << "Plug-In " << pluginImportPath << "(" + << pluginFile << ") does not have " + << func.data() << " function. Skipped." + << std::endl; + break; + } + } + + if (!valid) + { + Py_XDECREF(pluginObj); + continue; + } + + PyObject* enabledObj = PyObject_CallMethod( + pluginObj, "is_plugin_enabled", nullptr); + + if (enabledObj == nullptr) + { + PyErr_Print(); + } + + if (PyObject_IsTrue(enabledObj)) + { + pluginNames.insert(pluginImportPath); + plugins.emplace_back(pluginImportPath, pluginObj); + } + else + { + Py_XDECREF(pluginObj); + } + + Py_XDECREF(enabledObj); + } + else + { + std::cerr << "Failed to load " << pluginImportPath << "(" + << pluginFile << ")" << std::endl; + PyErr_Print(); + } } - } - - if( !valid ) - { - Py_XDECREF( pluginObj ); - continue; - } - - PyObject* enabledObj = PyObject_CallMethod( pluginObj, - "is_plugin_enabled", nullptr ); - - if( enabledObj == nullptr ) - { - PyErr_Print(); - } - - if( PyObject_IsTrue( enabledObj ) ) - { - pluginNames.insert( pluginImportPath ); - plugins.emplace_back( pluginImportPath, pluginObj ); - } else { - Py_XDECREF( pluginObj ); - } - - Py_XDECREF( enabledObj ); } - else - { - std::cerr << "Failed to load " << pluginImportPath << "(" - << pluginFile << ")" << std::endl; - PyErr_Print(); - } - } + pluginsLoaded = true; } - pluginsLoaded = true; - } - void unloadPlugins() - { - if( !pluginsLoaded || plugins.empty() ) + void unloadPlugins() { - return; - } + if (!pluginsLoaded || plugins.empty()) + { + return; + } - PyLockObject lock; - for( auto& pluginObjContainer : plugins ) - { - Py_XDECREF( pluginObjContainer.second ); + PyLockObject lock; + for (auto& pluginObjContainer : plugins) + { + Py_XDECREF(pluginObjContainer.second); + } + plugins.clear(); } - plugins.clear(); - } -} // namespace +} // namespace namespace TwkMediaLibrary { - class PyMediaLibrary; - - PyRootNode::PyRootNode( Library* lib ) - : PyNode( lib, nullptr, "", PyNodeType::PyRootType ) - { - } - - PyRootNode::~PyRootNode() - { - unloadPlugins(); - } + class PyMediaLibrary; - bool PyRootNode::isLibraryMediaURL( const URL& url ) const - { - return !mediaNodesForURL( url ).empty(); - } - - MediaNodeVector PyRootNode::mediaNodesForURL( const URL& url ) const - { - MediaNodeVector mediaNodes; - - if( !pluginsLoaded ) + PyRootNode::PyRootNode(Library* lib) + : PyNode(lib, nullptr, "", PyNodeType::PyRootType) { - loadPlugins(); } - if( plugins.empty() ) + PyRootNode::~PyRootNode() { unloadPlugins(); } + + bool PyRootNode::isLibraryMediaURL(const URL& url) const { - return mediaNodes; + return !mediaNodesForURL(url).empty(); } + MediaNodeVector PyRootNode::mediaNodesForURL(const URL& url) const { - PyLockObject lock; + MediaNodeVector mediaNodes; - for( const auto& pluginContainer : plugins ) - { - const auto& pluginName = pluginContainer.first; - const auto& plugin = pluginContainer.second; + if (!pluginsLoaded) + { + loadPlugins(); + } - PyObject* ret = PyObject_CallMethod( plugin, "is_library_media_url", - "s", url.c_str() ); - if( ret == nullptr ) + if (plugins.empty()) { - PyErr_Print(); - continue; + return mediaNodes; } - if( PyObject_IsTrue( ret ) ) { - mediaNodes.push_back( new PyMediaNode( m_library, url, (PyNode*)this, - plugin, pluginName ) ); + PyLockObject lock; + + for (const auto& pluginContainer : plugins) + { + const auto& pluginName = pluginContainer.first; + const auto& plugin = pluginContainer.second; + + PyObject* ret = PyObject_CallMethod( + plugin, "is_library_media_url", "s", url.c_str()); + if (ret == nullptr) + { + PyErr_Print(); + continue; + } + + if (PyObject_IsTrue(ret)) + { + mediaNodes.push_back(new PyMediaNode( + m_library, url, (PyNode*)this, plugin, pluginName)); + } + + Py_XDECREF(ret); + } } - Py_XDECREF( ret ); - } + return mediaNodes; } - - return mediaNodes; - } -} // namespace TwkMediaLibrary \ No newline at end of file +} // namespace TwkMediaLibrary diff --git a/src/lib/app/PyTwkApp/PyCommands.cpp b/src/lib/app/PyTwkApp/PyCommands.cpp index ccf280dde..8daa49931 100644 --- a/src/lib/app/PyTwkApp/PyCommands.cpp +++ b/src/lib/app/PyTwkApp/PyCommands.cpp @@ -1,9 +1,9 @@ // // Copyright (c) 2011 Tweak Software. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// // #include #include @@ -23,198 +23,204 @@ namespace TwkApp { - using namespace std; - - static PyObject* badArgument() - { - PyErr_SetString( PyExc_Exception, "Bad argument" ); - return NULL; - } + using namespace std; - static Document* currentDocument() - { - if( Document* d = Document::eventDocument() ) + static PyObject* badArgument() { - return d; + PyErr_SetString(PyExc_Exception, "Bad argument"); + return NULL; } - else - { - return Document::activeDocument(); - } - } - - static PyObject* bind( PyObject* self, PyObject* args ) - { - PyLockObject locker; - const char* modeName = 0; - const char* tableName = 0; - const char* eventName = 0; - PyObject* callable = 0; - const char* docString = 0; - if( !PyArg_ParseTuple( args, "sssOs", &modeName, &tableName, &eventName, - &callable, &docString ) ) - return NULL; - - if( !docString ) docString = ""; - Document* d = currentDocument(); - - if( !d ) + static Document* currentDocument() { - PyErr_SetString( PyExc_Exception, "No active document" ); - return NULL; + if (Document* d = Document::eventDocument()) + { + return d; + } + else + { + return Document::activeDocument(); + } } - if( Mode* mode = d->findModeByName( modeName ) ) + static PyObject* bind(PyObject* self, PyObject* args) { - EventTable* table = mode->findTableByName( tableName ); - - if( !table ) - { - table = new EventTable( tableName ); - mode->addEventTable( table ); - } - - PyFunctionAction* action = new PyFunctionAction( callable, docString ); - table->bind( eventName, action ); - // - // currentDocument has a copy of this table, so invalidate - // that copy. - // - d->invalidateEventTables(); + PyLockObject locker; + const char* modeName = 0; + const char* tableName = 0; + const char* eventName = 0; + PyObject* callable = 0; + const char* docString = 0; + + if (!PyArg_ParseTuple(args, "sssOs", &modeName, &tableName, &eventName, + &callable, &docString)) + return NULL; + + if (!docString) + docString = ""; + Document* d = currentDocument(); + + if (!d) + { + PyErr_SetString(PyExc_Exception, "No active document"); + return NULL; + } + + if (Mode* mode = d->findModeByName(modeName)) + { + EventTable* table = mode->findTableByName(tableName); + + if (!table) + { + table = new EventTable(tableName); + mode->addEventTable(table); + } + + PyFunctionAction* action = + new PyFunctionAction(callable, docString); + table->bind(eventName, action); + // + // currentDocument has a copy of this table, so invalidate + // that copy. + // + d->invalidateEventTables(); + } + else + { + return badArgument(); + } + // else + // { + // string msg = "No mode named " + string(modeName->c_str()); + // throwBadArgumentException(NODE_THIS, NODE_THREAD, msg); + // } + + return PyLong_FromLong(1); } - else - { - return badArgument(); - } - // else - // { - // string msg = "No mode named " + string(modeName->c_str()); - // throwBadArgumentException(NODE_THIS, NODE_THREAD, msg); - // } - - return PyLong_FromLong( 1 ); - } - - static PyObject* bindRegex( PyObject* self, PyObject* args ) - { - PyLockObject locker; - const char* modeName = 0; - const char* tableName = 0; - const char* eventName = 0; - PyObject* callable = 0; - const char* docString = 0; - - if( !PyArg_ParseTuple( args, "sssOs", &modeName, &tableName, &eventName, - &callable, &docString ) ) - return NULL; - - if( !docString ) docString = ""; - Document* d = currentDocument(); - - if( Mode* mode = d->findModeByName( modeName ) ) - { - EventTable* table = mode->findTableByName( tableName ); - - if( !table ) - { - table = new EventTable( tableName ); - mode->addEventTable( table ); - } - - PyFunctionAction* action = new PyFunctionAction( callable, docString ); - table->bindRegex( eventName, action ); - // - // currentDocument has a copy of this table, so invalidate - // that copy. - // - d->invalidateEventTables(); - } - else - { - return badArgument(); - } - // else - // { - // string msg = "No mode named " + string(modeName->c_str()); - // throwBadArgumentException(NODE_THIS, NODE_THREAD, msg); - // } - - return PyLong_FromLong( 1 ); - } - - static PyObject* defineModeMenu( PyObject* self, PyObject* args ) - { - PyLockObject locker; - PyObject* listobj; - const char* modeName; - int strict = 0; - - int ok = PyArg_ParseTuple( args, "sO!|i", &modeName, &PyList_Type, &listobj, - &strict ); - if( !ok ) return NULL; - - Document* d = currentDocument(); - Menu* menu = pyListToMenu( "Main", listobj ); - - if( Mode* m = d->findModeByName( modeName ) ) + + static PyObject* bindRegex(PyObject* self, PyObject* args) { - if( strict ) - m->setMenu( menu ); - else - m->merge( menu ); - - // - // If we are re-defining an existing menu, we need to invalidate - // the old menu. - // - d->invalidateMenu(); + PyLockObject locker; + const char* modeName = 0; + const char* tableName = 0; + const char* eventName = 0; + PyObject* callable = 0; + const char* docString = 0; + + if (!PyArg_ParseTuple(args, "sssOs", &modeName, &tableName, &eventName, + &callable, &docString)) + return NULL; + + if (!docString) + docString = ""; + Document* d = currentDocument(); + + if (Mode* mode = d->findModeByName(modeName)) + { + EventTable* table = mode->findTableByName(tableName); + + if (!table) + { + table = new EventTable(tableName); + mode->addEventTable(table); + } + + PyFunctionAction* action = + new PyFunctionAction(callable, docString); + table->bindRegex(eventName, action); + // + // currentDocument has a copy of this table, so invalidate + // that copy. + // + d->invalidateEventTables(); + } + else + { + return badArgument(); + } + // else + // { + // string msg = "No mode named " + string(modeName->c_str()); + // throwBadArgumentException(NODE_THIS, NODE_THREAD, msg); + // } + + return PyLong_FromLong(1); } - else + + static PyObject* defineModeMenu(PyObject* self, PyObject* args) { - return badArgument(); + PyLockObject locker; + PyObject* listobj; + const char* modeName; + int strict = 0; + + int ok = PyArg_ParseTuple(args, "sO!|i", &modeName, &PyList_Type, + &listobj, &strict); + if (!ok) + return NULL; + + Document* d = currentDocument(); + Menu* menu = pyListToMenu("Main", listobj); + + if (Mode* m = d->findModeByName(modeName)) + { + if (strict) + m->setMenu(menu); + else + m->merge(menu); + + // + // If we are re-defining an existing menu, we need to invalidate + // the old menu. + // + d->invalidateMenu(); + } + else + { + return badArgument(); + } + + return PyLong_FromLong(1); } - return PyLong_FromLong( 1 ); - } + static vector methods; - static vector methods; + static PyMethodDef localmethods[] = { + {"bind", bind, METH_VARARGS, "bind event to action."}, + {"bindRegex", bindRegex, METH_VARARGS, "bind regex event to action."}, + {"defineModeMenu", defineModeMenu, METH_VARARGS, + "define the menu for a mode."}, + {NULL}}; - static PyMethodDef localmethods[] = { - {"bind", bind, METH_VARARGS, "bind event to action."}, - {"bindRegex", bindRegex, METH_VARARGS, "bind regex event to action."}, - {"defineModeMenu", defineModeMenu, METH_VARARGS, - "define the menu for a mode."}, - {NULL}}; - - void pyInitCommands( void* othermethods ) - { - for( size_t i = 0; localmethods[i].ml_name; i++ ) - methods.push_back( localmethods[i] ); - - if( othermethods ) + void pyInitCommands(void* othermethods) { - for( PyMethodDef* d = (PyMethodDef*)othermethods; d->ml_name; d++ ) - methods.push_back( *d ); - } + for (size_t i = 0; localmethods[i].ml_name; i++) + methods.push_back(localmethods[i]); - PyMethodDef last = {NULL}; - methods.push_back( last ); + if (othermethods) + { + for (PyMethodDef* d = (PyMethodDef*)othermethods; d->ml_name; d++) + methods.push_back(*d); + } - PyObject* rvObj = PyImport_ImportModule( "rv" ); - PyObject* cmdObj = PyImport_AddModule( "rv.commands" ); + PyMethodDef last = {NULL}; + methods.push_back(last); - if( !rvObj ) cerr << "ERROR: Module 'rv' could not be imported" << endl; - if( !cmdObj ) - cerr << "ERROR: Module 'rv.commands' could not be imported" << endl; + PyObject* rvObj = PyImport_ImportModule("rv"); + PyObject* cmdObj = PyImport_AddModule("rv.commands"); - if( rvObj && cmdObj ) - { - PyModule_AddFunctions( cmdObj, &methods.front() ); + if (!rvObj) + cerr << "ERROR: Module 'rv' could not be imported" << endl; + if (!cmdObj) + cerr << "ERROR: Module 'rv.commands' could not be imported" << endl; + + if (rvObj && cmdObj) + { + PyModule_AddFunctions(cmdObj, &methods.front()); - PyModule_AddObject( rvObj, "commands", cmdObj ); - Py_XINCREF( cmdObj ); + PyModule_AddObject(rvObj, "commands", cmdObj); + Py_XINCREF(cmdObj); + } } - } -} // namespace TwkApp +} // namespace TwkApp diff --git a/src/lib/app/PyTwkApp/PyEventType.cpp b/src/lib/app/PyTwkApp/PyEventType.cpp index e9a39a918..1c44c6d3e 100644 --- a/src/lib/app/PyTwkApp/PyEventType.cpp +++ b/src/lib/app/PyTwkApp/PyEventType.cpp @@ -1,9 +1,9 @@ // // Copyright (c) 2011 Tweak Software. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// // #include #include @@ -16,584 +16,604 @@ namespace TwkApp { - static PyObject* BadEvent = 0; - - static PyObject* badArgument() - { - PyErr_SetString( PyExc_Exception, "Bad argument" ); - return NULL; - } + static PyObject* BadEvent = 0; - static PyObject* buttons( PyEventObject* self, PyObject* args ) - { - PyLockObject locker; - if( !self->event ) return badArgument(); - - if( const PointerEvent* pe = - dynamic_cast( self->event ) ) + static PyObject* badArgument() { - return PyLong_FromLong( pe->buttonStates() ); + PyErr_SetString(PyExc_Exception, "Bad argument"); + return NULL; } - return PyLong_FromLong( 0 ); - } - - static PyObject* modifiers( PyEventObject* self, PyObject* args ) - { - PyLockObject locker; - if( !self->event ) return badArgument(); - if( const ModifierEvent* pe = - dynamic_cast( self->event ) ) + static PyObject* buttons(PyEventObject* self, PyObject* args) { - return PyLong_FromLong( pe->modifiers() ); - } - - return PyLong_FromLong( 0 ); - } + PyLockObject locker; + if (!self->event) + return badArgument(); + + if (const PointerEvent* pe = + dynamic_cast(self->event)) + { + return PyLong_FromLong(pe->buttonStates()); + } + + return PyLong_FromLong(0); + } + + static PyObject* modifiers(PyEventObject* self, PyObject* args) + { + PyLockObject locker; + if (!self->event) + return badArgument(); + if (const ModifierEvent* pe = + dynamic_cast(self->event)) + { + return PyLong_FromLong(pe->modifiers()); + } + + return PyLong_FromLong(0); + } + + static PyObject* pointer(PyEventObject* self, PyObject* args) + { + PyLockObject locker; + if (!self->event) + return badArgument(); + if (const TabletEvent* te = + dynamic_cast(self->event)) + { + return Py_BuildValue("(f,f)", float(te->gx()), float(te->gy())); + } + else if (const PointerEvent* pe = + dynamic_cast(self->event)) + { + return Py_BuildValue("(f,f)", float(pe->x()), float(pe->y())); + } + else + { + return badArgument(); + } + + Py_RETURN_NONE; + } + + static PyObject* relativePointer(PyEventObject* self, PyObject* args) + { + PyLockObject locker; + if (!self->event) + return badArgument(); + if (const TabletEvent* te = + dynamic_cast(self->event)) + { + float v0 = te->gx(); + float v1 = te->gy(); + + if (te->eventTable()) + { + v0 -= te->eventTable()->bbox().min.x; + v1 -= te->eventTable()->bbox().min.y; + } + + return Py_BuildValue("(f,f)", v0, v1); + } + else if (const PointerEvent* pe = + dynamic_cast(self->event)) + { + float v0 = pe->x(); + float v1 = pe->y(); + + if (pe->eventTable()) + { + v0 -= pe->eventTable()->bbox().min.x; + v1 -= pe->eventTable()->bbox().min.y; + } + + return Py_BuildValue("(f,f)", v0, v1); + } + else + { + return badArgument(); + } + + Py_RETURN_NONE; + } + + static PyObject* domain(PyEventObject* self, PyObject* args) + { + PyLockObject locker; + if (!self->event) + return badArgument(); + float v[2]; + + if (const PointerEvent* pe = + dynamic_cast(self->event)) + { + v[0] = pe->w(); + v[1] = pe->h(); + } + else if (const RenderEvent* re = + dynamic_cast(self->event)) + { + v[0] = re->w(); + v[1] = re->h(); + } + else + { + return badArgument(); + } + + return Py_BuildValue("(f,f)", v[0], v[1]); + } + + static PyObject* domainVerticalFlip(PyEventObject* self, PyObject* args) + { + const Event* e = self->event; + + if (e) + { + if (const RenderEvent* re = dynamic_cast(e)) + { + return re->device()->capabilities() & VideoDevice::FlippedImage + ? Py_True + : Py_False; + } + else + { + return badArgument(); + } + } + + return Py_False; + } + + static PyObject* subDomain(PyEventObject* self, PyObject* args) + { + PyLockObject locker; + if (!self->event) + return badArgument(); + float v[2]; + + if (const PointerEvent* pe = + dynamic_cast(self->event)) + { + v[0] = pe->w(); + v[1] = pe->h(); + } + else if (const RenderEvent* re = + dynamic_cast(self->event)) + { + v[0] = re->w(); + v[1] = re->h(); + } + else + { + return badArgument(); + } + + if (self->event->eventTable()) + { + v[0] = self->event->eventTable()->bbox().size().x; + v[1] = self->event->eventTable()->bbox().size().y; + } + + return Py_BuildValue("(f,f)", v[0], v[1]); + } + + static PyObject* key(PyEventObject* self, PyObject* args) + { + PyLockObject locker; + if (!self->event) + return badArgument(); + int k = -1; + + if (const KeyEvent* ke = dynamic_cast(self->event)) + { + k = ke->key(); + } + else + { + return badArgument(); + } + + return Py_BuildValue("i", k); + } + + static PyObject* name(PyEventObject* self, PyObject* args) + { + PyLockObject locker; + if (!self->event) + return badArgument(); + return Py_BuildValue("s", self->event->name().c_str()); + } + + static PyObject* sender(PyEventObject* self, PyObject* args) + { + PyLockObject locker; + if (!self->event) + return badArgument(); + const char* s = 0; + + if (const GenericStringEvent* e = + dynamic_cast(self->event)) + { + s = e->senderName().c_str(); + } + else if (const RawDataEvent* e = + dynamic_cast(self->event)) + { + s = e->senderName().c_str(); + } + else + { + return badArgument(); + } + + return Py_BuildValue("s", s); + } + + static PyObject* contents(PyEventObject* self, PyObject* args) + { + PyLockObject locker; + if (!self->event) + return badArgument(); + const char* s = ""; + + if (const DragDropEvent* de = + dynamic_cast(self->event)) + { + s = de->stringContent().c_str(); + } + else if (const GenericStringEvent* e = + dynamic_cast(self->event)) + { + s = e->stringContent().c_str(); + } + else if (const RawDataEvent* e = + dynamic_cast(self->event)) + { + if (e->utf8()) + { + s = e->utf8(); + } + else + { + return badArgument(); + } + } + else if (const RenderEvent* re = + dynamic_cast(self->event)) + { + s = re->stringContent().c_str(); + } + else + { + return badArgument(); + } + + return Py_BuildValue("s", s); + } + + static PyObject* returnContents(PyEventObject* self, PyObject* args) + { + PyLockObject locker; + if (!self->event) + return badArgument(); + const char* s = ""; + + if (const GenericStringEvent* e = + dynamic_cast(self->event)) + { + s = e->returnContent().c_str(); + } + + return Py_BuildValue("s", s); + } + + static PyObject* dataContents(PyEventObject* self, PyObject* args) + { + PyLockObject locker; + if (!self->event) + return badArgument(); + if (const RawDataEvent* e = + dynamic_cast(self->event)) + { + int sz = e->rawDataSize(); + PyObject* list = PyList_New(sz); + + for (int i = 0; i < sz; ++i) + { + PyList_SetItem(list, i, PyLong_FromLong(e->rawData()[i])); + } + + return list; + } + + Py_RETURN_NONE; + } + + static PyObject* contentType(PyEventObject* self, PyObject* args) + { + PyLockObject locker; + if (!self->event) + return badArgument(); + int rval = 0; + + if (const DragDropEvent* de = + dynamic_cast(self->event)) + { + switch (de->contentType()) + { + case DragDropEvent::File: + rval = 1; + break; + case DragDropEvent::URL: + rval = 2; + break; + case DragDropEvent::Text: + rval = 3; + break; + default: + rval = -1; + break; + } + } + else + { + return badArgument(); + } + + return PyLong_FromLong(rval); + } + + static PyObject* contentMimeType(PyEventObject* self, PyObject* args) + { + PyLockObject locker; + if (!self->event) + return badArgument(); + const char* s = ""; + + if (const RawDataEvent* e = + dynamic_cast(self->event)) + { + s = e->contentType().c_str(); + } + else if (const GenericStringEvent* e = + dynamic_cast(self->event)) + { + s = "text/plain"; + } + else + { + return badArgument(); + } - static PyObject* pointer( PyEventObject* self, PyObject* args ) - { - PyLockObject locker; - if( !self->event ) return badArgument(); - if( const TabletEvent* te = - dynamic_cast( self->event ) ) - { - return Py_BuildValue( "(f,f)", float( te->gx() ), float( te->gy() ) ); + return PyBytes_FromString(s); } - else if( const PointerEvent* pe = - dynamic_cast( self->event ) ) - { - return Py_BuildValue( "(f,f)", float( pe->x() ), float( pe->y() ) ); - } - else - { - return badArgument(); - } - - Py_RETURN_NONE; - } - static PyObject* relativePointer( PyEventObject* self, PyObject* args ) - { - PyLockObject locker; - if( !self->event ) return badArgument(); - if( const TabletEvent* te = - dynamic_cast( self->event ) ) + static PyObject* timeStamp(PyEventObject* self, PyObject* args) { - float v0 = te->gx(); - float v1 = te->gy(); - - if( te->eventTable() ) - { - v0 -= te->eventTable()->bbox().min.x; - v1 -= te->eventTable()->bbox().min.y; - } - - return Py_BuildValue( "(f,f)", v0, v1 ); + PyLockObject locker; + if (!self->event) + return badArgument(); + return PyFloat_FromDouble(self->event->timeStamp()); } - else if( const PointerEvent* pe = - dynamic_cast( self->event ) ) - { - float v0 = pe->x(); - float v1 = pe->y(); - - if( pe->eventTable() ) - { - v0 -= pe->eventTable()->bbox().min.x; - v1 -= pe->eventTable()->bbox().min.y; - } - return Py_BuildValue( "(f,f)", v0, v1 ); - } - else + static PyObject* reject(PyEventObject* self, PyObject* args) { - return badArgument(); + PyLockObject locker; + if (!self->event) + return badArgument(); + self->event->handled = false; + Py_RETURN_NONE; } - Py_RETURN_NONE; - } - - static PyObject* domain( PyEventObject* self, PyObject* args ) - { - PyLockObject locker; - if( !self->event ) return badArgument(); - float v[2]; - - if( const PointerEvent* pe = - dynamic_cast( self->event ) ) - { - v[0] = pe->w(); - v[1] = pe->h(); - } - else if( const RenderEvent* re = - dynamic_cast( self->event ) ) + static PyObject* setReturnContent(PyEventObject* self, PyObject* args) { - v[0] = re->w(); - v[1] = re->h(); - } - else - { - return badArgument(); - } - - return Py_BuildValue( "(f,f)", v[0], v[1] ); - } + PyLockObject locker; + if (!self->event) + return badArgument(); + const char* s; + int ok = PyArg_ParseTuple(args, "s", &s); /* A string */ - static PyObject* domainVerticalFlip( PyEventObject* self, PyObject* args ) - { - const Event* e = self->event; + if (const GenericStringEvent* se = + dynamic_cast(self->event)) + { + se->setReturnContent(s); + } + else if (const RawDataEvent* rde = + dynamic_cast(self->event)) + { + rde->setReturnContent(s); + } + else + { + return badArgument(); + } - if( e ) - { - if( const RenderEvent* re = dynamic_cast( e ) ) - { - return re->device()->capabilities() & VideoDevice::FlippedImage - ? Py_True - : Py_False; - } - else - { - return badArgument(); - } + Py_RETURN_NONE; } - return Py_False; - } - - static PyObject* subDomain( PyEventObject* self, PyObject* args ) - { - PyLockObject locker; - if( !self->event ) return badArgument(); - float v[2]; - - if( const PointerEvent* pe = - dynamic_cast( self->event ) ) - { - v[0] = pe->w(); - v[1] = pe->h(); - } - else if( const RenderEvent* re = - dynamic_cast( self->event ) ) - { - v[0] = re->w(); - v[1] = re->h(); - } - else + static PyObject* pressure(PyEventObject* self, PyObject* args) { - return badArgument(); - } - - if( self->event->eventTable() ) - { - v[0] = self->event->eventTable()->bbox().size().x; - v[1] = self->event->eventTable()->bbox().size().y; - } - - return Py_BuildValue( "(f,f)", v[0], v[1] ); - } - - static PyObject* key( PyEventObject* self, PyObject* args ) - { - PyLockObject locker; - if( !self->event ) return badArgument(); - int k = -1; - - if( const KeyEvent* ke = dynamic_cast( self->event ) ) - { - k = ke->key(); - } - else - { - return badArgument(); - } - - return Py_BuildValue( "i", k ); - } - - static PyObject* name( PyEventObject* self, PyObject* args ) - { - PyLockObject locker; - if( !self->event ) return badArgument(); - return Py_BuildValue( "s", self->event->name().c_str() ); - } - - static PyObject* sender( PyEventObject* self, PyObject* args ) - { - PyLockObject locker; - if( !self->event ) return badArgument(); - const char* s = 0; - - if( const GenericStringEvent* e = - dynamic_cast( self->event ) ) - { - s = e->senderName().c_str(); - } - else if( const RawDataEvent* e = - dynamic_cast( self->event ) ) - { - s = e->senderName().c_str(); - } - else - { - return badArgument(); - } - - return Py_BuildValue( "s", s ); - } - - static PyObject* contents( PyEventObject* self, PyObject* args ) - { - PyLockObject locker; - if( !self->event ) return badArgument(); - const char* s = ""; - - if( const DragDropEvent* de = - dynamic_cast( self->event ) ) - { - s = de->stringContent().c_str(); - } - else if( const GenericStringEvent* e = - dynamic_cast( self->event ) ) - { - s = e->stringContent().c_str(); - } - else if( const RawDataEvent* e = - dynamic_cast( self->event ) ) - { - if( e->utf8() ) - { - s = e->utf8(); - } - else - { - return badArgument(); - } - } - else if( const RenderEvent* re = - dynamic_cast( self->event ) ) - { - s = re->stringContent().c_str(); - } - else - { - return badArgument(); - } - - return Py_BuildValue( "s", s ); - } - - static PyObject* returnContents( PyEventObject* self, PyObject* args ) - { - PyLockObject locker; - if( !self->event ) return badArgument(); - const char* s = ""; - - if( const GenericStringEvent* e = - dynamic_cast( self->event ) ) - { - s = e->returnContent().c_str(); - } - - return Py_BuildValue( "s", s ); - } - - static PyObject* dataContents( PyEventObject* self, PyObject* args ) - { - PyLockObject locker; - if( !self->event ) return badArgument(); - if( const RawDataEvent* e = - dynamic_cast( self->event ) ) - { - int sz = e->rawDataSize(); - PyObject* list = PyList_New( sz ); - - for( int i = 0; i < sz; ++i ) - { - PyList_SetItem( list, i, PyLong_FromLong( e->rawData()[i] ) ); - } - - return list; - } - - Py_RETURN_NONE; - } - - static PyObject* contentType( PyEventObject* self, PyObject* args ) - { - PyLockObject locker; - if( !self->event ) return badArgument(); - int rval = 0; - - if( const DragDropEvent* de = - dynamic_cast( self->event ) ) - { - switch( de->contentType() ) - { - case DragDropEvent::File: - rval = 1; - break; - case DragDropEvent::URL: - rval = 2; - break; - case DragDropEvent::Text: - rval = 3; - break; - default: - rval = -1; - break; - } - } - else - { - return badArgument(); - } - - return PyLong_FromLong( rval ); - } - - static PyObject* contentMimeType( PyEventObject* self, PyObject* args ) - { - PyLockObject locker; - if( !self->event ) return badArgument(); - const char* s = ""; - - if( const RawDataEvent* e = - dynamic_cast( self->event ) ) - { - s = e->contentType().c_str(); - } - else if( const GenericStringEvent* e = - dynamic_cast( self->event ) ) - { - s = "text/plain"; - } - else - { - return badArgument(); - } - - return PyBytes_FromString( s ); - } - - static PyObject* timeStamp( PyEventObject* self, PyObject* args ) - { - PyLockObject locker; - if( !self->event ) return badArgument(); - return PyFloat_FromDouble( self->event->timeStamp() ); - } - - static PyObject* reject( PyEventObject* self, PyObject* args ) - { - PyLockObject locker; - if( !self->event ) return badArgument(); - self->event->handled = false; - Py_RETURN_NONE; - } - - static PyObject* setReturnContent( PyEventObject* self, PyObject* args ) - { - PyLockObject locker; - if( !self->event ) return badArgument(); - const char* s; - int ok = PyArg_ParseTuple( args, "s", &s ); /* A string */ - - if( const GenericStringEvent* se = - dynamic_cast( self->event ) ) - { - se->setReturnContent( s ); - } - else if( const RawDataEvent* rde = - dynamic_cast( self->event ) ) - { - rde->setReturnContent( s ); - } - else - { - return badArgument(); - } - - Py_RETURN_NONE; - } - - static PyObject* pressure( PyEventObject* self, PyObject* args ) - { - PyLockObject locker; - if( !self->event ) return badArgument(); - double d = 1.0; - - if( const TabletEvent* te = - dynamic_cast( self->event ) ) - { - d = te->pressure(); - } - - return PyFloat_FromDouble( d ); - } - - static PyObject* tangentialPressure( PyEventObject* self, PyObject* args ) - { - PyLockObject locker; - if( !self->event ) return badArgument(); - double d = 1.0; - - if( const TabletEvent* te = - dynamic_cast( self->event ) ) - { - d = te->tangentialPressure(); - } - - return PyFloat_FromDouble( d ); - } - - static PyObject* rotation( PyEventObject* self, PyObject* args ) - { - PyLockObject locker; - if( !self->event ) return badArgument(); - double d = 1.0; - - if( const TabletEvent* te = - dynamic_cast( self->event ) ) - { - d = te->rotation(); - } - - return PyFloat_FromDouble( d ); - } - - static PyObject* xTilt( PyEventObject* self, PyObject* args ) - { - PyLockObject locker; - if( !self->event ) return badArgument(); - long d = 1.0; - - if( const TabletEvent* te = - dynamic_cast( self->event ) ) - { - d = te->xTilt(); - } - - return PyLong_FromLong( d ); - } - - static PyObject* yTilt( PyEventObject* self, PyObject* args ) - { - PyLockObject locker; - if( !self->event ) return badArgument(); - long d = 1.0; - - if( const TabletEvent* te = - dynamic_cast( self->event ) ) - { - d = te->yTilt(); - } - - return PyLong_FromLong( d ); - } - - static PyObject* activationTime( PyEventObject* self, PyObject* args ) - { - PyLockObject locker; - if( !self->event ) return badArgument(); - double d = 0.0; - - if( const PointerButtonPressEvent* pe = - dynamic_cast( self->event ) ) - { - d = pe->activationTime(); - } - - return PyFloat_FromDouble( d ); - } - - static PyMethodDef methods[] = { - {"pointer", (PyCFunction)pointer, METH_NOARGS, - "Return the pointer position"}, - {"relativePointer", (PyCFunction)relativePointer, METH_NOARGS, - "Return the pointer position"}, - {"domain", (PyCFunction)domain, METH_NOARGS, "Return the domain size"}, - {"subDomain", (PyCFunction)subDomain, METH_NOARGS, - "Return the domain size"}, - {"domainVerticalFlip", (PyCFunction)domainVerticalFlip, METH_NOARGS, - "Return the domain vflip flag"}, - {"buttons", (PyCFunction)buttons, METH_NOARGS, "Return the button mask"}, - {"modifiers", (PyCFunction)modifiers, METH_NOARGS, - "Return the modifier mask"}, - {"key", (PyCFunction)key, METH_NOARGS, "Return the key"}, - {"name", (PyCFunction)name, METH_NOARGS, "Return the key"}, - {"contents", (PyCFunction)contents, METH_NOARGS, "Return the key"}, - {"returnContents", (PyCFunction)returnContents, METH_NOARGS, - "Return the key"}, - {"dataContents", (PyCFunction)dataContents, METH_NOARGS, - "Return the key"}, - {"sender", (PyCFunction)sender, METH_NOARGS, "Return the key"}, - {"contentType", (PyCFunction)contentType, METH_NOARGS, "Return the key"}, - {"contentMimeType", (PyCFunction)contentMimeType, METH_NOARGS, - "Return the key"}, - {"timeStamp", (PyCFunction)timeStamp, METH_NOARGS, "Return the key"}, - {"reject", (PyCFunction)reject, METH_NOARGS, "Return the key"}, - {"setReturnContent", (PyCFunction)setReturnContent, METH_VARARGS, - "Return the key"}, - {"pressure", (PyCFunction)pressure, METH_NOARGS, "Return the key"}, - {"tangentialPressure", (PyCFunction)tangentialPressure, METH_NOARGS, - "Return the key"}, - {"rotation", (PyCFunction)rotation, METH_NOARGS, "Return the key"}, - {"xTilt", (PyCFunction)xTilt, METH_NOARGS, "Return the key"}, - {"yTilt", (PyCFunction)yTilt, METH_NOARGS, "Return the key"}, - {"activationTime", (PyCFunction)activationTime, METH_NOARGS, - "Return the key"}, - {NULL} /* Sentinel */ - }; - -static PyTypeObject type = -{ - PyVarObject_HEAD_INIT(NULL, 0) - "Event", /*tp_name*/ - sizeof( PyEventObject ), /*tp_basicsize*/ - 0, /* tp_itemsize */ - 0, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_reserved */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /*tp_flags*/ - "Application Event", /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - methods, /* tp_methods */ - }; - - PyTypeObject* pyEventType() - { - return &type; - } - - PyObject* PyEventFromEvent( const Event* event, const Document* doc ) - { - PyLockObject locker; - PyTypeObject* etype = pyEventType(); - PyEventObject* e = (PyEventObject*) etype->tp_alloc(etype, 0); - e->event = event; - e->document = doc; - return (PyObject*)e; - } - - void initPyEventType() - { - // - } - -} // namespace TwkApp + PyLockObject locker; + if (!self->event) + return badArgument(); + double d = 1.0; + + if (const TabletEvent* te = + dynamic_cast(self->event)) + { + d = te->pressure(); + } + + return PyFloat_FromDouble(d); + } + + static PyObject* tangentialPressure(PyEventObject* self, PyObject* args) + { + PyLockObject locker; + if (!self->event) + return badArgument(); + double d = 1.0; + + if (const TabletEvent* te = + dynamic_cast(self->event)) + { + d = te->tangentialPressure(); + } + + return PyFloat_FromDouble(d); + } + + static PyObject* rotation(PyEventObject* self, PyObject* args) + { + PyLockObject locker; + if (!self->event) + return badArgument(); + double d = 1.0; + + if (const TabletEvent* te = + dynamic_cast(self->event)) + { + d = te->rotation(); + } + + return PyFloat_FromDouble(d); + } + + static PyObject* xTilt(PyEventObject* self, PyObject* args) + { + PyLockObject locker; + if (!self->event) + return badArgument(); + long d = 1.0; + + if (const TabletEvent* te = + dynamic_cast(self->event)) + { + d = te->xTilt(); + } + + return PyLong_FromLong(d); + } + + static PyObject* yTilt(PyEventObject* self, PyObject* args) + { + PyLockObject locker; + if (!self->event) + return badArgument(); + long d = 1.0; + + if (const TabletEvent* te = + dynamic_cast(self->event)) + { + d = te->yTilt(); + } + + return PyLong_FromLong(d); + } + + static PyObject* activationTime(PyEventObject* self, PyObject* args) + { + PyLockObject locker; + if (!self->event) + return badArgument(); + double d = 0.0; + + if (const PointerButtonPressEvent* pe = + dynamic_cast(self->event)) + { + d = pe->activationTime(); + } + + return PyFloat_FromDouble(d); + } + + static PyMethodDef methods[] = { + {"pointer", (PyCFunction)pointer, METH_NOARGS, + "Return the pointer position"}, + {"relativePointer", (PyCFunction)relativePointer, METH_NOARGS, + "Return the pointer position"}, + {"domain", (PyCFunction)domain, METH_NOARGS, "Return the domain size"}, + {"subDomain", (PyCFunction)subDomain, METH_NOARGS, + "Return the domain size"}, + {"domainVerticalFlip", (PyCFunction)domainVerticalFlip, METH_NOARGS, + "Return the domain vflip flag"}, + {"buttons", (PyCFunction)buttons, METH_NOARGS, + "Return the button mask"}, + {"modifiers", (PyCFunction)modifiers, METH_NOARGS, + "Return the modifier mask"}, + {"key", (PyCFunction)key, METH_NOARGS, "Return the key"}, + {"name", (PyCFunction)name, METH_NOARGS, "Return the key"}, + {"contents", (PyCFunction)contents, METH_NOARGS, "Return the key"}, + {"returnContents", (PyCFunction)returnContents, METH_NOARGS, + "Return the key"}, + {"dataContents", (PyCFunction)dataContents, METH_NOARGS, + "Return the key"}, + {"sender", (PyCFunction)sender, METH_NOARGS, "Return the key"}, + {"contentType", (PyCFunction)contentType, METH_NOARGS, + "Return the key"}, + {"contentMimeType", (PyCFunction)contentMimeType, METH_NOARGS, + "Return the key"}, + {"timeStamp", (PyCFunction)timeStamp, METH_NOARGS, "Return the key"}, + {"reject", (PyCFunction)reject, METH_NOARGS, "Return the key"}, + {"setReturnContent", (PyCFunction)setReturnContent, METH_VARARGS, + "Return the key"}, + {"pressure", (PyCFunction)pressure, METH_NOARGS, "Return the key"}, + {"tangentialPressure", (PyCFunction)tangentialPressure, METH_NOARGS, + "Return the key"}, + {"rotation", (PyCFunction)rotation, METH_NOARGS, "Return the key"}, + {"xTilt", (PyCFunction)xTilt, METH_NOARGS, "Return the key"}, + {"yTilt", (PyCFunction)yTilt, METH_NOARGS, "Return the key"}, + {"activationTime", (PyCFunction)activationTime, METH_NOARGS, + "Return the key"}, + {NULL} /* Sentinel */ + }; + + static PyTypeObject type = { + PyVarObject_HEAD_INIT(NULL, 0) "Event", /*tp_name*/ + sizeof(PyEventObject), /*tp_basicsize*/ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /*tp_flags*/ + "Application Event", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + methods, /* tp_methods */ + }; + + PyTypeObject* pyEventType() { return &type; } + + PyObject* PyEventFromEvent(const Event* event, const Document* doc) + { + PyLockObject locker; + PyTypeObject* etype = pyEventType(); + PyEventObject* e = (PyEventObject*)etype->tp_alloc(etype, 0); + e->event = event; + e->document = doc; + return (PyObject*)e; + } + + void initPyEventType() + { + // + } + +} // namespace TwkApp diff --git a/src/lib/app/PyTwkApp/PyFunctionAction.cpp b/src/lib/app/PyTwkApp/PyFunctionAction.cpp index ba67ffd69..9afb22aed 100644 --- a/src/lib/app/PyTwkApp/PyFunctionAction.cpp +++ b/src/lib/app/PyTwkApp/PyFunctionAction.cpp @@ -1,9 +1,9 @@ //****************************************************************************** // Copyright (c) 2011 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #include #include @@ -18,73 +18,71 @@ namespace TwkApp { - using namespace std; + using namespace std; - PyFunctionAction::PyFunctionAction( PyObject* obj ) : Action() - { - PyLockObject locker; - m_exception = false; - m_func = obj; - Py_XINCREF( m_func ); - } - - PyFunctionAction::PyFunctionAction( PyObject* obj, const string& doc ) - : Action( doc ) - { - PyLockObject locker; - m_func = obj; - m_exception = false; - Py_XINCREF( m_func ); - } - - PyFunctionAction::~PyFunctionAction() - { - PyLockObject locker; - Py_XDECREF( m_func ); - } - - void PyFunctionAction::execute( Document* d, const Event& event ) const - { - PyLockObject locker; - PyObject* e = PyEventFromEvent( &event, d ); - event.handled = true; // the user can call reject() - - PyObject* args = Py_BuildValue( "(O)", e ); - PyObject* r = 0; - - try + PyFunctionAction::PyFunctionAction(PyObject* obj) + : Action() { - r = PyObject_Call( m_func, args, 0 ); + PyLockObject locker; + m_exception = false; + m_func = obj; + Py_XINCREF(m_func); } - catch( std::exception& exc ) + + PyFunctionAction::PyFunctionAction(PyObject* obj, const string& doc) + : Action(doc) { - cout << "ERROR: " << exc.what() - << " -- while executing action: " << docString() << endl; + PyLockObject locker; + m_func = obj; + m_exception = false; + Py_XINCREF(m_func); } - catch( ... ) + + PyFunctionAction::~PyFunctionAction() { - cout << "ERROR: uncaught exception " - << " -- while executing action: " << docString() << endl; + PyLockObject locker; + Py_XDECREF(m_func); } - Py_XDECREF( e ); - Py_XDECREF( args ); - - if( PyErr_Occurred() ) + void PyFunctionAction::execute(Document* d, const Event& event) const { - PyErr_Print(); - m_exception = true; + PyLockObject locker; + PyObject* e = PyEventFromEvent(&event, d); + event.handled = true; // the user can call reject() + + PyObject* args = Py_BuildValue("(O)", e); + PyObject* r = 0; + + try + { + r = PyObject_Call(m_func, args, 0); + } + catch (std::exception& exc) + { + cout << "ERROR: " << exc.what() + << " -- while executing action: " << docString() << endl; + } + catch (...) + { + cout << "ERROR: uncaught exception " + << " -- while executing action: " << docString() << endl; + } + + Py_XDECREF(e); + Py_XDECREF(args); + + if (PyErr_Occurred()) + { + PyErr_Print(); + m_exception = true; + } } - } - bool PyFunctionAction::error() const - { - return m_exception; - } + bool PyFunctionAction::error() const { return m_exception; } - Action* PyFunctionAction::copy() const - { - return new PyFunctionAction( m_func, docString() ); - } + Action* PyFunctionAction::copy() const + { + return new PyFunctionAction(m_func, docString()); + } -} // namespace TwkApp +} // namespace TwkApp diff --git a/src/lib/app/PyTwkApp/PyInterface.cpp b/src/lib/app/PyTwkApp/PyInterface.cpp index b84b173e7..43080dc56 100644 --- a/src/lib/app/PyTwkApp/PyInterface.cpp +++ b/src/lib/app/PyTwkApp/PyInterface.cpp @@ -1,9 +1,9 @@ // // Copyright (c) 2011 Tweak Software. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// // #include #include @@ -31,457 +31,472 @@ namespace TwkApp { - using namespace std; - - // extern "C" { void initcStringIO(void); } - - static Menu::Item* tupleToMenuItem( PyObject* ); - static Menu* listToMenu( const char*, PyObject* ); + using namespace std; - static Menu::Item* tupleToMenuItem( PyObject* t ) - { - PyLockObject locker; + // extern "C" { void initcStringIO(void); } - size_t n = PyTuple_Size( t ); + static Menu::Item* tupleToMenuItem(PyObject*); + static Menu* listToMenu(const char*, PyObject*); - if( n == 2 ) + static Menu::Item* tupleToMenuItem(PyObject* t) { - // - // Sub-Menu item - // + PyLockObject locker; - const char* label; - PyObject* obj; + size_t n = PyTuple_Size(t); - if( PyArg_ParseTuple( t, "sO", &label, &obj ) ) - { - if( PyList_Check( obj ) ) + if (n == 2) { - return new Menu::Item( label, 0, listToMenu( label, obj ) ); + // + // Sub-Menu item + // + + const char* label; + PyObject* obj; + + if (PyArg_ParseTuple(t, "sO", &label, &obj)) + { + if (PyList_Check(obj)) + { + return new Menu::Item(label, 0, listToMenu(label, obj)); + } + else if (obj == Py_None || PyCallable_Check(obj)) + { + return new Menu::Item( + label, + obj == Py_None ? NULL : new PyFunctionAction(obj)); + } + } + + ostringstream str; + str << "ERROR:" << (label ? label : ""); + return new Menu::Item(str.str(), NULL); } - else if( obj == Py_None || PyCallable_Check( obj ) ) + else if (n == 4) { - return new Menu::Item( - label, obj == Py_None ? NULL : new PyFunctionAction( obj ) ); + const char* label; + PyObject* actionFunc; + PyObject* keyObj; + PyObject* stateFunc; + + if (PyArg_ParseTuple(t, "sOOO", &label, &actionFunc, &keyObj, + &stateFunc)) + { + if ((actionFunc == Py_None || PyCallable_Check(actionFunc)) + && (stateFunc == Py_None || PyCallable_Check(stateFunc))) + { + std::string title = label; + std::string key; + + if (keyObj == Py_None) + { + key = ""; + } + else if (PyBytes_Check(keyObj)) + { + key = PyBytes_AsString(keyObj); + } + else if (PyUnicode_Check(keyObj)) + { + PyObject* keyObjBytes = PyUnicode_AsUTF8String(keyObj); + key = PyBytes_AsString(keyObjBytes); + Py_XDECREF(keyObjBytes); + } + else + { + title = std::string("ERROR: ") + title + + std::string(" (Invalid Shortcuts)"); + } + + return new Menu::Item( + title, + actionFunc == Py_None + ? NULL + : new PyFunctionAction(actionFunc), + key, + stateFunc == Py_None ? NULL + : new PyStateFunc(stateFunc)); + } + } + + ostringstream str; + str << "ERROR: " << (label ? label : ""); + return new Menu::Item(str.str(), NULL); } - } + else if (n > 0) + { + PyObject* l = PyTuple_GetItem(t, 0); + ostringstream str; + str << "ERROR: "; - ostringstream str; - str << "ERROR:" << ( label ? label : "" ); - return new Menu::Item( str.str(), NULL ); - } - else if( n == 4 ) - { - const char* label; - PyObject* actionFunc; - PyObject* keyObj; - PyObject* stateFunc; - - if( PyArg_ParseTuple( t, "sOOO", &label, &actionFunc, &keyObj, - &stateFunc ) ) - { - if( ( actionFunc == Py_None || PyCallable_Check( actionFunc ) ) && - ( stateFunc == Py_None || PyCallable_Check( stateFunc ) ) ) + if (PyBytes_Check(l)) + { + const char* s = PyBytes_AsString(l); + str << s; + } + + return new Menu::Item(str.str(), NULL); + } + else { - std::string title = label; - std::string key; - - if( keyObj == Py_None ) - { - key = ""; - } - else if( PyBytes_Check( keyObj ) ) - { - key = PyBytes_AsString( keyObj ); - } - else if( PyUnicode_Check( keyObj ) ) - { - PyObject* keyObjBytes = PyUnicode_AsUTF8String( keyObj ); - key = PyBytes_AsString( keyObjBytes ); - Py_XDECREF( keyObjBytes ); - } - else - { - title = std::string( "ERROR: " ) + title + - std::string( " (Invalid Shortcuts)" ); - } - - return new Menu::Item( - title, - actionFunc == Py_None ? NULL : new PyFunctionAction( actionFunc ), - key, stateFunc == Py_None ? NULL : new PyStateFunc( stateFunc ) ); + return NULL; } - } - - ostringstream str; - str << "ERROR: " << ( label ? label : "" ); - return new Menu::Item( str.str(), NULL ); } - else if( n > 0 ) + + static Menu* listToMenu(const char* name, PyObject* l) { - PyObject* l = PyTuple_GetItem( t, 0 ); - ostringstream str; - str << "ERROR: "; + size_t n = PyList_Size(l); + Menu* menu = new Menu(name); - if( PyBytes_Check( l ) ) - { - const char* s = PyBytes_AsString( l ); - str << s; - } + for (size_t i = 0; i < n; i++) + { + PyObject* t = PyList_GetItem(l, i); + + if (t && PyTuple_CheckExact(t)) + { + if (Menu::Item* item = tupleToMenuItem(t)) + { + menu->addItem(item); + } + } + } - return new Menu::Item( str.str(), NULL ); + return menu; } - else + + Menu* pyListToMenu(const char* name, void* p) { - return NULL; + return listToMenu(name, (PyObject*)p); } - } - - static Menu* listToMenu( const char* name, PyObject* l ) - { - size_t n = PyList_Size( l ); - Menu* menu = new Menu( name ); - for( size_t i = 0; i < n; i++ ) + namespace { - PyObject* t = PyList_GetItem( l, i ); + bool pythonHasBeenInitialized = false; + }; - if( t && PyTuple_CheckExact( t ) ) - { - if( Menu::Item* item = tupleToMenuItem( t ) ) - { - menu->addItem( item ); - } - } - } + void* callPythonFunction(const char* name, const char* module) + { + if (!pythonHasBeenInitialized) + return 0; - return menu; - } + PyObject *pModule, *pModuleDict, *pFunc; + PyObject *pArgs = 0, *pValue = 0; + PyLockObject locker; - Menu* pyListToMenu( const char* name, void* p ) - { - return listToMenu( name, (PyObject*)p ); - } + if (!module) + module = "__main__"; - namespace - { - bool pythonHasBeenInitialized = false; - }; + pModule = PyImport_ImportModule(module); - void* callPythonFunction( const char* name, const char* module ) - { - if( !pythonHasBeenInitialized ) return 0; + if (pModule == NULL) + { + if (PyErr_Occurred()) + { + PyErr_Print(); + } + return 0; + } - PyObject *pModule, *pModuleDict, *pFunc; - PyObject *pArgs = 0, *pValue = 0; - PyLockObject locker; + if (!PyObject_HasAttrString(pModule, name)) + { + Py_XDECREF(pModule); + return 0; + } - if( !module ) module = "__main__"; + pFunc = PyObject_GetAttrString(pModule, name); - pModule = PyImport_ImportModule( module ); + if (pFunc == NULL) + { + if (PyErr_Occurred()) + { + PyErr_Print(); + } + return 0; + } - if( pModule == NULL ) - { - if( PyErr_Occurred() ) - { - PyErr_Print(); - } - return 0; + if (PyCallable_Check(pFunc)) + { + pArgs = PyTuple_New(0); + pValue = PyObject_CallObject(pFunc, pArgs); + + Py_XDECREF(pFunc); + Py_XDECREF(pArgs); + + if (pValue != NULL) + { + return pValue; + } + else + { + if (PyErr_Occurred()) + { + PyErr_Print(); + } + return 0; + } + } + else + { + cerr << name << " is not callable" << endl; + Py_XDECREF(pFunc); + return 0; + } } - if( !PyObject_HasAttrString( pModule, name ) ) + void disposeOfPythonObject(void* obj) { - Py_XDECREF( pModule ); - return 0; - } + PyLockObject locker; - pFunc = PyObject_GetAttrString( pModule, name ); + if (obj) + { + PyObject* pobj = (PyObject*)obj; + Py_XDECREF(pobj); + } + } - if( pFunc == NULL ) + void evalPython(const char* text) { - if( PyErr_Occurred() ) - { - PyErr_Print(); - } - return 0; + PyLockObject locker; + + PyRun_SimpleString(text); } - if( PyCallable_Check( pFunc ) ) + void initPython(int argc, char** argv) { - pArgs = PyTuple_New( 0 ); - pValue = PyObject_CallObject( pFunc, pArgs ); - - Py_XDECREF( pFunc ); - Py_XDECREF( pArgs ); - - if( pValue != NULL ) - { - return pValue; - } - else - { - if( PyErr_Occurred() ) + // PreInitialize Python + // Note: This is necessary for Python to utilize environment variables + // like PYTHONUTF8 + PyPreConfig preconfig; + PyPreConfig_InitPythonConfig(&preconfig); + PyStatus status = Py_PreInitialize(&preconfig); + if (PyStatus_Exception(status)) { - PyErr_Print(); + Py_ExitStatusException(status); } - return 0; - } - } - else - { - cerr << name << " is not callable" << endl; - Py_XDECREF( pFunc ); - return 0; - } - } - - void disposeOfPythonObject( void* obj ) - { - PyLockObject locker; - if( obj ) - { - PyObject* pobj = (PyObject*)obj; - Py_XDECREF( pobj ); - } - } - - void evalPython( const char* text ) - { - PyLockObject locker; - - PyRun_SimpleString( text ); - } - - void initPython( int argc, char** argv ) - { - // PreInitialize Python - // Note: This is necessary for Python to utilize environment variables like PYTHONUTF8 - PyPreConfig preconfig; - PyPreConfig_InitPythonConfig(&preconfig); - PyStatus status=Py_PreInitialize(&preconfig); - if (PyStatus_Exception(status)) { - Py_ExitStatusException(status); - } + Py_InitializeEx(1); + static wchar_t delim = L'\0'; - Py_InitializeEx( 1 ); - static wchar_t delim = L'\0'; + wchar_t** w_argv = new wchar_t*[argc + 1]; + w_argv[argc] = &delim; - wchar_t** w_argv = new wchar_t*[argc + 1]; - w_argv[argc] = &delim; + for (int i = 0; i < argc; ++i) + { + w_argv[i] = Py_DecodeLocale(argv[i], nullptr); + } - for (int i = 0; i < argc; ++i ){ - w_argv[i] = Py_DecodeLocale(argv[i], nullptr); + PySys_SetArgvEx(argc, w_argv, 0); + + // + // Initialize python threading, acquire the GIL for the main + // thread. + // + PyEval_InitThreads(); + + // + // Release the GIL + // + (void)PyEval_SaveThread(); + + // + // Add MuPy to the default Mu modules + // + + Mu::Module* python = new Mu::PyModule(muContext(), "python"); + muContext()->globalScope()->addSymbol(python); + + // + // Set python3 as multiprocessing executable + // + + evalPython( + "" + "import multiprocessing, os, sys\n" + "bin_dir, bin_name = os.path.split(sys.executable)\n" + "bin_name, bin_ext = os.path.splitext(bin_name)\n" + "for python_process in ('python', 'python3', 'py-interp'):\n" + " python_exe = os.path.join(bin_dir, python_process + bin_ext)\n" + " if os.path.exists(python_exe):\n" + " multiprocessing.set_executable(python_exe)\n" + " break\n" + ""); } - PySys_SetArgvEx( argc, w_argv, 0 ); + void finalizePython() + { + // Deliberately not using PyLockObject to avoid calling + // PyGILState_Release in its destructor. + PyGILState_Ensure(); - // - // Initialize python threading, acquire the GIL for the main - // thread. - // - PyEval_InitThreads(); + Py_Finalize(); + } // - // Release the GIL + // Used by PyMu module to convert unknown types. In this case the + // Event type // - (void)PyEval_SaveThread(); - // - // Add MuPy to the default Mu modules - // + static Mu::ClassInstance* convertEventToMu(const Mu::Type* t, void* p) + { + PyLockObject locker; - Mu::Module* python = new Mu::PyModule( muContext(), "python" ); - muContext()->globalScope()->addSymbol( python ); + PyObject* pobj = (PyObject*)p; - // - // Set python3 as multiprocessing executable - // + if (Py_TYPE(pobj) == pyEventType()) + { + PyEventObject* eobj = reinterpret_cast(pobj); + Mu::Name ename = muContext()->lookupName("Event"); + const EventType* etype = + muContext()->findSymbolOfType(ename); + assert(etype); + + if (etype == t) + { + EventType::EventInstance* e = + new EventType::EventInstance(etype); + e->event = eobj->event; + e->document = eobj->document; + return e; + } + } + else if (Py_TYPE(pobj) == pyEventType()) + { + PyLockObject locker; + + PyEventObject* eobj = reinterpret_cast(pobj); + Mu::Name ename = muContext()->lookupName("Event"); + const EventType* etype = + muContext()->findSymbolOfType(ename); + assert(etype); + + if (etype == t) + { + EventType::EventInstance* e = + new EventType::EventInstance(etype); + e->event = eobj->event; + e->document = eobj->document; + return e; + } + } - evalPython("" - "import multiprocessing, os, sys\n" - "bin_dir, bin_name = os.path.split(sys.executable)\n" - "bin_name, bin_ext = os.path.splitext(bin_name)\n" - "for python_process in ('python', 'python3', 'py-interp'):\n" - " python_exe = os.path.join(bin_dir, python_process + bin_ext)\n" - " if os.path.exists(python_exe):\n" - " multiprocessing.set_executable(python_exe)\n" - " break\n" - "" - ); - - } - - void finalizePython() - { - // Deliberately not using PyLockObject to avoid calling - // PyGILState_Release in its destructor. - PyGILState_Ensure(); - - Py_Finalize(); - } - - // - // Used by PyMu module to convert unknown types. In this case the - // Event type - // - - static Mu::ClassInstance* convertEventToMu( const Mu::Type* t, void* p ) - { - PyLockObject locker; - - PyObject* pobj = (PyObject*)p; - - if( Py_TYPE( pobj ) == pyEventType() ) - { - PyEventObject* eobj = reinterpret_cast( pobj ); - Mu::Name ename = muContext()->lookupName( "Event" ); - const EventType* etype = - muContext()->findSymbolOfType( ename ); - assert( etype ); - - if( etype == t ) - { - EventType::EventInstance* e = new EventType::EventInstance( etype ); - e->event = eobj->event; - e->document = eobj->document; - return e; - } + return 0; } - else if( Py_TYPE( pobj ) == pyEventType() ) + + static void* convertEventToPy(const Mu::Type* t, Mu::ClassInstance* muobj) { - PyLockObject locker; - - PyEventObject* eobj = reinterpret_cast( pobj ); - Mu::Name ename = muContext()->lookupName( "Event" ); - const EventType* etype = - muContext()->findSymbolOfType( ename ); - assert( etype ); - - if( etype == t ) - { - EventType::EventInstance* e = new EventType::EventInstance( etype ); - e->event = eobj->event; - e->document = eobj->document; - return e; - } - } + PyLockObject locker; - return 0; - } + if (const EventType* etype = dynamic_cast(t)) + { + EventType::EventInstance* obj = + reinterpret_cast(muobj); + return PyEventFromEvent(obj->event, obj->document); + } - static void* convertEventToPy( const Mu::Type* t, Mu::ClassInstance* muobj ) - { - PyLockObject locker; + return 0; + } - if( const EventType* etype = dynamic_cast( t ) ) + static Mu::Pointer convertMuSymbolToSymbol(const Mu::Type* t, void* p) { - EventType::EventInstance* obj = - reinterpret_cast( muobj ); - return PyEventFromEvent( obj->event, obj->document ); - } + PyLockObject locker; - return 0; - } + PyObject* pobj = (PyObject*)p; - static Mu::Pointer convertMuSymbolToSymbol( const Mu::Type* t, void* p ) - { - PyLockObject locker; + if (t == muContext()->symbolType()) + { + if (Py_TYPE(pobj) == pyMuSymbolType()) + { + PyMuSymbolObject* o = reinterpret_cast(pobj); + return Mu::Pointer(o->symbol); + } + } - PyObject* pobj = (PyObject*)p; + return Mu::Pointer(0); + } - if( t == muContext()->symbolType() ) + static void* convertSymbolToMuSymbol(const Mu::Type* t, void* p) { - if( Py_TYPE( pobj ) == pyMuSymbolType() ) - { - PyMuSymbolObject* o = reinterpret_cast( pobj ); - return Mu::Pointer( o->symbol ); - } + PyLockObject locker; + if (t == muContext()->symbolType()) + { + if (PyMuSymbolObject* o = + (PyMuSymbolObject*)pyMuSymbolType()->tp_alloc( + pyMuSymbolType(), 0)) + { + o->symbol = reinterpret_cast(p); + o->function = dynamic_cast(o->symbol); + return (PyObject*)o; + } + } + + return 0; } - return Mu::Pointer( 0 ); - } + //------ - static void* convertSymbolToMuSymbol( const Mu::Type* t, void* p ) - { - PyLockObject locker; - if( t == muContext()->symbolType() ) - { - if( PyMuSymbolObject* o = (PyMuSymbolObject*)pyMuSymbolType()->tp_alloc( pyMuSymbolType(), 0 ) ) - { - o->symbol = reinterpret_cast( p ); - o->function = dynamic_cast( o->symbol ); - return (PyObject*)o; - } - } - - return 0; - } - - //------ - - void pyInitWithFile( const char* rcfile, void* commands0, void* commands1 ) - { - vector methods; - PyMethodDef* d = 0; - PyLockObject locker; - - Mu::PyModule::addConverterFunctions( convertEventToPy, convertEventToMu, 0, - 0 ); - Mu::PyModule::addConverterFunctions( 0, 0, convertSymbolToMuSymbol, - convertMuSymbolToSymbol ); - - if( commands0 ) - { - d = (PyMethodDef*)commands0; - for( size_t i = 0; d[i].ml_name; i++ ) methods.push_back( d[i] ); - } - if( commands1 ) + void pyInitWithFile(const char* rcfile, void* commands0, void* commands1) { - d = (PyMethodDef*)commands1; - for( size_t i = 0; d[i].ml_name; i++ ) methods.push_back( d[i] ); - } + vector methods; + PyMethodDef* d = 0; + PyLockObject locker; - PyMethodDef nulldef = { NULL }; - methods.push_back( nulldef ); - d = methods.empty() ? 0 : &methods.front(); + Mu::PyModule::addConverterFunctions(convertEventToPy, convertEventToMu, + 0, 0); + Mu::PyModule::addConverterFunctions(0, 0, convertSymbolToMuSymbol, + convertMuSymbolToSymbol); - // initcStringIO(); - pyInitCommands( d ); - PyObject* pymu = initPyMu(); + if (commands0) + { + d = (PyMethodDef*)commands0; + for (size_t i = 0; d[i].ml_name; i++) + methods.push_back(d[i]); + } + if (commands1) + { + d = (PyMethodDef*)commands1; + for (size_t i = 0; d[i].ml_name; i++) + methods.push_back(d[i]); + } - PyObject* pModule = PyImport_ImportModule( "__main__" ); + PyMethodDef nulldef = {NULL}; + methods.push_back(nulldef); + d = methods.empty() ? 0 : &methods.front(); - pyEventType()->tp_new = reinterpret_cast( PyType_GenericNew ); + // initcStringIO(); + pyInitCommands(d); + PyObject* pymu = initPyMu(); - if( PyType_Ready( pyEventType() ) >= 0 ) - { - Py_XINCREF( pyEventType() ); - PyModule_AddObject( pModule, "Event", - reinterpret_cast( pyEventType() ) ); - } + PyObject* pModule = PyImport_ImportModule("__main__"); - if( PyType_Ready( pyMuSymbolType() ) >= 0 ) - { - Py_XINCREF( pyMuSymbolType() ); - PyModule_AddObject( pymu, "MuSymbol", (PyObject*)pyMuSymbolType() ); - } + pyEventType()->tp_new = reinterpret_cast(PyType_GenericNew); - Py_XDECREF( pModule ); + if (PyType_Ready(pyEventType()) >= 0) + { + Py_XINCREF(pyEventType()); + PyModule_AddObject(pModule, "Event", + reinterpret_cast(pyEventType())); + } - PyObject* rcs = PyImport_ImportModule( "rv_commands_setup" ); + if (PyType_Ready(pyMuSymbolType()) >= 0) + { + Py_XINCREF(pyMuSymbolType()); + PyModule_AddObject(pymu, "MuSymbol", (PyObject*)pyMuSymbolType()); + } - std::ifstream fileSteam( rcfile ); - if( fileSteam.is_open() ) - { - std::string content( ( std::istreambuf_iterator( fileSteam ) ), - ( std::istreambuf_iterator() ) ); - PyRun_SimpleString( content.c_str() ); - } + Py_XDECREF(pModule); + + PyObject* rcs = PyImport_ImportModule("rv_commands_setup"); + + std::ifstream fileSteam(rcfile); + if (fileSteam.is_open()) + { + std::string content((std::istreambuf_iterator(fileSteam)), + (std::istreambuf_iterator())); + PyRun_SimpleString(content.c_str()); + } - pythonHasBeenInitialized = true; + pythonHasBeenInitialized = true; - Py_XDECREF( rcs ); - } + Py_XDECREF(rcs); + } -} // namespace TwkApp +} // namespace TwkApp diff --git a/src/lib/app/PyTwkApp/PyMenuItemType.cpp b/src/lib/app/PyTwkApp/PyMenuItemType.cpp index 4581d4b98..ae1028989 100644 --- a/src/lib/app/PyTwkApp/PyMenuItemType.cpp +++ b/src/lib/app/PyTwkApp/PyMenuItemType.cpp @@ -1,9 +1,9 @@ // // Copyright (c) 2011 Tweak Software. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// // #include @@ -15,136 +15,133 @@ namespace TwkApp { - using namespace std; + using namespace std; - static PyObject* MenuItem_new( PyTypeObject* type, PyObject* args, - PyObject* kwds ) - { - PyLockObject locker; - PyMenuItemObject* self; + static PyObject* MenuItem_new(PyTypeObject* type, PyObject* args, + PyObject* kwds) + { + PyLockObject locker; + PyMenuItemObject* self; + + if (self = (PyMenuItemObject*)type->tp_alloc(type, 0)) + { + self->label = 0; + self->actionHook = 0; + self->key = 0; + self->stateHook = 0; + self->subMenu = 0; + } + + return (PyObject*)self; + } + + int MenuItem_init(PyObject* _self, PyObject* args, PyObject* kwds) + { + PyMenuItemObject* self = (PyMenuItemObject*)_self; + + PyLockObject locker; + const char* label; + PyObject* action; + const char* key; + PyObject* state; + PyObject* subMenu; + + int ok = PyArg_ParseTuple(args, "sOsOO", &label, &action, &key, &state, + &subMenu); + + if (!ok) + return -1; + + Py_XINCREF(action); + Py_XINCREF(state); + Py_XINCREF(subMenu); + + self->label = PyBytes_FromString(label); + self->actionHook = action; + self->key = PyBytes_FromString(key); + self->stateHook = state; + self->subMenu = subMenu; + return 0; + } + + static void MenuItem_dealloc(PyObject* _self) + { + PyMenuItemObject* self = (PyMenuItemObject*)_self; + + PyLockObject locker; + + Py_XDECREF(self->label); + Py_XDECREF(self->actionHook); + Py_XDECREF(self->key); + Py_XDECREF(self->stateHook); + Py_XDECREF(self->subMenu); + + Py_TYPE(self)->tp_free(self); + } - if( self = (PyMenuItemObject*)type->tp_alloc( type, 0 ) ) + static PyMethodDef methods[] = { + {NULL} /* Sentinel */ + }; + + static PyMemberDef members[] = { + {"label", T_OBJECT_EX, offsetof(PyMenuItemObject, label), 0, + "User visible label"}, + {"actionHook", T_OBJECT_EX, offsetof(PyMenuItemObject, actionHook), 0, + "Activation callback"}, + {"key", T_OBJECT_EX, offsetof(PyMenuItemObject, actionHook), 0, + "Accelerator key"}, + {"stateHook", T_OBJECT_EX, offsetof(PyMenuItemObject, stateHook), 0, + "State callback"}, + {"subMenu", T_OBJECT_EX, offsetof(PyMenuItemObject, subMenu), 0, + "Sub-menu"}, + {NULL} /* Sentinel */ + }; + + static PyTypeObject type = { + PyVarObject_HEAD_INIT(NULL, 0) "MenuItem", /*tp_name*/ + sizeof(PyMenuItemObject), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + MenuItem_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT, /*tp_flags*/ + "Application Menu Item", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + MenuItem_init, /* tp_init */ + 0, /* tp_alloc */ + MenuItem_new, /* tp_new */ + }; + + PyTypeObject* pyMenuItemType() { return &type; } + + void initPyMenuItemType() { - self->label = 0; - self->actionHook = 0; - self->key = 0; - self->stateHook = 0; - self->subMenu = 0; + // } - return (PyObject*)self; - } - - int MenuItem_init( PyObject* _self, PyObject* args, PyObject* kwds ) - { - PyMenuItemObject* self = (PyMenuItemObject*) _self; - - PyLockObject locker; - const char* label; - PyObject* action; - const char* key; - PyObject* state; - PyObject* subMenu; - - int ok = PyArg_ParseTuple( args, "sOsOO", &label, &action, &key, &state, - &subMenu ); - - if( !ok ) return -1; - - Py_XINCREF( action ); - Py_XINCREF( state ); - Py_XINCREF( subMenu ); - - self->label = PyBytes_FromString( label ); - self->actionHook = action; - self->key = PyBytes_FromString( key ); - self->stateHook = state; - self->subMenu = subMenu; - return 0; - } - - static void MenuItem_dealloc( PyObject* _self ) - { - PyMenuItemObject* self = (PyMenuItemObject*) _self; - - PyLockObject locker; - - Py_XDECREF( self->label ); - Py_XDECREF( self->actionHook ); - Py_XDECREF( self->key ); - Py_XDECREF( self->stateHook ); - Py_XDECREF( self->subMenu ); - - Py_TYPE(self)->tp_free( self ); - } - - static PyMethodDef methods[] = { - { NULL } /* Sentinel */ - }; - - static PyMemberDef members[] = { - { "label", T_OBJECT_EX, offsetof( PyMenuItemObject, label ), 0, - "User visible label" }, - { "actionHook", T_OBJECT_EX, offsetof( PyMenuItemObject, actionHook ), 0, - "Activation callback" }, - { "key", T_OBJECT_EX, offsetof( PyMenuItemObject, actionHook ), 0, - "Accelerator key" }, - { "stateHook", T_OBJECT_EX, offsetof( PyMenuItemObject, stateHook ), 0, - "State callback" }, - { "subMenu", T_OBJECT_EX, offsetof( PyMenuItemObject, subMenu ), 0, - "Sub-menu" }, - { NULL } /* Sentinel */ - }; - - static PyTypeObject type = { - PyVarObject_HEAD_INIT( NULL, 0 ) - "MenuItem", /*tp_name*/ - sizeof( PyMenuItemObject ), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - MenuItem_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash */ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT, /*tp_flags*/ - "Application Menu Item", /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - MenuItem_init, /* tp_init */ - 0, /* tp_alloc */ - MenuItem_new, /* tp_new */ - }; - - PyTypeObject* pyMenuItemType() - { - return &type; - } - - void initPyMenuItemType() - { - // - } - -} // namespace TwkApp +} // namespace TwkApp diff --git a/src/lib/app/PyTwkApp/PyMenuState.cpp b/src/lib/app/PyTwkApp/PyMenuState.cpp index aca1e9e61..71f1249bd 100644 --- a/src/lib/app/PyTwkApp/PyMenuState.cpp +++ b/src/lib/app/PyTwkApp/PyMenuState.cpp @@ -1,9 +1,9 @@ // // Copyright (c) 2011 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// // #include @@ -18,51 +18,51 @@ namespace TwkApp { - using namespace std; - - PyStateFunc::PyStateFunc( PyObject* obj ) - : m_func( obj ), m_exception( false ) - { - PyLockObject locker; - if( obj ) Py_XINCREF( obj ); - } + using namespace std; - PyStateFunc::~PyStateFunc() - { - PyLockObject locker; - if( m_func ) Py_XDECREF( m_func ); - } - - int PyStateFunc::state() - { - PyLockObject locker; - int val = 1; + PyStateFunc::PyStateFunc(PyObject* obj) + : m_func(obj) + , m_exception(false) + { + PyLockObject locker; + if (obj) + Py_XINCREF(obj); + } - if( m_func ) + PyStateFunc::~PyStateFunc() { - PyObject* args = Py_BuildValue( "()" ); - PyObject* r = PyObject_Call( m_func, args, 0 ); - Py_XDECREF( args ); - if( PyErr_Occurred() ) - { - PyErr_Print(); - m_exception = true; - } - else - val = PyLong_AsLong( r ); + PyLockObject locker; + if (m_func) + Py_XDECREF(m_func); } - return val; - } + int PyStateFunc::state() + { + PyLockObject locker; + int val = 1; + + if (m_func) + { + PyObject* args = Py_BuildValue("()"); + PyObject* r = PyObject_Call(m_func, args, 0); + Py_XDECREF(args); + if (PyErr_Occurred()) + { + PyErr_Print(); + m_exception = true; + } + else + val = PyLong_AsLong(r); + } + + return val; + } - bool PyStateFunc::error() const - { - return m_exception; - } + bool PyStateFunc::error() const { return m_exception; } - Menu::StateFunc* PyStateFunc::copy() const - { - return new PyStateFunc( m_func ); - } + Menu::StateFunc* PyStateFunc::copy() const + { + return new PyStateFunc(m_func); + } -} // namespace TwkApp +} // namespace TwkApp diff --git a/src/lib/app/PyTwkApp/PyMu.cpp b/src/lib/app/PyTwkApp/PyMu.cpp index 0855e0d05..921a53f62 100644 --- a/src/lib/app/PyTwkApp/PyMu.cpp +++ b/src/lib/app/PyTwkApp/PyMu.cpp @@ -1,7 +1,7 @@ // -// Copyright (C) 2023 Autodesk, Inc. All Rights Reserved. -// -// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2023 Autodesk, Inc. All Rights Reserved. +// +// SPDX-License-Identifier: Apache-2.0 // #include #include @@ -35,56 +35,54 @@ namespace TwkApp { - using namespace std; + using namespace std; - static Mu::Value pyToMu( PyObject* obj ) - { - return Mu::Value(); - } + static Mu::Value pyToMu(PyObject* obj) { return Mu::Value(); } - /* 'self' is not used */ - static PyObject* mu_eval( PyObject* self, PyObject* args ) - { - PyLockObject locker; - const char* s; - if( !PyArg_ParseTuple( args, "s", &s ) ) return NULL; - Mu::Context::ModuleList modules; - string r = muEval( muContext(), muProcess(), modules, s, "muEval" ); - return Py_BuildValue( "s", r.c_str() ); - } + /* 'self' is not used */ + static PyObject* mu_eval(PyObject* self, PyObject* args) + { + PyLockObject locker; + const char* s; + if (!PyArg_ParseTuple(args, "s", &s)) + return NULL; + Mu::Context::ModuleList modules; + string r = muEval(muContext(), muProcess(), modules, s, "muEval"); + return Py_BuildValue("s", r.c_str()); + } - static PyMethodDef pymu_methods[] = { - {"muEval", mu_eval, METH_VARARGS, - "evaluate mu code -- to be used a fallback only"}, - {NULL, NULL} /* sentinel */ - }; + static PyMethodDef pymu_methods[] = { + {"muEval", mu_eval, METH_VARARGS, + "evaluate mu code -- to be used a fallback only"}, + {NULL, NULL} /* sentinel */ + }; - static struct PyModuleDef moduledef = { - { - 1, /* ob_refcnt */ - NULL, /* ob_type */ - NULL, /* m_init */ - 0, /* m_index */ - NULL, /* m_copy */ - }, - "pymu", /* m_name */ - NULL, /* m_doc */ - -1, /* m_size */ - pymu_methods, /* m_methods */ - NULL, /* m_reload */ - NULL, /* m_traverse */ - NULL, /* m_clear */ - NULL, /* m_free */ - }; + static struct PyModuleDef moduledef = { + { + 1, /* ob_refcnt */ + NULL, /* ob_type */ + NULL, /* m_init */ + 0, /* m_index */ + NULL, /* m_copy */ + }, + "pymu", /* m_name */ + NULL, /* m_doc */ + -1, /* m_size */ + pymu_methods, /* m_methods */ + NULL, /* m_reload */ + NULL, /* m_traverse */ + NULL, /* m_clear */ + NULL, /* m_free */ + }; - PyObject* initPyMu() - { - PyLockObject locker; - PyObject* pymu = PyImport_AddModule( "pymu" ); + PyObject* initPyMu() + { + PyLockObject locker; + PyObject* pymu = PyImport_AddModule("pymu"); - PyModule_Create( &moduledef ); + PyModule_Create(&moduledef); - return pymu; - } + return pymu; + } -} // namespace TwkApp +} // namespace TwkApp diff --git a/src/lib/app/PyTwkApp/PyMuSymbolType.cpp b/src/lib/app/PyTwkApp/PyMuSymbolType.cpp index 4dc265d35..2439e55e7 100644 --- a/src/lib/app/PyTwkApp/PyMuSymbolType.cpp +++ b/src/lib/app/PyTwkApp/PyMuSymbolType.cpp @@ -1,9 +1,9 @@ // // Copyright (c) 2011 Tweak Software. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// // #include #include @@ -51,425 +51,426 @@ namespace TwkApp { - using namespace std; - - Mu::FunctionObject* createFunctionObjectFromPyObject( - const Mu::FunctionType* t, PyObject* pyobj ) - { - PyLockObject locker; - Mu::MuLangContext* c = (Mu::MuLangContext*)t->context(); - Mu::NodeAssembler as( c ); - const Mu::Signature* sig = t->signature(); - size_t nargs = sig->size() - 1; - const Mu::Type* rtype = sig->returnType(); - const Mu::Type* ptype = c->findSymbolOfTypeByQualifiedName( - c->internName( "python.PyObject" ) ); - const Mu::Function* C = c->findSymbolOfTypeByQualifiedName( - c->internName( "python.PyObject_CallObject" ) ); - assert( C ); - assert( ptype ); - - // - // Search for a cast function from PyObject to the type we - // need. If not found throw out of here. - // - - string cname = "to_"; - cname += rtype->name().c_str(); - const Mu::Function* Fcast = - c->findSymbolOfTypeByQualifiedName( - c->internName( cname.c_str() ) ); - - if( Fcast ) - { - bool found = false; + using namespace std; - for( const Mu::Symbol* s = Fcast->firstOverload(); s; - s = s->nextOverload() ) - { - if( const Mu::Function* f = dynamic_cast( s ) ) + Mu::FunctionObject* + createFunctionObjectFromPyObject(const Mu::FunctionType* t, PyObject* pyobj) + { + PyLockObject locker; + Mu::MuLangContext* c = (Mu::MuLangContext*)t->context(); + Mu::NodeAssembler as(c); + const Mu::Signature* sig = t->signature(); + size_t nargs = sig->size() - 1; + const Mu::Type* rtype = sig->returnType(); + const Mu::Type* ptype = c->findSymbolOfTypeByQualifiedName( + c->internName("python.PyObject")); + const Mu::Function* C = + c->findSymbolOfTypeByQualifiedName( + c->internName("python.PyObject_CallObject")); + assert(C); + assert(ptype); + + // + // Search for a cast function from PyObject to the type we + // need. If not found throw out of here. + // + + string cname = "to_"; + cname += rtype->name().c_str(); + const Mu::Function* Fcast = + c->findSymbolOfTypeByQualifiedName( + c->internName(cname.c_str())); + + if (Fcast) { - if( f->returnType() == rtype && f->numArgs() == 1 && - f->argType( 0 ) == ptype ) - { - found = true; - break; - } + bool found = false; + + for (const Mu::Symbol* s = Fcast->firstOverload(); s; + s = s->nextOverload()) + { + if (const Mu::Function* f = + dynamic_cast(s)) + { + if (f->returnType() == rtype && f->numArgs() == 1 + && f->argType(0) == ptype) + { + found = true; + break; + } + } + } + + if (!found) + Fcast = 0; } - } - if( !found ) Fcast = 0; - } + if (!Fcast && rtype != c->voidType()) + { + ostringstream str; + str << "can't create PyCallable thunk which returns " + << rtype->fullyQualifiedName(); + throw invalid_argument(str.str().c_str()); + } - if( !Fcast && rtype != c->voidType() ) - { - ostringstream str; - str << "can't create PyCallable thunk which returns " - << rtype->fullyQualifiedName(); - throw invalid_argument( str.str().c_str() ); - } + // + // Assemble the thunk + // - // - // Assemble the thunk - // + Mu::NodeAssembler::SymbolList params = as.emptySymbolList(); + Mu::FunctionObject* fobj = new Mu::FunctionObject(t); - Mu::NodeAssembler::SymbolList params = as.emptySymbolList(); - Mu::FunctionObject* fobj = new Mu::FunctionObject( t ); + for (size_t i = 0; i < nargs; i++) + { + ostringstream name; + name << "_" << i; + const Mu::Type* argType = sig->argType(i); + params.push_back( + new Mu::ParameterVariable(c, name.str().c_str(), argType)); + } - for( size_t i = 0; i < nargs; i++ ) - { - ostringstream name; - name << "_" << i; - const Mu::Type* argType = sig->argType( i ); - params.push_back( - new Mu::ParameterVariable( c, name.str().c_str(), argType ) ); - } + as.newStackFrame(); - as.newStackFrame(); + Mu::Function* F = 0; - Mu::Function* F = 0; + if (nargs > 0) + { + F = new Mu::Function(c, "__lambda", rtype, nargs, + (Mu::ParameterVariable**)¶ms.front(), 0, + Mu::Function::ContextDependent + | Mu::Function::LambdaExpression); + } + else + { + F = new Mu::Function(c, "__lambda", rtype, 0, 0, 0, + Mu::Function::ContextDependent + | Mu::Function::LambdaExpression); + } - if( nargs > 0 ) - { - F = new Mu::Function( - c, "__lambda", rtype, nargs, (Mu::ParameterVariable**)¶ms.front(), - 0, Mu::Function::ContextDependent | Mu::Function::LambdaExpression ); - } - else - { - F = new Mu::Function( - c, "__lambda", rtype, 0, 0, 0, - Mu::Function::ContextDependent | Mu::Function::LambdaExpression ); - } + as.scope()->addAnonymousSymbol(F); + as.pushScope(F); + as.declareParameters(params); + as.removeSymbolList(params); - as.scope()->addAnonymousSymbol( F ); - as.pushScope( F ); - as.declareParameters( params ); - as.removeSymbolList( params ); + // Mu::Node* root = ... - // Mu::Node* root = ... + // Make a constant for the pyobj + Mu::DataNode* pynode = as.constant(ptype); + pynode->_data._Pointer = pyobj; + Mu::Node* argNode = 0; - // Make a constant for the pyobj - Mu::DataNode* pynode = as.constant( ptype ); - pynode->_data._Pointer = pyobj; - Mu::Node* argNode = 0; + if (nargs > 1) + { + // make a tuple out of the rest of the args + Mu::NodeAssembler::NodeList nl = as.emptyNodeList(); - if( nargs > 1 ) - { - // make a tuple out of the rest of the args - Mu::NodeAssembler::NodeList nl = as.emptyNodeList(); + for (size_t i = 0; i < nargs; i++) + { + nl.push_back(as.dereferenceVariable(F->parameter(i))); + } - for( size_t i = 0; i < nargs; i++ ) - { - nl.push_back( as.dereferenceVariable( F->parameter( i ) ) ); - } + Mu::Node* tnode = as.tupleNode(nl); + as.removeNodeList(nl); + argNode = tnode; + } + else if (nargs == 1) + { + argNode = as.dereferenceVariable(F->parameter(0)); + } + else + { + Mu::DataNode* dn = as.constant(t); // t could be anything as long as + // its a Mu::Class + dn->_data._Pointer = 0; + argNode = dn; + } - Mu::Node* tnode = as.tupleNode( nl ); - as.removeNodeList( nl ); - argNode = tnode; - } - else if( nargs == 1 ) - { - argNode = as.dereferenceVariable( F->parameter( 0 ) ); - } - else - { - Mu::DataNode* dn = as.constant( t ); // t could be anything as long as - // its a Mu::Class - dn->_data._Pointer = 0; - argNode = dn; - } + Mu::NodeAssembler::NodeList nl = as.newNodeList(pynode); + nl.push_back(argNode); + Mu::Node* root = as.callFunction(C, nl); + as.removeNodeList(nl); - Mu::NodeAssembler::NodeList nl = as.newNodeList( pynode ); - nl.push_back( argNode ); - Mu::Node* root = as.callFunction( C, nl ); - as.removeNodeList( nl ); + if (Fcast) + { + nl = as.newNodeList(root); + root = as.callFunction(Fcast, nl); + as.removeNodeList(nl); + } - if( Fcast ) - { - nl = as.newNodeList( root ); - root = as.callFunction( Fcast, nl ); - as.removeNodeList( nl ); - } + int stackSize = as.endStackFrame(); + as.popScope(); + F->stackSize(stackSize); - int stackSize = as.endStackFrame(); - as.popScope(); - F->stackSize( stackSize ); + if (F->hasReturn()) + { + F->setBody(root); + } + else if (Mu::Node* code = as.cast(root, F->returnType())) + { + F->setBody(code); + } + else + { + throw invalid_argument( + "failed to build closue for PyObject because of bad cast"); + } - if( F->hasReturn() ) - { - F->setBody( root ); - } - else if( Mu::Node* code = as.cast( root, F->returnType() ) ) - { - F->setBody( code ); - } - else - { - throw invalid_argument( - "failed to build closue for PyObject because of bad cast" ); + fobj->setFunction(F); + return fobj; } - fobj->setFunction( F ); - return fobj; - } - + static PyObject* MuSymbol_new(PyTypeObject* type, PyObject* args, + PyObject* kwds) + { + PyLockObject locker; + PyMuSymbolObject* self; + if (self = (PyMuSymbolObject*)type->tp_alloc(type, 0)) + { + self->symbol = 0; + self->function = 0; + } - static PyObject* MuSymbol_new( PyTypeObject* type, PyObject* args, - PyObject* kwds ) - { - PyLockObject locker; - PyMuSymbolObject* self; + return (PyObject*)self; + } - if( self = (PyMuSymbolObject*)type->tp_alloc( type, 0 ) ) + int MuSymbol_init(PyObject* _self, PyObject* args, PyObject* kwds) { - self->symbol = 0; - self->function = 0; - } + PyMuSymbolObject* self = (PyMuSymbolObject*)_self; - return (PyObject*)self; - } + PyLockObject locker; + const char* name; - int MuSymbol_init( PyObject* _self, PyObject* args, PyObject* kwds ) - { - PyMuSymbolObject* self = (PyMuSymbolObject*) _self; + int ok = PyArg_ParseTuple(args, "s", &name); + if (!ok) + return -1; - PyLockObject locker; - const char* name; + const Mu::Symbol* symbol = muContext()->findSymbolByQualifiedName( + muContext()->internName(name), true); - int ok = PyArg_ParseTuple( args, "s", &name ); - if( !ok ) return -1; + if (!symbol) + { + vector parts; + boost::algorithm::split(parts, name, boost::is_any_of(string("."))); + if (parts.size() > 1) + { + Mu::Name modname = muContext()->internName(parts[0].c_str()); + Mu::Module::load(modname, muProcess(), muContext()); + symbol = muContext()->findSymbolByQualifiedName( + muContext()->internName(name), true); + } + } - const Mu::Symbol* symbol = muContext()->findSymbolByQualifiedName( - muContext()->internName( name ), true ); + if (!symbol) + { + ostringstream str; + str << "Could not find Mu symbol '" << name << "'" << endl; + PyErr_SetString(PyExc_Exception, str.str().c_str()); + self->symbol = 0; + self->function = 0; + return -1; + } + else + { + self->symbol = symbol; + self->function = dynamic_cast(symbol); + } - if( !symbol ) - { - vector parts; - boost::algorithm::split( parts, name, boost::is_any_of( string( "." ) ) ); - if( parts.size() > 1 ) - { - Mu::Name modname = muContext()->internName( parts[0].c_str() ); - Mu::Module::load( modname, muProcess(), muContext() ); - symbol = muContext()->findSymbolByQualifiedName( - muContext()->internName( name ), true ); - } + return 0; } - if( !symbol ) - { - ostringstream str; - str << "Could not find Mu symbol '" << name << "'" << endl; - PyErr_SetString( PyExc_Exception, str.str().c_str() ); - self->symbol = 0; - self->function = 0; - return -1; - } - else + static void MuSymbol_dealloc(PyObject* self) { - self->symbol = symbol; - self->function = dynamic_cast( symbol ); + PyLockObject locker; + Py_TYPE(self)->tp_free(self); } - return 0; - } - static void MuSymbol_dealloc( PyObject* self ) - { - PyLockObject locker; - Py_TYPE(self)->tp_free(self); - } + //---------------------------------------------------------------------- - //---------------------------------------------------------------------- + static PyObject* MuSymbol_call(PyObject* _self, PyObject* args, + PyObject* kwds) + { - static PyObject* MuSymbol_call( PyObject* _self, PyObject* args, - PyObject* kwds ) - { + PyLockObject locker; + PyMuSymbolObject* self = (PyMuSymbolObject*)_self; - PyLockObject locker; - PyMuSymbolObject* self = (PyMuSymbolObject*) _self; + if (!self->function) + { + PyErr_SetString(PyExc_Exception, + "Mu symbol is not a function -- cannot call"); + return NULL; + } - if( !self->function ) - { - PyErr_SetString( PyExc_Exception, - "Mu symbol is not a function -- cannot call" ); - return NULL; - } + size_t nargs = PyTuple_Size(args); - size_t nargs = PyTuple_Size( args ); + Mu::Function::ArgumentVector muargs(self->function->numArgs()); + size_t i = 0; - Mu::Function::ArgumentVector muargs( self->function->numArgs() ); - size_t i = 0; + // + // Check that caller provided an acceptable number of args. + // + if (nargs > self->function->numArgs() + || nargs < self->function->minimumArgs()) + { + ostringstream str; + str << "Wrong number of arguments (" << nargs << ") to function " + << self->function->fullyQualifiedName() << " -- requires " + << self->function->numArgs() << " or less and at least " + << self->function->minimumArgs() << endl; + + PyErr_SetString(PyExc_Exception, str.str().c_str()); + return NULL; + } - // - // Check that caller provided an acceptable number of args. - // - if( nargs > self->function->numArgs() || - nargs < self->function->minimumArgs() ) - { - ostringstream str; - str << "Wrong number of arguments (" << nargs << ") to function " - << self->function->fullyQualifiedName() << " -- requires " - << self->function->numArgs() << " or less and at least " - << self->function->minimumArgs() << endl; - - PyErr_SetString( PyExc_Exception, str.str().c_str() ); - return NULL; - } + // + // Fill in arg values provided by caller. + // + try + { + for (i = 0; i < nargs; i++) + { + muargs[i] = Mu::PyModule::py2mu(muContext(), muProcess(), + self->function->argType(i), + PyTuple_GetItem(args, i)); + } + } + catch (std::exception& e) + { + ostringstream str; + str << "Bad argument (" << i << ") to function " + << self->function->fullyQualifiedName() << ": " << e.what(); - // - // Fill in arg values provided by caller. - // - try - { - for( i = 0; i < nargs; i++ ) - { - muargs[i] = Mu::PyModule::py2mu( muContext(), muProcess(), - self->function->argType( i ), - PyTuple_GetItem( args, i ) ); - } - } - catch( std::exception& e ) - { - ostringstream str; - str << "Bad argument (" << i << ") to function " - << self->function->fullyQualifiedName() << ": " << e.what(); + PyErr_SetString(PyExc_TypeError, str.str().c_str()); + return NULL; + } - PyErr_SetString( PyExc_TypeError, str.str().c_str() ); - return NULL; - } + // + // Fill in remaining arg values from default values. + // + for (i = nargs; i < self->function->numArgs(); ++i) + { + const Mu::ParameterVariable* p = self->function->parameter(i); + + if (!p->hasDefaultValue()) + { + ostringstream str; + str << "Bad argument (" << i << ") to function " + << self->function->fullyQualifiedName() << ": " + << p->fullyQualifiedName() << " has no default value"; + + PyErr_SetString(PyExc_TypeError, str.str().c_str()); + return NULL; + } + muargs[i] = p->defaultValue(); + } - // - // Fill in remaining arg values from default values. - // - for( i = nargs; i < self->function->numArgs(); ++i ) - { - const Mu::ParameterVariable* p = self->function->parameter( i ); - - if( !p->hasDefaultValue() ) - { - ostringstream str; - str << "Bad argument (" << i << ") to function " - << self->function->fullyQualifiedName() << ": " - << p->fullyQualifiedName() << " has no default value"; - - PyErr_SetString( PyExc_TypeError, str.str().c_str() ); - return NULL; - } - muargs[i] = p->defaultValue(); + try + { + const Mu::Value v = + muAppThread()->call(self->function, muargs, false); + + if (muAppThread()->uncaughtException()) + { + throw true; + } + else + { + return Mu::PyModule::mu2py(muContext(), muProcess(), + self->function->returnType(), v); + } + } + catch (std::exception& exc) + { + ostringstream str; + str << "Exception thrown while calling " + << self->function->fullyQualifiedName(); + + if (const Mu::Object* o = muAppThread()->exception()) + { + str << " -- "; + o->type()->outputValue(str, (Mu::ValuePointer)&o); + } + + str << ", "; + str << exc.what(); + + if (muContext()->debugging()) + { + // Printing the error using cerr right away because the + // exception string does not get displayed. The issue is that + // PyErr_Occurred does not return true and the printing is + // skipped in PyStateFunc::state(). + cerr << "ERROR: " << str.str() << endl; + } + + PyErr_SetString(PyExc_Exception, str.str().c_str()); + return NULL; + } + catch (...) + { + ostringstream str; + str << "Exception thrown while calling " + << self->function->fullyQualifiedName(); + + if (const Mu::Object* o = muAppThread()->exception()) + { + str << " -- "; + o->type()->outputValue(str, (Mu::ValuePointer)&o); + } + + PyErr_SetString(PyExc_Exception, str.str().c_str()); + return NULL; + } } - try + static PyMethodDef methods[] = { + {NULL} /* Sentinel */ + }; + + static PyTypeObject type = { + PyVarObject_HEAD_INIT(NULL, 0) "MuSymbol", /*tp_name*/ + sizeof(PyMuSymbolObject), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + MuSymbol_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + MuSymbol_call, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT, /*tp_flags*/ + "Application Menu Item", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + MuSymbol_init, /* tp_init */ + 0, /* tp_alloc */ + MuSymbol_new, /* tp_new */ + }; + + PyTypeObject* pyMuSymbolType() { return &type; } + + void initPyMuSymbolType() { - const Mu::Value v = muAppThread()->call( self->function, muargs, false ); - - if( muAppThread()->uncaughtException() ) - { - throw true; - } - else - { - return Mu::PyModule::mu2py( muContext(), muProcess(), - self->function->returnType(), v ); - } + // } - catch( std::exception& exc ) - { - ostringstream str; - str << "Exception thrown while calling " - << self->function->fullyQualifiedName(); - - if( const Mu::Object* o = muAppThread()->exception() ) - { - str << " -- "; - o->type()->outputValue( str, (Mu::ValuePointer)&o ); - } - - str << ", "; - str << exc.what(); - - if (muContext()->debugging()) - { - // Printing the error using cerr right away because the exception string does not get - // displayed. The issue is that PyErr_Occurred does not return true and the printing is - // skipped in PyStateFunc::state(). - cerr << "ERROR: " << str.str() << endl; - } - - - PyErr_SetString( PyExc_Exception, str.str().c_str() ); - return NULL; - } - catch( ... ) - { - ostringstream str; - str << "Exception thrown while calling " - << self->function->fullyQualifiedName(); - - if( const Mu::Object* o = muAppThread()->exception() ) - { - str << " -- "; - o->type()->outputValue( str, (Mu::ValuePointer)&o ); - } - - PyErr_SetString( PyExc_Exception, str.str().c_str() ); - return NULL; - } - } - - static PyMethodDef methods[] = { - {NULL} /* Sentinel */ - }; - - static PyTypeObject type = { - PyVarObject_HEAD_INIT(NULL, 0) - "MuSymbol", /*tp_name*/ - sizeof( PyMuSymbolObject ), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - MuSymbol_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash */ - MuSymbol_call, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT, /*tp_flags*/ - "Application Menu Item", /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - MuSymbol_init, /* tp_init */ - 0, /* tp_alloc */ - MuSymbol_new, /* tp_new */ - }; - - PyTypeObject* pyMuSymbolType() - { - return &type; - } - - void initPyMuSymbolType() - { - // - } - -} // namespace TwkApp + +} // namespace TwkApp diff --git a/src/lib/app/PyTwkApp/PyTwkApp/PyCommands.h b/src/lib/app/PyTwkApp/PyTwkApp/PyCommands.h index afcbebfbd..72f855fd5 100644 --- a/src/lib/app/PyTwkApp/PyTwkApp/PyCommands.h +++ b/src/lib/app/PyTwkApp/PyTwkApp/PyCommands.h @@ -1,9 +1,9 @@ // // Copyright (c) 2011 Tweak Software. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// // #ifndef __PyTwkApp__PyCommands__h__ #define __PyTwkApp__PyCommands__h__ @@ -12,8 +12,8 @@ namespace TwkApp { - void pyInitCommands( void* othermethods = 0 ); + void pyInitCommands(void* othermethods = 0); -} // namespace TwkApp +} // namespace TwkApp -#endif // __PyTwkApp__PyCommands__h__ +#endif // __PyTwkApp__PyCommands__h__ diff --git a/src/lib/app/PyTwkApp/PyTwkApp/PyEventType.h b/src/lib/app/PyTwkApp/PyTwkApp/PyEventType.h index 7db1cc0e6..e0b8be613 100644 --- a/src/lib/app/PyTwkApp/PyTwkApp/PyEventType.h +++ b/src/lib/app/PyTwkApp/PyTwkApp/PyEventType.h @@ -1,9 +1,9 @@ // // Copyright (c) 2011 Tweak Software. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// // #ifndef __PyTwkApp__PyEventType__h__ #define __PyTwkApp__PyEventType__h__ @@ -12,25 +12,24 @@ namespace TwkApp { - class Event; - class Document; + class Event; + class Document; - typedef struct - { - PyObject_HEAD - const Event* event; - const Document* document; - } PyEventObject; + typedef struct + { + PyObject_HEAD const Event* event; + const Document* document; + } PyEventObject; - PyTypeObject* pyEventType(); + PyTypeObject* pyEventType(); - void initPyEventType(); + void initPyEventType(); - // - // Create a new event object. The new object has 1 ref on it - // - PyObject* PyEventFromEvent( const Event*, const Document* ); + // + // Create a new event object. The new object has 1 ref on it + // + PyObject* PyEventFromEvent(const Event*, const Document*); -} // namespace TwkApp +} // namespace TwkApp -#endif // __PyTwkApp__PyEventType__h__ +#endif // __PyTwkApp__PyEventType__h__ diff --git a/src/lib/app/PyTwkApp/PyTwkApp/PyFunctionAction.h b/src/lib/app/PyTwkApp/PyTwkApp/PyFunctionAction.h index 509db96e1..19209b141 100644 --- a/src/lib/app/PyTwkApp/PyTwkApp/PyFunctionAction.h +++ b/src/lib/app/PyTwkApp/PyTwkApp/PyFunctionAction.h @@ -1,9 +1,9 @@ //****************************************************************************** // Copyright (c) 2011 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #ifndef __PyTwkApp__PyFunctionAction__h__ #define __PyTwkApp__PyFunctionAction__h__ @@ -13,30 +13,27 @@ namespace TwkApp { - // - // An action which holds a function object and executes on demand. - // + // + // An action which holds a function object and executes on demand. + // - class PyFunctionAction : public Action - { - public: - PyFunctionAction( PyObject* ); - PyFunctionAction( PyObject*, const std::string& docstring ); - virtual ~PyFunctionAction(); - virtual void execute( Document*, const Event& ) const; - virtual Action* copy() const; - virtual bool error() const; - - PyObject* fobj() const + class PyFunctionAction : public Action { - return m_func; - } + public: + PyFunctionAction(PyObject*); + PyFunctionAction(PyObject*, const std::string& docstring); + virtual ~PyFunctionAction(); + virtual void execute(Document*, const Event&) const; + virtual Action* copy() const; + virtual bool error() const; + + PyObject* fobj() const { return m_func; } - private: - PyObject* m_func; - mutable bool m_exception; - }; + private: + PyObject* m_func; + mutable bool m_exception; + }; -} // namespace TwkApp +} // namespace TwkApp -#endif // __PyTwkApp__PyFunctionAction__h__ +#endif // __PyTwkApp__PyFunctionAction__h__ diff --git a/src/lib/app/PyTwkApp/PyTwkApp/PyInterface.h b/src/lib/app/PyTwkApp/PyTwkApp/PyInterface.h index ea3927417..4cc0b11a0 100644 --- a/src/lib/app/PyTwkApp/PyTwkApp/PyInterface.h +++ b/src/lib/app/PyTwkApp/PyTwkApp/PyInterface.h @@ -1,9 +1,9 @@ //****************************************************************************** // Copyright (c) 2011 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #ifndef __PyTwkApp__PyInterface__h__ #define __PyTwkApp__PyInterface__h__ @@ -17,17 +17,17 @@ namespace TwkApp { - class Menu; - class Document; + class Menu; + class Document; - TwkApp::Menu* pyListToMenu( const char* name, void* pyobj ); - void* callPythonFunction( const char* name, const char* module = 0 ); - void disposeOfPythonObject( void* ); - void evalPython( const char* text ); - void initPython( int argc = 0, char** argv = NULL ); - void finalizePython(); - void pyInitWithFile( const char* rcfile, void* commands0, void* commands1 ); + TwkApp::Menu* pyListToMenu(const char* name, void* pyobj); + void* callPythonFunction(const char* name, const char* module = 0); + void disposeOfPythonObject(void*); + void evalPython(const char* text); + void initPython(int argc = 0, char** argv = NULL); + void finalizePython(); + void pyInitWithFile(const char* rcfile, void* commands0, void* commands1); -} // namespace TwkApp +} // namespace TwkApp -#endif // __PyTwkApp__PyInterface__h__ +#endif // __PyTwkApp__PyInterface__h__ diff --git a/src/lib/app/PyTwkApp/PyTwkApp/PyMenuItemType.h b/src/lib/app/PyTwkApp/PyTwkApp/PyMenuItemType.h index 7aa92a355..a9bb2dc3e 100644 --- a/src/lib/app/PyTwkApp/PyTwkApp/PyMenuItemType.h +++ b/src/lib/app/PyTwkApp/PyTwkApp/PyMenuItemType.h @@ -1,9 +1,9 @@ // // Copyright (c) 2011 Tweak Software. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// // #ifndef __PyTwkApp__PyMenuItem__h__ #define __PyTwkApp__PyMenuItem__h__ @@ -11,22 +11,22 @@ namespace TwkApp { - class Event; - class Document; + class Event; + class Document; - typedef struct - { - PyObject_HEAD PyObject* label; - PyObject* actionHook; - PyObject* key; - PyObject* stateHook; - PyObject* subMenu; - } PyMenuItemObject; + typedef struct + { + PyObject_HEAD PyObject* label; + PyObject* actionHook; + PyObject* key; + PyObject* stateHook; + PyObject* subMenu; + } PyMenuItemObject; - PyTypeObject* pyMenuItemType(); + PyTypeObject* pyMenuItemType(); - void initPyMenuItemType(); + void initPyMenuItemType(); -} // namespace TwkApp +} // namespace TwkApp -#endif // __PyTwkApp__PyMenuItem__h__ +#endif // __PyTwkApp__PyMenuItem__h__ diff --git a/src/lib/app/PyTwkApp/PyTwkApp/PyMenuState.h b/src/lib/app/PyTwkApp/PyTwkApp/PyMenuState.h index b8eab2b4f..c77d5c56b 100644 --- a/src/lib/app/PyTwkApp/PyTwkApp/PyMenuState.h +++ b/src/lib/app/PyTwkApp/PyTwkApp/PyMenuState.h @@ -1,9 +1,9 @@ // // Copyright (c) 2011 Tweak Software // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// // #ifndef __PyTwkApp__MenuState__h__ #define __PyTwkApp__MenuState__h__ @@ -12,25 +12,22 @@ namespace TwkApp { - class PyStateFunc : public Menu::StateFunc - { - public: - PyStateFunc( PyObject* ); - virtual ~PyStateFunc(); - virtual int state(); - virtual Menu::StateFunc* copy() const; - virtual bool error() const; - - bool exceptionOccuredLastTime() const + class PyStateFunc : public Menu::StateFunc { - return m_exception; - } + public: + PyStateFunc(PyObject*); + virtual ~PyStateFunc(); + virtual int state(); + virtual Menu::StateFunc* copy() const; + virtual bool error() const; + + bool exceptionOccuredLastTime() const { return m_exception; } - private: - PyObject* m_func; - bool m_exception; - }; + private: + PyObject* m_func; + bool m_exception; + }; -} // namespace TwkApp +} // namespace TwkApp -#endif // __PyTwkApp__MenuState__h__ +#endif // __PyTwkApp__MenuState__h__ diff --git a/src/lib/app/PyTwkApp/PyTwkApp/PyMu.h b/src/lib/app/PyTwkApp/PyTwkApp/PyMu.h index a0278aad7..7a38c0508 100644 --- a/src/lib/app/PyTwkApp/PyTwkApp/PyMu.h +++ b/src/lib/app/PyTwkApp/PyTwkApp/PyMu.h @@ -1,12 +1,12 @@ // // Copyright (c) 2011, Jim Hourihan // All rights reserved. -// -// SPDX-License-Identifier: Apache-2.0 +// +// SPDX-License-Identifier: Apache-2.0 // namespace TwkApp { - PyObject* initPyMu(); + PyObject* initPyMu(); } diff --git a/src/lib/app/PyTwkApp/PyTwkApp/PyMuSymbolType.h b/src/lib/app/PyTwkApp/PyTwkApp/PyMuSymbolType.h index bb528a7e7..895a123bf 100644 --- a/src/lib/app/PyTwkApp/PyTwkApp/PyMuSymbolType.h +++ b/src/lib/app/PyTwkApp/PyTwkApp/PyMuSymbolType.h @@ -1,9 +1,9 @@ // // Copyright (c) 2011 Tweak Software. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// // #ifndef __PyTwkApp__PyMuSymbol__h__ #define __PyTwkApp__PyMuSymbol__h__ @@ -14,26 +14,25 @@ namespace Mu { - class Symbol; - class Function; -} // namespace Mu + class Symbol; + class Function; +} // namespace Mu namespace TwkApp { - class Event; - class Document; + class Event; + class Document; - typedef struct - { - PyObject_HEAD - const Mu::Symbol* symbol; - const Mu::Function* function; - } PyMuSymbolObject; + typedef struct + { + PyObject_HEAD const Mu::Symbol* symbol; + const Mu::Function* function; + } PyMuSymbolObject; - PyTypeObject* pyMuSymbolType(); + PyTypeObject* pyMuSymbolType(); - void initPyMuSymbolType(); + void initPyMuSymbolType(); -} // namespace TwkApp +} // namespace TwkApp -#endif // __PyTwkApp__PyMuSymbol__h__ +#endif // __PyTwkApp__PyMuSymbol__h__ diff --git a/src/lib/app/QTBundle/QTBundle.cpp b/src/lib/app/QTBundle/QTBundle.cpp index efbcf9c3b..863edf17c 100644 --- a/src/lib/app/QTBundle/QTBundle.cpp +++ b/src/lib/app/QTBundle/QTBundle.cpp @@ -1,9 +1,9 @@ //****************************************************************************** -// Copyright (c) 2007 Tweak Inc. +// Copyright (c) 2007 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #include #include @@ -17,580 +17,602 @@ #define SEP ":" #endif -namespace TwkApp { -using namespace std; - -QTBundle::QTBundle(const FileName& appName, - size_t majv, - size_t minv, - size_t revn, - bool unused, - bool sandboxed, - bool inheritedSandbox) - : Bundle(appName, majv, minv, revn, sandboxed, inheritedSandbox), - m_appName(appName.c_str()), - m_initialized(false) +namespace TwkApp { - ostringstream str; - str << majv << "." << minv << "." << revn; - setEnvVar("TWK_APP_VERSION", str.str().c_str(), true); -} + using namespace std; + + QTBundle::QTBundle(const FileName& appName, size_t majv, size_t minv, + size_t revn, bool unused, bool sandboxed, + bool inheritedSandbox) + : Bundle(appName, majv, minv, revn, sandboxed, inheritedSandbox) + , m_appName(appName.c_str()) + , m_initialized(false) + { + ostringstream str; + str << majv << "." << minv << "." << revn; + setEnvVar("TWK_APP_VERSION", str.str().c_str(), true); + } -QTBundle::~QTBundle() -{ -} + QTBundle::~QTBundle() {} -void -QTBundle::initializeAfterQApplication() -{ - if (!m_initialized) init(); -} + void QTBundle::initializeAfterQApplication() + { + if (!m_initialized) + init(); + } -void -QTBundle::init() -{ - m_initialized = true; - m_bin = QCoreApplication::applicationDirPath(); - m_home = QDir::homePath(); - m_root = m_bin; - m_root.cdUp(); - m_scripts = m_root; - m_plugins = m_root; - m_doc = m_root; - m_html = m_root; - m_etc = m_root; - m_ui = m_root; - if (!m_scripts.cd("scripts")) cerr << "WARNING: missing scripts dir in bundle" << endl; - if (!m_plugins.cd("plugins")) cerr << "WARNING: missing plugin dir in bundle" << endl; - - // Note: we do not issue a warning here for a potentially missing 'etc' dir since - // it is optional and is not populated on all platforms like on Linux for example. - m_etc.cd("etc"); + void QTBundle::init() + { + m_initialized = true; + m_bin = QCoreApplication::applicationDirPath(); + m_home = QDir::homePath(); + m_root = m_bin; + m_root.cdUp(); + m_scripts = m_root; + m_plugins = m_root; + m_doc = m_root; + m_html = m_root; + m_etc = m_root; + m_ui = m_root; + if (!m_scripts.cd("scripts")) + cerr << "WARNING: missing scripts dir in bundle" << endl; + if (!m_plugins.cd("plugins")) + cerr << "WARNING: missing plugin dir in bundle" << endl; + + // Note: we do not issue a warning here for a potentially missing 'etc' + // dir since it is optional and is not populated on all platforms like + // on Linux for example. + m_etc.cd("etc"); #ifdef PLATFORM_LINUX - m_homeSupport = m_home; - - if (!m_homeSupport.cd(".rv")) - { m_homeSupport = m_home; - m_homeSupport.mkpath(".rv"); - m_homeSupport.cd(".rv"); - } + + if (!m_homeSupport.cd(".rv")) + { + m_homeSupport = m_home; + m_homeSupport.mkpath(".rv"); + m_homeSupport.cd(".rv"); + } #endif #ifdef PLATFORM_WINDOWS - m_homeSupport = getenv("APPDATA"); - - if (!m_homeSupport.cd("RV")) - { m_homeSupport = getenv("APPDATA"); - m_homeSupport.mkpath("RV"); - m_homeSupport.cd("RV"); - } -#endif - m_pyhome = m_root; - m_pyhome.cd("lib"); - m_pyhome.cd("python" PYTHON_VERSION); - bool setPythonHome = !(getenv("PYTHONHOME") && getenv("RV_ALLOW_SITE_PYTHONHOME")); - if (setPythonHome) setEnvVar("PYTHONHOME", m_root.absolutePath().toUtf8().constData(), true); + if (!m_homeSupport.cd("RV")) + { + m_homeSupport = getenv("APPDATA"); + m_homeSupport.mkpath("RV"); + m_homeSupport.cd("RV"); + } +#endif - bool forceToFront = (!getenv("RV_PYTHONPATH_APPEND_ONLY")); + m_pyhome = m_root; + m_pyhome.cd("lib"); + m_pyhome.cd("python" PYTHON_VERSION); + bool setPythonHome = + !(getenv("PYTHONHOME") && getenv("RV_ALLOW_SITE_PYTHONHOME")); + if (setPythonHome) + setEnvVar("PYTHONHOME", m_root.absolutePath().toUtf8().constData(), + true); + + bool forceToFront = (!getenv("RV_PYTHONPATH_APPEND_ONLY")); + + addPathToEnvVar( + "PYTHONPATH", + m_pyhome.absoluteFilePath("lib-dynload").toUtf8().constData(), + forceToFront); + addPathToEnvVar("PYTHONPATH", + m_pyhome.absolutePath().toUtf8().constData(), + forceToFront); + + if (const char* c = getenv("RV_SUPPORT_PATH")) + { + vector tokens; + stl_ext::tokenize(tokens, c, SEP); - addPathToEnvVar("PYTHONPATH", m_pyhome.absoluteFilePath("lib-dynload").toUtf8().constData(), forceToFront); - addPathToEnvVar("PYTHONPATH", m_pyhome.absolutePath().toUtf8().constData(), forceToFront); + for (size_t i = 0; i < tokens.size(); i++) + { + m_supportPath.push_back(QDir(tokens[i].c_str())); + } - if (const char* c = getenv("RV_SUPPORT_PATH")) - { - vector tokens; - stl_ext::tokenize(tokens, c, SEP); + // + // Add the plugins area if its not in there. Otherwise the app + // might not start. + // - for (size_t i=0; i < tokens.size(); i++) - { - m_supportPath.push_back(QDir(tokens[i].c_str())); + if (!m_supportPath.contains(m_plugins)) + { + m_supportPath.push_back(m_plugins); + } } - - // - // Add the plugins area if its not in there. Otherwise the app - // might not start. - // - - if (!m_supportPath.contains(m_plugins)) + else { + m_supportPath.push_back(m_homeSupport); m_supportPath.push_back(m_plugins); } - } - else - { - m_supportPath.push_back(m_homeSupport); - m_supportPath.push_back(m_plugins); - } - - for (size_t i = 0; i < m_supportPath.size(); i++) - { - QDir& dir = m_supportPath[i]; - // cerr << "supp path " << i << ": '" << dir.absolutePath().toUtf8().constData() << "'" << endl; - if (dir.exists()) + for (size_t i = 0; i < m_supportPath.size(); i++) { - // cerr << " exists" << endl; - QDir profiles(dir.absoluteFilePath("Profiles")); + QDir& dir = m_supportPath[i]; + // cerr << "supp path " << i << ": '" << + // dir.absolutePath().toUtf8().constData() << "'" << endl; - if (!profiles.exists()) + if (dir.exists()) { - static const char* dirs[] = {"Packages", "ImageFormats", "MovieFormats", - "Mu", "SupportFiles", "ConfigFiles", "lib", - "Python", "OIIO", "Nodes", "Profiles", - "Output", "MediaLibrary", - NULL}; + // cerr << " exists" << endl; + QDir profiles(dir.absoluteFilePath("Profiles")); - for (size_t q = 0; dirs[q]; q++) + if (!profiles.exists()) { - QDir d(dir.absoluteFilePath(dirs[q])); - if (!d.exists()) dir.mkdir(dirs[q]); + static const char* dirs[] = {"Packages", "ImageFormats", + "MovieFormats", "Mu", + "SupportFiles", "ConfigFiles", + "lib", "Python", + "OIIO", "Nodes", + "Profiles", "Output", + "MediaLibrary", NULL}; + + for (size_t q = 0; dirs[q]; q++) + { + QDir d(dir.absoluteFilePath(dirs[q])); + if (!d.exists()) + dir.mkdir(dirs[q]); + } } - } - if (dir.exists("Profiles")) - { - addPathToEnvVar("TWK_PROFILE_PLUGIN_PATH", - dir.absoluteFilePath("Profiles").toUtf8().constData()); - } + if (dir.exists("Profiles")) + { + addPathToEnvVar( + "TWK_PROFILE_PLUGIN_PATH", + dir.absoluteFilePath("Profiles").toUtf8().constData()); + } - if (dir.exists("ImageFormats")) - { - addPathToEnvVar("TWK_FB_PLUGIN_PATH", - dir.absoluteFilePath("ImageFormats").toUtf8().constData()); - } + if (dir.exists("ImageFormats")) + { + addPathToEnvVar("TWK_FB_PLUGIN_PATH", + dir.absoluteFilePath("ImageFormats") + .toUtf8() + .constData()); + } - if (dir.exists("Nodes")) - { - addPathToEnvVar("TWK_NODE_PLUGIN_PATH", - dir.absoluteFilePath("Nodes").toUtf8().constData()); - } + if (dir.exists("Nodes")) + { + addPathToEnvVar( + "TWK_NODE_PLUGIN_PATH", + dir.absoluteFilePath("Nodes").toUtf8().constData()); + } - if (dir.exists("OIIO")) - { - addPathToEnvVar("OIIO_LIBRARY_PATH", - dir.absoluteFilePath("OIIO").toUtf8().constData()); - } + if (dir.exists("OIIO")) + { + addPathToEnvVar( + "OIIO_LIBRARY_PATH", + dir.absoluteFilePath("OIIO").toUtf8().constData()); + } - if (dir.exists("Output")) - { - addPathToEnvVar("TWK_OUTPUT_PLUGIN_PATH", - dir.absoluteFilePath("Output").toUtf8().constData()); - } + if (dir.exists("Output")) + { + addPathToEnvVar( + "TWK_OUTPUT_PLUGIN_PATH", + dir.absoluteFilePath("Output").toUtf8().constData()); + } - if (dir.exists("MovieFormats")) - { - addPathToEnvVar("TWK_MOVIE_PLUGIN_PATH", - dir.absoluteFilePath("MovieFormats").toUtf8().constData()); - } + if (dir.exists("MovieFormats")) + { + addPathToEnvVar("TWK_MOVIE_PLUGIN_PATH", + dir.absoluteFilePath("MovieFormats") + .toUtf8() + .constData()); + } - if (dir.exists("Mu")) - { - // cerr << " Mu subdir exists" << endl; - addPathToEnvVar("MU_MODULE_PATH", - dir.absoluteFilePath("Mu").toUtf8().constData()); - } + if (dir.exists("Mu")) + { + // cerr << " Mu subdir exists" << endl; + addPathToEnvVar( + "MU_MODULE_PATH", + dir.absoluteFilePath("Mu").toUtf8().constData()); + } - if (dir.exists("Python")) - { - // cerr << " Mu subdir exists" << endl; - addPathToEnvVar("PYTHONPATH", - dir.absoluteFilePath("Python").toUtf8().constData()); - } + if (dir.exists("Python")) + { + // cerr << " Mu subdir exists" << endl; + addPathToEnvVar( + "PYTHONPATH", + dir.absoluteFilePath("Python").toUtf8().constData()); + } - if (dir.exists("MediaLibrary")) + if (dir.exists("MediaLibrary")) + { + addPathToEnvVar("TWK_MEDIA_LIBRARY_PLUGIN_PATH", + dir.absoluteFilePath("MediaLibrary") + .toUtf8() + .constData()); + addPathToEnvVar("PYTHONPATH", + dir.absoluteFilePath("MediaLibrary") + .toUtf8() + .constData()); + } + } + else { - addPathToEnvVar("TWK_MEDIA_LIBRARY_PLUGIN_PATH", - dir.absoluteFilePath("MediaLibrary").toUtf8().constData()); - addPathToEnvVar("PYTHONPATH", - dir.absoluteFilePath("MediaLibrary").toUtf8().constData()); + m_supportPath.erase(m_supportPath.begin() + i); + i--; } } - else - { - m_supportPath.erase(m_supportPath.begin() + i); - i--; - } - } - - addPathToEnvVar("TWK_APP_SUPPORT_PATH", supportPath()); - // - // On windows, need to add the bin directory to the path so that io/mio - // plugins, which load from subdirectories of the plugins dir, will find - // additional dlls (like jpeg.dll) in the bin directory. - // - #ifdef PLATFORM_WINDOWS - addPathToEnvVar("PATH", m_bin.absolutePath().toUtf8().constData(), true); - #endif -} + addPathToEnvVar("TWK_APP_SUPPORT_PATH", supportPath()); -Bundle::Path -QTBundle::top() -{ - if (!m_initialized) init(); - return Path(m_root.absolutePath().toUtf8().data()); -} +// +// On windows, need to add the bin directory to the path so that io/mio +// plugins, which load from subdirectories of the plugins dir, will find +// additional dlls (like jpeg.dll) in the bin directory. +// +#ifdef PLATFORM_WINDOWS + addPathToEnvVar("PATH", m_bin.absolutePath().toUtf8().constData(), + true); +#endif + } -Bundle::Path -QTBundle::resource(const FileName& name, const FileName& type) -{ - if (!m_initialized) init(); - QString fname(name.c_str()); - fname += "."; - fname += QString(type.c_str()); + Bundle::Path QTBundle::top() + { + if (!m_initialized) + init(); + return Path(m_root.absolutePath().toUtf8().data()); + } - if (type == "pdf") + Bundle::Path QTBundle::resource(const FileName& name, const FileName& type) { - if (m_doc.exists()) + if (!m_initialized) + init(); + QString fname(name.c_str()); + fname += "."; + fname += QString(type.c_str()); + + if (type == "pdf") { + if (m_doc.exists()) + { - QFileInfo file(m_doc.absoluteFilePath(fname)); + QFileInfo file(m_doc.absoluteFilePath(fname)); - if (file.exists() && file.isReadable()) - { - return Path(file.absoluteFilePath().toUtf8().data()); + if (file.exists() && file.isReadable()) + { + return Path(file.absoluteFilePath().toUtf8().data()); + } } } - } - else if (type == "html" || type == "xhtml") - { - if (m_html.exists()) + else if (type == "html" || type == "xhtml") { - QFileInfo file(m_html.absoluteFilePath(fname)); - - if (file.exists() && file.isReadable()) + if (m_html.exists()) { - return Path(file.absoluteFilePath().toUtf8().data()); + QFileInfo file(m_html.absoluteFilePath(fname)); + + if (file.exists() && file.isReadable()) + { + return Path(file.absoluteFilePath().toUtf8().data()); + } } } - } - else if (type == "ui") - { - if (m_ui.exists()) + else if (type == "ui") { - QFileInfo file(m_ui.absoluteFilePath(fname)); - - if (file.exists() && file.isReadable()) + if (m_ui.exists()) { - return Path(file.absoluteFilePath().toUtf8().data()); + QFileInfo file(m_ui.absoluteFilePath(fname)); + + if (file.exists() && file.isReadable()) + { + return Path(file.absoluteFilePath().toUtf8().data()); + } } } - } - // - // Should add images, etc - // + // + // Should add images, etc + // - return Path(); -} + return Path(); + } -Bundle::Path -QTBundle::executableFile(const FileName& name) -{ - if (!m_initialized) init(); - string n = name; + Bundle::Path QTBundle::executableFile(const FileName& name) + { + if (!m_initialized) + init(); + string n = name; #ifdef WIN32 - n += ".exe"; + n += ".exe"; #endif - QFileInfo file(m_bin.absoluteFilePath(n.c_str())); + QFileInfo file(m_bin.absoluteFilePath(n.c_str())); + + if (file.exists() && file.isExecutable()) + { + return file.absoluteFilePath().toUtf8().data(); + } + else + { + return Path(); + } + } - if (file.exists() && file.isExecutable()) + Bundle::Path QTBundle::application(const FileName& name) { - return file.absoluteFilePath().toUtf8().data(); + if (!m_initialized) + init(); + // + // With tweak bundle, there are no other applications, just + // executables. + // + + return executableFile(name); } - else + + Bundle::Path QTBundle::defaultLicense(const FileName& licFileName, + const FileName& type) { - return Path(); + if (!m_initialized) + init(); + QString lic(licFileName.c_str()); + lic += "."; + lic += QString(type.c_str()); + return string(m_etc.absoluteFilePath(lic).toUtf8().data()); } -} -Bundle::Path -QTBundle::application(const FileName& name) -{ - if (!m_initialized) init(); - // - // With tweak bundle, there are no other applications, just - // executables. - // - - return executableFile(name); -} - -Bundle::Path -QTBundle::defaultLicense(const FileName& licFileName, - const FileName& type) -{ - if (!m_initialized) init(); - QString lic(licFileName.c_str()); - lic += "."; - lic += QString(type.c_str()); - return string(m_etc.absoluteFilePath(lic).toUtf8().data()); -} - -Bundle::PathVector -QTBundle::licenseFiles(const FileName& licFileName, - const FileName& type) -{ - if (!m_initialized) init(); - PathVector paths; + Bundle::PathVector QTBundle::licenseFiles(const FileName& licFileName, + const FileName& type) + { + if (!m_initialized) + init(); + PathVector paths; - QList searchPath = m_supportPath; - searchPath.push_back(m_etc); + QList searchPath = m_supportPath; + searchPath.push_back(m_etc); - for (size_t i = 0; i < searchPath.size(); i++) - { - if (searchPath[i].exists()) + for (size_t i = 0; i < searchPath.size(); i++) { - QString lic(licFileName.c_str()); - lic += "."; - lic += QString(type.c_str()); + if (searchPath[i].exists()) + { + QString lic(licFileName.c_str()); + lic += "."; + lic += QString(type.c_str()); - QFileInfo file(searchPath[i].absoluteFilePath(lic)); + QFileInfo file(searchPath[i].absoluteFilePath(lic)); - if (file.exists() && file.isReadable()) - { - paths.push_back(file.absoluteFilePath().toUtf8().data()); + if (file.exists() && file.isReadable()) + { + paths.push_back(file.absoluteFilePath().toUtf8().data()); + } } } - } - Path dpath = defaultLicense(licFileName, type); + Path dpath = defaultLicense(licFileName, type); - if (find(paths.begin(), paths.end(), dpath) == paths.end()) - { - paths.push_back(dpath); - } - - if (paths.empty()) - { - cerr << "WARNING: no license files found" << endl; - } - - return paths; -} + if (find(paths.begin(), paths.end(), dpath) == paths.end()) + { + paths.push_back(dpath); + } -Bundle::Path -QTBundle::rcfile(const FileName& rcfileName, - const FileName& type, - const EnvVar& rcenv) -{ - if (!m_initialized) init(); + if (paths.empty()) + { + cerr << "WARNING: no license files found" << endl; + } - if (const char* e = getenv(rcenv.c_str())) - { - return Path(e); + return paths; } - else - { - QString base = rcfileName.c_str(); - base += "."; - base += type.c_str(); - QString dot = "."; - dot += base; - QFileInfo homeInit(m_home.absoluteFilePath(dot)); + Bundle::Path QTBundle::rcfile(const FileName& rcfileName, + const FileName& type, const EnvVar& rcenv) + { + if (!m_initialized) + init(); - if (homeInit.exists() && homeInit.isReadable()) + if (const char* e = getenv(rcenv.c_str())) { - return Path(homeInit.absoluteFilePath().toUtf8().data()); + return Path(e); } else { - QDir scriptsDir(m_scripts); + QString base = rcfileName.c_str(); + base += "."; + base += type.c_str(); + QString dot = "."; + dot += base; - if (scriptsDir.cd(m_appName)) + QFileInfo homeInit(m_home.absoluteFilePath(dot)); + + if (homeInit.exists() && homeInit.isReadable()) { - QFileInfo initInfo(scriptsDir.absoluteFilePath(base)); - - if (initInfo.exists() && initInfo.isReadable()) + return Path(homeInit.absoluteFilePath().toUtf8().data()); + } + else + { + QDir scriptsDir(m_scripts); + + if (scriptsDir.cd(m_appName)) { - return initInfo.absoluteFilePath().toUtf8().data(); + QFileInfo initInfo(scriptsDir.absoluteFilePath(base)); + + if (initInfo.exists() && initInfo.isReadable()) + { + return initInfo.absoluteFilePath().toUtf8().data(); + } } } } - } - return Path(); -} + return Path(); + } -Bundle::PathVector -QTBundle::supportPath() -{ - PathVector paths; - //paths.push_back(m_homeSupport.absolutePath().toUtf8().data()); - for (size_t i = 0; i < m_supportPath.size(); i++) + Bundle::PathVector QTBundle::supportPath() { - paths.push_back(m_supportPath[i].absolutePath().toUtf8().constData()); + PathVector paths; + // paths.push_back(m_homeSupport.absolutePath().toUtf8().data()); + for (size_t i = 0; i < m_supportPath.size(); i++) + { + paths.push_back( + m_supportPath[i].absolutePath().toUtf8().constData()); + } + + return paths; } - return paths; -} + Bundle::PathVector QTBundle::pluginPath(const DirName& pluginType) + { + if (!m_initialized) + init(); -Bundle::PathVector -QTBundle::pluginPath(const DirName& pluginType) -{ - if (!m_initialized) init(); + PathVector paths; - PathVector paths; + for (size_t i = 0; i < m_supportPath.size(); i++) + { + paths.push_back(m_supportPath[i] + .absoluteFilePath(pluginType.c_str()) + .toUtf8() + .constData()); + } - for (size_t i = 0; i < m_supportPath.size(); i++) - { - paths.push_back(m_supportPath[i].absoluteFilePath(pluginType.c_str()).toUtf8().constData()); + return paths; } - return paths; -} + Bundle::PathVector QTBundle::scriptPath(const DirName& scriptType) + { + if (!m_initialized) + init(); + PathVector paths; + QDir dir(m_scripts); + dir.cd(scriptType.c_str()); -Bundle::PathVector -QTBundle::scriptPath(const DirName& scriptType) -{ - if (!m_initialized) init(); - PathVector paths; - QDir dir(m_scripts); - dir.cd(scriptType.c_str()); + if (dir.exists()) + { + paths.push_back(dir.absolutePath().toUtf8().data()); + } - if (dir.exists()) - { - paths.push_back(dir.absolutePath().toUtf8().data()); + QDir homeScripts(m_homeSupport); + bool homeOK = homeScripts.cd(scriptType.c_str()); + + if (homeOK && homeScripts.exists()) + paths.push_back(homeScripts.absolutePath().toUtf8().data()); + + return paths; } - QDir homeScripts(m_homeSupport); - bool homeOK = homeScripts.cd(scriptType.c_str()); - - if (homeOK && homeScripts.exists()) - paths.push_back(homeScripts.absolutePath().toUtf8().data()); + QTBundle::Path QTBundle::appPluginPath(const DirName& pluginType) + { + if (!m_initialized) + init(); + Path p = m_plugins.absolutePath().toUtf8().constData(); + if (p[p.size() - 1] != '/') + p += "/"; + p += pluginType; + return p; + } - return paths; -} + QTBundle::Path QTBundle::appScriptPath(const DirName& pluginType) + { + if (!m_initialized) + init(); + Path p = m_scripts.absolutePath().toUtf8().constData(); + if (p[p.size() - 1] != '/') + p += "/"; + p += pluginType; + return p; + } -QTBundle::Path -QTBundle::appPluginPath(const DirName& pluginType) -{ - if (!m_initialized) init(); - Path p = m_plugins.absolutePath().toUtf8().constData(); - if (p[p.size()-1] != '/') p += "/"; - p += pluginType; - return p; -} - -QTBundle::Path -QTBundle::appScriptPath(const DirName& pluginType) -{ - if (!m_initialized) init(); - Path p = m_scripts.absolutePath().toUtf8().constData(); - if (p[p.size()-1] != '/') p += "/"; - p += pluginType; - return p; -} - -QTBundle::Path -QTBundle::userCacheDir() -{ - QString s = m_homeSupport.absoluteFilePath("Caches"); - return s.toUtf8().constData(); -} + QTBundle::Path QTBundle::userCacheDir() + { + QString s = m_homeSupport.absoluteFilePath("Caches"); + return s.toUtf8().constData(); + } -void -QTBundle::setEnvVar(const EnvVar& var, const Path& value, bool force) -{ - if (!getenv(var.c_str()) || force) + void QTBundle::setEnvVar(const EnvVar& var, const Path& value, bool force) { + if (!getenv(var.c_str()) || force) + { #ifdef WIN32 - ostringstream es; - es << var << "=" << value; - // - // "::putenv" stopped working on windows, no idea why it - // used to work and now doesn't. Changing to "::_putenv" - // makes it work again. - // - int ret = ::_putenv(es.str().c_str()); - // cerr << "putenv " << es.str() << ", returns " << ret << endl; - // const char *charVar = getenv(var.c_str()); - // string strVar = (charVar) ? charVar : ""; - // cerr << "val is now '" << strVar << "'" << endl; + ostringstream es; + es << var << "=" << value; + // + // "::putenv" stopped working on windows, no idea why it + // used to work and now doesn't. Changing to "::_putenv" + // makes it work again. + // + int ret = ::_putenv(es.str().c_str()); + // cerr << "putenv " << es.str() << ", returns " << ret << endl; + // const char *charVar = getenv(var.c_str()); + // string strVar = (charVar) ? charVar : ""; + // cerr << "val is now '" << strVar << "'" << endl; #else - setenv(var.c_str(), value.c_str(), 1); + setenv(var.c_str(), value.c_str(), 1); #endif + } } -} -void -QTBundle::addPathToEnvVar(const EnvVar& var, const Path& value, bool toHead) -{ - ostringstream str; - const char* envvar = getenv(var.c_str()); - - if (toHead) + void QTBundle::addPathToEnvVar(const EnvVar& var, const Path& value, + bool toHead) { - str << value; - if (envvar) str << SEP << envvar; + ostringstream str; + const char* envvar = getenv(var.c_str()); + + if (toHead) + { + str << value; + if (envvar) + str << SEP << envvar; + } + else + { + if (envvar) + str << envvar << SEP; + str << value; + } + setEnvVar(var, str.str(), true); } - else + + void QTBundle::addPathToEnvVar(const EnvVar& var, const PathVector& value) { - if (envvar) str << envvar << SEP; - str << value; - } - setEnvVar(var, str.str(), true); -} + ostringstream str; + const char* envvar = getenv(var.c_str()); + if (envvar) + str << envvar; -void -QTBundle::addPathToEnvVar(const EnvVar& var, const PathVector& value) -{ - ostringstream str; - const char* envvar = getenv(var.c_str()); - if (envvar) str << envvar; + for (int i = 0; i < value.size(); i++) + { + if (i || envvar) + str << SEP; + str << value[i]; + } - for (int i=0; i < value.size(); i++) - { - if (i || envvar) str << SEP; - str << value[i]; + setEnvVar(var, str.str(), true); } - setEnvVar(var, str.str(), true); -} - -Bundle::FileName -QTBundle::crashLogFile() -{ - return FileName(".tweak_crash_log"); -} + Bundle::FileName QTBundle::crashLogFile() + { + return FileName(".tweak_crash_log"); + } -Bundle::Path -QTBundle::crashLogDirectory() -{ - return getenv("HOME"); -} + Bundle::Path QTBundle::crashLogDirectory() { return getenv("HOME"); } -Bundle::Path -QTBundle::userPluginPath(const DirName& pluginType) -{ - QString s = m_homeSupport.absoluteFilePath(pluginType.c_str()); - return s.toUtf8().constData(); -} + Bundle::Path QTBundle::userPluginPath(const DirName& pluginType) + { + QString s = m_homeSupport.absoluteFilePath(pluginType.c_str()); + return s.toUtf8().constData(); + } -TwkApp::Bundle::FileAccessPermission -QTBundle::permissionForFileAccess(const Path&, bool readonly) const -{ - FileAccessPermission permission; - return permission; -} + TwkApp::Bundle::FileAccessPermission + QTBundle::permissionForFileAccess(const Path&, bool readonly) const + { + FileAccessPermission permission; + return permission; + } -TwkApp::Bundle::AccessObject -QTBundle::beginFileAccessWithPermission(const FileAccessPermission&) const -{ - return AccessObject(0x1); -} + TwkApp::Bundle::AccessObject + QTBundle::beginFileAccessWithPermission(const FileAccessPermission&) const + { + return AccessObject(0x1); + } -void -QTBundle::endFileAccessWithPermission(AccessObject) const -{ - // - // Nothing yet - // -} + void QTBundle::endFileAccessWithPermission(AccessObject) const + { + // + // Nothing yet + // + } -} // TwkApp +} // namespace TwkApp diff --git a/src/lib/app/QTBundle/QTBundle/QTBundle.h b/src/lib/app/QTBundle/QTBundle/QTBundle.h index 29fe1aa4d..6dfae7638 100644 --- a/src/lib/app/QTBundle/QTBundle/QTBundle.h +++ b/src/lib/app/QTBundle/QTBundle/QTBundle.h @@ -1,117 +1,117 @@ //****************************************************************************** -// Copyright (c) 2007 Tweak Inc. +// Copyright (c) 2007 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #ifndef __QTBundle__QTBundle__h__ #define __QTBundle__QTBundle__h__ #include #include -namespace TwkApp { - -// -// QTBundle implements the TwkApp::Bundle API using QT functions. -// The Bundle layout on disk should look like this: -// -// root/ -// bin/ -// the_app_binary -// auxillary_binary -// lib/ -// libs_for_plugins.a -// some_dso.so (could be .dylib) -// plugins/ -// plugins/ -// TwkFB/ (for example) -// TwkMovie/ (for example) -// scripts/ -// rv/ (for example) -// doc/ -// manual.pdf (for example) -// html/ -// index.html (for example) -// etc/ -// license.gto -// ui/ -// preferences.ui -// - -class QTBundle : public Bundle +namespace TwkApp { -public: - QTBundle(const FileName& AppName, - size_t major_version, - size_t minor_version, - size_t revision_number, - bool unused = false, - bool sandboxed = false, - bool inheritedSandbox = false); - virtual ~QTBundle(); // - // Need to call this if no other functions are called. + // QTBundle implements the TwkApp::Bundle API using QT functions. + // The Bundle layout on disk should look like this: + // + // root/ + // bin/ + // the_app_binary + // auxillary_binary + // lib/ + // libs_for_plugins.a + // some_dso.so (could be .dylib) + // plugins/ + // plugins/ + // TwkFB/ (for example) + // TwkMovie/ (for example) + // scripts/ + // rv/ (for example) + // doc/ + // manual.pdf (for example) + // html/ + // index.html (for example) + // etc/ + // license.gto + // ui/ + // preferences.ui // - void initializeAfterQApplication(); + class QTBundle : public Bundle + { + public: + QTBundle(const FileName& AppName, size_t major_version, + size_t minor_version, size_t revision_number, + bool unused = false, bool sandboxed = false, + bool inheritedSandbox = false); + virtual ~QTBundle(); - // - // Bundle API - // + // + // Need to call this if no other functions are called. + // - virtual Path top(); - virtual Path executableFile(const FileName& name); - virtual Path application(const FileName& name); - virtual Path rcfile(const FileName& rcfileName, - const FileName& type, - const EnvVar& rcenv); - virtual Path userPluginPath(const DirName& pluginType); - virtual PathVector pluginPath(const DirName& pluginType); - virtual PathVector scriptPath(const DirName& scriptType); - virtual Path appPluginPath(const DirName& pluginType); - virtual Path appScriptPath(const DirName& pluginType); - virtual Path userCacheDir(); - virtual Path resource(const FileName& name, const FileName& type); - virtual PathVector supportPath(); - virtual PathVector licenseFiles(const FileName& licFileName, - const FileName& type); - virtual Path defaultLicense(const FileName& licFileName, - const FileName& type); - virtual void setEnvVar(const EnvVar& name, const Path& value, bool force=false); - virtual void addPathToEnvVar(const EnvVar& name, const PathVector& value); - virtual void addPathToEnvVar(const EnvVar& name, const Path& value, bool toHead=false); - virtual FileName crashLogFile(); - virtual Path crashLogDirectory(); + void initializeAfterQApplication(); - virtual FileAccessPermission permissionForFileAccess(const Path&, bool readonly) const; - virtual AccessObject beginFileAccessWithPermission(const FileAccessPermission&) const; - virtual void endFileAccessWithPermission(AccessObject) const; + // + // Bundle API + // -private: - void init(); + virtual Path top(); + virtual Path executableFile(const FileName& name); + virtual Path application(const FileName& name); + virtual Path rcfile(const FileName& rcfileName, const FileName& type, + const EnvVar& rcenv); + virtual Path userPluginPath(const DirName& pluginType); + virtual PathVector pluginPath(const DirName& pluginType); + virtual PathVector scriptPath(const DirName& scriptType); + virtual Path appPluginPath(const DirName& pluginType); + virtual Path appScriptPath(const DirName& pluginType); + virtual Path userCacheDir(); + virtual Path resource(const FileName& name, const FileName& type); + virtual PathVector supportPath(); + virtual PathVector licenseFiles(const FileName& licFileName, + const FileName& type); + virtual Path defaultLicense(const FileName& licFileName, + const FileName& type); + virtual void setEnvVar(const EnvVar& name, const Path& value, + bool force = false); + virtual void addPathToEnvVar(const EnvVar& name, + const PathVector& value); + virtual void addPathToEnvVar(const EnvVar& name, const Path& value, + bool toHead = false); + virtual FileName crashLogFile(); + virtual Path crashLogDirectory(); -private: - bool m_initialized; - QString m_appName; - QDir m_bin; - QDir m_home; - QDir m_root; - QDir m_scripts; - QDir m_plugins; - QDir m_doc; - QDir m_html; - QDir m_etc; - QDir m_ui; - QDir m_profiles; - QDir m_homeSupport; - QDir m_pyhome; - QList m_supportPath; -}; + virtual FileAccessPermission + permissionForFileAccess(const Path&, bool readonly) const; + virtual AccessObject + beginFileAccessWithPermission(const FileAccessPermission&) const; + virtual void endFileAccessWithPermission(AccessObject) const; + private: + void init(); -} // TwkApp + private: + bool m_initialized; + QString m_appName; + QDir m_bin; + QDir m_home; + QDir m_root; + QDir m_scripts; + QDir m_plugins; + QDir m_doc; + QDir m_html; + QDir m_etc; + QDir m_ui; + QDir m_profiles; + QDir m_homeSupport; + QDir m_pyhome; + QList m_supportPath; + }; -#endif // __QTBundle__QTBundle__h__ +} // namespace TwkApp +#endif // __QTBundle__QTBundle__h__ diff --git a/src/lib/app/RvApp/CommandsModule.cpp b/src/lib/app/RvApp/CommandsModule.cpp index 6ea82a209..d0f14a220 100644 --- a/src/lib/app/RvApp/CommandsModule.cpp +++ b/src/lib/app/RvApp/CommandsModule.cpp @@ -1,9 +1,9 @@ // // Copyright (c) 2013 Tweak Software // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// // #include #include @@ -79,613 +79,633 @@ TwkUtil::Timer theTimer; -namespace Rv { -using namespace TwkApp; -using namespace TwkAudio; -using namespace TwkMath; -using namespace TwkMovie; -using namespace Mu; -using namespace std; -using namespace TwkContainer; -using namespace TwkUtil; -using namespace IPCore; - -typedef Session::PropertyVector PropertyVector; -typedef TwkApp::EventType::EventInstance Event; - -//---------------------------------------------------------------------- - -static void throwBadArgumentException(const Mu::Node& node, - Mu::Thread& thread, - const Mu::String& msg) +namespace Rv { - const Mu::MuLangContext* context = static_cast(thread.context()); - ExceptionType::Exception *e = new ExceptionType::Exception(context->exceptionType()); + using namespace TwkApp; + using namespace TwkAudio; + using namespace TwkMath; + using namespace TwkMovie; + using namespace Mu; + using namespace std; + using namespace TwkContainer; + using namespace TwkUtil; + using namespace IPCore; - ostringstream str; + typedef Session::PropertyVector PropertyVector; + typedef TwkApp::EventType::EventInstance Event; - if (context->debugging()) + //---------------------------------------------------------------------- + + static void throwBadArgumentException(const Mu::Node& node, + Mu::Thread& thread, + const Mu::String& msg) { - const Mu::AnnotatedNode& anode = static_cast(node); - // When linenum is 0, it indicates that sourceFileName is either empty or not - // null-terminated. This typically occurs when an exception is raised from a Python plugin. - // Despite populating the exception object with relevant information, the text does not - // display in the console for such cases. - if (anode.linenum() > 0) + const Mu::MuLangContext* context = + static_cast(thread.context()); + ExceptionType::Exception* e = + new ExceptionType::Exception(context->exceptionType()); + + ostringstream str; + + if (context->debugging()) { - str << anode.sourceFileName() - << ", line " << anode.linenum() - << ", char " << anode.charnum() - << ": "; + const Mu::AnnotatedNode& anode = + static_cast(node); + // When linenum is 0, it indicates that sourceFileName is either + // empty or not null-terminated. This typically occurs when an + // exception is raised from a Python plugin. Despite populating the + // exception object with relevant information, the text does not + // display in the console for such cases. + if (anode.linenum() > 0) + { + str << anode.sourceFileName() << ", line " << anode.linenum() + << ", char " << anode.charnum() << ": "; + } } - } - str << "in " << node.symbol()->fullyQualifiedName() << ": " << msg; - e->string() = str.str().c_str(); - ProgramException exc(thread, e); - thread.setException(e); - e->setBackTrace(exc); - throw exc; -} + str << "in " << node.symbol()->fullyQualifiedName() << ": " << msg; + e->string() = str.str().c_str(); + ProgramException exc(thread, e); + thread.setException(e); + e->setBackTrace(exc); + throw exc; + } -static void -throwBadProperty(Thread& thread, - const Mu::Node& node, - const Mu::String& name) -{ - Process* process = thread.process(); - MuLangContext* context = static_cast(process->context()); - ExceptionType::Exception *e = new ExceptionType::Exception(context->exceptionType()); + static void throwBadProperty(Thread& thread, const Mu::Node& node, + const Mu::String& name) + { + Process* process = thread.process(); + MuLangContext* context = + static_cast(process->context()); + ExceptionType::Exception* e = + new ExceptionType::Exception(context->exceptionType()); - ostringstream str; + ostringstream str; - if (context->debugging()) - { - const Mu::AnnotatedNode& anode = static_cast(node); - if (anode.linenum() > 0) + if (context->debugging()) { - str << anode.sourceFileName() - << ", line " << anode.linenum() - << ", char " << anode.charnum() - << ": "; + const Mu::AnnotatedNode& anode = + static_cast(node); + if (anode.linenum() > 0) + { + str << anode.sourceFileName() << ", line " << anode.linenum() + << ", char " << anode.charnum() << ": "; + } } - } - str << "invalid property name " << name.c_str(); + str << "invalid property name " << name.c_str(); - e->string() = str.str().c_str(); - thread.setException(e); - ProgramException exc(thread, e); - e->setBackTrace(exc); - throw exc; -} + e->string() = str.str().c_str(); + thread.setException(e); + ProgramException exc(thread, e); + e->setBackTrace(exc); + throw exc; + } -static void -throwBadPropertyType(Thread& thread, - const Mu::Node& node, - const Mu::String& name) -{ - Process* process = thread.process(); - MuLangContext* context = static_cast(process->context()); - ExceptionType::Exception *e = - new ExceptionType::Exception(context->exceptionType()); + static void throwBadPropertyType(Thread& thread, const Mu::Node& node, + const Mu::String& name) + { + Process* process = thread.process(); + MuLangContext* context = + static_cast(process->context()); + ExceptionType::Exception* e = + new ExceptionType::Exception(context->exceptionType()); - ostringstream str; + ostringstream str; - if (context->debugging()) - { - const Mu::AnnotatedNode& anode = static_cast(node); - if (anode.linenum() > 0) + if (context->debugging()) { - str << anode.sourceFileName() - << ", line " << anode.linenum() - << ", char " << anode.charnum() - << ": "; + const Mu::AnnotatedNode& anode = + static_cast(node); + if (anode.linenum() > 0) + { + str << anode.sourceFileName() << ", line " << anode.linenum() + << ", char " << anode.charnum() << ": "; + } } - } - - str << "wrong property type " << name.c_str(); - e->string() = str.str().c_str(); - thread.setException(e); - ProgramException exc(thread, e); - e->setBackTrace(exc); - throw exc; -} + str << "wrong property type " << name.c_str(); + e->string() = str.str().c_str(); + thread.setException(e); + ProgramException exc(thread, e); + e->setBackTrace(exc); + throw exc; + } -static void -getProperty(Session::PropertyVector& props, - Mu::Thread& thread, - const Mu::Node& node, - const Mu::StringType::String* name) -{ - if (!name) throwBadArgumentException(node, thread, "node name is nil"); - - Session* session = Session::currentSession(); - session->findProperty(props, name->c_str()); - if (props.empty()) throwBadProperty(thread, node, name->c_str()); -} + static void getProperty(Session::PropertyVector& props, Mu::Thread& thread, + const Mu::Node& node, + const Mu::StringType::String* name) + { + if (!name) + throwBadArgumentException(node, thread, "node name is nil"); -//---------------------------------------------------------------------- + Session* session = Session::currentSession(); + session->findProperty(props, name->c_str()); + if (props.empty()) + throwBadProperty(thread, node, name->c_str()); + } -Mu::Function* -sessionFunction(const char* name) -{ - USING_MU_FUNCTION_SYMBOLS; - MuLangContext* context = TwkApp::muContext(); - Name n = context->internName(name); - Symbol::SymbolVector symbols = context->findSymbolsOfType(n); + //---------------------------------------------------------------------- - for (int i=0; i < symbols.size(); i++) + Mu::Function* sessionFunction(const char* name) { - Function* F = static_cast(symbols[i]); + USING_MU_FUNCTION_SYMBOLS; + MuLangContext* context = TwkApp::muContext(); + Name n = context->internName(name); + Symbol::SymbolVector symbols = context->findSymbolsOfType(n); - if (F->numArgs() == 0) + for (int i = 0; i < symbols.size(); i++) { - return F; - } - } - - return 0; -} - -//---------------------------------------------------------------------- + Function* F = static_cast(symbols[i]); + if (F->numArgs() == 0) + { + return F; + } + } + return 0; + } -struct FrameBufferFinder -{ - FrameBufferFinder() : fbImage(0) {} - const IPImage* fbImage; + //---------------------------------------------------------------------- - void operator () (IPImage* i) + struct FrameBufferFinder { - if (fbImage) return; - - if (i->destination != IPImage::OutputTexture) + FrameBufferFinder() + : fbImage(0) { - fbImage = i; } - } -}; -NODE_IMPLEMENTATION(getCurrentImageSize, Mu::Vector2f) -{ - Session* s = Session::currentSession(); - Vector2f v; + const IPImage* fbImage; - FrameBufferFinder finder; - foreach_ip ((IPImage*) s->displayImage(), finder); + void operator()(IPImage* i) + { + if (fbImage) + return; - if (const IPImage* i = finder.fbImage) + if (i->destination != IPImage::OutputTexture) + { + fbImage = i; + } + } + }; + + NODE_IMPLEMENTATION(getCurrentImageSize, Mu::Vector2f) { - if (TwkFB::FrameBuffer* fb = i->fb) + Session* s = Session::currentSession(); + Vector2f v; + + FrameBufferFinder finder; + foreach_ip((IPImage*)s->displayImage(), finder); + + if (const IPImage* i = finder.fbImage) { - if (fb->uncrop()) + if (TwkFB::FrameBuffer* fb = i->fb) { - v[0] = fb->uncropWidth(); - v[1] = fb->uncropHeight(); + if (fb->uncrop()) + { + v[0] = fb->uncropWidth(); + v[1] = fb->uncropHeight(); + } + else + { + v[0] = fb->width(); + v[1] = fb->height(); + } } else { - v[0] = fb->width(); - v[1] = fb->height(); + v[0] = i->width; + v[1] = i->height; } } else { - v[0] = i->width; - v[1] = i->height; + v[0] = 0; + v[1] = 0; } - } - else - { - v[0] = 0; - v[1] = 0; - } - NODE_RETURN(v); -} + NODE_RETURN(v); + } + NODE_IMPLEMENTATION(getCurrentNodesOfType, Mu::Pointer) + { + Process* p = NODE_THREAD.process(); + MuLangContext* c = TwkApp::muContext(); + Session* s = Session::currentSession(); + const DynamicArrayType* atype = + reinterpret_cast(NODE_THIS.type()); + const StringType* stype = c->stringType(); + const StringType::String* tname = + NODE_ARG_OBJECT(0, StringType::String); + + if (!tname) + throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil tname"); + + Session::NodeVector nodes; + s->findCurrentNodesByTypeName(nodes, tname->c_str()); + DynamicArray* array = new DynamicArray(atype, 1); + array->resize(nodes.size()); + + for (int i = 0; i < nodes.size(); i++) + { + array->element(i) = + stype->allocate(nodes[i]->name()); + } + NODE_RETURN(array); + } + // + // DEPRECATED (RV-ONLY) CORE COMMANDS + // -NODE_IMPLEMENTATION(getCurrentNodesOfType, Mu::Pointer) -{ - Process* p = NODE_THREAD.process(); - MuLangContext* c = TwkApp::muContext(); - Session* s = Session::currentSession(); - const DynamicArrayType* atype = reinterpret_cast(NODE_THIS.type()); - const StringType* stype = c->stringType(); - const StringType::String* tname = NODE_ARG_OBJECT(0, StringType::String); + NODE_IMPLEMENTATION(sourceMedia, Pointer) + { + Process* p = NODE_THREAD.process(); + MuLangContext* c = TwkApp::muContext(); + Session* s = Session::currentSession(); + const TupleType* ttype = + static_cast(NODE_THIS.type()); + const StringType* stype = + static_cast(ttype->tupleFieldTypes()[0]); + const DynamicArrayType* atype = + static_cast(ttype->tupleFieldTypes()[1]); + const StringType::String* name = NODE_ARG_OBJECT(0, StringType::String); + + if (!name) + { + throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil source"); + } - if (!tname) throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil tname"); + string n = name->c_str(); + string frame = ""; + string mindex = ""; + size_t p0 = n.find('.'); + size_t p1 = n.find('/'); - Session::NodeVector nodes; - s->findCurrentNodesByTypeName(nodes, tname->c_str()); - DynamicArray* array = new DynamicArray(atype, 1); - array->resize(nodes.size()); + struct STuple + { + StringType::String* name; + DynamicArray* layers; + DynamicArray* views; + }; - for (int i=0; i < nodes.size(); i++) - { - array->element(i) = stype->allocate(nodes[i]->name()); - } + ClassInstance* obj = ClassInstance::allocate(ttype); + STuple* tuple = reinterpret_cast(obj->structure()); - NODE_RETURN(array); -} + tuple->views = new DynamicArray(atype, 1); + tuple->layers = new DynamicArray(atype, 1); + if (p0 != string::npos) + { + n = n.substr(0, p0); -// -// DEPRECATED (RV-ONLY) CORE COMMANDS -// + if (p1 != string::npos) + { + mindex = name->utf8().substr(p0 + 1, p1 - p0 - 1).c_str(); + frame = name->utf8().substr(p1 + 1, n.size() - p1 - 1).c_str(); + } + } -NODE_IMPLEMENTATION(sourceMedia, Pointer) -{ - Process* p = NODE_THREAD.process(); - MuLangContext* c = TwkApp::muContext(); - Session* s = Session::currentSession(); - const TupleType* ttype = static_cast(NODE_THIS.type()); - const StringType* stype = static_cast(ttype->tupleFieldTypes()[0]); - const DynamicArrayType* atype = static_cast(ttype->tupleFieldTypes()[1]); - const StringType::String* name = NODE_ARG_OBJECT(0, StringType::String); + SourceIPNode* node = dynamic_cast(s->node(n)); - if (!name) - { - throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil source"); - } + if (!node) + { + throwBadArgumentException(NODE_THIS, NODE_THREAD, + "bad source name"); + } - string n = name->c_str(); - string frame = ""; - string mindex = ""; - size_t p0 = n.find('.'); - size_t p1 = n.find('/'); + size_t index = atoi(mindex.c_str()); + const MovieInfo& info = node->mediaMovieInfo(index); + const string& filename = node->mediaName(index); - struct STuple - { - StringType::String* name; - DynamicArray* layers; - DynamicArray* views; - }; + tuple->name = stype->allocate(filename); + const vector& views = info.views; + const vector& layers = info.layers; - ClassInstance* obj = ClassInstance::allocate(ttype); - STuple* tuple = reinterpret_cast(obj->structure()); + tuple->views->resize(views.size()); + tuple->layers->resize(layers.size()); - tuple->views = new DynamicArray(atype, 1); - tuple->layers = new DynamicArray(atype, 1); + for (unsigned int i = 0; i < views.size(); i++) + { + tuple->views->element(i) = + stype->allocate(views[i]); + } - if (p0 != string::npos) - { - n = n.substr(0,p0); - - if (p1 != string::npos) + for (unsigned int i = 0; i < layers.size(); i++) { - mindex = name->utf8().substr(p0+1, p1 - p0 - 1).c_str(); - frame = name->utf8().substr(p1+1, n.size() - p1-1).c_str(); + tuple->layers->element(i) = + stype->allocate(layers[i]); } - } - SourceIPNode* node = dynamic_cast(s->node(n)); + NODE_RETURN(obj); + } - if (!node) + NODE_IMPLEMENTATION(startTimer, void) { - throwBadArgumentException(NODE_THIS, NODE_THREAD, "bad source name"); + Session* s = Session::currentSession(); + if (s->userTimer().isRunning()) + s->userTimer().stop(); + s->userTimer().start(); } - size_t index = atoi(mindex.c_str()); - const MovieInfo& info = node->mediaMovieInfo(index); - const string& filename = node->mediaName(index); - - tuple->name = stype->allocate(filename); - const vector& views = info.views; - const vector& layers = info.layers; - - tuple->views->resize(views.size()); - tuple->layers->resize(layers.size()); - - for (unsigned int i=0; i < views.size(); i++) + NODE_IMPLEMENTATION(elapsedTime, float) { - tuple->views->element(i) = stype->allocate(views[i]); + Session* s = Session::currentSession(); + NODE_RETURN(float(s->userTimer().elapsed())); } - for (unsigned int i=0; i < layers.size(); i++) + NODE_IMPLEMENTATION(theTime, float) { - tuple->layers->element(i) = stype->allocate(layers[i]); + NODE_RETURN(float(theTimer.elapsed())); } - NODE_RETURN(obj); -} - -NODE_IMPLEMENTATION(startTimer, void) -{ - Session* s = Session::currentSession(); - if (s->userTimer().isRunning()) s->userTimer().stop(); - s->userTimer().start(); -} - -NODE_IMPLEMENTATION(elapsedTime, float) -{ - Session* s = Session::currentSession(); - NODE_RETURN(float(s->userTimer().elapsed())); -} - -NODE_IMPLEMENTATION(theTime, float) -{ - NODE_RETURN(float(theTimer.elapsed())); -} - -NODE_IMPLEMENTATION(stopTimer, float) -{ - Session* s = Session::currentSession(); - NODE_RETURN(float(s->userTimer().stop())); -} - -NODE_IMPLEMENTATION(isTimerRunning, bool) -{ - Session* s = Session::currentSession(); - NODE_RETURN(s->userTimer().isRunning()); -} + NODE_IMPLEMENTATION(stopTimer, float) + { + Session* s = Session::currentSession(); + NODE_RETURN(float(s->userTimer().stop())); + } -NODE_IMPLEMENTATION(setSessionType, void) -{ - Session* s = Session::currentSession(); - int type = NODE_ARG(0, int); - s->setSessionType((Session::SessionType)type); -} + NODE_IMPLEMENTATION(isTimerRunning, bool) + { + Session* s = Session::currentSession(); + NODE_RETURN(s->userTimer().isRunning()); + } -NODE_IMPLEMENTATION(getSessionType, int) -{ - Session* s = Session::currentSession(); - NODE_RETURN(int(s->getSessionType())); -} + NODE_IMPLEMENTATION(setSessionType, void) + { + Session* s = Session::currentSession(); + int type = NODE_ARG(0, int); + s->setSessionType((Session::SessionType)type); + } + NODE_IMPLEMENTATION(getSessionType, int) + { + Session* s = Session::currentSession(); + NODE_RETURN(int(s->getSessionType())); + } -//---------------------------------------------------------------------- -// -// RVSESSION COMMANDS -// + //---------------------------------------------------------------------- + // + // RVSESSION COMMANDS + // -NODE_IMPLEMENTATION(readCDL, void) -{ - Process* p = NODE_THREAD.process(); - const StringType::String* name = NODE_ARG_OBJECT(0, StringType::String); - const StringType::String* node = NODE_ARG_OBJECT(1, StringType::String); - const bool activate = NODE_ARG(2, bool); + NODE_IMPLEMENTATION(readCDL, void) + { + Process* p = NODE_THREAD.process(); + const StringType::String* name = NODE_ARG_OBJECT(0, StringType::String); + const StringType::String* node = NODE_ARG_OBJECT(1, StringType::String); + const bool activate = NODE_ARG(2, bool); + + if (!name) + throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil name"); + if (!node) + throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil node"); + + IPGraph::GraphEdit edit(RvSession::currentRvSession()->graph()); + RvSession::currentRvSession()->readCDL(name->c_str(), node->c_str(), + activate); + } - if (!name) throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil name"); - if (!node) throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil node"); + NODE_IMPLEMENTATION(readLUT, void) + { + Process* p = NODE_THREAD.process(); + const StringType::String* name = NODE_ARG_OBJECT(0, StringType::String); + const StringType::String* node = NODE_ARG_OBJECT(1, StringType::String); + const bool activate = NODE_ARG(2, bool); + + if (!name) + throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil name"); + if (!node) + throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil node"); + + IPGraph::GraphEdit edit(RvSession::currentRvSession()->graph()); + RvSession::currentRvSession()->readLUT(name->c_str(), node->c_str(), + activate); + } - IPGraph::GraphEdit edit(RvSession::currentRvSession()->graph()); - RvSession::currentRvSession()->readCDL(name->c_str(), node->c_str(), activate); -} + NODE_IMPLEMENTATION(updateLUT, void) + { + // No-Op + } -NODE_IMPLEMENTATION(readLUT, void) -{ - Process* p = NODE_THREAD.process(); - const StringType::String* name = NODE_ARG_OBJECT(0, StringType::String); - const StringType::String* node = NODE_ARG_OBJECT(1, StringType::String); - const bool activate = NODE_ARG(2, bool); + NODE_IMPLEMENTATION(exportCurrentSourceFrame, void) + { + RvSession* s = RvSession::currentRvSession(); + StringType::String* name = NODE_ARG_OBJECT(0, StringType::String); + const TwkFB::FrameBuffer* fb = s->currentFB(); - if (!name) throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil name"); - if (!node) throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil node"); + const TwkFB::FrameBuffer* outfb = fb; - IPGraph::GraphEdit edit(RvSession::currentRvSession()->graph()); - RvSession::currentRvSession()->readLUT(name->c_str(), node->c_str(), activate); -} + if (fb->dataType() >= TwkFB::FrameBuffer::PACKED_R10_G10_B10_X2) + { + outfb = convertToLinearRGB709(fb); + } + outfb = copyConvert(outfb, TwkFB::FrameBuffer::HALF); -NODE_IMPLEMENTATION(updateLUT, void) -{ - // No-Op -} + if (!name) + throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil filename"); -NODE_IMPLEMENTATION(exportCurrentSourceFrame, void) -{ - RvSession* s = RvSession::currentRvSession(); - StringType::String* name = NODE_ARG_OBJECT(0, StringType::String); - const TwkFB::FrameBuffer* fb = s->currentFB(); + string filename = name->c_str(); + if (extension(filename) == "") + filename += ".tif"; - const TwkFB::FrameBuffer* outfb = fb; + TwkFB::FrameBufferIO::WriteRequest request; + TwkFB::FrameBufferIO::ConstFrameBufferVector fbs(1); + fbs.front() = outfb; - if (fb->dataType() >= TwkFB::FrameBuffer::PACKED_R10_G10_B10_X2) - { - outfb = convertToLinearRGB709(fb); + try + { + TwkFB::GenericIO::writeImages(fbs, filename, request); + } + catch (...) + { + if (fb != outfb) + delete outfb; + throw; + } } - outfb = copyConvert(outfb, TwkFB::FrameBuffer::HALF); - - if (!name) throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil filename"); - - string filename = name->c_str(); - if (extension(filename) == "") filename += ".tif"; - - TwkFB::FrameBufferIO::WriteRequest request; - TwkFB::FrameBufferIO::ConstFrameBufferVector fbs(1); - fbs.front() = outfb; - - try + NODE_IMPLEMENTATION(exportCurrentFrame, void) { - TwkFB::GenericIO::writeImages(fbs, filename, request); - } - catch (...) - { - if (fb != outfb) delete outfb; - throw; - } -} + StringType::String* name = NODE_ARG_OBJECT(0, StringType::String); + Session* s = Session::currentSession(); + ImageRenderer* renderer = s->renderer(); + const TwkGLF::GLVideoDevice* d = renderer->controlDevice().glDevice; -NODE_IMPLEMENTATION(exportCurrentFrame, void) -{ - StringType::String* name = NODE_ARG_OBJECT(0, StringType::String); - Session* s = Session::currentSession(); - ImageRenderer* renderer = s->renderer(); - const TwkGLF::GLVideoDevice* d = renderer->controlDevice().glDevice; - - if (!name) throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil filename"); + if (!name) + throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil filename"); - string filename = name->c_str(); - if (extension(filename) == "") filename += ".tif"; + string filename = name->c_str(); + if (extension(filename) == "") + filename += ".tif"; - TwkApp::VideoDevice::Margins m = s->eventVideoDevice()->margins(); + TwkApp::VideoDevice::Margins m = s->eventVideoDevice()->margins(); - TwkFB::FrameBuffer* fb = new TwkFB::FrameBuffer(d->width() - m.left - m.right, - d->height() - m.bottom - m.top, - 4, - TwkFB::FrameBuffer::UCHAR); + TwkFB::FrameBuffer* fb = new TwkFB::FrameBuffer( + d->width() - m.left - m.right, d->height() - m.bottom - m.top, 4, + TwkFB::FrameBuffer::UCHAR); - const ImageRenderer::GLFBO* fbo = renderer->newOutputOnlyImageFBO(GL_RGBA8)->fbo(); - renderer->render(s->currentFrame(), s->displayImage()); + const ImageRenderer::GLFBO* fbo = + renderer->newOutputOnlyImageFBO(GL_RGBA8)->fbo(); + renderer->render(s->currentFrame(), s->displayImage()); - glFinish(); + glFinish(); - glReadPixels(m.left, m.bottom, - d->width() - m.left - m.right, - d->height() - m.bottom - m.top, - GL_RGBA, GL_UNSIGNED_BYTE, - fb->pixels()); - - glFinish(); + glReadPixels(m.left, m.bottom, d->width() - m.left - m.right, + d->height() - m.bottom - m.top, GL_RGBA, GL_UNSIGNED_BYTE, + fb->pixels()); - fbo->unbind(); - renderer->releaseImageFBO(fbo); + glFinish(); - TwkFB::FrameBufferIO::WriteRequest request; - TwkFB::FrameBufferIO::ConstFrameBufferVector fbs(1); - fbs.front() = fb; - TwkFB::GenericIO::writeImages(fbs, filename, request); -} + fbo->unbind(); + renderer->releaseImageFBO(fbo); - -NODE_IMPLEMENTATION(newImageSource, Pointer) -{ - RvSession* s = RvSession::currentRvSession(); - Process* p = NODE_THREAD.process(); - MuLangContext* c = static_cast(p->context()); - const StringType* stype = c->stringType(); - StringType::String* name = NODE_ARG_OBJECT(0, StringType::String); - int width = NODE_ARG(1, int); - int height = NODE_ARG(2, int); - int uncropWidth = NODE_ARG(3, int); - int uncropHeight = NODE_ARG(4, int); - int uncropX = NODE_ARG(5, int); - int uncropY = NODE_ARG(6, int); - float pixelAspect = NODE_ARG(7, float); - int channels = NODE_ARG(8, int); - int bits = NODE_ARG(9, int); - bool fp = NODE_ARG(10, bool); - int fs = NODE_ARG(11, int); - int fe = NODE_ARG(12, int); - float fps = NODE_ARG(13, float); - DynamicArray* layers = NODE_ARG_OBJECT(14, DynamicArray); - DynamicArray* views = NODE_ARG_OBJECT(15, DynamicArray); - - if (!name) throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil source name"); - - IPNode::MovieInfo info; - info.width = width; - info.height = height; - info.uncropWidth = uncropWidth; - info.uncropHeight = uncropHeight; - info.uncropX = uncropX; - info.uncropY = uncropY; - info.pixelAspect = pixelAspect; - info.numChannels = channels; - info.fps = fps; - info.start = fs; - info.end = fe; - info.inc = 1; - - switch (bits) - { - case 8: - info.dataType = TwkFB::FrameBuffer::UCHAR; - break; - case 16: - info.dataType = fp ? TwkFB::FrameBuffer::HALF : TwkFB::FrameBuffer::USHORT; - break; - case 32: - info.dataType = TwkFB::FrameBuffer::FLOAT; - break; - } - - if (layers) - { - for (size_t i = 0; i < layers->size(); i++) - { - StringType::String* s = layers->element(i); - info.layers.push_back(s->c_str()); - } + TwkFB::FrameBufferIO::WriteRequest request; + TwkFB::FrameBufferIO::ConstFrameBufferVector fbs(1); + fbs.front() = fb; + TwkFB::GenericIO::writeImages(fbs, filename, request); } - if (views) + NODE_IMPLEMENTATION(newImageSource, Pointer) { - for (size_t i = 0; i < views->size(); i++) + RvSession* s = RvSession::currentRvSession(); + Process* p = NODE_THREAD.process(); + MuLangContext* c = static_cast(p->context()); + const StringType* stype = c->stringType(); + StringType::String* name = NODE_ARG_OBJECT(0, StringType::String); + int width = NODE_ARG(1, int); + int height = NODE_ARG(2, int); + int uncropWidth = NODE_ARG(3, int); + int uncropHeight = NODE_ARG(4, int); + int uncropX = NODE_ARG(5, int); + int uncropY = NODE_ARG(6, int); + float pixelAspect = NODE_ARG(7, float); + int channels = NODE_ARG(8, int); + int bits = NODE_ARG(9, int); + bool fp = NODE_ARG(10, bool); + int fs = NODE_ARG(11, int); + int fe = NODE_ARG(12, int); + float fps = NODE_ARG(13, float); + DynamicArray* layers = NODE_ARG_OBJECT(14, DynamicArray); + DynamicArray* views = NODE_ARG_OBJECT(15, DynamicArray); + + if (!name) + throwBadArgumentException(NODE_THIS, NODE_THREAD, + "nil source name"); + + IPNode::MovieInfo info; + info.width = width; + info.height = height; + info.uncropWidth = uncropWidth; + info.uncropHeight = uncropHeight; + info.uncropX = uncropX; + info.uncropY = uncropY; + info.pixelAspect = pixelAspect; + info.numChannels = channels; + info.fps = fps; + info.start = fs; + info.end = fe; + info.inc = 1; + + switch (bits) { - StringType::String* s = views->element(i); - info.views.push_back(s->c_str()); + case 8: + info.dataType = TwkFB::FrameBuffer::UCHAR; + break; + case 16: + info.dataType = + fp ? TwkFB::FrameBuffer::HALF : TwkFB::FrameBuffer::USHORT; + break; + case 32: + info.dataType = TwkFB::FrameBuffer::FLOAT; + break; } - } - IPGraph::GraphEdit edit(s->graph()); - SourceIPNode* node = s->addImageSource(name->c_str(), info); - StringType::String* nodeName = stype->allocate(node->name()); - NODE_RETURN(nodeName); -} + if (layers) + { + for (size_t i = 0; i < layers->size(); i++) + { + StringType::String* s = layers->element(i); + info.layers.push_back(s->c_str()); + } + } -NODE_IMPLEMENTATION(newImageSourcePixels, Pointer) -{ - RvSession* s = RvSession::currentRvSession(); - Process* p = NODE_THREAD.process(); - MuLangContext* c = static_cast(p->context()); - const StringType* stype = c->stringType(); - StringType::String* source = NODE_ARG_OBJECT(0, StringType::String); - int frame = NODE_ARG(1, int); - StringType::String* layer = NODE_ARG_OBJECT(2, StringType::String); - StringType::String* view = NODE_ARG_OBJECT(3, StringType::String); + if (views) + { + for (size_t i = 0; i < views->size(); i++) + { + StringType::String* s = views->element(i); + info.views.push_back(s->c_str()); + } + } - if (!source) throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil source name"); + IPGraph::GraphEdit edit(s->graph()); + SourceIPNode* node = s->addImageSource(name->c_str(), info); + StringType::String* nodeName = stype->allocate(node->name()); + NODE_RETURN(nodeName); + } - if (IPNode* node = s->graph().findNode(source->c_str())) + NODE_IMPLEMENTATION(newImageSourcePixels, Pointer) { - if (ImageSourceIPNode* imageNode = dynamic_cast(node)) + RvSession* s = RvSession::currentRvSession(); + Process* p = NODE_THREAD.process(); + MuLangContext* c = static_cast(p->context()); + const StringType* stype = c->stringType(); + StringType::String* source = NODE_ARG_OBJECT(0, StringType::String); + int frame = NODE_ARG(1, int); + StringType::String* layer = NODE_ARG_OBJECT(2, StringType::String); + StringType::String* view = NODE_ARG_OBJECT(3, StringType::String); + + if (!source) + throwBadArgumentException(NODE_THIS, NODE_THREAD, + "nil source name"); + + if (IPNode* node = s->graph().findNode(source->c_str())) { - IPGraph::GraphEdit edit(s->graph()); - - Property* p = imageNode->findCreatePixels(frame, - view ? view->c_str() : "-", - layer ? layer->c_str() : "-"); - ostringstream str; - str << name(node) << ".image." << p->name(); - NODE_RETURN(stype->allocate(str)); + if (ImageSourceIPNode* imageNode = + dynamic_cast(node)) + { + IPGraph::GraphEdit edit(s->graph()); + + Property* p = imageNode->findCreatePixels( + frame, view ? view->c_str() : "-", + layer ? layer->c_str() : "-"); + ostringstream str; + str << name(node) << ".image." << p->name(); + NODE_RETURN(stype->allocate(str)); + } } - } - - NODE_RETURN(Pointer(0)); -} -NODE_IMPLEMENTATION(insertCreatePixelBlock, void) -{ - RvSession* s = RvSession::currentRvSession(); - Process* p = NODE_THREAD.process(); - MuLangContext* c = static_cast(p->context()); - Event* event = NODE_ARG_OBJECT(0, Event); + NODE_RETURN(Pointer(0)); + } - if (const PixelBlockTransferEvent* pe = - dynamic_cast(event->event)) + NODE_IMPLEMENTATION(insertCreatePixelBlock, void) { - const RvGraph::Sources& sources = s->rvgraph().imageSources(); + RvSession* s = RvSession::currentRvSession(); + Process* p = NODE_THREAD.process(); + MuLangContext* c = static_cast(p->context()); + Event* event = NODE_ARG_OBJECT(0, Event); - for (size_t i=0; i < sources.size(); i++) + if (const PixelBlockTransferEvent* pe = + dynamic_cast(event->event)) { - if (ImageSourceIPNode* node = - dynamic_cast(sources[i])) - { - size_t index = node->mediaIndex(pe->media()); + const RvGraph::Sources& sources = s->rvgraph().imageSources(); - if (index != size_t(-1)) + for (size_t i = 0; i < sources.size(); i++) + { + if (ImageSourceIPNode* node = + dynamic_cast(sources[i])) { - try + size_t index = node->mediaIndex(pe->media()); + + if (index != size_t(-1)) { + try + { #if 0 cout << "pixel block x,y = " @@ -697,1583 +717,1585 @@ NODE_IMPLEMENTATION(insertCreatePixelBlock, void) << endl; #endif - IPGraph::GraphEdit edit(s->graph()); - - node->insertPixels(pe->view(), - pe->layer(), - pe->frame(), - pe->x(), pe->y(), pe->width(), pe->height(), - pe->pixels(), - pe->size()); - } - catch (PixelBlockSizeMismatchExc& exc) - { - cerr << "ERROR: " << exc.what() << endl; - throwBadArgumentException(NODE_THIS, NODE_THREAD, - "bad pixel block recieved"); + IPGraph::GraphEdit edit(s->graph()); + + node->insertPixels(pe->view(), pe->layer(), + pe->frame(), pe->x(), pe->y(), + pe->width(), pe->height(), + pe->pixels(), pe->size()); + } + catch (PixelBlockSizeMismatchExc& exc) + { + cerr << "ERROR: " << exc.what() << endl; + throwBadArgumentException( + NODE_THIS, NODE_THREAD, + "bad pixel block recieved"); + } } } } } + else + { + throwBadArgumentException(NODE_THIS, NODE_THREAD, "bad event type"); + } } - else + + NODE_IMPLEMENTATION(optionsPlay, int) { - throwBadArgumentException(NODE_THIS, NODE_THREAD, "bad event type"); + Rv::Options& opts = Rv::Options::sharedOptions(); + NODE_RETURN(opts.play); } -} - -NODE_IMPLEMENTATION(optionsPlay, int) -{ - Rv::Options& opts = Rv::Options::sharedOptions(); - NODE_RETURN (opts.play); -} -NODE_IMPLEMENTATION(optionsPlayReset, void) -{ - Rv::Options& opts = Rv::Options::sharedOptions(); - opts.play = 0; -} - -NODE_IMPLEMENTATION(optionsNoPackages, int) -{ - Rv::Options& opts = Rv::Options::sharedOptions(); - NODE_RETURN (opts.noPackages); -} - -NODE_IMPLEMENTATION(optionsProgressiveLoading, int) -{ - Rv::Options& opts = Rv::Options::sharedOptions(); - NODE_RETURN (opts.progressiveSourceLoading); -} + NODE_IMPLEMENTATION(optionsPlayReset, void) + { + Rv::Options& opts = Rv::Options::sharedOptions(); + opts.play = 0; + } -NODE_IMPLEMENTATION(loadTotal, int) -{ - RvSession* s = RvSession::currentRvSession(); - NODE_RETURN(s->loadTotal()); -} + NODE_IMPLEMENTATION(optionsNoPackages, int) + { + Rv::Options& opts = Rv::Options::sharedOptions(); + NODE_RETURN(opts.noPackages); + } -NODE_IMPLEMENTATION(loadCount, int) -{ - RvSession* s = RvSession::currentRvSession(); - NODE_RETURN(s->loadCount()); -} + NODE_IMPLEMENTATION(optionsProgressiveLoading, int) + { + Rv::Options& opts = Rv::Options::sharedOptions(); + NODE_RETURN(opts.progressiveSourceLoading); + } + NODE_IMPLEMENTATION(loadTotal, int) + { + RvSession* s = RvSession::currentRvSession(); + NODE_RETURN(s->loadTotal()); + } -NODE_IMPLEMENTATION(data, Pointer) -{ - RvSession* s = RvSession::currentRvSession(); - if (!s) throwBadArgumentException(NODE_THIS, NODE_THREAD, "No active session available"); - NODE_RETURN(s->data()); -} + NODE_IMPLEMENTATION(loadCount, int) + { + RvSession* s = RvSession::currentRvSession(); + NODE_RETURN(s->loadCount()); + } + NODE_IMPLEMENTATION(data, Pointer) + { + RvSession* s = RvSession::currentRvSession(); + if (!s) + throwBadArgumentException(NODE_THIS, NODE_THREAD, + "No active session available"); + NODE_RETURN(s->data()); + } -NODE_IMPLEMENTATION(sources, Pointer) -{ - RvSession* s = RvSession::currentRvSession(); - Process* p = NODE_THREAD.process(); - MuLangContext* c = static_cast(NODE_THREAD.context()); - DynamicArrayType* type = (DynamicArrayType*)NODE_THIS.type(); - const TupleType* ttype = static_cast(type->elementType()); - - struct STuple - { - StringType::String* name; - int start; - int end; - int inc; - float fps; - bool audio; - bool video; - }; + NODE_IMPLEMENTATION(sources, Pointer) + { + RvSession* s = RvSession::currentRvSession(); + Process* p = NODE_THREAD.process(); + MuLangContext* c = static_cast(NODE_THREAD.context()); + DynamicArrayType* type = (DynamicArrayType*)NODE_THIS.type(); + const TupleType* ttype = + static_cast(type->elementType()); + + struct STuple + { + StringType::String* name; + int start; + int end; + int inc; + float fps; + bool audio; + bool video; + }; - const RvSession::Sources& sources = s->rvgraph().imageSources(); + const RvSession::Sources& sources = s->rvgraph().imageSources(); - DynamicArray* array = new DynamicArray(type, 1); - array->resize(sources.size()); + DynamicArray* array = new DynamicArray(type, 1); + array->resize(sources.size()); - for (int i=0; i < sources.size(); i++) - { - SourceIPNode* source = sources[i]; - ClassInstance* tuple = ClassInstance::allocate(ttype); + for (int i = 0; i < sources.size(); i++) + { + SourceIPNode* source = sources[i]; + ClassInstance* tuple = ClassInstance::allocate(ttype); - STuple* st = reinterpret_cast(tuple->structure()); + STuple* st = reinterpret_cast(tuple->structure()); - if (source) - { - try + if (source) { - const MovieInfo& info = source->mediaMovieInfo(0); - const string& mediaName = source->mediaName(0); - - st->name = c->stringType()->allocate(mediaName); - st->start = info.start; - st->end = info.end; - st->inc = info.inc; - st->fps = info.fps; - st->audio = info.audio; - st->video = info.video; - - array->element(i) = tuple; + try + { + const MovieInfo& info = source->mediaMovieInfo(0); + const string& mediaName = source->mediaName(0); + + st->name = c->stringType()->allocate(mediaName); + st->start = info.start; + st->end = info.end; + st->inc = info.inc; + st->fps = info.fps; + st->audio = info.audio; + st->video = info.video; + + array->element(i) = tuple; + } + catch (...) + { + array->element(i) = NULL; + } } - catch (...) + else { array->element(i) = NULL; } } - else - { - array->element(i) = NULL; - } - } - NODE_RETURN(array); -} - -NODE_IMPLEMENTATION(getCurrentPixelValue, Mu::Vector4f) -{ - RvSession* s = RvSession::currentRvSession(); - - const Vector2f inp = NODE_ARG(0, Vector2f); - const float x = inp[0]; - const float y = inp[1]; + NODE_RETURN(array); + } - if (!s->currentFB()) + NODE_IMPLEMENTATION(getCurrentPixelValue, Mu::Vector4f) { - NODE_RETURN(Mu::Vector4f()); - } + RvSession* s = RvSession::currentRvSession(); - Vector4f p; - const TwkFB::FrameBuffer* fb = s->currentFB(); + const Vector2f inp = NODE_ARG(0, Vector2f); + const float x = inp[0]; + const float y = inp[1]; - const int fbw = fb->width(); - const int fbh = fb->height(); + if (!s->currentFB()) + { + NODE_RETURN(Mu::Vector4f()); + } - const float ia = float(fbw) / float(fbh); - int ix = int(x / ia * fbw); - int iy = int(y * fbh); + Vector4f p; + const TwkFB::FrameBuffer* fb = s->currentFB(); - if (ix < 0) ix = 0; - if (iy < 0) iy = 0; - if (ix >= fbw) ix = fbw - 1; - if (iy >= fbh) iy = fbh - 1; + const int fbw = fb->width(); + const int fbh = fb->height(); - TwkFB::linearRGBA709pixelValue(fb, ix, iy, &p[0]); + const float ia = float(fbw) / float(fbh); + int ix = int(x / ia * fbw); + int iy = int(y * fbh); - NODE_RETURN(p); -} + if (ix < 0) + ix = 0; + if (iy < 0) + iy = 0; + if (ix >= fbw) + ix = fbw - 1; + if (iy >= fbh) + iy = fbh - 1; -NODE_IMPLEMENTATION(getCurrentImageChannelNames, Mu::Pointer) -{ - Process* p = NODE_THREAD.process(); - MuLangContext* c = TwkApp::muContext(); - RvSession* s = RvSession::currentRvSession(); - const DynamicArrayType* atype = reinterpret_cast(NODE_THIS.type()); - const StringType* stype = c->stringType(); + TwkFB::linearRGBA709pixelValue(fb, ix, iy, &p[0]); - if (!s->currentFB()) - { - NODE_RETURN(0); + NODE_RETURN(p); } - const TwkFB::FrameBuffer* fb = s->currentFB(); - - DynamicArray* array = new DynamicArray(atype, 1); - size_t nchannels = 0; - - for (const TwkFB::FrameBuffer* f = fb; f; f = f->nextPlane()) + NODE_IMPLEMENTATION(getCurrentImageChannelNames, Mu::Pointer) { - nchannels += f->numChannels(); - } + Process* p = NODE_THREAD.process(); + MuLangContext* c = TwkApp::muContext(); + RvSession* s = RvSession::currentRvSession(); + const DynamicArrayType* atype = + reinterpret_cast(NODE_THIS.type()); + const StringType* stype = c->stringType(); + + if (!s->currentFB()) + { + NODE_RETURN(0); + } - array->resize(nchannels); + const TwkFB::FrameBuffer* fb = s->currentFB(); - int index = 0; + DynamicArray* array = new DynamicArray(atype, 1); + size_t nchannels = 0; - for (const TwkFB::FrameBuffer* f = fb; f; f = f->nextPlane()) - { - for (int i=0; i < f->numChannels(); i++, index++) + for (const TwkFB::FrameBuffer* f = fb; f; f = f->nextPlane()) { - array->element(index) = - stype->allocate(f->channelName(i)); + nchannels += f->numChannels(); } - } - NODE_RETURN(array); -} + array->resize(nchannels); -NODE_IMPLEMENTATION(getCurrentAttributes, Mu::Pointer) -{ - Process* p = NODE_THREAD.process(); - MuLangContext* c = TwkApp::muContext(); - RvSession* s = RvSession::currentRvSession(); - const DynamicArrayType* atype = reinterpret_cast(NODE_THIS.type()); - const Class* ttype = static_cast(atype->elementType()); - const StringType* stype = c->stringType(); + int index = 0; - if (!s->currentFB()) - { - NODE_RETURN(0); + for (const TwkFB::FrameBuffer* f = fb; f; f = f->nextPlane()) + { + for (int i = 0; i < f->numChannels(); i++, index++) + { + array->element(index) = + stype->allocate(f->channelName(i)); + } + } + + NODE_RETURN(array); } - const TwkFB::FrameBuffer* fb = s->currentFB(); + NODE_IMPLEMENTATION(getCurrentAttributes, Mu::Pointer) + { + Process* p = NODE_THREAD.process(); + MuLangContext* c = TwkApp::muContext(); + RvSession* s = RvSession::currentRvSession(); + const DynamicArrayType* atype = + reinterpret_cast(NODE_THIS.type()); + const Class* ttype = static_cast(atype->elementType()); + const StringType* stype = c->stringType(); + + if (!s->currentFB()) + { + NODE_RETURN(0); + } - const TwkFB::FrameBuffer::AttributeVector& attributes = - fb->attributes(); + const TwkFB::FrameBuffer* fb = s->currentFB(); - struct STuple - { - StringType::String* attrName; - StringType::String* attrValue; - }; + const TwkFB::FrameBuffer::AttributeVector& attributes = + fb->attributes(); - DynamicArray* array = new DynamicArray(atype, 1); - array->resize(attributes.size()); + struct STuple + { + StringType::String* attrName; + StringType::String* attrValue; + }; - for (int i=0; i < attributes.size(); i++) - { - ClassInstance* tuple = ClassInstance::allocate(ttype); - STuple* st = reinterpret_cast(tuple->structure()); - st->attrName = stype->allocate(attributes[i]->name()); - st->attrValue = stype->allocate(attributes[i]->valueAsString()); - - array->element(i) = tuple; - } + DynamicArray* array = new DynamicArray(atype, 1); + array->resize(attributes.size()); - NODE_RETURN(array); -} + for (int i = 0; i < attributes.size(); i++) + { + ClassInstance* tuple = ClassInstance::allocate(ttype); + STuple* st = reinterpret_cast(tuple->structure()); + st->attrName = stype->allocate(attributes[i]->name()); + st->attrValue = stype->allocate(attributes[i]->valueAsString()); -NODE_IMPLEMENTATION(sourceAttributes, Pointer) -{ - Process* p = NODE_THREAD.process(); - MuLangContext* c = TwkApp::muContext(); - RvSession* s = RvSession::currentRvSession(); - const DynamicArrayType* atype = static_cast(NODE_THIS.type()); - const Class* ttype = static_cast(atype->elementType()); - const StringType* stype = c->stringType(); - const StringType::String* name = NODE_ARG_OBJECT(0, StringType::String); - const StringType::String* media = NODE_ARG_OBJECT(1, StringType::String); - - const TwkFB::FrameBuffer* fb = name ? s->currentFB(name->c_str()) - : s->currentFB(); + array->element(i) = tuple; + } - // - // Even if we found an FB above, this source media may have changed since - // the last time it was rendered, in which case the attributes on the FB - // will be out-of-date. So if the caller requested specific media, see if - // we can find it. - // + NODE_RETURN(array); + } - if (media) + NODE_IMPLEMENTATION(sourceAttributes, Pointer) { + Process* p = NODE_THREAD.process(); + MuLangContext* c = TwkApp::muContext(); + RvSession* s = RvSession::currentRvSession(); + const DynamicArrayType* atype = + static_cast(NODE_THIS.type()); + const Class* ttype = static_cast(atype->elementType()); + const StringType* stype = c->stringType(); + const StringType::String* name = NODE_ARG_OBJECT(0, StringType::String); + const StringType::String* media = + NODE_ARG_OBJECT(1, StringType::String); + + const TwkFB::FrameBuffer* fb = + name ? s->currentFB(name->c_str()) : s->currentFB(); + // - // The name doesn't exactly match one of the rendered images + // Even if we found an FB above, this source media may have changed + // since the last time it was rendered, in which case the attributes on + // the FB will be out-of-date. So if the caller requested specific + // media, see if we can find it. // - if (IPNode* node = s->graph().findNode(name->c_str())) + if (media) { - if (SourceIPNode* snode = dynamic_cast(node)) + // + // The name doesn't exactly match one of the rendered images + // + + if (IPNode* node = s->graph().findNode(name->c_str())) { - size_t index = snode->mediaIndex(media->c_str()); - if (index == size_t(-1)) - throwBadArgumentException(NODE_THIS, NODE_THREAD, "bad source name"); - fb = &snode->mediaMovieInfo(index).proxy; + if (SourceIPNode* snode = dynamic_cast(node)) + { + size_t index = snode->mediaIndex(media->c_str()); + if (index == size_t(-1)) + throwBadArgumentException(NODE_THIS, NODE_THREAD, + "bad source name"); + fb = &snode->mediaMovieInfo(index).proxy; + } } } - } - if (!fb) NODE_RETURN(0); + if (!fb) + NODE_RETURN(0); - const TwkFB::FrameBuffer::AttributeVector& attributes = fb->attributes(); + const TwkFB::FrameBuffer::AttributeVector& attributes = + fb->attributes(); - struct STuple - { - const StringType::String* attrName; - const StringType::String* attrValue; - }; + struct STuple + { + const StringType::String* attrName; + const StringType::String* attrValue; + }; - DynamicArray* array = new DynamicArray(atype, 1); - array->resize(attributes.size()); + DynamicArray* array = new DynamicArray(atype, 1); + array->resize(attributes.size()); - for (int i=0; i < attributes.size(); i++) - { - ClassInstance* tuple = ClassInstance::allocate(ttype); - STuple* st = reinterpret_cast(tuple->structure()); - st->attrName = stype->allocate(attributes[i]->name()); - st->attrValue = stype->allocate(attributes[i]->valueAsString()); - - array->element(i) = tuple; - } - - NODE_RETURN(array); -} + for (int i = 0; i < attributes.size(); i++) + { + ClassInstance* tuple = ClassInstance::allocate(ttype); + STuple* st = reinterpret_cast(tuple->structure()); + st->attrName = stype->allocate(attributes[i]->name()); + st->attrValue = stype->allocate(attributes[i]->valueAsString()); -NODE_IMPLEMENTATION(sourceDataAttributes, Pointer) -{ - Process* p = NODE_THREAD.process(); - MuLangContext* c = TwkApp::muContext(); - RvSession* s = RvSession::currentRvSession(); - const DynamicArrayType* atype = static_cast(NODE_THIS.type()); - const TupleType* ttype = static_cast(atype->elementType()); - const DynamicArrayType* btype = static_cast(ttype->tupleFieldTypes()[1]); - const StringType* stype = c->stringType(); - const StringType::String* name = NODE_ARG_OBJECT(0, StringType::String); - const StringType::String* media = NODE_ARG_OBJECT(1, StringType::String); - - const TwkFB::FrameBuffer* fb = name ? s->currentFB(name->c_str()) - : s->currentFB(); + array->element(i) = tuple; + } - // - // Even if we found an FB above, this source media may have changed since - // the last time it was rendered, in which case the attributes on the FB - // will be out-of-date. So if the caller requested specific media, see if - // we can find it. - // + NODE_RETURN(array); + } - if (media) + NODE_IMPLEMENTATION(sourceDataAttributes, Pointer) { + Process* p = NODE_THREAD.process(); + MuLangContext* c = TwkApp::muContext(); + RvSession* s = RvSession::currentRvSession(); + const DynamicArrayType* atype = + static_cast(NODE_THIS.type()); + const TupleType* ttype = + static_cast(atype->elementType()); + const DynamicArrayType* btype = + static_cast(ttype->tupleFieldTypes()[1]); + const StringType* stype = c->stringType(); + const StringType::String* name = NODE_ARG_OBJECT(0, StringType::String); + const StringType::String* media = + NODE_ARG_OBJECT(1, StringType::String); + + const TwkFB::FrameBuffer* fb = + name ? s->currentFB(name->c_str()) : s->currentFB(); + // - // The name doesn't exactly match one of the rendered images + // Even if we found an FB above, this source media may have changed + // since the last time it was rendered, in which case the attributes on + // the FB will be out-of-date. So if the caller requested specific + // media, see if we can find it. // - if (IPNode* node = s->graph().findNode(name->c_str())) + if (media) { - if (SourceIPNode* snode = dynamic_cast(node)) + // + // The name doesn't exactly match one of the rendered images + // + + if (IPNode* node = s->graph().findNode(name->c_str())) { - size_t index = snode->mediaIndex(media->c_str()); - if (index == size_t(-1)) - throwBadArgumentException(NODE_THIS, NODE_THREAD, "bad source name"); - fb = &snode->mediaMovieInfo(index).proxy; + if (SourceIPNode* snode = dynamic_cast(node)) + { + size_t index = snode->mediaIndex(media->c_str()); + if (index == size_t(-1)) + throwBadArgumentException(NODE_THIS, NODE_THREAD, + "bad source name"); + fb = &snode->mediaMovieInfo(index).proxy; + } } } - } - if (!fb) NODE_RETURN(0); + if (!fb) + NODE_RETURN(0); - const TwkFB::FrameBuffer::AttributeVector& attributes = fb->attributes(); - - struct STuple - { - const StringType::String* attrName; - const DynamicArray* attrValue; - }; + const TwkFB::FrameBuffer::AttributeVector& attributes = + fb->attributes(); - int count = 0; - - for (int i=0; i < attributes.size(); i++) - { - if (TwkFB::DataContainerAttribute* da = - dynamic_cast(attributes[i])) + struct STuple { - count++; - } - } + const StringType::String* attrName; + const DynamicArray* attrValue; + }; - DynamicArray* array = new DynamicArray(atype, 1); // 1-dimensional - array->resize(count); + int count = 0; - for (int i=0, c=0; i < attributes.size(); i++) - { - if (TwkFB::DataContainerAttribute* da = - dynamic_cast(attributes[i])) + for (int i = 0; i < attributes.size(); i++) { - ClassInstance* tuple = ClassInstance::allocate(ttype); - STuple* st = reinterpret_cast(tuple->structure()); - st->attrName = stype->allocate(da->name()); - - DynamicArray* barray = new DynamicArray(btype, 1); // 1-dimensional - const TwkFB::DataContainer* data = da->dataContainer(); - const size_t n = data->size(); - - barray->resize(n); - - for (int q = 0; q < n; q++) + if (TwkFB::DataContainerAttribute* da = + dynamic_cast(attributes[i])) { - barray->element(q) = (*data)[q]; + count++; } - - st->attrValue = barray; - array->element(c) = tuple; - c++; } - } - - NODE_RETURN(array); -} + DynamicArray* array = new DynamicArray(atype, 1); // 1-dimensional + array->resize(count); -NODE_IMPLEMENTATION(sourcePixelValue, Mu::Vector4f) -{ - MuLangContext* c = TwkApp::muContext(); - RvSession* s = RvSession::currentRvSession(); - const StringType::String* name = NODE_ARG_OBJECT(0, StringType::String); - float x = NODE_ARG(1, float); - float y = NODE_ARG(2, float); - - Mu::Vector4f p; - p[0] = 0; - p[1] = 0; - p[2] = 0; - p[3] = 0; + for (int i = 0, c = 0; i < attributes.size(); i++) + { + if (TwkFB::DataContainerAttribute* da = + dynamic_cast(attributes[i])) + { + ClassInstance* tuple = ClassInstance::allocate(ttype); + STuple* st = reinterpret_cast(tuple->structure()); + st->attrName = stype->allocate(da->name()); - const TwkFB::FrameBuffer* fb = name ? s->currentFB(name->c_str()) - : s->currentFB(); + DynamicArray* barray = + new DynamicArray(btype, 1); // 1-dimensional + const TwkFB::DataContainer* data = da->dataContainer(); + const size_t n = data->size(); - if (fb && fb->uncrop()) - { - // - // Handle the case of an uncropped image. Reorient the coordinate - // offsets based on the FB orientation. The uncrop x and y values - // are always measured from the bottom left. - // + barray->resize(n); - double offsetX = fb->uncropX(); - double offsetY = fb->uncropY(); - int orientation = fb->orientation(); - if (orientation == TwkFB::FrameBuffer::BOTTOMRIGHT || - orientation == TwkFB::FrameBuffer::TOPRIGHT) - offsetX = double(fb->uncropWidth()) - double(fb->width()) - double(fb->uncropX()); - if (orientation == TwkFB::FrameBuffer::TOPLEFT || - orientation == TwkFB::FrameBuffer::TOPRIGHT) - offsetY = double(fb->uncropHeight()) - double(fb->height()) - double(fb->uncropY()); + for (int q = 0; q < n; q++) + { + barray->element(q) = (*data)[q]; + } - const double w = double(fb->width()); - const double h = double(fb->height()); - const double cx0 = double(offsetX) / double(fb->uncropWidth()); - const double cy0 = double(offsetY) / double(fb->uncropHeight()); - const double cx1 = double(offsetX + fb->width()) / double(fb->uncropWidth()); - const double cy1 = double(offsetY + fb->height()) / double(fb->uncropHeight()); - const double cw = cx1 - cx0; - const double ch = cy1 - cy0; + st->attrValue = barray; + array->element(c) = tuple; + c++; + } + } - x = (double(x) / double(fb->uncropWidth()) - cx0) / cw * (fb->width() - 1); - y = (double(y) / double(fb->uncropHeight()) - cy0) / ch * (fb->height() - 1); + NODE_RETURN(array); } - // Because of tiling, we can obtain x/y coordinates that are in the full-FB - // range. But they are always in the "high range" (ie.: upper-right tile) so - // converting them to relative coords work. - x = static_cast(x+0.5f) % fb->width(); - y = static_cast(y+0.5f) % fb->height(); - - if (!fb || x >= fb->width() || y >= fb->height() || x < 0 || y < 0) + NODE_IMPLEMENTATION(sourcePixelValue, Mu::Vector4f) { - return p; - } - - TwkFB::linearRGBA709pixelValue(fb, int(x), int(y), &p[0]); - NODE_RETURN(p); -} - -NODE_IMPLEMENTATION(sourceDisplayChannelNames, Mu::Pointer) -{ - Process* p = NODE_THREAD.process(); - MuLangContext* c = TwkApp::muContext(); - RvSession* s = RvSession::currentRvSession(); - const StringType::String* name = NODE_ARG_OBJECT(0, StringType::String); - const DynamicArrayType* atype = reinterpret_cast(NODE_THIS.type()); - const StringType* stype = c->stringType(); + MuLangContext* c = TwkApp::muContext(); + RvSession* s = RvSession::currentRvSession(); + const StringType::String* name = NODE_ARG_OBJECT(0, StringType::String); + float x = NODE_ARG(1, float); + float y = NODE_ARG(2, float); + + Mu::Vector4f p; + p[0] = 0; + p[1] = 0; + p[2] = 0; + p[3] = 0; + + const TwkFB::FrameBuffer* fb = + name ? s->currentFB(name->c_str()) : s->currentFB(); + + if (fb && fb->uncrop()) + { + // + // Handle the case of an uncropped image. Reorient the coordinate + // offsets based on the FB orientation. The uncrop x and y values + // are always measured from the bottom left. + // + + double offsetX = fb->uncropX(); + double offsetY = fb->uncropY(); + int orientation = fb->orientation(); + if (orientation == TwkFB::FrameBuffer::BOTTOMRIGHT + || orientation == TwkFB::FrameBuffer::TOPRIGHT) + offsetX = double(fb->uncropWidth()) - double(fb->width()) + - double(fb->uncropX()); + if (orientation == TwkFB::FrameBuffer::TOPLEFT + || orientation == TwkFB::FrameBuffer::TOPRIGHT) + offsetY = double(fb->uncropHeight()) - double(fb->height()) + - double(fb->uncropY()); + + const double w = double(fb->width()); + const double h = double(fb->height()); + const double cx0 = double(offsetX) / double(fb->uncropWidth()); + const double cy0 = double(offsetY) / double(fb->uncropHeight()); + const double cx1 = + double(offsetX + fb->width()) / double(fb->uncropWidth()); + const double cy1 = + double(offsetY + fb->height()) / double(fb->uncropHeight()); + const double cw = cx1 - cx0; + const double ch = cy1 - cy0; + + x = (double(x) / double(fb->uncropWidth()) - cx0) / cw + * (fb->width() - 1); + y = (double(y) / double(fb->uncropHeight()) - cy0) / ch + * (fb->height() - 1); + } - const TwkFB::FrameBuffer* fb = name ? s->currentFB(name->c_str()) - : s->currentFB(); + // Because of tiling, we can obtain x/y coordinates that are in the + // full-FB range. But they are always in the "high range" (ie.: + // upper-right tile) so converting them to relative coords work. + x = static_cast(x + 0.5f) % fb->width(); + y = static_cast(y + 0.5f) % fb->height(); - if (!fb) NODE_RETURN(0); + if (!fb || x >= fb->width() || y >= fb->height() || x < 0 || y < 0) + { + return p; + } - DynamicArray* array = new DynamicArray(atype, 1); - size_t nchannels = 0; + TwkFB::linearRGBA709pixelValue(fb, int(x), int(y), &p[0]); + NODE_RETURN(p); + } - for (const TwkFB::FrameBuffer* f = fb; f; f = f->nextPlane()) + NODE_IMPLEMENTATION(sourceDisplayChannelNames, Mu::Pointer) { - nchannels += f->numChannels(); - } + Process* p = NODE_THREAD.process(); + MuLangContext* c = TwkApp::muContext(); + RvSession* s = RvSession::currentRvSession(); + const StringType::String* name = NODE_ARG_OBJECT(0, StringType::String); + const DynamicArrayType* atype = + reinterpret_cast(NODE_THIS.type()); + const StringType* stype = c->stringType(); - array->resize(nchannels); + const TwkFB::FrameBuffer* fb = + name ? s->currentFB(name->c_str()) : s->currentFB(); - int index = 0; + if (!fb) + NODE_RETURN(0); - for (const TwkFB::FrameBuffer* f = fb; f; f = f->nextPlane()) - { - for (int i=0; i < f->numChannels(); i++, index++) + DynamicArray* array = new DynamicArray(atype, 1); + size_t nchannels = 0; + + for (const TwkFB::FrameBuffer* f = fb; f; f = f->nextPlane()) { - array->element(index) = stype->allocate(f->channelName(i)); + nchannels += f->numChannels(); } - } - NODE_RETURN(array); -} + array->resize(nchannels); -NODE_IMPLEMENTATION(addSource, void) -{ - Session* s = RvSession::currentRvSession(); - const StringType::String* source = NODE_ARG_OBJECT(0, StringType::String); - const StringType::String* tag = NODE_ARG_OBJECT(1, StringType::String); + int index = 0; - if (!source) throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil source"); - - Document::ReadRequest request; - request.setOption("tag", string(tag ? tag->c_str() : "")); - request.setOption("append", true); + for (const TwkFB::FrameBuffer* f = fb; f; f = f->nextPlane()) + { + for (int i = 0; i < f->numChannels(); i++, index++) + { + array->element(index) = + stype->allocate(f->channelName(i)); + } + } - IPGraph::GraphEdit edit(s->graph()); - s->read(source->c_str(), request); - s->askForRedraw(); -} + NODE_RETURN(array); + } -NODE_IMPLEMENTATION(addSourceMulti, void) -{ - RvSession* s = RvSession::currentRvSession(); - DynamicArray* array = NODE_ARG_OBJECT(0, DynamicArray); - StringType::String* muTag = NODE_ARG_OBJECT(1, StringType::String); - string tag = (muTag) ? muTag->c_str() : ""; - - vector files; - - for (size_t i = 0; i < array->size(); i++) - files.push_back(array->element(i)->c_str()); - - IPGraph::GraphEdit edit(s->graph()); - s->addSourceWithTag (files, tag); - s->askForRedraw(); -} - -NODE_IMPLEMENTATION(addSourceVerbose, Pointer) -{ - RvSession* s = RvSession::currentRvSession(); - DynamicArray* array = NODE_ARG_OBJECT(0, DynamicArray); - StringType::String* muTag = NODE_ARG_OBJECT(1, StringType::String); - string tag = (muTag) ? muTag->c_str() : ""; - Process* p = NODE_THREAD.process(); - MuLangContext* c = static_cast(p->context()); - const StringType* stype = c->stringType(); + NODE_IMPLEMENTATION(addSource, void) + { + Session* s = RvSession::currentRvSession(); + const StringType::String* source = + NODE_ARG_OBJECT(0, StringType::String); + const StringType::String* tag = NODE_ARG_OBJECT(1, StringType::String); - vector filesAndOptions; - filesAndOptions.reserve(array->size()); - for (size_t i = 0; i < array->size(); i++) - filesAndOptions.emplace_back(array->element(i)->c_str()); + if (!source) + throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil source"); - IPGraph::GraphEdit edit(s->graph()); + Document::ReadRequest request; + request.setOption("tag", string(tag ? tag->c_str() : "")); + request.setOption("append", true); - if(Options::sharedOptions().delaySessionLoading){ - s->userGenericEvent("before-progressive-loading", ""); - - // Note: It was decided to trigger the before-progressive-proxy-loading - // event even when progressive source loading is disabled - s->userGenericEvent("before-progressive-proxy-loading", ""); + IPGraph::GraphEdit edit(s->graph()); + s->read(source->c_str(), request); + s->askForRedraw(); } - SourceIPNode* node = s->addSourceWithTag (filesAndOptions, tag); - - if(Options::sharedOptions().delaySessionLoading) + NODE_IMPLEMENTATION(addSourceMulti, void) { - // Note: It was decided to trigger the after-progressive-proxy-loading - // event even when progressive source loading is disabled - s->userGenericEvent("after-progressive-proxy-loading", ""); + RvSession* s = RvSession::currentRvSession(); + DynamicArray* array = NODE_ARG_OBJECT(0, DynamicArray); + StringType::String* muTag = NODE_ARG_OBJECT(1, StringType::String); + string tag = (muTag) ? muTag->c_str() : ""; - if (!Options::sharedOptions().progressiveSourceLoading) - { - s->userGenericEvent("after-progressive-loading", ""); - } - } - - s->askForRedraw(); + vector files; - StringType::String* nodeName = stype->allocate(node->name()); - NODE_RETURN(nodeName); -} + for (size_t i = 0; i < array->size(); i++) + files.push_back(array->element(i)->c_str()); -NODE_IMPLEMENTATION(addSources, void) -{ - RvSession* s = RvSession::currentRvSession(); - DynamicArray* array = NODE_ARG_OBJECT(0, DynamicArray); - StringType::String* muTag = NODE_ARG_OBJECT(1, StringType::String); - bool processOpts = NODE_ARG(2, bool); - bool merge = NODE_ARG(3, bool); - string tag = (muTag) ? muTag->c_str() : ""; + IPGraph::GraphEdit edit(s->graph()); + s->addSourceWithTag(files, tag); + s->askForRedraw(); + } - vector sargs; - - for (size_t i = 0; i < array->size(); i++) + NODE_IMPLEMENTATION(addSourceVerbose, Pointer) { - string arg = array->element(i)->c_str(); - sargs.push_back(IPCore::Application::mapFromVar(arg)); - } + RvSession* s = RvSession::currentRvSession(); + DynamicArray* array = NODE_ARG_OBJECT(0, DynamicArray); + StringType::String* muTag = NODE_ARG_OBJECT(1, StringType::String); + string tag = (muTag) ? muTag->c_str() : ""; + Process* p = NODE_THREAD.process(); + MuLangContext* c = static_cast(p->context()); + const StringType* stype = c->stringType(); - // - // Note we do not make GraphEdit object here, since this load will be - // asynchronous. - // + vector filesAndOptions; + filesAndOptions.reserve(array->size()); + for (size_t i = 0; i < array->size(); i++) + filesAndOptions.emplace_back( + array->element(i)->c_str()); - s->readUnorganizedFileList (sargs, processOpts, merge, tag); - s->askForRedraw(); -} + IPGraph::GraphEdit edit(s->graph()); -NODE_IMPLEMENTATION(addSourcesVerbose, Pointer) -{ - RvSession* s = RvSession::currentRvSession(); - DynamicArray* array = NODE_ARG_OBJECT(0, DynamicArray); - const DynamicArrayType* atype = reinterpret_cast(NODE_THIS.type()); - StringType::String* muTag = NODE_ARG_OBJECT(1, StringType::String); - string tag = (muTag) ? muTag->c_str() : ""; - MuLangContext* c = TwkApp::muContext(); - const StringType* stype = c->stringType(); - - DynamicArray* names = new DynamicArray(atype, 1); - names->resize(array->size()); - IPGraph::GraphEdit edit(s->graph()); - - if(Options::sharedOptions().delaySessionLoading){ - s->userGenericEvent("before-progressive-loading", ""); - - // Note: It was decided to trigger the before-progressive-proxy-loading - // event even when progressive source loading is disabled - s->userGenericEvent("before-progressive-proxy-loading", ""); - } - - for (size_t i = 0; i < array->size(); i++) - { - DynamicArray* currentSource = array->element(i); + if (Options::sharedOptions().delaySessionLoading) + { + s->userGenericEvent("before-progressive-loading", ""); - vector filesAndOptions; - filesAndOptions.reserve(currentSource->size()); - for(size_t j = 0; j < currentSource->size(); j++){ - string arg = currentSource->element(j)->c_str(); - filesAndOptions.emplace_back(IPCore::Application::mapFromVar(arg)); + // Note: It was decided to trigger the + // before-progressive-proxy-loading event even when progressive + // source loading is disabled + s->userGenericEvent("before-progressive-proxy-loading", ""); } - string nodeName = s->addSourceWithTag(filesAndOptions, tag)->name(); - names->element(i) = stype->allocate(nodeName); - } - - if(Options::sharedOptions().delaySessionLoading) - { - // Note: It was decided to trigger the after-progressive-proxy-loading - // event even when progressive source loading is disabled - s->userGenericEvent("after-progressive-proxy-loading", ""); + SourceIPNode* node = s->addSourceWithTag(filesAndOptions, tag); - if (!Options::sharedOptions().progressiveSourceLoading) + if (Options::sharedOptions().delaySessionLoading) { - s->userGenericEvent("after-progressive-loading", ""); - } - } - s->askForRedraw(); - NODE_RETURN(names); -} + // Note: It was decided to trigger the + // after-progressive-proxy-loading event even when progressive + // source loading is disabled + s->userGenericEvent("after-progressive-proxy-loading", ""); -NODE_IMPLEMENTATION(addSourceBegin, void) -{ - RvSession* s = RvSession::currentRvSession(); - s->rvgraph().addSourceBegin(); -} - -NODE_IMPLEMENTATION(addSourceEnd, void) -{ - RvSession* s = RvSession::currentRvSession(); - IPGraph::GraphEdit edit(s->graph()); - s->rvgraph().addSourceEnd(); - s->askForRedraw(); -} + if (!Options::sharedOptions().progressiveSourceLoading) + { + s->userGenericEvent("after-progressive-loading", ""); + } + } -NODE_IMPLEMENTATION(setProgressiveSourceLoading, void) -{ - const bool enable = NODE_ARG(0, bool); - - // Note : the settings need to be applied to two separate entities because - // they correspond to two different levels of abstraction: - // 1. The RV App high level Rv::Options::sharedOptions() - // 2. The IPCore lower level of abstraction: IPCore::Application::optionValue - // I decided to update both instead of relying only on one and risking that - // the other gets used inadvertantly in the future. - Rv::Options::sharedOptions().progressiveSourceLoading = enable; - IPCore::Application::setOptionValue("progressiveSourceLoading", enable); -} - -NODE_IMPLEMENTATION(progressiveSourceLoading, bool) -{ - Rv::Options& opts = Rv::Options::sharedOptions(); - NODE_RETURN (opts.progressiveSourceLoading!=0); -} + s->askForRedraw(); -NODE_IMPLEMENTATION(addToSource, void) -{ - RvSession* s = RvSession::currentRvSession(); - StringType::String* file = NODE_ARG_OBJECT(0, StringType::String); - StringType::String* tag = NODE_ARG_OBJECT(1, StringType::String); + StringType::String* nodeName = stype->allocate(node->name()); + NODE_RETURN(nodeName); + } - if (!file) throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil file arg"); + NODE_IMPLEMENTATION(addSources, void) + { + RvSession* s = RvSession::currentRvSession(); + DynamicArray* array = NODE_ARG_OBJECT(0, DynamicArray); + StringType::String* muTag = NODE_ARG_OBJECT(1, StringType::String); + bool processOpts = NODE_ARG(2, bool); + bool merge = NODE_ARG(3, bool); + string tag = (muTag) ? muTag->c_str() : ""; - IPGraph::GraphEdit edit(s->graph()); - s->addToSource("", file->c_str(), string(tag ? tag->c_str() : "")); - s->askForRedraw(); -} + vector sargs; -NODE_IMPLEMENTATION(addToSource2, void) -{ - RvSession* s = RvSession::currentRvSession(); - StringType::String* node = NODE_ARG_OBJECT(0, StringType::String); - StringType::String* file = NODE_ARG_OBJECT(1, StringType::String); - StringType::String* tag = NODE_ARG_OBJECT(2, StringType::String); + for (size_t i = 0; i < array->size(); i++) + { + string arg = array->element(i)->c_str(); + sargs.push_back(IPCore::Application::mapFromVar(arg)); + } - if (!node) throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil node arg"); - if (!file) throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil file arg"); + // + // Note we do not make GraphEdit object here, since this load will be + // asynchronous. + // - IPGraph::GraphEdit edit(s->graph()); - s->addToSource(node->c_str(), file->c_str(), string(tag ? tag->c_str() : "")); - s->askForRedraw(); -} + s->readUnorganizedFileList(sargs, processOpts, merge, tag); + s->askForRedraw(); + } -NODE_IMPLEMENTATION(setSourceMedia, void) -{ - RvSession* s = RvSession::currentRvSession(); - StringType::String* node = NODE_ARG_OBJECT(0, StringType::String); - DynamicArray* array = NODE_ARG_OBJECT(1, DynamicArray); - StringType::String* tag = NODE_ARG_OBJECT(2, StringType::String); + NODE_IMPLEMENTATION(addSourcesVerbose, Pointer) + { + RvSession* s = RvSession::currentRvSession(); + DynamicArray* array = NODE_ARG_OBJECT(0, DynamicArray); + const DynamicArrayType* atype = + reinterpret_cast(NODE_THIS.type()); + StringType::String* muTag = NODE_ARG_OBJECT(1, StringType::String); + string tag = (muTag) ? muTag->c_str() : ""; + MuLangContext* c = TwkApp::muContext(); + const StringType* stype = c->stringType(); + + DynamicArray* names = new DynamicArray(atype, 1); + names->resize(array->size()); + IPGraph::GraphEdit edit(s->graph()); + + if (Options::sharedOptions().delaySessionLoading) + { + s->userGenericEvent("before-progressive-loading", ""); - if (!node) throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil node arg"); + // Note: It was decided to trigger the + // before-progressive-proxy-loading event even when progressive + // source loading is disabled + s->userGenericEvent("before-progressive-proxy-loading", ""); + } - vector files; - - for (size_t i = 0; i < array->size(); i++) - files.push_back(array->element(i)->c_str()); + for (size_t i = 0; i < array->size(); i++) + { + DynamicArray* currentSource = array->element(i); - IPGraph::GraphEdit edit(s->graph()); - s->setSourceMedia(node->c_str(), files, string(tag ? tag->c_str() : "")); - s->askForRedraw(); -} + vector filesAndOptions; + filesAndOptions.reserve(currentSource->size()); + for (size_t j = 0; j < currentSource->size(); j++) + { + string arg = + currentSource->element(j)->c_str(); + filesAndOptions.emplace_back( + IPCore::Application::mapFromVar(arg)); + } -NODE_IMPLEMENTATION(addSourceMediaRep, Pointer) -{ - RvSession* s = RvSession::currentRvSession(); - StringType::String* sourceNode = NODE_ARG_OBJECT(0, StringType::String); - StringType::String* mediaRepName = NODE_ARG_OBJECT(1, StringType::String); - DynamicArray* mediaRepPathsAndOptionsArg = NODE_ARG_OBJECT(2, DynamicArray); - StringType::String* tag = NODE_ARG_OBJECT(3, StringType::String); - Process* p = NODE_THREAD.process(); - MuLangContext* c = static_cast(p->context()); - const StringType* stype = c->stringType(); - - if (!sourceNode) throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil source node arg"); - if (!mediaRepName) throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil media representation name arg"); - if (!mediaRepPathsAndOptionsArg) throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil media representation paths arg"); - - vector mediaRepPathsAndOptions; - mediaRepPathsAndOptions.reserve(mediaRepPathsAndOptionsArg->size()); - for (size_t i = 0; i < mediaRepPathsAndOptionsArg->size(); i++) - mediaRepPathsAndOptions.emplace_back(mediaRepPathsAndOptionsArg->element(i)->c_str()); - - IPGraph::GraphEdit edit(s->graph()); - SourceIPNode* node = s->addSourceMediaRep(sourceNode->c_str(), mediaRepName->c_str(), mediaRepPathsAndOptions, string(tag ? tag->c_str() : "")); - StringType::String* nodeName = stype->allocate(node ? node->name() : ""); - NODE_RETURN(nodeName); -} - -NODE_IMPLEMENTATION(setActiveSourceMediaRep, void) -{ - RvSession* s = RvSession::currentRvSession(); - StringType::String* sourceNode = NODE_ARG_OBJECT(0, StringType::String); - StringType::String* mediaRepName = NODE_ARG_OBJECT(1, StringType::String); - StringType::String* tag = NODE_ARG_OBJECT(2, StringType::String); + string nodeName = s->addSourceWithTag(filesAndOptions, tag)->name(); + names->element(i) = stype->allocate(nodeName); + } - if (!sourceNode) throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil source node arg"); - if (!mediaRepName) throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil media representation name arg"); + if (Options::sharedOptions().delaySessionLoading) + { + // Note: It was decided to trigger the + // after-progressive-proxy-loading event even when progressive + // source loading is disabled + s->userGenericEvent("after-progressive-proxy-loading", ""); - IPGraph::GraphEdit edit(s->graph()); + if (!Options::sharedOptions().progressiveSourceLoading) + { + s->userGenericEvent("after-progressive-loading", ""); + } + } + s->askForRedraw(); + NODE_RETURN(names); + } - try + NODE_IMPLEMENTATION(addSourceBegin, void) { - s->setActiveSourceMediaRep(sourceNode->c_str(), mediaRepName->c_str(), string(tag ? tag->c_str() : "")); + RvSession* s = RvSession::currentRvSession(); + s->rvgraph().addSourceBegin(); } - catch (TwkExc::Exception& exc) + + NODE_IMPLEMENTATION(addSourceEnd, void) { - throwBadArgumentException(NODE_THIS, NODE_THREAD, exc.what()); + RvSession* s = RvSession::currentRvSession(); + IPGraph::GraphEdit edit(s->graph()); + s->rvgraph().addSourceEnd(); + s->askForRedraw(); } - - s->askForRedraw(); -} -NODE_IMPLEMENTATION(sourceMediaRep, Pointer) -{ - RvSession* s = RvSession::currentRvSession(); - StringType::String* sourceNode = NODE_ARG_OBJECT(0, StringType::String); - Process* p = NODE_THREAD.process(); - MuLangContext* c = static_cast(p->context()); - const DynamicArrayType* atype = reinterpret_cast(NODE_THIS.type()); - const StringType* stype = c->stringType(); + NODE_IMPLEMENTATION(setProgressiveSourceLoading, void) + { + const bool enable = NODE_ARG(0, bool); + + // Note : the settings need to be applied to two separate entities + // because they correspond to two different levels of abstraction: + // 1. The RV App high level Rv::Options::sharedOptions() + // 2. The IPCore lower level of abstraction: + // IPCore::Application::optionValue I decided to update both instead of + // relying only on one and risking that the other gets used + // inadvertantly in the future. + Rv::Options::sharedOptions().progressiveSourceLoading = enable; + IPCore::Application::setOptionValue("progressiveSourceLoading", + enable); + } - if (!sourceNode) throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil source node arg"); + NODE_IMPLEMENTATION(progressiveSourceLoading, bool) + { + Rv::Options& opts = Rv::Options::sharedOptions(); + NODE_RETURN(opts.progressiveSourceLoading != 0); + } - std::string mediaRepName = s->sourceMediaRep(sourceNode->c_str()); - StringType::String* name = stype->allocate(mediaRepName); + NODE_IMPLEMENTATION(addToSource, void) + { + RvSession* s = RvSession::currentRvSession(); + StringType::String* file = NODE_ARG_OBJECT(0, StringType::String); + StringType::String* tag = NODE_ARG_OBJECT(1, StringType::String); - NODE_RETURN(name); -} + if (!file) + throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil file arg"); -NODE_IMPLEMENTATION(sourceMediaReps, Pointer) -{ - RvSession* s = RvSession::currentRvSession(); - StringType::String* sourceNode = NODE_ARG_OBJECT(0, StringType::String); - Process* p = NODE_THREAD.process(); - MuLangContext* c = static_cast(p->context()); - const DynamicArrayType* atype = reinterpret_cast(NODE_THIS.type()); - const StringType* stype = c->stringType(); - - if (!sourceNode) throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil source node arg"); + IPGraph::GraphEdit edit(s->graph()); + s->addToSource("", file->c_str(), string(tag ? tag->c_str() : "")); + s->askForRedraw(); + } - Session::StringVector mediaReps; - s->sourceMediaReps(sourceNode->c_str(), mediaReps); - DynamicArray* names = new DynamicArray(atype, 1); - names->resize(mediaReps.size()); - for (size_t i = 0; i < mediaReps.size(); i++) + NODE_IMPLEMENTATION(addToSource2, void) { - names->element(i) = stype->allocate(mediaReps[i]); + RvSession* s = RvSession::currentRvSession(); + StringType::String* node = NODE_ARG_OBJECT(0, StringType::String); + StringType::String* file = NODE_ARG_OBJECT(1, StringType::String); + StringType::String* tag = NODE_ARG_OBJECT(2, StringType::String); + + if (!node) + throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil node arg"); + if (!file) + throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil file arg"); + + IPGraph::GraphEdit edit(s->graph()); + s->addToSource(node->c_str(), file->c_str(), + string(tag ? tag->c_str() : "")); + s->askForRedraw(); } - NODE_RETURN(names); -} + NODE_IMPLEMENTATION(setSourceMedia, void) + { + RvSession* s = RvSession::currentRvSession(); + StringType::String* node = NODE_ARG_OBJECT(0, StringType::String); + DynamicArray* array = NODE_ARG_OBJECT(1, DynamicArray); + StringType::String* tag = NODE_ARG_OBJECT(2, StringType::String); -NODE_IMPLEMENTATION(sourceMediaRepsAndNodes, Pointer) -{ - RvSession* s = RvSession::currentRvSession(); - StringType::String* sourceOrSwitchNode = NODE_ARG_OBJECT(0, StringType::String); - Process* p = NODE_THREAD.process(); - MuLangContext* c = static_cast(p->context()); - const DynamicArrayType* atype = reinterpret_cast(NODE_THIS.type()); - const TupleType* ttype = static_cast(atype->elementType()); - const StringType* stype = c->stringType(); + if (!node) + throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil node arg"); - if (!sourceOrSwitchNode) throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil source or switch node arg"); + vector files; - Session::StringVector mediaRepNames; - Session::StringVector mediaRepSrcNodes; - s->sourceMediaReps(sourceOrSwitchNode->c_str(), mediaRepNames, &mediaRepSrcNodes); + for (size_t i = 0; i < array->size(); i++) + files.push_back(array->element(i)->c_str()); - if (mediaRepNames.empty() || (mediaRepNames.size() != mediaRepSrcNodes.size())) NODE_RETURN(0); + IPGraph::GraphEdit edit(s->graph()); + s->setSourceMedia(node->c_str(), files, + string(tag ? tag->c_str() : "")); + s->askForRedraw(); + } - struct STuple + NODE_IMPLEMENTATION(addSourceMediaRep, Pointer) { - const StringType::String* mediaRepName; - const StringType::String* mediaRepSrcNode; - }; - - DynamicArray* array = new DynamicArray(atype, 1); - array->resize(mediaRepNames.size()); + RvSession* s = RvSession::currentRvSession(); + StringType::String* sourceNode = NODE_ARG_OBJECT(0, StringType::String); + StringType::String* mediaRepName = + NODE_ARG_OBJECT(1, StringType::String); + DynamicArray* mediaRepPathsAndOptionsArg = + NODE_ARG_OBJECT(2, DynamicArray); + StringType::String* tag = NODE_ARG_OBJECT(3, StringType::String); + Process* p = NODE_THREAD.process(); + MuLangContext* c = static_cast(p->context()); + const StringType* stype = c->stringType(); + + if (!sourceNode) + throwBadArgumentException(NODE_THIS, NODE_THREAD, + "nil source node arg"); + if (!mediaRepName) + throwBadArgumentException(NODE_THIS, NODE_THREAD, + "nil media representation name arg"); + if (!mediaRepPathsAndOptionsArg) + throwBadArgumentException(NODE_THIS, NODE_THREAD, + "nil media representation paths arg"); + + vector mediaRepPathsAndOptions; + mediaRepPathsAndOptions.reserve(mediaRepPathsAndOptionsArg->size()); + for (size_t i = 0; i < mediaRepPathsAndOptionsArg->size(); i++) + mediaRepPathsAndOptions.emplace_back( + mediaRepPathsAndOptionsArg->element(i) + ->c_str()); + + IPGraph::GraphEdit edit(s->graph()); + SourceIPNode* node = s->addSourceMediaRep( + sourceNode->c_str(), mediaRepName->c_str(), mediaRepPathsAndOptions, + string(tag ? tag->c_str() : "")); + StringType::String* nodeName = + stype->allocate(node ? node->name() : ""); + NODE_RETURN(nodeName); + } - for (int i=0; i < mediaRepNames.size(); i++) + NODE_IMPLEMENTATION(setActiveSourceMediaRep, void) { - ClassInstance* tuple = ClassInstance::allocate(ttype); - STuple* st = reinterpret_cast(tuple->structure()); - st->mediaRepName = stype->allocate(mediaRepNames[i]); - st->mediaRepSrcNode = stype->allocate(mediaRepSrcNodes[i]); - - array->element(i) = tuple; + RvSession* s = RvSession::currentRvSession(); + StringType::String* sourceNode = NODE_ARG_OBJECT(0, StringType::String); + StringType::String* mediaRepName = + NODE_ARG_OBJECT(1, StringType::String); + StringType::String* tag = NODE_ARG_OBJECT(2, StringType::String); + + if (!sourceNode) + throwBadArgumentException(NODE_THIS, NODE_THREAD, + "nil source node arg"); + if (!mediaRepName) + throwBadArgumentException(NODE_THIS, NODE_THREAD, + "nil media representation name arg"); + + IPGraph::GraphEdit edit(s->graph()); + + try + { + s->setActiveSourceMediaRep(sourceNode->c_str(), + mediaRepName->c_str(), + string(tag ? tag->c_str() : "")); + } + catch (TwkExc::Exception& exc) + { + throwBadArgumentException(NODE_THIS, NODE_THREAD, exc.what()); + } + + s->askForRedraw(); } - NODE_RETURN(array); -} + NODE_IMPLEMENTATION(sourceMediaRep, Pointer) + { + RvSession* s = RvSession::currentRvSession(); + StringType::String* sourceNode = NODE_ARG_OBJECT(0, StringType::String); + Process* p = NODE_THREAD.process(); + MuLangContext* c = static_cast(p->context()); + const DynamicArrayType* atype = + reinterpret_cast(NODE_THIS.type()); + const StringType* stype = c->stringType(); + + if (!sourceNode) + throwBadArgumentException(NODE_THIS, NODE_THREAD, + "nil source node arg"); + + std::string mediaRepName = s->sourceMediaRep(sourceNode->c_str()); + StringType::String* name = stype->allocate(mediaRepName); + + NODE_RETURN(name); + } -NODE_IMPLEMENTATION(sourceMediaRepSwitchNode, Pointer) -{ - RvSession* s = RvSession::currentRvSession(); - StringType::String* sourceNode = NODE_ARG_OBJECT(0, StringType::String); - Process* p = NODE_THREAD.process(); - MuLangContext* c = static_cast(p->context()); - const DynamicArrayType* atype = reinterpret_cast(NODE_THIS.type()); - const StringType* stype = c->stringType(); + NODE_IMPLEMENTATION(sourceMediaReps, Pointer) + { + RvSession* s = RvSession::currentRvSession(); + StringType::String* sourceNode = NODE_ARG_OBJECT(0, StringType::String); + Process* p = NODE_THREAD.process(); + MuLangContext* c = static_cast(p->context()); + const DynamicArrayType* atype = + reinterpret_cast(NODE_THIS.type()); + const StringType* stype = c->stringType(); + + if (!sourceNode) + throwBadArgumentException(NODE_THIS, NODE_THREAD, + "nil source node arg"); + + Session::StringVector mediaReps; + s->sourceMediaReps(sourceNode->c_str(), mediaReps); + DynamicArray* names = new DynamicArray(atype, 1); + names->resize(mediaReps.size()); + for (size_t i = 0; i < mediaReps.size(); i++) + { + names->element(i) = + stype->allocate(mediaReps[i]); + } - if (!sourceNode) throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil source node arg"); + NODE_RETURN(names); + } - std::string switchNodeName = s->sourceMediaRepSwitchNode(sourceNode->c_str()); - StringType::String* name = stype->allocate(switchNodeName); + NODE_IMPLEMENTATION(sourceMediaRepsAndNodes, Pointer) + { + RvSession* s = RvSession::currentRvSession(); + StringType::String* sourceOrSwitchNode = + NODE_ARG_OBJECT(0, StringType::String); + Process* p = NODE_THREAD.process(); + MuLangContext* c = static_cast(p->context()); + const DynamicArrayType* atype = + reinterpret_cast(NODE_THIS.type()); + const TupleType* ttype = + static_cast(atype->elementType()); + const StringType* stype = c->stringType(); + + if (!sourceOrSwitchNode) + throwBadArgumentException(NODE_THIS, NODE_THREAD, + "nil source or switch node arg"); + + Session::StringVector mediaRepNames; + Session::StringVector mediaRepSrcNodes; + s->sourceMediaReps(sourceOrSwitchNode->c_str(), mediaRepNames, + &mediaRepSrcNodes); + + if (mediaRepNames.empty() + || (mediaRepNames.size() != mediaRepSrcNodes.size())) + NODE_RETURN(0); + + struct STuple + { + const StringType::String* mediaRepName; + const StringType::String* mediaRepSrcNode; + }; - NODE_RETURN(name); -} + DynamicArray* array = new DynamicArray(atype, 1); + array->resize(mediaRepNames.size()); -NODE_IMPLEMENTATION(sourceMediaRepSourceNode, Pointer) -{ - RvSession* s = RvSession::currentRvSession(); - StringType::String* sourceNode = NODE_ARG_OBJECT(0, StringType::String); - Process* p = NODE_THREAD.process(); - MuLangContext* c = static_cast(p->context()); - const DynamicArrayType* atype = reinterpret_cast(NODE_THIS.type()); - const StringType* stype = c->stringType(); + for (int i = 0; i < mediaRepNames.size(); i++) + { + ClassInstance* tuple = ClassInstance::allocate(ttype); + STuple* st = reinterpret_cast(tuple->structure()); + st->mediaRepName = stype->allocate(mediaRepNames[i]); + st->mediaRepSrcNode = stype->allocate(mediaRepSrcNodes[i]); - if (!sourceNode) throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil source node arg"); + array->element(i) = tuple; + } - std::string sourceNodeName = s->sourceMediaRepSourceNode(sourceNode->c_str()); - StringType::String* name = stype->allocate(sourceNodeName); + NODE_RETURN(array); + } - NODE_RETURN(name); -} + NODE_IMPLEMENTATION(sourceMediaRepSwitchNode, Pointer) + { + RvSession* s = RvSession::currentRvSession(); + StringType::String* sourceNode = NODE_ARG_OBJECT(0, StringType::String); + Process* p = NODE_THREAD.process(); + MuLangContext* c = static_cast(p->context()); + const DynamicArrayType* atype = + reinterpret_cast(NODE_THIS.type()); + const StringType* stype = c->stringType(); + + if (!sourceNode) + throwBadArgumentException(NODE_THIS, NODE_THREAD, + "nil source node arg"); + + std::string switchNodeName = + s->sourceMediaRepSwitchNode(sourceNode->c_str()); + StringType::String* name = stype->allocate(switchNodeName); + + NODE_RETURN(name); + } -NODE_IMPLEMENTATION(relocateSource, void) -{ - RvSession* s = RvSession::currentRvSession(); - StringType::String* oldName = NODE_ARG_OBJECT(0, StringType::String); - StringType::String* newName = NODE_ARG_OBJECT(1, StringType::String); + NODE_IMPLEMENTATION(sourceMediaRepSourceNode, Pointer) + { + RvSession* s = RvSession::currentRvSession(); + StringType::String* sourceNode = NODE_ARG_OBJECT(0, StringType::String); + Process* p = NODE_THREAD.process(); + MuLangContext* c = static_cast(p->context()); + const DynamicArrayType* atype = + reinterpret_cast(NODE_THIS.type()); + const StringType* stype = c->stringType(); + + if (!sourceNode) + throwBadArgumentException(NODE_THIS, NODE_THREAD, + "nil source node arg"); + + std::string sourceNodeName = + s->sourceMediaRepSourceNode(sourceNode->c_str()); + StringType::String* name = stype->allocate(sourceNodeName); + + NODE_RETURN(name); + } - IPGraph::GraphEdit edit(s->graph()); - s->relocateSource(oldName->c_str(), newName->c_str()); - s->askForRedraw(); -} + NODE_IMPLEMENTATION(relocateSource, void) + { + RvSession* s = RvSession::currentRvSession(); + StringType::String* oldName = NODE_ARG_OBJECT(0, StringType::String); + StringType::String* newName = NODE_ARG_OBJECT(1, StringType::String); -NODE_IMPLEMENTATION(relocateSource2, void) -{ - RvSession* s = RvSession::currentRvSession(); - StringType::String* node = NODE_ARG_OBJECT(0, StringType::String); - StringType::String* oldName = NODE_ARG_OBJECT(1, StringType::String); - StringType::String* newName = NODE_ARG_OBJECT(2, StringType::String); + IPGraph::GraphEdit edit(s->graph()); + s->relocateSource(oldName->c_str(), newName->c_str()); + s->askForRedraw(); + } - if (!node) throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil node arg"); - if (!oldName) throwBadArgumentException(NODE_THIS, NODE_THREAD, "old media name is nil"); - if (!newName) throwBadArgumentException(NODE_THIS, NODE_THREAD, "new media name is nil"); + NODE_IMPLEMENTATION(relocateSource2, void) + { + RvSession* s = RvSession::currentRvSession(); + StringType::String* node = NODE_ARG_OBJECT(0, StringType::String); + StringType::String* oldName = NODE_ARG_OBJECT(1, StringType::String); + StringType::String* newName = NODE_ARG_OBJECT(2, StringType::String); + + if (!node) + throwBadArgumentException(NODE_THIS, NODE_THREAD, "nil node arg"); + if (!oldName) + throwBadArgumentException(NODE_THIS, NODE_THREAD, + "old media name is nil"); + if (!newName) + throwBadArgumentException(NODE_THIS, NODE_THREAD, + "new media name is nil"); + + IPGraph::GraphEdit edit(s->graph()); + s->relocateSource(oldName->c_str(), newName->c_str(), node->c_str()); + s->askForRedraw(); + } - IPGraph::GraphEdit edit(s->graph()); - s->relocateSource(oldName->c_str(), newName->c_str(), node->c_str()); - s->askForRedraw(); -} + NODE_IMPLEMENTATION(commandLineFlag, Pointer) + { + RvSession* s = RvSession::currentRvSession(); + const StringType* t = static_cast(NODE_THIS.type()); + const StringType::String* key = NODE_ARG_OBJECT(0, StringType::String); + const StringType::String* defaultValue = + NODE_ARG_OBJECT(1, StringType::String); -NODE_IMPLEMENTATION(commandLineFlag, Pointer) -{ - RvSession* s = RvSession::currentRvSession(); - const StringType* t = static_cast(NODE_THIS.type()); - const StringType::String* key = NODE_ARG_OBJECT(0, StringType::String); - const StringType::String* defaultValue = NODE_ARG_OBJECT(1, StringType::String); + if (!key) + throwBadArgumentException(NODE_THIS, NODE_THREAD, + "flag key is nil"); - if (!key) throwBadArgumentException(NODE_THIS, NODE_THREAD, "flag key is nil"); + string val = s->lookupMuFlag(key->c_str()); - string val = s->lookupMuFlag(key->c_str()); + if (val.empty()) + NODE_RETURN(Pointer(defaultValue)); + NODE_RETURN(t->allocate(val)); + } - if (val.empty()) NODE_RETURN(Pointer(defaultValue)); - NODE_RETURN(t->allocate(val)); -} + NODE_IMPLEMENTATION(ocioUpdateConfig, void) + { + Session* s = Session::currentSession(); + StringType::String* name = NODE_ARG_OBJECT(0, StringType::String); + IPNode* node = 0; -NODE_IMPLEMENTATION(ocioUpdateConfig, void) -{ - Session* s = Session::currentSession(); - StringType::String* name = NODE_ARG_OBJECT(0, StringType::String); + if (name) + { + if (!(node = s->graph().findNode(name->c_str()))) + { + throwBadArgumentException(NODE_THIS, NODE_THREAD, + "Bad ocio node name"); + } + } + else + { + throwBadArgumentException(NODE_THIS, NODE_THREAD, + "Null ocio node name"); + } - IPNode* node = 0; + OCIOIPNode* ocioNode = dynamic_cast(node); + if (!ocioNode) + { + throwBadArgumentException(NODE_THIS, NODE_THREAD, + "Not an ocio node"); + } - if (name) - { - if (!(node = s->graph().findNode(name->c_str()))) + try { - throwBadArgumentException(NODE_THIS, NODE_THREAD, "Bad ocio node name"); + ocioNode->updateConfig(); + } + catch (TwkExc::Exception& exc) + { + throwBadArgumentException(NODE_THIS, NODE_THREAD, exc.what()); } - } - else - { - throwBadArgumentException(NODE_THIS, NODE_THREAD, "Null ocio node name"); } - OCIOIPNode* ocioNode = dynamic_cast (node); - if (!ocioNode) + NODE_IMPLEMENTATION(shortAppName, Pointer) { - throwBadArgumentException(NODE_THIS, NODE_THREAD, "Not an ocio node"); + Process* p = NODE_THREAD.process(); + MuLangContext* c = static_cast(p->context()); + const StringType* stype = c->stringType(); + + StringType::String* name = stype->allocate(TWK_DEPLOY_SHORT_APP_NAME()); + + NODE_RETURN(name); } - try + NODE_IMPLEMENTATION(licensingState, int) { - ocioNode->updateConfig(); + NODE_RETURN(TWK_DEPLOY_GET_LICENSE_STATE()); } - catch (TwkExc::Exception& exc) + + //---------------------------------------------------------------------- + // + // INIT MODULE + // + + void initCommands(Mu::MuLangContext* context) { - throwBadArgumentException(NODE_THIS, NODE_THREAD, exc.what()); - } -} + theTimer.start(); + + USING_MU_FUNCTION_SYMBOLS; + typedef ParameterVariable Param; + + if (!context) + context = TwkApp::muContext(); + MuLangContext* c = context; + Symbol* root = context->globalScope(); + Name cname = c->internName("commands"); + Mu::Module* commands = root->findSymbolOfType(cname); + // Mu::GLModule::init("gl", context); + context->globalScope()->addSymbol(new Mu::GLModule(c, "gl")); + context->globalScope()->addSymbol(new Mu::GLTextModule(c, "gltext")); + context->globalScope()->addSymbol(new Mu::GLUModule(c, "glu")); + + Module* autodoc = new Mu::AutoDocModule(context, "autodoc"); + Module* io = new Mu::IOModule(context, "io"); + Module* sys = new Mu::SystemModule(context, "system"); + Module* img = new Mu::ImageModule(context, "image"); + Module* enc = new Mu::EncodingModule(context, "encoding"); + Module* lin = new Mu::MathLinearModule(context, "math_linear"); + + root->addSymbols(autodoc, io, sys, img, enc, lin, EndArguments); + + TwkApp::muModuleList().push_back(autodoc); + TwkApp::muModuleList().push_back(io); + IPMu::initCommands(c); -NODE_IMPLEMENTATION(shortAppName, Pointer) -{ - Process* p = NODE_THREAD.process(); - MuLangContext* c = static_cast(p->context()); - const StringType* stype = c->stringType(); + // + // construct (string,string)[] type + // + Context::TypeVector types; + types.push_back(context->stringType()); + types.push_back(context->stringType()); + TupleType* st = context->tupleType(types); + const Type* stArray = context->arrayType(st, 1, 0); - StringType::String* name = stype->allocate(TWK_DEPLOY_SHORT_APP_NAME()); + context->arrayType(context->halfType(), 1, 0); - NODE_RETURN(name); -} + const Type* sarray = context->arrayType(context->stringType(), 1, 0); -NODE_IMPLEMENTATION(licensingState, int) -{ - NODE_RETURN(TWK_DEPLOY_GET_LICENSE_STATE()); -} + // + // Construct (int,int,int,int) + // + types.resize(4); + types[0] = context->intType(); + types[1] = context->intType(); + types[2] = context->intType(); + types[3] = context->intType(); + const Type* i4tupleType = context->tupleType(types); + + // float[4,4] + const Type* m44 = context->arrayType(context->floatType(), 2, 4, 4, 0); + + Context::NameValuePairs fields; + fields.resize(15); + fields[0] = make_pair(string("module"), context->stringType()); + fields[1] = make_pair(string("device"), context->stringType()); + fields[2] = make_pair(string("videoFormat"), context->stringType()); + fields[3] = make_pair(string("rate"), context->floatType()); + fields[4] = make_pair(string("width"), context->intType()); + fields[5] = make_pair(string("height"), context->intType()); + fields[6] = make_pair(string("dataFormat"), context->stringType()); + fields[7] = make_pair(string("sync"), context->stringType()); + fields[8] = make_pair(string("syncSource"), context->stringType()); + fields[9] = make_pair(string("audioFormat"), context->stringType()); + fields[10] = make_pair(string("audioRate"), context->floatType()); + fields[11] = make_pair(string("audioBits"), context->intType()); + fields[12] = make_pair(string("audioChannels"), context->intType()); + fields[13] = make_pair(string("audioFloat"), context->boolType()); + fields[14] = make_pair(string("displayMode"), context->intType()); + context->arrayType(context->structType(0, "VideoDeviceState", fields), + 1, 0); + + fields.resize(3); + fields[0] = make_pair(string("name"), context->stringType()); + fields[1] = make_pair(string("description"), context->stringType()); + fields[2] = make_pair(string("type"), context->stringType()); + context->arrayType(context->structType(0, "IOParameter", fields), 1, 0); + + fields.resize(7); + fields[0] = make_pair(string("start"), context->intType()); + fields[1] = make_pair(string("end"), context->intType()); + fields[2] = make_pair(string("inc"), context->intType()); + fields[3] = make_pair(string("fps"), context->floatType()); + fields[4] = make_pair(string("cutIn"), context->intType()); + fields[5] = make_pair(string("cutOut"), context->intType()); + fields[6] = make_pair(string("isUndiscovered"), context->boolType()); + context->structType(0, "NodeRangeInfo", fields); + + fields.resize(6); + fields[0] = make_pair(string("name"), context->stringType()); + fields[1] = make_pair(string("type"), context->intType()); + fields[2] = make_pair(string("dimensions"), i4tupleType); + fields[3] = make_pair(string("size"), context->intType()); + fields[4] = make_pair(string("userDefined"), context->boolType()); + fields[5] = make_pair(string("info"), context->stringType()); + context->arrayType(context->structType(0, "PropertyInfo", fields), 1, + 0); + + fields.resize(3); + fields[0] = make_pair(string("node"), context->stringType()); + fields[1] = make_pair(string("nodeType"), context->stringType()); + fields[2] = make_pair(string("frame"), context->intType()); + context->arrayType(context->structType(0, "MetaEvalInfo", fields), 1, + 0); + + fields.resize(5); + fields[0] = make_pair(string("extension"), context->stringType()); + fields[1] = make_pair(string("description"), context->stringType()); + fields[2] = make_pair(string("capabilities"), context->intType()); + fields[3] = make_pair(string("imageCodecs"), stArray); + fields[4] = make_pair(string("audioCodecs"), stArray); + context->arrayType(context->structType(0, "IOFormat", fields), 1, 0); + + types.clear(); + types.push_back(context->stringType()); + types.push_back(context->arrayType(context->byteType(), 1, 0)); + context->arrayType(context->tupleType(types), 1, 0); + + types.clear(); + types.push_back(context->stringType()); // source name + types.push_back(context->intType()); // start frame + types.push_back(context->intType()); // end frame + types.push_back(context->intType()); // inc + types.push_back(context->floatType()); // fps + types.push_back(context->boolType()); // audio + types.push_back(context->boolType()); // video + st = context->tupleType(types); + context->arrayType(st, 1, 0); + + types.clear(); // cacheInfo() return tuple + types.push_back(context->int64Type()); // capacity in bytes + types.push_back(context->int64Type()); // used in bytes + types.push_back(context->int64Type()); // used in look ahead in bytes + types.push_back(context->floatType()); // seconds of look ahead cache + types.push_back(context->floatType()); // min seconds of look ahead + // cache requested by user + types.push_back(context->floatType()); // seconds of audio cached + types.push_back(context->arrayType(context->intType(), 1, + 0)); // cached frame ranges + context->tupleType(types); + + types.clear(); // edl commands use (int,int,int) + types.push_back(context->intType()); + types.push_back(context->intType()); + types.push_back(context->intType()); + context->tupleType(types); + + types.clear(); // sourceMedia -> (string,string[],string[]) + types.push_back(context->stringType()); + types.push_back(context->arrayType(context->stringType(), 1, 0)); + types.push_back(context->arrayType(context->stringType(), 1, 0)); + context->tupleType(types); + + context->arrayType(context->intType(), 1, 0); + + types.erase(types.begin()); + context->tupleType(types); // (string[],string[]) + + commands->addSymbols( + new SymbolicConstant(c, "RGB709", "int", Value(0)), + new SymbolicConstant(c, "CIEXYZ", "int", Value(1)), + + new SymbolicConstant(c, "PlayLoop", "int", Value(0)), + new SymbolicConstant(c, "PlayOnce", "int", Value(1)), + new SymbolicConstant(c, "PlayPingPong", "int", Value(2)), + + new SymbolicConstant(c, "OkImageStatus", "int", + Value(Session::OkStatus)), + new SymbolicConstant(c, "ErrorImageStatus", "int", + Value(Session::ErrorStatus)), + new SymbolicConstant(c, "WarningImageStatus", "int", + Value(Session::WarningStatus)), + new SymbolicConstant(c, "NoImageStatus", "int", + Value(Session::NoImageStatus)), + new SymbolicConstant(c, "PartialImageStatus", "int", + Value(Session::PartialStatus)), + new SymbolicConstant(c, "LoadingImageStatus", "int", + Value(Session::LoadingStatus)), + + new SymbolicConstant(c, "SequenceSession", "int", + Value(Session::SequenceSession)), + new SymbolicConstant(c, "StackSession", "int", + Value(Session::StackSession)), + + new SymbolicConstant(c, "CacheOff", "int", + Value(Session::NeverCache)), + new SymbolicConstant(c, "CacheBuffer", "int", + Value(Session::BufferCache)), + new SymbolicConstant(c, "CacheGreedy", "int", + Value(Session::GreedyCache)), + + new SymbolicConstant(c, "IntType", "int", + Value(Property::IntLayout)), + new SymbolicConstant(c, "FloatType", "int", + Value(Property::FloatLayout)), + new SymbolicConstant(c, "HalfType", "int", + Value(Property::HalfLayout)), + new SymbolicConstant(c, "StringType", "int", + Value(Property::StringLayout)), + new SymbolicConstant(c, "ByteType", "int", + Value(Property::ByteLayout)), + new SymbolicConstant(c, "ShortType", "int", + Value(Property::ShortLayout)), + + new SymbolicConstant(c, "IndependentDisplayMode", "int", + Value(VideoDevice::IndependentDisplayMode)), + new SymbolicConstant(c, "MirrorDisplayMode", "int", + Value(VideoDevice::MirrorDisplayMode)), + new SymbolicConstant(c, "NotADisplayMode", "int", + Value(VideoDevice::NotADisplayMode)), + + new SymbolicConstant(c, "VideoAndDataFormatID", "int", + Value(VideoDevice::VideoAndDataFormatID)), + new SymbolicConstant(c, "DeviceNameID", "int", + Value(VideoDevice::DeviceNameID)), + new SymbolicConstant(c, "ModuleNameID", "int", + Value(VideoDevice::ModuleNameID)), + + EndArguments); + + commands->addSymbols( + + new Function(c, "data", data, None, Return, "object", End), + + new Function(c, "sources", sources, None, Return, + "(string,int,int,int,float,bool,bool)[]", End), + + new Function(c, "sourceMedia", sourceMedia, None, Return, + "(string,string[],string[])", Parameters, + new Param(c, "sourceName", "string"), End), + + new Function(c, "sourcePixelValue", sourcePixelValue, None, Return, + "vector float[4]", Parameters, + new Param(c, "sourceName", "string"), + new Param(c, "px", "float"), + new Param(c, "py", "float"), End), + + new Function(c, "sourceAttributes", sourceAttributes, None, Return, + "(string,string)[]", Parameters, + new Param(c, "sourceName", "string"), + new Param(c, "mediaName", "string", Value()), End), + + new Function(c, "sourceDataAttributes", sourceDataAttributes, None, + Return, "(string,byte[])[]", Parameters, + new Param(c, "sourceName", "string"), + new Param(c, "mediaName", "string", Value()), End), + + new Function(c, "sourceDisplayChannelNames", + sourceDisplayChannelNames, None, Parameters, + new Param(c, "sourceName", "string"), Return, + "string[]", End), + + new Function(c, "getCurrentImageSize", getCurrentImageSize, None, + Return, "vector float[2]", End), + + new Function(c, "getCurrentPixelValue", getCurrentPixelValue, None, + Return, "vector float[4]", Parameters, + new Param(c, "point", "vector float[2]"), End), + + new Function(c, "getCurrentAttributes", getCurrentAttributes, None, + Return, "(string,string)[]", End), + + new Function(c, "getCurrentImageChannelNames", + getCurrentImageChannelNames, None, Return, "string[]", + End), + + new Function(c, "getCurrentNodesOfType", getCurrentNodesOfType, + None, Parameters, new Param(c, "typeName", "string"), + Return, "string[]", End), + + new Function(c, "addSource", addSource, None, Return, "void", + Parameters, new Param(c, "fileName", "string"), + new Param(c, "tag", "string", Value()), End), + + new Function(c, "addSource", addSourceMulti, None, Return, "void", + Parameters, new Param(c, "fileNames", "string[]"), + new Param(c, "tag", "string", Value()), End), + + new Function(c, "addSourceVerbose", addSourceVerbose, None, Return, + "string", Parameters, + new Param(c, "filePathsAndOptions", "string[]"), + new Param(c, "tag", "string", Value()), End), + + new Function(c, "addSourceBegin", addSourceBegin, None, Return, + "void", End), + + new Function(c, "addSourceEnd", addSourceEnd, None, Return, "void", + End), + + new Function(c, "addSources", addSources, None, Return, "void", + Parameters, new Param(c, "fileNames", "string[]"), + new Param(c, "tag", "string", Value()), + new Param(c, "processOpts", "bool", Value(false)), + new Param(c, "merge", "bool", Value(false)), End), + + new Function(c, "addSourcesVerbose", addSourcesVerbose, None, + Return, "string[]", Parameters, + new Param(c, "filePathsAndOptions", "string[][]"), + new Param(c, "tag", "string", Value()), End), + + new Function(c, "setProgressiveSourceLoading", + setProgressiveSourceLoading, None, Return, "void", + Parameters, new Param(c, "enable", "bool"), End), + + new Function(c, "progressiveSourceLoading", + progressiveSourceLoading, None, Return, "bool", End), + + new Function( + c, "newImageSource", newImageSource, None, Return, "string", + Parameters, new Param(c, "mediaName", "string"), + new Param(c, "width", "int"), new Param(c, "height", "int"), + new Param(c, "uncropWidth", "int"), + new Param(c, "uncropHeight", "int"), + new Param(c, "uncropX", "int"), new Param(c, "uncropY", "int"), + new Param(c, "pixelAspect", "float"), + new Param(c, "channels", "int"), + new Param(c, "bitsPerChannel", "int"), + new Param(c, "floatingPoint", "bool"), + new Param(c, "startFrame", "int"), + new Param(c, "endFrame", "int"), new Param(c, "fps", "float"), + new Param(c, "layers", "string[]", Value()), + new Param(c, "views", "string[]", Value()), End), + + new Function(c, "newImageSourcePixels", newImageSourcePixels, None, + Return, "string", Parameters, + new Param(c, "sourceName", "string"), + new Param(c, "frame", "int"), + new Param(c, "layer", "string", Value()), + new Param(c, "view", "string", Value()), End), + + new Function(c, "insertCreatePixelBlock", insertCreatePixelBlock, + None, Return, "void", Parameters, + new Param(c, "event", "Event"), End), + + new Function(c, "addToSource", addToSource, None, Return, "void", + Parameters, new Param(c, "fileName", "string"), + new Param(c, "tag", "string", Value()), End), + + new Function(c, "addToSource", addToSource2, None, Return, "void", + Parameters, new Param(c, "sourceNode", "string"), + new Param(c, "fileName", "string"), + new Param(c, "tag", "string"), End), + + new Function(c, "setSourceMedia", setSourceMedia, None, Return, + "void", Parameters, + new Param(c, "sourceNode", "string"), + new Param(c, "fileNames", "string[]"), + new Param(c, "tag", "string", Value()), End), + + new Function(c, "addSourceMediaRep", addSourceMediaRep, None, + Return, "string", Parameters, + new Param(c, "sourceNode", "string"), + new Param(c, "mediaRepName", "string"), + new Param(c, "mediaRepPathsAndOptions", "string[]"), + new Param(c, "tag", "string", Value()), End), + + new Function(c, "setActiveSourceMediaRep", setActiveSourceMediaRep, + None, Return, "void", Parameters, + new Param(c, "sourceNode", "string"), + new Param(c, "mediaRepName", "string"), + new Param(c, "tag", "string", Value()), End), + + new Function(c, "sourceMediaRep", sourceMediaRep, None, Return, + "string", Parameters, + new Param(c, "sourceNode", "string"), End), + + new Function(c, "sourceMediaReps", sourceMediaReps, None, Return, + "string[]", Parameters, + new Param(c, "sourceNode", "string"), End), + + new Function(c, "sourceMediaRepsAndNodes", sourceMediaRepsAndNodes, + None, Return, "(string,string)[]", Parameters, + new Param(c, "sourceOrSwitchNode", "string"), End), + + new Function(c, "sourceMediaRepSwitchNode", + sourceMediaRepSwitchNode, None, Return, "string", + Parameters, new Param(c, "sourceNode", "string"), End), + + new Function(c, "sourceMediaRepSourceNode", + sourceMediaRepSourceNode, None, Return, "string", + Parameters, new Param(c, "sourceNode", "string"), End), + + new Function(c, "relocateSource", relocateSource, None, Return, + "void", Parameters, + new Param(c, "oldFileName", "string"), + new Param(c, "newFileName", "string"), End), + + new Function(c, "relocateSource", relocateSource2, None, Return, + "void", Parameters, + new Param(c, "sourceNode", "string"), + new Param(c, "oldFileName", "string"), + new Param(c, "newFileName", "string"), End), + + new Function( + c, "commandLineFlag", commandLineFlag, None, Return, "string", + Parameters, new Param(c, "flagName", "string"), + new Param(c, "defaultValue", "string", Value(Pointer(0))), End), + + new Function(c, "readLUT", readLUT, None, Return, "void", + Parameters, new Param(c, "filename", "string"), + new Param(c, "nodeName", "string"), + new Param(c, "activate", "bool", Value(false)), End), + + new Function(c, "readCDL", readCDL, None, Return, "void", + Parameters, new Param(c, "filename", "string"), + new Param(c, "nodeName", "string"), + new Param(c, "activate", "bool", Value(false)), End), + + new Function(c, "setSessionType", setSessionType, None, Return, + "void", Parameters, new Param(c, "sessionType", "int"), + End), + + new Function(c, "getSessionType", getSessionType, None, Return, + "int", End), + + new Function(c, "startTimer", startTimer, None, Return, "void", + End), -//---------------------------------------------------------------------- -// -// INIT MODULE -// + new Function(c, "elapsedTime", elapsedTime, None, Return, "float", + End), -void initCommands(Mu::MuLangContext* context) -{ - theTimer.start(); - - USING_MU_FUNCTION_SYMBOLS; - typedef ParameterVariable Param; - - if (!context) context = TwkApp::muContext(); - MuLangContext* c = context; - Symbol* root = context->globalScope(); - Name cname = c->internName("commands"); - Mu::Module* commands = root->findSymbolOfType(cname); - //Mu::GLModule::init("gl", context); - context->globalScope()->addSymbol(new Mu::GLModule(c, "gl")); - context->globalScope()->addSymbol(new Mu::GLTextModule(c, "gltext")); - context->globalScope()->addSymbol(new Mu::GLUModule(c, "glu")); - - Module* autodoc = new Mu::AutoDocModule(context, "autodoc"); - Module* io = new Mu::IOModule(context, "io"); - Module* sys = new Mu::SystemModule(context, "system"); - Module* img = new Mu::ImageModule(context, "image"); - Module* enc = new Mu::EncodingModule(context, "encoding"); - Module* lin = new Mu::MathLinearModule(context, "math_linear"); - - root->addSymbols(autodoc, io, sys, img, enc, lin, EndArguments); - - TwkApp::muModuleList().push_back(autodoc); - TwkApp::muModuleList().push_back(io); - IPMu::initCommands(c); + new Function(c, "theTime", theTime, None, Return, "float", End), - // - // construct (string,string)[] type - // - Context::TypeVector types; - types.push_back(context->stringType()); - types.push_back(context->stringType()); - TupleType* st = context->tupleType(types); - const Type* stArray = context->arrayType(st, 1, 0); + new Function(c, "stopTimer", stopTimer, None, Return, "float", End), - context->arrayType(context->halfType(), 1, 0); + new Function(c, "isTimerRunning", isTimerRunning, None, Return, + "bool", End), - const Type* sarray = context->arrayType(context->stringType(), 1, 0); + new Function(c, "updateLUT", updateLUT, None, Return, "void", End), - // - // Construct (int,int,int,int) - // + new Function(c, "exportCurrentFrame", exportCurrentFrame, None, + Return, "void", Parameters, + new Param(c, "filename", "string"), End), + + new Function(c, "exportCurrentSourceFrame", + exportCurrentSourceFrame, None, Return, "void", + Parameters, new Param(c, "filename", "string"), End), + + new Function(c, "optionsPlay", optionsPlay, None, Return, "int", + End), + + new Function(c, "optionsPlayReset", optionsPlayReset, None, Return, + "void", End), + + new Function(c, "optionsNoPackages", optionsNoPackages, None, + Return, "int", End), - types.resize(4); - types[0] = context->intType(); - types[1] = context->intType(); - types[2] = context->intType(); - types[3] = context->intType(); - const Type* i4tupleType = context->tupleType(types); - - // float[4,4] - const Type* m44 = context->arrayType(context->floatType(), - 2, 4, 4, 0); - - Context::NameValuePairs fields; - fields.resize(15); - fields[0] = make_pair(string("module"), context->stringType()); - fields[1] = make_pair(string("device"), context->stringType()); - fields[2] = make_pair(string("videoFormat"), context->stringType()); - fields[3] = make_pair(string("rate"), context->floatType()); - fields[4] = make_pair(string("width"), context->intType()); - fields[5] = make_pair(string("height"), context->intType()); - fields[6] = make_pair(string("dataFormat"), context->stringType()); - fields[7] = make_pair(string("sync"), context->stringType()); - fields[8] = make_pair(string("syncSource"), context->stringType()); - fields[9] = make_pair(string("audioFormat"), context->stringType()); - fields[10] = make_pair(string("audioRate"), context->floatType()); - fields[11] = make_pair(string("audioBits"), context->intType()); - fields[12] = make_pair(string("audioChannels"), context->intType()); - fields[13] = make_pair(string("audioFloat"), context->boolType()); - fields[14] = make_pair(string("displayMode"), context->intType()); - context->arrayType(context->structType(0, "VideoDeviceState", fields), 1, 0); - - fields.resize(3); - fields[0] = make_pair(string("name"), context->stringType()); - fields[1] = make_pair(string("description"), context->stringType()); - fields[2] = make_pair(string("type"), context->stringType()); - context->arrayType(context->structType(0, "IOParameter", fields), 1, 0); - - fields.resize(7); - fields[0] = make_pair(string("start"), context->intType()); - fields[1] = make_pair(string("end"), context->intType()); - fields[2] = make_pair(string("inc"), context->intType()); - fields[3] = make_pair(string("fps"), context->floatType()); - fields[4] = make_pair(string("cutIn"), context->intType()); - fields[5] = make_pair(string("cutOut"), context->intType()); - fields[6] = make_pair(string("isUndiscovered"), context->boolType()); - context->structType(0, "NodeRangeInfo", fields); - - fields.resize(6); - fields[0] = make_pair(string("name"), context->stringType()); - fields[1] = make_pair(string("type"), context->intType()); - fields[2] = make_pair(string("dimensions"), i4tupleType); - fields[3] = make_pair(string("size"), context->intType()); - fields[4] = make_pair(string("userDefined"), context->boolType()); - fields[5] = make_pair(string("info"), context->stringType()); - context->arrayType(context->structType(0, "PropertyInfo", fields), 1, 0); - - fields.resize(3); - fields[0] = make_pair(string("node"), context->stringType()); - fields[1] = make_pair(string("nodeType"), context->stringType()); - fields[2] = make_pair(string("frame"), context->intType()); - context->arrayType(context->structType(0, "MetaEvalInfo", fields), 1, 0); - - fields.resize(5); - fields[0] = make_pair(string("extension"), context->stringType()); - fields[1] = make_pair(string("description"), context->stringType()); - fields[2] = make_pair(string("capabilities"), context->intType()); - fields[3] = make_pair(string("imageCodecs"), stArray); - fields[4] = make_pair(string("audioCodecs"), stArray); - context->arrayType(context->structType(0, "IOFormat", fields), 1, 0); - - types.clear(); - types.push_back(context->stringType()); - types.push_back(context->arrayType(context->byteType(), 1, 0)); - context->arrayType(context->tupleType(types), 1, 0); - - types.clear(); - types.push_back(context->stringType()); // source name - types.push_back(context->intType()); // start frame - types.push_back(context->intType()); // end frame - types.push_back(context->intType()); // inc - types.push_back(context->floatType()); // fps - types.push_back(context->boolType()); // audio - types.push_back(context->boolType()); // video - st = context->tupleType(types); - context->arrayType(st, 1, 0); - - types.clear(); // cacheInfo() return tuple - types.push_back(context->int64Type()); // capacity in bytes - types.push_back(context->int64Type()); // used in bytes - types.push_back(context->int64Type()); // used in look ahead in bytes - types.push_back(context->floatType()); // seconds of look ahead cache - types.push_back(context->floatType()); // min seconds of look ahead cache requested by user - types.push_back(context->floatType()); // seconds of audio cached - types.push_back(context->arrayType(context->intType(), 1, 0)); // cached frame ranges - context->tupleType(types); - - types.clear(); // edl commands use (int,int,int) - types.push_back(context->intType()); - types.push_back(context->intType()); - types.push_back(context->intType()); - context->tupleType(types); - - types.clear(); // sourceMedia -> (string,string[],string[]) - types.push_back(context->stringType()); - types.push_back(context->arrayType(context->stringType(), 1, 0)); - types.push_back(context->arrayType(context->stringType(), 1, 0)); - context->tupleType(types); - - context->arrayType(context->intType(), 1, 0); - - types.erase(types.begin()); - context->tupleType(types); // (string[],string[]) - - commands->addSymbols(new SymbolicConstant(c, "RGB709", "int", Value(0)), - new SymbolicConstant(c, "CIEXYZ", "int", Value(1)), - - new SymbolicConstant(c, "PlayLoop", "int", Value(0)), - new SymbolicConstant(c, "PlayOnce", "int", Value(1)), - new SymbolicConstant(c, "PlayPingPong", "int", Value(2)), - - new SymbolicConstant(c, "OkImageStatus", "int", Value(Session::OkStatus)), - new SymbolicConstant(c, "ErrorImageStatus", "int", Value(Session::ErrorStatus)), - new SymbolicConstant(c, "WarningImageStatus", "int", Value(Session::WarningStatus)), - new SymbolicConstant(c, "NoImageStatus", "int", Value(Session::NoImageStatus)), - new SymbolicConstant(c, "PartialImageStatus", "int", Value(Session::PartialStatus)), - new SymbolicConstant(c, "LoadingImageStatus", "int", Value(Session::LoadingStatus)), - - new SymbolicConstant(c, "SequenceSession", "int", Value(Session::SequenceSession)), - new SymbolicConstant(c, "StackSession", "int", Value(Session::StackSession)), - - new SymbolicConstant(c, "CacheOff", "int", Value(Session::NeverCache)), - new SymbolicConstant(c, "CacheBuffer", "int", Value(Session::BufferCache)), - new SymbolicConstant(c, "CacheGreedy", "int", Value(Session::GreedyCache)), - - new SymbolicConstant(c, "IntType", "int", Value(Property::IntLayout)), - new SymbolicConstant(c, "FloatType", "int", Value(Property::FloatLayout)), - new SymbolicConstant(c, "HalfType", "int", Value(Property::HalfLayout)), - new SymbolicConstant(c, "StringType", "int", Value(Property::StringLayout)), - new SymbolicConstant(c, "ByteType", "int", Value(Property::ByteLayout)), - new SymbolicConstant(c, "ShortType", "int", Value(Property::ShortLayout)), - - new SymbolicConstant(c, "IndependentDisplayMode", "int", Value(VideoDevice::IndependentDisplayMode)), - new SymbolicConstant(c, "MirrorDisplayMode", "int", Value(VideoDevice::MirrorDisplayMode)), - new SymbolicConstant(c, "NotADisplayMode", "int", Value(VideoDevice::NotADisplayMode)), - - new SymbolicConstant(c, "VideoAndDataFormatID", "int", Value(VideoDevice::VideoAndDataFormatID)), - new SymbolicConstant(c, "DeviceNameID", "int", Value(VideoDevice::DeviceNameID)), - new SymbolicConstant(c, "ModuleNameID", "int", Value(VideoDevice::ModuleNameID)), - - EndArguments); - - commands->addSymbols( - - new Function(c, "data", data, None, - Return, "object", - End), - - new Function(c, "sources", sources, None, - Return, "(string,int,int,int,float,bool,bool)[]", - End), - - new Function(c, "sourceMedia", sourceMedia, None, - Return, "(string,string[],string[])", - Parameters, - new Param(c, "sourceName", "string"), - End), - - new Function(c, "sourcePixelValue", sourcePixelValue, None, - Return, "vector float[4]", - Parameters, - new Param(c, "sourceName", "string"), - new Param(c, "px", "float"), - new Param(c, "py", "float"), - End), - - new Function(c, "sourceAttributes", sourceAttributes, None, - Return, "(string,string)[]", - Parameters, - new Param(c, "sourceName", "string"), - new Param(c, "mediaName", "string", Value()), - End), - - new Function(c, "sourceDataAttributes", sourceDataAttributes, None, - Return, "(string,byte[])[]", - Parameters, - new Param(c, "sourceName", "string"), - new Param(c, "mediaName", "string", Value()), - End), - - new Function(c, "sourceDisplayChannelNames", - sourceDisplayChannelNames, None, - Parameters, - new Param(c, "sourceName", "string"), - Return, "string[]", - End), - - new Function(c, "getCurrentImageSize", getCurrentImageSize, - None, - Return, "vector float[2]", - End), - - new Function(c, "getCurrentPixelValue", getCurrentPixelValue, - None, - Return, "vector float[4]", - Parameters, - new Param(c, "point", "vector float[2]"), - End), - - new Function(c, "getCurrentAttributes", getCurrentAttributes, - None, - Return, "(string,string)[]", - End), - - new Function(c, "getCurrentImageChannelNames", - getCurrentImageChannelNames, - None, - Return, "string[]", - End), - - new Function(c, "getCurrentNodesOfType", - getCurrentNodesOfType, - None, - Parameters, - new Param(c, "typeName", "string"), - Return, "string[]", - End), - - new Function(c, "addSource", addSource, None, - Return, "void", - Parameters, - new Param(c, "fileName", "string"), - new Param(c, "tag", "string", Value()), - End), - - new Function(c, "addSource", addSourceMulti, None, - Return, "void", - Parameters, - new Param(c, "fileNames", "string[]"), - new Param(c, "tag", "string", Value()), - End), - - new Function(c, "addSourceVerbose", addSourceVerbose, None, - Return, "string", - Parameters, - new Param(c, "filePathsAndOptions", "string[]"), - new Param(c, "tag", "string", Value()), - End), - - new Function(c, "addSourceBegin", addSourceBegin, None, - Return, "void", - End), - - new Function(c, "addSourceEnd", addSourceEnd, None, - Return, "void", - End), - - new Function(c, "addSources", addSources, None, - Return, "void", - Parameters, - new Param(c, "fileNames", "string[]"), - new Param(c, "tag", "string", Value()), - new Param(c, "processOpts", "bool", Value(false)), - new Param(c, "merge", "bool", Value(false)), - End), - - new Function(c, "addSourcesVerbose", addSourcesVerbose, None, - Return, "string[]", - Parameters, - new Param(c, "filePathsAndOptions", "string[][]"), - new Param(c, "tag", "string", Value()), - End), - - new Function(c, "setProgressiveSourceLoading", setProgressiveSourceLoading, None, - Return, "void", - Parameters, - new Param(c, "enable", "bool"), - End), - - new Function(c, "progressiveSourceLoading", progressiveSourceLoading, None, - Return, "bool", - End), - - new Function(c, "newImageSource", newImageSource, None, - Return, "string", - Parameters, - new Param(c, "mediaName", "string"), - new Param(c, "width", "int"), - new Param(c, "height", "int"), - new Param(c, "uncropWidth", "int"), - new Param(c, "uncropHeight", "int"), - new Param(c, "uncropX", "int"), - new Param(c, "uncropY", "int"), - new Param(c, "pixelAspect", "float"), - new Param(c, "channels", "int"), - new Param(c, "bitsPerChannel", "int"), - new Param(c, "floatingPoint", "bool"), - new Param(c, "startFrame", "int"), - new Param(c, "endFrame", "int"), - new Param(c, "fps", "float"), - new Param(c, "layers", "string[]", Value()), - new Param(c, "views", "string[]", Value()), - End), - - new Function(c, "newImageSourcePixels", newImageSourcePixels, None, - Return, "string", - Parameters, - new Param(c, "sourceName", "string"), - new Param(c, "frame", "int"), - new Param(c, "layer", "string", Value()), - new Param(c, "view", "string", Value()), - End), - - new Function(c, "insertCreatePixelBlock", - insertCreatePixelBlock, None, - Return, "void", - Parameters, - new Param(c, "event", "Event"), - End), - - new Function(c, "addToSource", addToSource, None, - Return, "void", - Parameters, - new Param(c, "fileName", "string"), - new Param(c, "tag", "string", Value()), - End), - - new Function(c, "addToSource", addToSource2, None, - Return, "void", - Parameters, - new Param(c, "sourceNode", "string"), - new Param(c, "fileName", "string"), - new Param(c, "tag", "string"), - End), - - new Function(c, "setSourceMedia", setSourceMedia, None, - Return, "void", - Parameters, - new Param(c, "sourceNode", "string"), - new Param(c, "fileNames", "string[]"), - new Param(c, "tag", "string", Value()), - End), - - new Function(c, "addSourceMediaRep", addSourceMediaRep, None, - Return, "string", - Parameters, - new Param(c, "sourceNode", "string"), - new Param(c, "mediaRepName", "string"), - new Param(c, "mediaRepPathsAndOptions", "string[]"), - new Param(c, "tag", "string", Value()), - End), - - new Function(c, "setActiveSourceMediaRep", setActiveSourceMediaRep, None, - Return, "void", - Parameters, - new Param(c, "sourceNode", "string"), - new Param(c, "mediaRepName", "string"), - new Param(c, "tag", "string", Value()), - End), - - new Function(c, "sourceMediaRep", sourceMediaRep, None, - Return, "string", - Parameters, - new Param(c, "sourceNode", "string"), - End), - - new Function(c, "sourceMediaReps", sourceMediaReps, None, - Return, "string[]", - Parameters, - new Param(c, "sourceNode", "string"), - End), - - new Function(c, "sourceMediaRepsAndNodes", sourceMediaRepsAndNodes, None, - Return, "(string,string)[]", - Parameters, - new Param(c, "sourceOrSwitchNode", "string"), - End), - - new Function(c, "sourceMediaRepSwitchNode", sourceMediaRepSwitchNode, None, - Return, "string", - Parameters, - new Param(c, "sourceNode", "string"), - End), - - new Function(c, "sourceMediaRepSourceNode", sourceMediaRepSourceNode, None, - Return, "string", - Parameters, - new Param(c, "sourceNode", "string"), - End), - - new Function(c, "relocateSource", relocateSource, None, - Return, "void", - Parameters, - new Param(c, "oldFileName", "string"), - new Param(c, "newFileName", "string"), - End), - - new Function(c, "relocateSource", relocateSource2, None, - Return, "void", - Parameters, - new Param(c, "sourceNode", "string"), - new Param(c, "oldFileName", "string"), - new Param(c, "newFileName", "string"), - End), - - new Function(c, "commandLineFlag", commandLineFlag, None, - Return, "string", - Parameters, - new Param(c, "flagName", "string"), - new Param(c, "defaultValue", "string", Value(Pointer(0))), - End), - - new Function(c, "readLUT", readLUT, None, - Return, "void", - Parameters, - new Param(c, "filename", "string"), - new Param(c, "nodeName", "string"), - new Param(c, "activate", "bool", Value(false)), - End), - - new Function(c, "readCDL", readCDL, None, - Return, "void", - Parameters, - new Param(c, "filename", "string"), - new Param(c, "nodeName", "string"), - new Param(c, "activate", "bool", Value(false)), - End), - - new Function(c, "setSessionType", setSessionType, None, - Return, "void", - Parameters, - new Param(c, "sessionType", "int"), - End), - - new Function(c, "getSessionType", getSessionType, None, - Return, "int", - End), - - new Function(c, "startTimer", startTimer, - None, - Return, "void", - End), - - new Function(c, "elapsedTime", elapsedTime, - None, - Return, "float", - End), - - new Function(c, "theTime", theTime, - None, - Return, "float", - End), - - new Function(c, "stopTimer", stopTimer, - None, - Return, "float", - End), - - new Function(c, "isTimerRunning", isTimerRunning, - None, - Return, "bool", - End), - - new Function(c, "updateLUT", updateLUT, - None, - Return, "void", - End), - - new Function(c, "exportCurrentFrame", exportCurrentFrame, - None, - Return, "void", - Parameters, - new Param(c, "filename", "string"), - End), - - new Function(c, "exportCurrentSourceFrame", exportCurrentSourceFrame, - None, - Return, "void", - Parameters, - new Param(c, "filename", "string"), - End), - - new Function(c, "optionsPlay", optionsPlay, - None, - Return, "int", - End), - - new Function(c, "optionsPlayReset", optionsPlayReset, - None, - Return, "void", - End), - - new Function(c, "optionsNoPackages", optionsNoPackages, - None, - Return, "int", - End), - - new Function(c, "optionsProgressiveLoading", optionsProgressiveLoading, - None, - Return, "int", - End), - - new Function(c, "loadTotal", loadTotal, None, - Return, "int", - End), - - new Function(c, "loadCount", loadCount, None, - Return, "int", - End), - - new Function(c, "shortAppName", shortAppName, None, - Return, "string", - End), - - new Function(c, "ocioUpdateConfig", ocioUpdateConfig, None, - Return, "void", - Parameters, - new Param(c, "node", "string", Value(Pointer(0))), - End), - - new Function(c, "licensingState", licensingState, None, - Return, "int", - End), - - EndArguments); -} - -} // IPGraph + new Function(c, "optionsProgressiveLoading", + optionsProgressiveLoading, None, Return, "int", End), + + new Function(c, "loadTotal", loadTotal, None, Return, "int", End), + + new Function(c, "loadCount", loadCount, None, Return, "int", End), + + new Function(c, "shortAppName", shortAppName, None, Return, + "string", End), + + new Function(c, "ocioUpdateConfig", ocioUpdateConfig, None, Return, + "void", Parameters, + new Param(c, "node", "string", Value(Pointer(0))), + End), + + new Function(c, "licensingState", licensingState, None, Return, + "int", End), + + EndArguments); + } +} // namespace Rv diff --git a/src/lib/app/RvApp/FileSpaceLinearizeIPNode.cpp b/src/lib/app/RvApp/FileSpaceLinearizeIPNode.cpp index 84785f266..a6b5f1a14 100644 --- a/src/lib/app/RvApp/FileSpaceLinearizeIPNode.cpp +++ b/src/lib/app/RvApp/FileSpaceLinearizeIPNode.cpp @@ -1,9 +1,9 @@ //****************************************************************************** -// Copyright (c) 2005 Tweak Inc. +// Copyright (c) 2005 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #include #include @@ -22,525 +22,567 @@ #include #include -namespace IPCore { -using namespace std; -using namespace TwkContainer; -using namespace TwkMath; - -// -// LUTS: -// -// Luminance LUT: type == "Luminance", dimensions == 1 -// - -static inline Imath::V2f convert(Vec2f v) { return Imath::V2f(v.x, v.y); } -static inline Imath::V3f convert(Vec3f v) { return Imath::V3f(v.x, v.y, v.z); } -static inline Vec2f convert(Imath::V2f v) { return Vec2f(v.x, v.y); } -static inline Vec3f convert(Imath::V3f v) { return Vec3f(v.x, v.y, v.z); } - -static inline Mat44f convert(const Imath::M44f& m) -{ - return reinterpret_cast(&m)->transposed(); -} - -#define NO_FLOAT_3D_TEXTURES - -FileSpaceLinearizeIPNode::FileSpaceLinearizeIPNode(const std::string& name, - const NodeDefinition* def, - IPGraph* graph, - GroupIPNode* group) - : LUTIPNode(name, def, graph, group) -{ - setMaxInputs(1); - - m_colorAlphaType = declareProperty("color.alphaType", 0); - m_colorLogType = declareProperty("color.logtype", 0); - m_cineonWhite = declareProperty("cineon.whiteCodeValue", 0); - m_cineonBlack = declareProperty("cineon.blackCodeValue", 0); - m_cineonBreakPoint = declareProperty("cineon.breakPointValue", 0); - m_colorYUV = declareProperty("color.YUV", 0); - - // XXX we may have to always write these to file, since if they have been - // set to "Linear" for some reason (IE we have a linear DPX file or - // somethign), then when we load that session file, source_setup will think - // they need to be configured (since they were not set in file). - - m_colorsRGB2Linear = declareProperty("color.sRGB2linear", 0); - m_colorRec7092Linear = declareProperty("color.Rec709ToLinear", 0); - m_colorFileGamma = declareProperty("color.fileGamma", 1.0f); - m_colorActive = declareProperty("color.active", 1); - m_colorIgnoreChromaticities = declareProperty("color.ignoreChromaticities", 0); - m_CDLactive = declareProperty("CDL.active", 0); - m_CDLslope = declareProperty("CDL.slope", Vec3f(1.0f)); - m_CDLoffset = declareProperty("CDL.offset", Vec3f(0.0f)); - m_CDLpower = declareProperty("CDL.power", Vec3f(1.0f)); - m_CDLsaturation = declareProperty("CDL.saturation", 1.0f); - m_CDLnoclamp = declareProperty("CDL.noClamp", 0); -} - -FileSpaceLinearizeIPNode::~FileSpaceLinearizeIPNode() +namespace IPCore { -} + using namespace std; + using namespace TwkContainer; + using namespace TwkMath; + // + // LUTS: + // + // Luminance LUT: type == "Luminance", dimensions == 1 + // -void FileSpaceLinearizeIPNode::setLogLin(int t) { setProperty(m_colorLogType, t); } -void FileSpaceLinearizeIPNode::setSRGB(int t) { setProperty(m_colorsRGB2Linear, t); } -void FileSpaceLinearizeIPNode::setRec709(int t) { setProperty(m_colorRec7092Linear, t); } -void FileSpaceLinearizeIPNode::setFileGamma(float y) { setProperty(m_colorFileGamma, y); } + static inline Imath::V2f convert(Vec2f v) { return Imath::V2f(v.x, v.y); } + static inline Imath::V3f convert(Vec3f v) + { + return Imath::V3f(v.x, v.y, v.z); + } -IPImage* -FileSpaceLinearizeIPNode::evaluate(const Context& context) -{ - IPImage* head = IPNode::evaluate(context); + static inline Vec2f convert(Imath::V2f v) { return Vec2f(v.x, v.y); } - if (!head) return IPImage::newNoImage(this, "No Input"); + static inline Vec3f convert(Imath::V3f v) { return Vec3f(v.x, v.y, v.z); } - if ( !head->shaderExpr && head->children && head->noIntermediate ) + static inline Mat44f convert(const Imath::M44f& m) { - // If the head node has no shaderExpr, has children and does not - // support intermediate renders, we must explicitly loop over the - // children and apply the linearization logic to each of them. This - // usually happens in the context of a tiled-source. - size_t i = 0; - for (IPImage* child = head->children; child; child = child->next, i++) - { - evaluateOne( child, context ); - } - } - else - { - // - // If input to this node is a blend, prepare head for shaderExpr mods, - // etc. - // - convertBlendRenderTypeToIntermediate(head); - evaluateOne(head, context); + return reinterpret_cast(&m)->transposed(); } - return head; - -} - -void -FileSpaceLinearizeIPNode::evaluateOne(IPImage* img, const Context& context) -{ - Vec2f cred; - Vec2f cgreen; - Vec2f cblue; - Vec2f cwhite; - Vec2f cneutral; - bool rec709 = true; - bool xyzMatrix = false; - Mat44f RGBXYZ; - - // - // The intent of this CDL operation is for it to happen in "File Space", - // so do it before anything else. - // +#define NO_FLOAT_3D_TEXTURES - const bool active = propertyValue(m_colorActive, 1) != 0; - const bool CDLactive = propertyValue(m_CDLactive, 1) != 0; + FileSpaceLinearizeIPNode::FileSpaceLinearizeIPNode( + const std::string& name, const NodeDefinition* def, IPGraph* graph, + GroupIPNode* group) + : LUTIPNode(name, def, graph, group) + { + setMaxInputs(1); + + m_colorAlphaType = declareProperty("color.alphaType", 0); + m_colorLogType = declareProperty("color.logtype", 0); + m_cineonWhite = + declareProperty("cineon.whiteCodeValue", 0); + m_cineonBlack = + declareProperty("cineon.blackCodeValue", 0); + m_cineonBreakPoint = + declareProperty("cineon.breakPointValue", 0); + m_colorYUV = declareProperty("color.YUV", 0); + + // XXX we may have to always write these to file, since if they have + // been set to "Linear" for some reason (IE we have a linear DPX file or + // somethign), then when we load that session file, source_setup will + // think they need to be configured (since they were not set in file). + + m_colorsRGB2Linear = + declareProperty("color.sRGB2linear", 0); + m_colorRec7092Linear = + declareProperty("color.Rec709ToLinear", 0); + m_colorFileGamma = + declareProperty("color.fileGamma", 1.0f); + m_colorActive = declareProperty("color.active", 1); + m_colorIgnoreChromaticities = + declareProperty("color.ignoreChromaticities", 0); + m_CDLactive = declareProperty("CDL.active", 0); + m_CDLslope = declareProperty("CDL.slope", Vec3f(1.0f)); + m_CDLoffset = declareProperty("CDL.offset", Vec3f(0.0f)); + m_CDLpower = declareProperty("CDL.power", Vec3f(1.0f)); + m_CDLsaturation = + declareProperty("CDL.saturation", 1.0f); + m_CDLnoclamp = declareProperty("CDL.noClamp", 0); + } - Vec3f CDL_offset = propertyValue(m_CDLoffset, Vec3f(0.0f)); - Vec3f CDL_slope = propertyValue(m_CDLslope, Vec3f(1.0f)); - Vec3f CDL_power = propertyValue(m_CDLpower, Vec3f(1.0f)); - float CDL_saturation = propertyValue(m_CDLsaturation, 1.0f); + FileSpaceLinearizeIPNode::~FileSpaceLinearizeIPNode() {} - if (CDLactive && (CDL_offset != Vec3f(0.0f) || - CDL_slope != Vec3f(1.0f) || - CDL_power != Vec3f(1.0f) || - CDL_saturation != 1.0f)) + void FileSpaceLinearizeIPNode::setLogLin(int t) { - const bool noClamp = (propertyValue(m_CDLnoclamp, 0) != 0); - - img->shaderExpr = Shader::newColorCDL(img->shaderExpr, - CDL_slope, - CDL_offset, - CDL_power, - CDL_saturation, - noClamp); + setProperty(m_colorLogType, t); } - if (img->fb && img->fb->hasRGBtoXYZMatrix()) + void FileSpaceLinearizeIPNode::setSRGB(int t) { - RGBXYZ = img->fb->attribute(TwkFB::ColorSpace::RGBtoXYZMatrix()); - xyzMatrix = true; - rec709 = false; - - cwhite = Vec2f(0.3127f, 0.3290f); - cred = Vec2f(0.6400f, 0.3300f); - cgreen = Vec2f(0.3000f, 0.6000f); - cblue = Vec2f(0.1500f, 0.0600f); + setProperty(m_colorsRGB2Linear, t); } - else if (img->fb && img->fb->hasPrimaries()) + + void FileSpaceLinearizeIPNode::setRec709(int t) { - cwhite = img->fb->attribute(TwkFB::ColorSpace::WhitePrimary()); - cred = img->fb->attribute(TwkFB::ColorSpace::RedPrimary()); - cgreen = img->fb->attribute(TwkFB::ColorSpace::GreenPrimary()); - cblue = img->fb->attribute(TwkFB::ColorSpace::BluePrimary()); - rec709 = false; + setProperty(m_colorRec7092Linear, t); } - else + + void FileSpaceLinearizeIPNode::setFileGamma(float y) { - cwhite = Vec2f(0.3127f, 0.3290f); - cred = Vec2f(0.6400f, 0.3300f); - cgreen = Vec2f(0.3000f, 0.6000f); - cblue = Vec2f(0.1500f, 0.0600f); + setProperty(m_colorFileGamma, y); } - if (img->fb && img->fb->hasAdoptedNeutral()) + IPImage* FileSpaceLinearizeIPNode::evaluate(const Context& context) { - cneutral = img->fb->attribute(TwkFB::ColorSpace::AdoptedNeutral()); - rec709 = false; + IPImage* head = IPNode::evaluate(context); + + if (!head) + return IPImage::newNoImage(this, "No Input"); + + if (!head->shaderExpr && head->children && head->noIntermediate) + { + // If the head node has no shaderExpr, has children and does not + // support intermediate renders, we must explicitly loop over the + // children and apply the linearization logic to each of them. This + // usually happens in the context of a tiled-source. + size_t i = 0; + for (IPImage* child = head->children; child; + child = child->next, i++) + { + evaluateOne(child, context); + } + } + else + { + // + // If input to this node is a blend, prepare head for shaderExpr + // mods, etc. + // + convertBlendRenderTypeToIntermediate(head); + evaluateOne(head, context); + } + + return head; } - else + + void FileSpaceLinearizeIPNode::evaluateOne(IPImage* img, + const Context& context) { - cneutral = cwhite; - } + Vec2f cred; + Vec2f cgreen; + Vec2f cblue; + Vec2f cwhite; + Vec2f cneutral; + bool rec709 = true; + bool xyzMatrix = false; + Mat44f RGBXYZ; - Mat44f M = Rec709FullRangeRGBToYUV8(); - const float rw709 = M.m00; - const float gw709 = M.m01; - const float bw709 = M.m02; + // + // The intent of this CDL operation is for it to happen in "File + // Space", so do it before anything else. + // - bool alreadyUnpremulted = img->unpremulted; + const bool active = propertyValue(m_colorActive, 1) != 0; + const bool CDLactive = propertyValue(m_CDLactive, 1) != 0; - // - // Allow alpha type setting to be used regardless of color.active value - // + Vec3f CDL_offset = + propertyValue(m_CDLoffset, Vec3f(0.0f)); + Vec3f CDL_slope = propertyValue(m_CDLslope, Vec3f(1.0f)); + Vec3f CDL_power = propertyValue(m_CDLpower, Vec3f(1.0f)); + float CDL_saturation = + propertyValue(m_CDLsaturation, 1.0f); - if (IntProperty* atype = m_colorAlphaType) - { - if (atype->front() == 0) + if (CDLactive + && (CDL_offset != Vec3f(0.0f) || CDL_slope != Vec3f(1.0f) + || CDL_power != Vec3f(1.0f) || CDL_saturation != 1.0f)) { - if (img->fb) + const bool noClamp = + (propertyValue(m_CDLnoclamp, 0) != 0); + + img->shaderExpr = + Shader::newColorCDL(img->shaderExpr, CDL_slope, CDL_offset, + CDL_power, CDL_saturation, noClamp); + } + + if (img->fb && img->fb->hasRGBtoXYZMatrix()) + { + RGBXYZ = + img->fb->attribute(TwkFB::ColorSpace::RGBtoXYZMatrix()); + xyzMatrix = true; + rec709 = false; + + cwhite = Vec2f(0.3127f, 0.3290f); + cred = Vec2f(0.6400f, 0.3300f); + cgreen = Vec2f(0.3000f, 0.6000f); + cblue = Vec2f(0.1500f, 0.0600f); + } + else if (img->fb && img->fb->hasPrimaries()) + { + cwhite = + img->fb->attribute(TwkFB::ColorSpace::WhitePrimary()); + cred = img->fb->attribute(TwkFB::ColorSpace::RedPrimary()); + cgreen = + img->fb->attribute(TwkFB::ColorSpace::GreenPrimary()); + cblue = img->fb->attribute(TwkFB::ColorSpace::BluePrimary()); + rec709 = false; + } + else + { + cwhite = Vec2f(0.3127f, 0.3290f); + cred = Vec2f(0.6400f, 0.3300f); + cgreen = Vec2f(0.3000f, 0.6000f); + cblue = Vec2f(0.1500f, 0.0600f); + } + + if (img->fb && img->fb->hasAdoptedNeutral()) + { + cneutral = + img->fb->attribute(TwkFB::ColorSpace::AdoptedNeutral()); + rec709 = false; + } + else + { + cneutral = cwhite; + } + + Mat44f M = Rec709FullRangeRGBToYUV8(); + const float rw709 = M.m00; + const float gw709 = M.m01; + const float bw709 = M.m02; + + bool alreadyUnpremulted = img->unpremulted; + + // + // Allow alpha type setting to be used regardless of color.active value + // + + if (IntProperty* atype = m_colorAlphaType) + { + if (atype->front() == 0) { - if (const TwkFB::FBAttribute* a = - img->fb->findAttribute("AlphaType")) + if (img->fb) { - if (const TwkFB::StringAttribute* sa = - dynamic_cast(a)) + if (const TwkFB::FBAttribute* a = + img->fb->findAttribute("AlphaType")) { - alreadyUnpremulted = sa->value() == "Unpremultiplied"; + if (const TwkFB::StringAttribute* sa = + dynamic_cast(a)) + { + alreadyUnpremulted = + sa->value() == "Unpremultiplied"; + } } } } + else + { + alreadyUnpremulted = atype->front() == 2; + } } - else - { - alreadyUnpremulted = atype->front() == 2; - } - } - img->unpremulted = alreadyUnpremulted; + img->unpremulted = alreadyUnpremulted; - if (active) - { - if (IntProperty* loglin = m_colorLogType) + if (active) { - int logtype = loglin->front(); - - if (logtype == 1) // Kodak Cineon Log + if (IntProperty* loglin = m_colorLogType) { - double cinblack = 95; + int logtype = loglin->front(); - if (IntProperty* black = m_cineonBlack) + if (logtype == 1) // Kodak Cineon Log { - if (!black->empty() && black->front() != 0) - { - cinblack = black->front(); - } - else + double cinblack = 95; + + if (IntProperty* black = m_cineonBlack) { - if (img->fb) + if (!black->empty() && black->front() != 0) + { + cinblack = black->front(); + } + else { - if (const TwkFB::FloatAttribute* fattr = - dynamic_cast(img->fb->findAttribute(TwkFB::ColorSpace::BlackPoint()))) + if (img->fb) { - float ftmp = fattr->value(); - if (ftmp >= 1.0f) + if (const TwkFB::FloatAttribute* fattr = + dynamic_cast< + const TwkFB::FloatAttribute*>( + img->fb->findAttribute( + TwkFB::ColorSpace:: + BlackPoint()))) { - cinblack = (double) ftmp; + float ftmp = fattr->value(); + if (ftmp >= 1.0f) + { + cinblack = (double)ftmp; + } } } } } - } - double cinwhite = 685; - if (IntProperty* white = m_cineonWhite) - { - if (!white->empty() && white->front() != 0) - { - cinwhite = white->front(); - } - else + double cinwhite = 685; + if (IntProperty* white = m_cineonWhite) { - if (img->fb) + if (!white->empty() && white->front() != 0) { - if (const TwkFB::FloatAttribute* fattr = - dynamic_cast(img->fb->findAttribute(TwkFB::ColorSpace::WhitePoint()))) + cinwhite = white->front(); + } + else + { + if (img->fb) { - float ftmp = fattr->value(); - if (ftmp >= 1.0f) + if (const TwkFB::FloatAttribute* fattr = + dynamic_cast< + const TwkFB::FloatAttribute*>( + img->fb->findAttribute( + TwkFB::ColorSpace:: + WhitePoint()))) { - cinwhite = (double) ftmp; + float ftmp = fattr->value(); + if (ftmp >= 1.0f) + { + cinwhite = (double)ftmp; + } } } } } - } - double cinbreakpoint = cinwhite; - if (IntProperty* breakpoint = m_cineonBreakPoint) - { - if (!breakpoint->empty() && breakpoint->front() != 0) - { - cinbreakpoint = breakpoint->front(); - } - else + double cinbreakpoint = cinwhite; + if (IntProperty* breakpoint = m_cineonBreakPoint) { - if (img->fb) + if (!breakpoint->empty() && breakpoint->front() != 0) { - if (const TwkFB::FloatAttribute* fattr = - dynamic_cast(img->fb->findAttribute(TwkFB::ColorSpace::BreakPoint()))) + cinbreakpoint = breakpoint->front(); + } + else + { + if (img->fb) { - float ftmp = fattr->value(); - if (ftmp >= 1.0f) + if (const TwkFB::FloatAttribute* fattr = + dynamic_cast< + const TwkFB::FloatAttribute*>( + img->fb->findAttribute( + TwkFB::ColorSpace:: + BreakPoint()))) { - cinbreakpoint = (double) ftmp; + float ftmp = fattr->value(); + if (ftmp >= 1.0f) + { + cinbreakpoint = (double)ftmp; + } } } } } - } - img->shaderExpr = Shader::newColorCineonLogToLinear(img->shaderExpr, - cinblack, - cinwhite, - (cinwhite-cinbreakpoint)); - } - else if (logtype == 2) - { - img->shaderExpr = Shader::newColorViperLogToLinear(img->shaderExpr); - } - else if ((logtype == 3) || (logtype == 4)) // logC or logC_Film - { - if (logtype == 4) // logC_Film + img->shaderExpr = Shader::newColorCineonLogToLinear( + img->shaderExpr, cinblack, cinwhite, + (cinwhite - cinbreakpoint)); + } + else if (logtype == 2) { - // - // Undo the Film Style Matrix; this is done prior to linearizing the logC. - // - img->shaderExpr = Shader::newColorMatrix(img->shaderExpr, ArriFilmStyleInverseMatrix()); + img->shaderExpr = + Shader::newColorViperLogToLinear(img->shaderExpr); } + else if ((logtype == 3) || (logtype == 4)) // logC or logC_Film + { + if (logtype == 4) // logC_Film + { + // + // Undo the Film Style Matrix; this is done prior to + // linearizing the logC. + // + img->shaderExpr = Shader::newColorMatrix( + img->shaderExpr, + ArriFilmStyleInverseMatrix()); + } - TwkFB::LogCTransformParams params; + TwkFB::LogCTransformParams params; - TwkFB::getLogCCurveParams(params, img->fb); + TwkFB::getLogCCurveParams(params, img->fb); - img->shaderExpr = Shader::newColorLogCLinear(img->shaderExpr, - params.LogCBlackSignal, // pbs - params.LogCEncodingOffset, // eo - params.LogCEncodingGain, // eg - params.LogCGraySignal, // gs - params.LogCBlackOffset, // bo - params.LogCLinearSlope, // ls - params.LogCLinearOffset, // lo - params.LogCLinearCutPoint); // logc to linear cutoff - } - else if (logtype == 6) - { - img->shaderExpr = Shader::newColorRedLogToLinear(img->shaderExpr); - } - else if (logtype == 7) // RedLogFilm - { - // Red Log Film is Cineon Log - double cinblack = 95; - double cinwhite = 685; - double cinbreakpoint = cinwhite; - - img->shaderExpr = Shader::newColorCineonLogToLinear(img->shaderExpr, - cinblack, - cinwhite, - (cinwhite-cinbreakpoint)); + img->shaderExpr = Shader::newColorLogCLinear( + img->shaderExpr, + params.LogCBlackSignal, // pbs + params.LogCEncodingOffset, // eo + params.LogCEncodingGain, // eg + params.LogCGraySignal, // gs + params.LogCBlackOffset, // bo + params.LogCLinearSlope, // ls + params.LogCLinearOffset, // lo + params.LogCLinearCutPoint); // logc to linear cutoff + } + else if (logtype == 6) + { + img->shaderExpr = + Shader::newColorRedLogToLinear(img->shaderExpr); + } + else if (logtype == 7) // RedLogFilm + { + // Red Log Film is Cineon Log + double cinblack = 95; + double cinwhite = 685; + double cinbreakpoint = cinwhite; + + img->shaderExpr = Shader::newColorCineonLogToLinear( + img->shaderExpr, cinblack, cinwhite, + (cinwhite - cinbreakpoint)); + } } } - } - // - // FILE lut - // + // + // FILE lut + // - addLUTPipeline(context, img); + addLUTPipeline(context, img); - if (active) - { - if (IntProperty* srgb = m_colorsRGB2Linear) + if (active) { - if (srgb->size() && srgb->front()) + if (IntProperty* srgb = m_colorsRGB2Linear) { - img->shaderExpr = Shader::newColorSRGBToLinear(img->shaderExpr); + if (srgb->size() && srgb->front()) + { + img->shaderExpr = + Shader::newColorSRGBToLinear(img->shaderExpr); + } } - } - if (IntProperty* rec7092L = m_colorRec7092Linear) - { - if (rec7092L->size() && rec7092L->front()) + if (IntProperty* rec7092L = m_colorRec7092Linear) { - img->shaderExpr = Shader::newColorRec709ToLinear(img->shaderExpr); + if (rec7092L->size() && rec7092L->front()) + { + img->shaderExpr = + Shader::newColorRec709ToLinear(img->shaderExpr); + } } - } - if (FloatProperty* fileGamma = m_colorFileGamma) - { - Vec3f g = Vec3f(fileGamma->front()); - - if (g != Vec3f(1.0)) + if (FloatProperty* fileGamma = m_colorFileGamma) { - // if (g.x != 0.f) g.x = 1.0f / g.x; - // else g.x = Math::max(); - - // if (g.y != 0.f) g.y = 1.0f / g.y; - // else g.y = Math::max(); - - // if (g.z != 0.f) g.z = 1.0f / g.z; - // else g.z = Math::max(); - - img->shaderExpr = Shader::newColorGamma(img->shaderExpr, g); + Vec3f g = Vec3f(fileGamma->front()); + + if (g != Vec3f(1.0)) + { + // if (g.x != 0.f) g.x = 1.0f / g.x; + // else g.x = Math::max(); + + // if (g.y != 0.f) g.y = 1.0f / g.y; + // else g.y = Math::max(); + + // if (g.z != 0.f) g.z = 1.0f / g.z; + // else g.z = Math::max(); + + img->shaderExpr = Shader::newColorGamma(img->shaderExpr, g); + } } } - } - Mat44f C; - typedef TwkFB::TypedFBAttribute V2fAttr; + Mat44f C; + typedef TwkFB::TypedFBAttribute V2fAttr; - if (!rec709) - { - if (IntProperty* ignoreColorSpace = m_colorIgnoreChromaticities) + if (!rec709) { - if (ignoreColorSpace->front() == 0) + if (IntProperty* ignoreColorSpace = m_colorIgnoreChromaticities) { - Imf::Chromaticities chr709; - if (xyzMatrix) - { - Mat44f A; - TwkFB::colorSpaceConversionMatrix((const float*)&chr709, - (const float*)&chr709, - (const float*)&cneutral, - (const float*)&chr709.white, - true, - (float*)&A); - - Mat44f m1 = convert(XYZtoRGB(Imf::Chromaticities(), 1.0)); - C = m1 * A * RGBXYZ * C; - } - else + if (ignoreColorSpace->front() == 0) { - Imf::Chromaticities chr(convert(cred), - convert(cgreen), - convert(cblue), - convert(cwhite)); - TwkFB::colorSpaceConversionMatrix((const float*)&chr, - (const float*)&chr709, - (const float*)&cneutral, - (const float*)&chr709.white, - true, - (float*)&C); + Imf::Chromaticities chr709; + if (xyzMatrix) + { + Mat44f A; + TwkFB::colorSpaceConversionMatrix( + (const float*)&chr709, (const float*)&chr709, + (const float*)&cneutral, + (const float*)&chr709.white, true, (float*)&A); + + Mat44f m1 = + convert(XYZtoRGB(Imf::Chromaticities(), 1.0)); + C = m1 * A * RGBXYZ * C; + } + else + { + Imf::Chromaticities chr(convert(cred), convert(cgreen), + convert(cblue), + convert(cwhite)); + TwkFB::colorSpaceConversionMatrix( + (const float*)&chr, (const float*)&chr709, + (const float*)&cneutral, + (const float*)&chr709.white, true, (float*)&C); + } } } } - } - // We should investigate the real impact of this check. - if ( img->fb) - { - if (const TwkFB::FloatAttribute* lsa = - dynamic_cast ( - img->fb->findAttribute(TwkFB::ColorSpace::LinearScale()))) + // We should investigate the real impact of this check. + if (img->fb) { - Mat44f S; - Vec3f scl(lsa->value()); - S.makeScale(scl); - C = S * C; + if (const TwkFB::FloatAttribute* lsa = + dynamic_cast( + img->fb->findAttribute( + TwkFB::ColorSpace::LinearScale()))) + { + Mat44f S; + Vec3f scl(lsa->value()); + S.makeScale(scl); + C = S * C; + } } - } - if (IntProperty* yuv = m_colorYUV) - { - if (yuv->size() && yuv->front()) + if (IntProperty* yuv = m_colorYUV) { - // RGB -> YUV - // [0,1] -> [[0,1], [-.5,.5], [-.5,.5]] - // - // [ [ 0.299, 0.587, 0.114, 0 ] - // [ -0.168735891648, -0.331264108352, 0.5, 0. ] - // [ 0.5, -0.418687589158, -0.0813124108417, 0. ] - // [ 0, 0, 0, 1 ] ] - // - // inverse: - // [ [ 1., 2.8e-13, 1.402, 0. ] - // [ 1., -0.344136286201, -0.714136286201, 0. ] - // [ 1., 1.772, 5.4932e-13, 0. ] - // [ 0., 0., 0., 1. ] ] - // - // [ [ 1, 0, 0, 0 ] - // [ 0, 1, 0, -0.5 ] - // [ 0, 0, 1, -0.5 ] - // [ 0, 0, 0, 1 ] ] - // - - - Mat44f T(1., 0, 1.402, 0. , - 1., -0.344136286201, -0.714136286201, 0. , - 1., 1.772, 0, 0. , - 0., 0., 0., 1. ); - - C = T * C; + if (yuv->size() && yuv->front()) + { + // RGB -> YUV + // [0,1] -> [[0,1], [-.5,.5], [-.5,.5]] + // + // [ [ 0.299, 0.587, 0.114, 0 ] + // [ -0.168735891648, -0.331264108352, 0.5, 0. ] + // [ 0.5, -0.418687589158, -0.0813124108417, 0. ] + // [ 0, 0, 0, 1 ] + // ] + // + // inverse: + // [ [ 1., 2.8e-13, 1.402, 0. ] + // [ 1., -0.344136286201, -0.714136286201, 0. ] + // [ 1., 1.772, 5.4932e-13, 0. ] + // [ 0., 0., 0., 1. ] ] + // + // [ [ 1, 0, 0, 0 ] + // [ 0, 1, 0, -0.5 ] + // [ 0, 0, 1, -0.5 ] + // [ 0, 0, 0, 1 ] ] + // + + Mat44f T(1., 0, 1.402, 0., 1., -0.344136286201, -0.714136286201, + 0., 1., 1.772, 0, 0., 0., 0., 0., 1.); + + C = T * C; + } } - } - // - // XXX I think maybe this is wrong. The color changes applied here are - // not "artistic" and you would expect them to operate on the RGB values - // regardless of the alpha. I think. - // - // Yes, wrong - removing this for now. - // - - bool unpremult = false; // (C != Mat44f() && active) && !alreadyUnpremulted; - bool willPremult = unpremult || alreadyUnpremulted; - - if (unpremult) - { - // add unpremult shader - img->shaderExpr = Shader::newColorUnpremult(img->shaderExpr); - } - else if (willPremult) - { - // add stash alpha shader - } + // + // XXX I think maybe this is wrong. The color changes applied here are + // not "artistic" and you would expect them to operate on the RGB + // values regardless of the alpha. I think. + // + // Yes, wrong - removing this for now. + // - if (C != Mat44f() && active) - { - img->shaderExpr = Shader::newColorMatrix(img->shaderExpr, C); - } + bool unpremult = + false; // (C != Mat44f() && active) && !alreadyUnpremulted; + bool willPremult = unpremult || alreadyUnpremulted; - if (willPremult) - { - // premult shader if (unpremult) { - // We have done an earlier unpremult shader op because there was a - // color operation to perform. - img->shaderExpr = Shader::newColorPremultLight(img->shaderExpr); + // add unpremult shader + img->shaderExpr = Shader::newColorUnpremult(img->shaderExpr); } - else + else if (willPremult) { - img->shaderExpr = Shader::newColorPremult(img->shaderExpr); + // add stash alpha shader + } + + if (C != Mat44f() && active) + { + img->shaderExpr = Shader::newColorMatrix(img->shaderExpr, C); } - } -} + if (willPremult) + { + // premult shader + if (unpremult) + { + // We have done an earlier unpremult shader op because there was + // a color operation to perform. + img->shaderExpr = Shader::newColorPremultLight(img->shaderExpr); + } + else + { + img->shaderExpr = Shader::newColorPremult(img->shaderExpr); + } + } + } -} // Rv +} // namespace IPCore diff --git a/src/lib/app/RvApp/FormatIPNode.cpp b/src/lib/app/RvApp/FormatIPNode.cpp index e0c4623d6..2d9359b3f 100644 --- a/src/lib/app/RvApp/FormatIPNode.cpp +++ b/src/lib/app/RvApp/FormatIPNode.cpp @@ -1,9 +1,9 @@ //****************************************************************************** -// Copyright (c) 2005 Tweak Inc. +// Copyright (c) 2005 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #include @@ -19,672 +19,729 @@ #include #include -namespace IPCore { -using namespace TwkContainer; -using namespace TwkFB; -using namespace std; -using namespace TwkMath; +namespace IPCore +{ + using namespace TwkContainer; + using namespace TwkFB; + using namespace std; + using namespace TwkMath; -int FormatIPNode::defaultBitDepth = 0; // any depth -bool FormatIPNode::defaultAllowFP = true; -string FormatIPNode::defaultResampleMethod = "area"; + int FormatIPNode::defaultBitDepth = 0; // any depth + bool FormatIPNode::defaultAllowFP = true; + string FormatIPNode::defaultResampleMethod = "area"; -IPNode::ImageStructureInfo -outResFromParams(float w, float h, FormatIPNode::Params& s) -{ - float aspect; - float fx = w; - float fy = h; - - // - // Make sure that we don't wind up dividing by zero and having - // undefined or NaN values in the resulting ImageStructureInfo - // - // In particular if either of the incoming dimensions are 0 at - // this point, then try to preemptively use the fit parameters - // to create the aspect if they are both valid - // - // Otherwise we set aspect to 1.0 and use the following checks - // to construct the ImageStructureInfo - // - - if (fx == 0 || fy == 0) + IPNode::ImageStructureInfo outResFromParams(float w, float h, + FormatIPNode::Params& s) { - aspect = (s.xfit && s.yfit) ? float(s.xfit) / float(s.yfit) : 1.0; - } - else aspect = fx / fy; + float aspect; + float fx = w; + float fy = h; - if (s.xresize && !s.yresize) - { - fx = s.xresize; - fy = fx / aspect; - } - else if (s.yresize && !s.xresize) - { - fy = s.yresize; - fx = fy * aspect; - } - else if (s.xresize && s.yresize) - { - fx = s.xresize; - fy = s.yresize; - } - else if (s.xfit && !s.yfit) - { - fx = s.xfit; - fy = fx / aspect; - } - else if (s.yfit && !s.xfit) - { - fy = s.yfit; - fx = fy * aspect; - } - else if (s.xfit && s.yfit) - { - // the goal here is to make the output match the user specified - // s.xfit and s.yfit at least in one dimension - // but also make sure the output dimension does NOT exceed - // either s.xfit or s.yfit - float oaspect = float(s.xfit) / float(s.yfit); - if (oaspect >= aspect) + // + // Make sure that we don't wind up dividing by zero and having + // undefined or NaN values in the resulting ImageStructureInfo + // + // In particular if either of the incoming dimensions are 0 at + // this point, then try to preemptively use the fit parameters + // to create the aspect if they are both valid + // + // Otherwise we set aspect to 1.0 and use the following checks + // to construct the ImageStructureInfo + // + + if (fx == 0 || fy == 0) { - fy = s.yfit; - fx = fy * aspect; + aspect = (s.xfit && s.yfit) ? float(s.xfit) / float(s.yfit) : 1.0; } else + aspect = fx / fy; + + if (s.xresize && !s.yresize) + { + fx = s.xresize; + fy = fx / aspect; + } + else if (s.yresize && !s.xresize) + { + fy = s.yresize; + fx = fy * aspect; + } + else if (s.xresize && s.yresize) + { + fx = s.xresize; + fy = s.yresize; + } + else if (s.xfit && !s.yfit) { fx = s.xfit; fy = fx / aspect; } - } - else if (s.scale != 1.0) - { - fx *= s.scale; - fy *= s.scale; - } - - return IPNode::ImageStructureInfo(int(fx + 0.49f), int(fy + 0.49f), 1.0); -} - -FormatIPNode::FormatIPNode(const std::string& name, - const NodeDefinition* def, - IPGraph* g, - GroupIPNode* group) - : IPNode(name, def, g, group), - m_xmin(0), - m_xmax(0), - m_ymin(0), - m_ymax(0), - m_leftCrop(0), - m_rightCrop(0), - m_topCrop(0), - m_bottomCrop(0), - m_cropManip(0) -{ - setMaxInputs(1); - m_xfit = declareProperty("geometry.xfit", 0); - m_yfit = declareProperty("geometry.yfit", 0); - m_xresize = declareProperty("geometry.xresize", 0); - m_yresize = declareProperty("geometry.yresize", 0); - m_scale = declareProperty("geometry.scale", 1.0f); - m_resampleMethod = declareProperty("geometry.resampleMethod", defaultResampleMethod); - m_maxBitDepth = declareProperty("color.maxBitDepth", defaultBitDepth); - m_allowFloatingPoint = declareProperty("color.allowFloatingPoint", defaultAllowFP ? 1 : 0); - m_cropActive = declareProperty("crop.active", 0); - m_uncropActive = declareProperty("uncrop.active", 0); - m_uncropWidth = declareProperty("uncrop.width", 0); - m_uncropHeight = declareProperty("uncrop.height", 0); - m_uncropX = declareProperty("uncrop.x", 0); - m_uncropY = declareProperty("uncrop.y", 0); - - if (def->intValue("defaults.cropLRBT", 0) == 0) - { - m_xmin = declareProperty("crop.xmin", 0); - m_ymin = declareProperty("crop.ymin", 0); - m_xmax = declareProperty("crop.xmax", 0); - m_ymax = declareProperty("crop.ymax", 0); - } - else - { - m_leftCrop = declareProperty("crop.left", 0); - m_rightCrop = declareProperty("crop.right", 0); - m_topCrop = declareProperty("crop.top", 0); - m_bottomCrop = declareProperty("crop.bottom", 0); - - PropertyInfo* noSave = new PropertyInfo(PropertyInfo::NotPersistent); - m_cropManip = declareProperty("crop.manip", 0, noSave); - } - -} - -FormatIPNode::~FormatIPNode() -{ -} - -void -FormatIPNode::setCrop(int x0, int y0, int x1, int y1) -{ - if (m_xmin) - { - setProperty(m_xmin, x0); - setProperty(m_ymin, y0); - setProperty(m_xmax, x1); - setProperty(m_ymax, y1); - } - else - { - setProperty(m_leftCrop, x0); - setProperty(m_topCrop, y0); - setProperty(m_rightCrop, x1); - setProperty(m_bottomCrop, y1); - } - - setProperty(m_cropActive, 1); -} - -void -FormatIPNode::setUncrop(int w, int h, int x, int y) -{ - setProperty(m_uncropWidth, w); - setProperty(m_uncropHeight, h); - setProperty(m_uncropX, x); - setProperty(m_uncropY, y); - setProperty(m_uncropActive, 1); -} - -void -FormatIPNode::setFitResolution(int w, int h) -{ - setProperty(m_xfit, w); - setProperty(m_yfit, h); -} - -void -FormatIPNode::setResizeResolution(int w, int h) -{ - setProperty(m_xresize, w); - setProperty(m_yresize, h); -} - -void -FormatIPNode::outputDisconnect(IPNode* node) -{ - IPNode::outputDisconnect(node); -} - -static -FrameBuffer* -resizeImage(FrameBuffer* in, float sx, float sy, FrameBuffer::DataType outType) -{ - // - // sx here is really representing outWidth/inWidth (both integers), but - // due to imprecise representation of that rational number as a float, we - // _must_ round here to make sure we recover the correct outWidth and not - // outWidth-1. - // - int ow = int(0.49f + float(in->width()) * sx); - int oh = int(0.49f + float(in->height()) * sy); - - if (ow != in->width() || oh != in->height() || outType != in->dataType()) - { - /* - cout << "resize from " << in->width() << ", " << in->height() - << " to " << ow << ", " << oh << endl; - */ - - FrameBuffer* fb = new FrameBuffer(ow, oh, in->numChannels(), - outType, 0, &in->channelNames(), - in->orientation()); - if (fb->isRootPlane()) fb->idstream() << in->identifier(); - if (in->nextPlane()) fb->appendPlane(resizeImage(in->nextPlane(), sx, sy, outType)); - return fb; - } - else - { - return in; - } -} - - + else if (s.yfit && !s.xfit) + { + fy = s.yfit; + fx = fy * aspect; + } + else if (s.xfit && s.yfit) + { + // the goal here is to make the output match the user specified + // s.xfit and s.yfit at least in one dimension + // but also make sure the output dimension does NOT exceed + // either s.xfit or s.yfit + float oaspect = float(s.xfit) / float(s.yfit); + if (oaspect >= aspect) + { + fy = s.yfit; + fx = fy * aspect; + } + else + { + fx = s.xfit; + fy = fx / aspect; + } + } + else if (s.scale != 1.0) + { + fx *= s.scale; + fy *= s.scale; + } -FormatIPNode::Params -FormatIPNode::params() const -{ - Params s; - - s.floatOk = true; - s.scale = 1.0; - s.xfit = 0; - s.yfit = 0; - s.xresize = 0.0; - s.yresize = 0.0; - s.maxBitDepth = 32; - s.bestIntegral = FrameBuffer::USHORT; - s.bestFloat = FrameBuffer::FLOAT; - s.crop = false; - s.cropX0 = 0; - s.cropY0 = 0; - s.cropX1 = 0; - s.cropY1 = 0; - s.leftCrop = 0; - s.rightCrop = 0; - s.topCrop = 0; - s.bottomCrop = 0; - s.uncrop = false; - s.uncropWidth = 0; - s.uncropHeight = 0; - s.uncropX = 0; - s.uncropY = 0; - s.method = TwkFBAux::AreaInterpolation; - - if (const StringProperty* sp = m_resampleMethod) - { - if (sp->size()) + return IPNode::ImageStructureInfo(int(fx + 0.49f), int(fy + 0.49f), + 1.0); + } + + FormatIPNode::FormatIPNode(const std::string& name, + const NodeDefinition* def, IPGraph* g, + GroupIPNode* group) + : IPNode(name, def, g, group) + , m_xmin(0) + , m_xmax(0) + , m_ymin(0) + , m_ymax(0) + , m_leftCrop(0) + , m_rightCrop(0) + , m_topCrop(0) + , m_bottomCrop(0) + , m_cropManip(0) + { + setMaxInputs(1); + m_xfit = declareProperty("geometry.xfit", 0); + m_yfit = declareProperty("geometry.yfit", 0); + m_xresize = declareProperty("geometry.xresize", 0); + m_yresize = declareProperty("geometry.yresize", 0); + m_scale = declareProperty("geometry.scale", 1.0f); + m_resampleMethod = declareProperty( + "geometry.resampleMethod", defaultResampleMethod); + m_maxBitDepth = + declareProperty("color.maxBitDepth", defaultBitDepth); + m_allowFloatingPoint = declareProperty( + "color.allowFloatingPoint", defaultAllowFP ? 1 : 0); + m_cropActive = declareProperty("crop.active", 0); + m_uncropActive = declareProperty("uncrop.active", 0); + m_uncropWidth = declareProperty("uncrop.width", 0); + m_uncropHeight = declareProperty("uncrop.height", 0); + m_uncropX = declareProperty("uncrop.x", 0); + m_uncropY = declareProperty("uncrop.y", 0); + + if (def->intValue("defaults.cropLRBT", 0) == 0) + { + m_xmin = declareProperty("crop.xmin", 0); + m_ymin = declareProperty("crop.ymin", 0); + m_xmax = declareProperty("crop.xmax", 0); + m_ymax = declareProperty("crop.ymax", 0); + } + else { - if (sp->front() == "linear") s.method = TwkFBAux::LinearInterpolation; + m_leftCrop = declareProperty("crop.left", 0); + m_rightCrop = declareProperty("crop.right", 0); + m_topCrop = declareProperty("crop.top", 0); + m_bottomCrop = declareProperty("crop.bottom", 0); + + PropertyInfo* noSave = + new PropertyInfo(PropertyInfo::NotPersistent); + m_cropManip = declareProperty("crop.manip", 0, noSave); } } - if (const IntProperty* bdepth = m_maxBitDepth) - { - s.maxBitDepth = bdepth->front(); - - if (s.maxBitDepth >= 8 ) s.bestIntegral = FrameBuffer::UCHAR; - if (s.maxBitDepth >= 16) s.bestIntegral = FrameBuffer::USHORT; - if (s.maxBitDepth >= 32) s.bestIntegral = FrameBuffer::UINT; - } + FormatIPNode::~FormatIPNode() {} - if (const IntProperty* allowFloat = m_allowFloatingPoint) + void FormatIPNode::setCrop(int x0, int y0, int x1, int y1) { - s.floatOk = allowFloat->front() == 0 ? false : true; - s.floatOk = ImageRenderer::hasFloatFormats() ? s.floatOk : false; - - if (s.floatOk) + if (m_xmin) { - if (s.maxBitDepth >= 16) s.bestFloat = FrameBuffer::HALF; - if (s.maxBitDepth >= 32) s.bestFloat = FrameBuffer::FLOAT; + setProperty(m_xmin, x0); + setProperty(m_ymin, y0); + setProperty(m_xmax, x1); + setProperty(m_ymax, y1); } else { - s.bestFloat = s.bestIntegral; + setProperty(m_leftCrop, x0); + setProperty(m_topCrop, y0); + setProperty(m_rightCrop, x1); + setProperty(m_bottomCrop, y1); } + + setProperty(m_cropActive, 1); } - if (const FloatProperty* scaleP = m_scale) + void FormatIPNode::setUncrop(int w, int h, int x, int y) { - s.scale = scaleP->front(); + setProperty(m_uncropWidth, w); + setProperty(m_uncropHeight, h); + setProperty(m_uncropX, x); + setProperty(m_uncropY, y); + setProperty(m_uncropActive, 1); } - if (const IntProperty* xfit = m_xfit) + void FormatIPNode::setFitResolution(int w, int h) { - s.xfit = xfit->front(); + setProperty(m_xfit, w); + setProperty(m_yfit, h); } - if (const IntProperty* yfit = m_yfit) + void FormatIPNode::setResizeResolution(int w, int h) { - s.yfit = yfit->front(); + setProperty(m_xresize, w); + setProperty(m_yresize, h); } - if (const IntProperty* xresize = m_xresize) + void FormatIPNode::outputDisconnect(IPNode* node) { - s.xresize = xresize->front(); + IPNode::outputDisconnect(node); } - if (const IntProperty* yresize = m_yresize) + static FrameBuffer* resizeImage(FrameBuffer* in, float sx, float sy, + FrameBuffer::DataType outType) { - s.yresize = yresize->front(); + // + // sx here is really representing outWidth/inWidth (both integers), but + // due to imprecise representation of that rational number as a float, + // we _must_ round here to make sure we recover the correct outWidth + // and not outWidth-1. + // + int ow = int(0.49f + float(in->width()) * sx); + int oh = int(0.49f + float(in->height()) * sy); + + if (ow != in->width() || oh != in->height() + || outType != in->dataType()) + { + /* + cout << "resize from " << in->width() << ", " << in->height() + << " to " << ow << ", " << oh << endl; + */ + + FrameBuffer* fb = + new FrameBuffer(ow, oh, in->numChannels(), outType, 0, + &in->channelNames(), in->orientation()); + if (fb->isRootPlane()) + fb->idstream() << in->identifier(); + if (in->nextPlane()) + fb->appendPlane(resizeImage(in->nextPlane(), sx, sy, outType)); + return fb; + } + else + { + return in; + } } - s.crop = propertyValue(m_cropActive, 0) && !propertyValue(m_cropManip, 0); + FormatIPNode::Params FormatIPNode::params() const + { + Params s; + + s.floatOk = true; + s.scale = 1.0; + s.xfit = 0; + s.yfit = 0; + s.xresize = 0.0; + s.yresize = 0.0; + s.maxBitDepth = 32; + s.bestIntegral = FrameBuffer::USHORT; + s.bestFloat = FrameBuffer::FLOAT; + s.crop = false; + s.cropX0 = 0; + s.cropY0 = 0; + s.cropX1 = 0; + s.cropY1 = 0; + s.leftCrop = 0; + s.rightCrop = 0; + s.topCrop = 0; + s.bottomCrop = 0; + s.uncrop = false; + s.uncropWidth = 0; + s.uncropHeight = 0; + s.uncropX = 0; + s.uncropY = 0; + s.method = TwkFBAux::AreaInterpolation; + + if (const StringProperty* sp = m_resampleMethod) + { + if (sp->size()) + { + if (sp->front() == "linear") + s.method = TwkFBAux::LinearInterpolation; + } + } - if (const IntProperty* x0 = m_xmin) - { - s.cropX0 = x0->front(); - } + if (const IntProperty* bdepth = m_maxBitDepth) + { + s.maxBitDepth = bdepth->front(); + + if (s.maxBitDepth >= 8) + s.bestIntegral = FrameBuffer::UCHAR; + if (s.maxBitDepth >= 16) + s.bestIntegral = FrameBuffer::USHORT; + if (s.maxBitDepth >= 32) + s.bestIntegral = FrameBuffer::UINT; + } - if (m_leftCrop) s.leftCrop = m_leftCrop->front(); - if (m_rightCrop) s.rightCrop = m_rightCrop->front(); - if (m_topCrop) s.topCrop = m_topCrop->front(); - if (m_bottomCrop) s.bottomCrop = m_bottomCrop->front(); + if (const IntProperty* allowFloat = m_allowFloatingPoint) + { + s.floatOk = allowFloat->front() == 0 ? false : true; + s.floatOk = ImageRenderer::hasFloatFormats() ? s.floatOk : false; - if (const IntProperty* x1 = m_xmax) - { - s.cropX1 = x1->front(); - } + if (s.floatOk) + { + if (s.maxBitDepth >= 16) + s.bestFloat = FrameBuffer::HALF; + if (s.maxBitDepth >= 32) + s.bestFloat = FrameBuffer::FLOAT; + } + else + { + s.bestFloat = s.bestIntegral; + } + } - if (const IntProperty* y0 = m_ymin) - { - s.cropY0 = y0->front(); - } + if (const FloatProperty* scaleP = m_scale) + { + s.scale = scaleP->front(); + } - if (const IntProperty* y1 = m_ymax) - { - s.cropY1 = y1->front(); - } + if (const IntProperty* xfit = m_xfit) + { + s.xfit = xfit->front(); + } - if (const IntProperty* a = m_uncropActive) - { - s.uncrop = a->front() != 0; - } + if (const IntProperty* yfit = m_yfit) + { + s.yfit = yfit->front(); + } - if (const IntProperty* w = m_uncropWidth) - { - s.uncropWidth = w->front(); - } + if (const IntProperty* xresize = m_xresize) + { + s.xresize = xresize->front(); + } - if (const IntProperty* h = m_uncropHeight) - { - s.uncropHeight = h->front(); - } + if (const IntProperty* yresize = m_yresize) + { + s.yresize = yresize->front(); + } - if (const IntProperty* x = m_uncropX) - { - s.uncropX = x->front(); - } + s.crop = + propertyValue(m_cropActive, 0) && !propertyValue(m_cropManip, 0); - if (const IntProperty* y = m_uncropY) - { - s.uncropY = y->front(); - } + if (const IntProperty* x0 = m_xmin) + { + s.cropX0 = x0->front(); + } - return s; -} + if (m_leftCrop) + s.leftCrop = m_leftCrop->front(); + if (m_rightCrop) + s.rightCrop = m_rightCrop->front(); + if (m_topCrop) + s.topCrop = m_topCrop->front(); + if (m_bottomCrop) + s.bottomCrop = m_bottomCrop->front(); -IPImage* -FormatIPNode::evaluate(const Context& context) -{ - int frame = context.frame; - IPImage* head = IPNode::evaluate(context); - IPImage* img = head; + if (const IntProperty* x1 = m_xmax) + { + s.cropX1 = x1->front(); + } - if (!head) return 0; + if (const IntProperty* y0 = m_ymin) + { + s.cropY0 = y0->front(); + } - Params s = params(); + if (const IntProperty* y1 = m_ymax) + { + s.cropY1 = y1->front(); + } - if (FrameBuffer* in = img->fb) - { - FrameBuffer::DataType outType; - FrameBuffer::DataType inType = in->dataType(); + if (const IntProperty* a = m_uncropActive) + { + s.uncrop = a->front() != 0; + } - int originalWidth = in->width(); - int originalHeight = in->height(); + if (const IntProperty* w = m_uncropWidth) + { + s.uncropWidth = w->front(); + } - if (inType == FrameBuffer::PACKED_R10_G10_B10_X2 || - inType == FrameBuffer::PACKED_X2_B10_G10_R10 || - inType == FrameBuffer::PACKED_Y8_Cb8_Y8_Cr8 || - inType == FrameBuffer::PACKED_Cb8_Y8_Cr8_Y8) + if (const IntProperty* h = m_uncropHeight) { - outType = inType; + s.uncropHeight = h->front(); } - else + + if (const IntProperty* x = m_uncropX) { - if (inType >= FrameBuffer::HALF) - { - outType = (inType > s.bestFloat) ? s.bestFloat : inType; - } - else - { - outType = (inType > s.bestIntegral) ? s.bestIntegral : inType; - } - - if (ImageRenderer::fbAcceptableTypes().count(outType) == 0) - { - outType = FrameBuffer::UCHAR; - } + s.uncropX = x->front(); } - if (s.scale == 1.0f && - s.xfit == 0 && s.yfit == 0 && - s.xresize == 0 && s.yresize == 0) + if (const IntProperty* y = m_uncropY) { - if (s.crop) - { - FrameBuffer* cfb = 0; + s.uncropY = y->front(); + } - try - { - bool sameType = (in->dataType() == outType); - if (m_xmin) - { - cfb = crop(in, s.cropX0, s.cropY0, s.cropX1, s.cropY1); - } - else - { - cfb = crop(in, - s.leftCrop, - s.bottomCrop, - in->width() - s.rightCrop - 1, - in->height() - s.topCrop - 1); - } + return s; + } - cfb->setIdentifier(in->identifier()); - in->copyAttributesTo(cfb); - cfb->setPixelAspectRatio(in->pixelAspectRatio()); - img->fb = cfb; - delete in; - in = cfb; + IPImage* FormatIPNode::evaluate(const Context& context) + { + int frame = context.frame; + IPImage* head = IPNode::evaluate(context); + IPImage* img = head; - // Adjust the img header's width and height accordingly since - // we've just replaced its underlying FrameBuffer - img->width = cfb->width(); - img->height = cfb->height(); + if (!head) + return 0; - // - // Crop may have changed in's dataType. If we had - // previously matched inType to outType, make sure we do - // so again. - // - if (sameType) outType = in->dataType(); - } - catch (...) - { - // just ignore bad params here - } - } + Params s = params(); - if (in->dataType() != outType && - in->dataType() != FrameBuffer::PACKED_Cb8_Y8_Cr8_Y8 && - in->dataType() != FrameBuffer::PACKED_Y8_Cb8_Y8_Cr8) - { - FrameBuffer* fb = 0; + if (FrameBuffer* in = img->fb) + { + FrameBuffer::DataType outType; + FrameBuffer::DataType inType = in->dataType(); + + int originalWidth = in->width(); + int originalHeight = in->height(); - if (in->isYRYBYPlanar() || in->isYRYBY()) + if (inType == FrameBuffer::PACKED_R10_G10_B10_X2 + || inType == FrameBuffer::PACKED_X2_B10_G10_R10 + || inType == FrameBuffer::PACKED_Y8_Cb8_Y8_Cr8 + || inType == FrameBuffer::PACKED_Cb8_Y8_Cr8_Y8) + { + outType = inType; + } + else + { + if (inType >= FrameBuffer::HALF) { - fb = copyConvertYRYBYtoYUV(in, outType); + outType = (inType > s.bestFloat) ? s.bestFloat : inType; } else { - fb = copyConvert(in, outType); + outType = + (inType > s.bestIntegral) ? s.bestIntegral : inType; } - in->copyAttributesTo(fb); - fb->setPixelAspectRatio(in->pixelAspectRatio()); - img->fb = fb; - img->fb->setIdentifier(in->identifier()); - delete in; - } - else - { - // mR - 10/28/07 - // make sure our identifier is set - img->fb->setIdentifier(in->identifier()); + if (ImageRenderer::fbAcceptableTypes().count(outType) == 0) + { + outType = FrameBuffer::UCHAR; + } } - } - else - { - // - // scale and/or fit - // - if (s.crop) + if (s.scale == 1.0f && s.xfit == 0 && s.yfit == 0 && s.xresize == 0 + && s.yresize == 0) { - FrameBuffer* cfb = 0; + if (s.crop) + { + FrameBuffer* cfb = 0; + + try + { + bool sameType = (in->dataType() == outType); + if (m_xmin) + { + cfb = crop(in, s.cropX0, s.cropY0, s.cropX1, + s.cropY1); + } + else + { + cfb = crop(in, s.leftCrop, s.bottomCrop, + in->width() - s.rightCrop - 1, + in->height() - s.topCrop - 1); + } + + cfb->setIdentifier(in->identifier()); + in->copyAttributesTo(cfb); + cfb->setPixelAspectRatio(in->pixelAspectRatio()); + img->fb = cfb; + delete in; + in = cfb; + + // Adjust the img header's width and height accordingly + // since we've just replaced its underlying FrameBuffer + img->width = cfb->width(); + img->height = cfb->height(); + + // + // Crop may have changed in's dataType. If we had + // previously matched inType to outType, make sure we + // do so again. + // + if (sameType) + outType = in->dataType(); + } + catch (...) + { + // just ignore bad params here + } + } - try + if (in->dataType() != outType + && in->dataType() != FrameBuffer::PACKED_Cb8_Y8_Cr8_Y8 + && in->dataType() != FrameBuffer::PACKED_Y8_Cb8_Y8_Cr8) { - bool sameType = (in->dataType() == outType); - if (m_xmin) + FrameBuffer* fb = 0; + + if (in->isYRYBYPlanar() || in->isYRYBY()) { - cfb = crop(in, s.cropX0, s.cropY0, s.cropX1, s.cropY1); + fb = copyConvertYRYBYtoYUV(in, outType); } else { - cfb = crop(in, - s.leftCrop, - s.bottomCrop, - in->width() - s.rightCrop - 1, - in->height() - s.topCrop - 1); + fb = copyConvert(in, outType); } - cfb->setIdentifier(in->identifier()); - in->copyAttributesTo(cfb); - cfb->setPixelAspectRatio(in->pixelAspectRatio()); - img->fb = cfb; - delete in; - in = cfb; - // Adjust the img header's width and height accordingly since - // we've just replaced its underlying FrameBuffer - img->width = cfb->width(); - img->height = cfb->height(); - - // - // Crop may have changed in's dataType. If we had - // previously matched inType to outType, make sure we do - // so again. - // - if (sameType) outType = in->dataType(); + in->copyAttributesTo(fb); + fb->setPixelAspectRatio(in->pixelAspectRatio()); + img->fb = fb; + img->fb->setIdentifier(in->identifier()); + delete in; } - catch (...) + else { - // ignore bad crop parameters + // mR - 10/28/07 + // make sure our identifier is set + img->fb->setIdentifier(in->identifier()); } } - - ImageStructureInfo ii; - float scalex = 1.0; - float scaley = 1.0; - - if (s.uncrop) + else { // - // Don't totally understand this. It loooks - // like the image will be scaled appropriately - // for the uncrop later by - // CompositeRenderer::initializePlane(), so if - // we do it here we get a double scale. - // - // ii = outResFromParams(s.uncropWidth, s.uncropHeight, s); - // scale = float(ii.width) / float(s.uncropWidth); + // scale and/or fit // -// cout << "s.uncrop = " << s.uncropWidth << ", " << s.uncropHeight -// << ", scale = " << scale << endl; -// cout << "fit = " << s.xfit << ", " << s.yfit << endl; - } - else if (in->width() && in->height()) - { - ii = outResFromParams(in->width(), in->height(), s); - scalex = float(ii.width) / float(in->width()); - scaley = float(ii.height) / float(in->height()); - } + if (s.crop) + { + FrameBuffer* cfb = 0; - if (inType == FrameBuffer::PACKED_Cb8_Y8_Cr8_Y8 || - inType == FrameBuffer::PACKED_Y8_Cb8_Y8_Cr8) - { - FrameBuffer* fb0 = convertToLinearRGB709(in); - FrameBuffer* fb1 = resizeImage(fb0, scalex, scaley, FrameBuffer::UCHAR); + try + { + bool sameType = (in->dataType() == outType); + if (m_xmin) + { + cfb = crop(in, s.cropX0, s.cropY0, s.cropX1, + s.cropY1); + } + else + { + cfb = crop(in, s.leftCrop, s.bottomCrop, + in->width() - s.rightCrop - 1, + in->height() - s.topCrop - 1); + } + cfb->setIdentifier(in->identifier()); + in->copyAttributesTo(cfb); + cfb->setPixelAspectRatio(in->pixelAspectRatio()); + img->fb = cfb; + delete in; + in = cfb; + + // Adjust the img header's width and height accordingly + // since we've just replaced its underlying FrameBuffer + img->width = cfb->width(); + img->height = cfb->height(); + + // + // Crop may have changed in's dataType. If we had + // previously matched inType to outType, make sure we + // do so again. + // + if (sameType) + outType = in->dataType(); + } + catch (...) + { + // ignore bad crop parameters + } + } + + ImageStructureInfo ii; + float scalex = 1.0; + float scaley = 1.0; - if (fb0 != fb1) + if (s.uncrop) { - TwkFBAux::resize(fb0, fb1); - img->fb = fb1; - delete fb0; + // + // Don't totally understand this. It loooks + // like the image will be scaled appropriately + // for the uncrop later by + // CompositeRenderer::initializePlane(), so if + // we do it here we get a double scale. + // + // ii = outResFromParams(s.uncropWidth, s.uncropHeight, s); + // scale = float(ii.width) / float(s.uncropWidth); + // + + // cout << "s.uncrop = " << + // s.uncropWidth << ", " << + // s.uncropHeight + // << ", scale = " << scale << + // endl; + // cout << "fit = " << s.xfit << ", " << + // s.yfit << endl; } - else + else if (in->width() && in->height()) { - img->fb = fb0; + ii = outResFromParams(in->width(), in->height(), s); + scalex = float(ii.width) / float(in->width()); + scaley = float(ii.height) / float(in->height()); } - // Adjust the img header's width and height accordingly since - // we've just replaced its underlying FrameBuffer - img->width = img->fb->width(); - img->height = img->fb->height(); - } - else if (inType == outType) - { - FrameBuffer* fb = resizeImage(in, scalex, scaley, outType); - - if (fb != in) + if (inType == FrameBuffer::PACKED_Cb8_Y8_Cr8_Y8 + || inType == FrameBuffer::PACKED_Y8_Cb8_Y8_Cr8) { - TwkFBAux::resize(in, fb); + FrameBuffer* fb0 = convertToLinearRGB709(in); + FrameBuffer* fb1 = + resizeImage(fb0, scalex, scaley, FrameBuffer::UCHAR); + + if (fb0 != fb1) + { + TwkFBAux::resize(fb0, fb1); + img->fb = fb1; + delete fb0; + } + else + { + img->fb = fb0; + } + + // Adjust the img header's width and height accordingly + // since we've just replaced its underlying FrameBuffer + img->width = img->fb->width(); + img->height = img->fb->height(); } + else if (inType == outType) + { + FrameBuffer* fb = resizeImage(in, scalex, scaley, outType); - img->fb = fb; - - //Avoid the off by one error - img->width = int(0.49f + (float(img->width)) * scalex); - img->height = int(0.49f + (float(img->height)) * scaley); - } - else - { - FrameBuffer* fb0 = resizeImage(in, scalex, scaley, outType); - FrameBuffer* fb1 = 0; + if (fb != in) + { + TwkFBAux::resize(in, fb); + } + + img->fb = fb; - if (fb0 != in) + // Avoid the off by one error + img->width = int(0.49f + (float(img->width)) * scalex); + img->height = int(0.49f + (float(img->height)) * scaley); + } + else { - TwkFBAux::resize(in, fb0); + FrameBuffer* fb0 = resizeImage(in, scalex, scaley, outType); + FrameBuffer* fb1 = 0; - if (in->isYRYBYPlanar() || in->isYRYBY()) + if (fb0 != in) { - fb1 = copyConvertYRYBYtoYUV(fb0, outType); + TwkFBAux::resize(in, fb0); + + if (in->isYRYBYPlanar() || in->isYRYBY()) + { + fb1 = copyConvertYRYBYtoYUV(fb0, outType); + } + else + { + fb1 = copyConvert(fb0, outType); + } + + img->fb = fb1; + delete fb0; } else { - fb1 = copyConvert(fb0, outType); + img->fb = in; } - img->fb = fb1; - delete fb0; + // Adjust the img header's width and height accordingly + // since we've just replaced its underlying FrameBuffer + img->width = img->fb->width(); + img->height = img->fb->height(); } - else + img->fb->setUncrop(int(scalex * in->uncropWidth() + 0.49f), + int(scaley * in->uncropHeight() + 0.49f), + int(scalex * in->uncropX() + 0.49f), + int(scaley * in->uncropY() + 0.49f)); + + img->fb->setUncropActive(in->uncrop()); + in->copyAttributesTo(img->fb); + img->fb->setIdentifier(in->identifier()); + img->fb->setPixelAspectRatio(in->pixelAspectRatio()); + if (in != img->fb) + delete in; + } + + if (s.uncrop) + { + img->fb->setUncrop(s.uncropWidth, s.uncropHeight, s.uncropX, + s.uncropY); + img->fb->setUncropActive(in->uncrop()); + img->width = s.uncropWidth; + img->height = s.uncropHeight; + } + + if (s.scale != 1.0f || s.bestFloat != FrameBuffer::FLOAT + || s.bestIntegral != FrameBuffer::USHORT || s.xfit || s.yfit + || s.xresize || s.yresize || s.crop || s.uncrop) + { + // + // NOTE: you can just get rid of xfit and yfit here and + // use a single scale value: you don't in principle know + // the resolution here that the xfit and yfit are + // relative to, so you have to include them in the hash + // + + img->fb->idstream() + << ":fmt/s" << s.scale << ":f" << s.bestFloat << ":i" + << s.bestIntegral << ":r" << s.method << ":xf" << s.xfit + << ":yf" << s.yfit << ":xr" << s.xresize << ":yr" + << s.yresize; + + if (s.crop) { - img->fb = in; + img->fb->idstream() << ":c" + << "+" << s.cropX0 << "+" << s.cropY0 + << "+" << s.cropX1 << "+" << s.cropY1; } - // Adjust the img header's width and height accordingly since - // we've just replaced its underlying FrameBuffer - img->width = img->fb->width(); - img->height = img->fb->height(); + if (s.uncrop) + { + img->fb->idstream() + << ":u" + << "+" << s.uncropWidth << "+" << s.uncropHeight << "+" + << s.uncropX << "+" << s.uncropY; + } } - img->fb->setUncrop(int(scalex*in->uncropWidth() + 0.49f), - int(scaley*in->uncropHeight() + 0.49f), - int(scalex*in->uncropX() + 0.49f), - int(scaley*in->uncropY() + 0.49f)); - - img->fb->setUncropActive(in->uncrop()); - in->copyAttributesTo(img->fb); - img->fb->setIdentifier(in->identifier()); - img->fb->setPixelAspectRatio(in->pixelAspectRatio()); - if (in != img->fb) delete in; } - if (s.uncrop) - { - img->fb->setUncrop(s.uncropWidth, s.uncropHeight, s.uncropX, s.uncropY); - img->fb->setUncropActive(in->uncrop()); - img->width = s.uncropWidth; - img->height = s.uncropHeight; - } + return head; + } - if (s.scale != 1.0f || - s.bestFloat != FrameBuffer::FLOAT || - s.bestIntegral != FrameBuffer::USHORT || - s.xfit || - s.yfit || - s.xresize || - s.yresize || - s.crop || - s.uncrop) + IPImageID* FormatIPNode::evaluateIdentifier(const Context& context) + { + IPImageID* imgid = IPNode::evaluateIdentifier(context); + float scale = 1.0f; + int depth = 0; + + Params p = params(); + + IPImageID* i = imgid; + ostringstream str; + + if (p.scale != 1.0f || p.bestFloat != FrameBuffer::FLOAT + || p.bestIntegral != FrameBuffer::USHORT || p.xfit || p.yfit + || p.xresize || p.yresize || p.crop || p.uncrop) { // // NOTE: you can just get rid of xfit and yfit here and @@ -693,146 +750,75 @@ FormatIPNode::evaluate(const Context& context) // relative to, so you have to include them in the hash // - img->fb->idstream() << ":fmt/s" << s.scale - << ":f" << s.bestFloat - << ":i" << s.bestIntegral - << ":r" << s.method - << ":xf" << s.xfit - << ":yf" << s.yfit - << ":xr" << s.xresize - << ":yr" << s.yresize; + str << i->id; - if (s.crop) + str << ":fmt/s" << p.scale << ":f" << p.bestFloat << ":i" + << p.bestIntegral << ":r" << p.method << ":xf" << p.xfit + << ":yf" << p.yfit << ":xr" << p.xresize << ":yr" << p.yresize; + + if (p.crop) { - img->fb->idstream() << ":c" - << "+" << s.cropX0 - << "+" << s.cropY0 - << "+" << s.cropX1 - << "+" << s.cropY1; + str << ":c" + << "+" << p.cropX0 << "+" << p.cropY0 << "+" << p.cropX1 + << "+" << p.cropY1; } - if (s.uncrop) + if (p.uncrop) { - img->fb->idstream() << ":u" - << "+" << s.uncropWidth - << "+" << s.uncropHeight - << "+" << s.uncropX - << "+" << s.uncropY; + str << ":u" + << "+" << p.uncropWidth << "+" << p.uncropHeight << "+" + << p.uncropX << "+" << p.uncropY; } + + i->id = str.str(); } + return imgid; } - return head; -} - -IPImageID* -FormatIPNode::evaluateIdentifier(const Context& context) -{ - IPImageID* imgid = IPNode::evaluateIdentifier(context); - float scale = 1.0f; - int depth = 0; - - Params p = params(); - - IPImageID* i = imgid; - ostringstream str; - - if (p.scale != 1.0f || - p.bestFloat != FrameBuffer::FLOAT || - p.bestIntegral != FrameBuffer::USHORT || - p.xfit || - p.yfit || - p.xresize || - p.yresize || - p.crop || - p.uncrop) + IPNode::ImageStructureInfo + FormatIPNode::imageStructureInfo(const Context& context) const { - // - // NOTE: you can just get rid of xfit and yfit here and - // use a single scale value: you don't in principle know - // the resolution here that the xfit and yfit are - // relative to, so you have to include them in the hash - // + if (!inputs().empty()) + { + Params p = params(); + ImageStructureInfo i = + inputs().front()->imageStructureInfo(context); - str << i->id; + if (p.crop) + { + i.width = p.cropX1 - p.cropX0 + 1; + i.height = p.cropY1 - p.cropY0 + 1; + } - str << ":fmt/s" << p.scale - << ":f" << p.bestFloat - << ":i" << p.bestIntegral - << ":r" << p.method - << ":xf" << p.xfit - << ":yf" << p.yfit - << ":xr" << p.xresize - << ":yr" << p.yresize; + ImageStructureInfo n = outResFromParams(i.width, i.height, p); - if (p.crop) - { - str << ":c" - << "+" << p.cropX0 - << "+" << p.cropY0 - << "+" << p.cropX1 - << "+" << p.cropY1; - } + if (p.uncrop) + { + n.width = p.uncropWidth; + n.height = p.uncropHeight; + } - if (p.uncrop) - { - str << ":u" - << "+" << p.uncropWidth - << "+" << p.uncropHeight - << "+" << p.uncropX - << "+" << p.uncropY; + n.pixelAspect = i.pixelAspect; + n.orientation = i.orientation; + return n; } - i->id = str.str(); + return ImageStructureInfo(); } - return imgid; -} - - -IPNode::ImageStructureInfo -FormatIPNode::imageStructureInfo(const Context& context) const -{ - if (!inputs().empty()) + void FormatIPNode::propertyChanged(const Property* p) { - Params p = params(); - ImageStructureInfo i = inputs().front()->imageStructureInfo(context); - - if (p.crop) - { - i.width = p.cropX1 - p.cropX0 + 1; - i.height = p.cropY1 - p.cropY0 + 1; - } - - ImageStructureInfo n = outResFromParams(i.width, i.height, p); - - if (p.uncrop) - { - n.width = p.uncropWidth; - n.height = p.uncropHeight; - } + // + // All properties of this node affect caching of all frames of the + // corresponding source. so if the props change, flush all frames from + // this source. + // + if (group()) + group()->flushIDsOfGroup(); - n.pixelAspect = i.pixelAspect; - n.orientation = i.orientation; - return n; + IPNode::propertyChanged(p); + propagateImageStructureChange(); } - return ImageStructureInfo(); -} - -void -FormatIPNode::propertyChanged(const Property* p) -{ - // - // All properties of this node affect caching of all frames of the corresponding - // source. so if the props change, flush all frames from this source. - // - if (group()) group()->flushIDsOfGroup(); - - IPNode::propertyChanged(p); - propagateImageStructureChange(); -} - - -} // Rv +} // namespace IPCore diff --git a/src/lib/app/RvApp/Options.cpp b/src/lib/app/RvApp/Options.cpp index 57b4495ca..22f8a3526 100644 --- a/src/lib/app/RvApp/Options.cpp +++ b/src/lib/app/RvApp/Options.cpp @@ -1,9 +1,9 @@ // // Copyright (c) 2013 Tweak Software // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// // #include #include @@ -48,1276 +48,1472 @@ extern void TwkFB_GenericIO_setDebug(bool); namespace { - const int DEFAULT_AUDIO_CACHE_SIZE_IN_SECONDS_PER_GB_OF_USABLE_MEMORY = 4; + const int DEFAULT_AUDIO_CACHE_SIZE_IN_SECONDS_PER_GB_OF_USABLE_MEMORY = 4; } -namespace Rv { -using namespace TwkUtil; -using namespace std; -using namespace IPCore; -using namespace boost; +namespace Rv +{ + using namespace TwkUtil; + using namespace std; + using namespace IPCore; + using namespace boost; -static Options* globalOptions=0; + static Options* globalOptions = 0; -static ENVVAR_INT( evProgressiveSourceLoading, "RV_PROGRESSIVE_SOURCE_LOADING", 0 ); + static ENVVAR_INT(evProgressiveSourceLoading, + "RV_PROGRESSIVE_SOURCE_LOADING", 0); -// If you add a new debugging switch, please update getDebugCategories for the help menu too. -void debugSwitches(const std::string& name) -{ - if (name == "events") TwkApp::Document::debugEvents(); - else if (name == "threads") stl_ext::thread_group::debug_all(true); - else if (name == "gpu") ImageRenderer::reportGL(true); - else if (name == "audio") { AudioRenderer::setDebug(true); TwkMovie::ResamplingMovie::setDebug(true); } - else if (name == "audioverbose") { AudioRenderer::setDebugVerbose(true); AudioRenderer::setDebug(true); TwkMovie::ResamplingMovie::setDebug(true); } - else if (name == "dumpaudio") { AudioRenderer::setDumpAudio(true); TwkMovie::ResamplingMovie::setDumpAudio(true); } - else if (name == "shaders") { Shader::setDebugging(Shader::AllDebugInfo); } - else if (name == "shadercode") { Shader::setDebugging(Shader::ShaderCodeDebugInfo); } - else if (name == "profile") debugProfile = true; - else if (name == "playback") debugPlayback = true; - else if (name == "playbackverbose") debugPlaybackVerbose = debugPlayback =true; - else if (name == "cache") TwkFB::Cache::debug() = true; - else if (name == "mu") TwkApp::setDebugging(true); - else if (name == "muc") TwkApp::setDebugMUC(true); - else if (name == "compile") TwkApp::setCompileOnDemand(true); - else if (name == "dtree") IPGraph::setDebugTreeOutput(true); - else if (name == "passes") ImageRenderer::setPassDebug(true); - else if (name == "imagefbo") ImageRenderer::setOutputIntermediateDebug(true); - else if (name == "nogpucache") ImageRenderer::setNoGPUCache(true); - else if (name == "imagefbolog") ImageRenderer::setIntermediateLogging(true); - else if (name == "nodes") NodeManager::setDebug(true); - else if (name == "plugins") + // If you add a new debugging switch, please update getDebugCategories for + // the help menu too. + void debugSwitches(const std::string& name) { - TwkMovie_GenericIO_setDebug(true); - TwkFB_GenericIO_setDebug(true); + if (name == "events") + TwkApp::Document::debugEvents(); + else if (name == "threads") + stl_ext::thread_group::debug_all(true); + else if (name == "gpu") + ImageRenderer::reportGL(true); + else if (name == "audio") + { + AudioRenderer::setDebug(true); + TwkMovie::ResamplingMovie::setDebug(true); + } + else if (name == "audioverbose") + { + AudioRenderer::setDebugVerbose(true); + AudioRenderer::setDebug(true); + TwkMovie::ResamplingMovie::setDebug(true); + } + else if (name == "dumpaudio") + { + AudioRenderer::setDumpAudio(true); + TwkMovie::ResamplingMovie::setDumpAudio(true); + } + else if (name == "shaders") + { + Shader::setDebugging(Shader::AllDebugInfo); + } + else if (name == "shadercode") + { + Shader::setDebugging(Shader::ShaderCodeDebugInfo); + } + else if (name == "profile") + debugProfile = true; + else if (name == "playback") + debugPlayback = true; + else if (name == "playbackverbose") + debugPlaybackVerbose = debugPlayback = true; + else if (name == "cache") + TwkFB::Cache::debug() = true; + else if (name == "mu") + TwkApp::setDebugging(true); + else if (name == "muc") + TwkApp::setDebugMUC(true); + else if (name == "compile") + TwkApp::setCompileOnDemand(true); + else if (name == "dtree") + IPGraph::setDebugTreeOutput(true); + else if (name == "passes") + ImageRenderer::setPassDebug(true); + else if (name == "imagefbo") + ImageRenderer::setOutputIntermediateDebug(true); + else if (name == "nogpucache") + ImageRenderer::setNoGPUCache(true); + else if (name == "imagefbolog") + ImageRenderer::setIntermediateLogging(true); + else if (name == "nodes") + NodeManager::setDebug(true); + else if (name == "plugins") + { + TwkMovie_GenericIO_setDebug(true); + TwkFB_GenericIO_setDebug(true); + } + else + { + Notifier::MessageId mid = Notifier::registerMessage(name); + Notifier::debugMessage(mid, true); + + cout << "INFO: debugging message \"" << name << "\"" << endl; + } } - else + + const char* getDebugCategories() { - Notifier::MessageId mid = Notifier::registerMessage(name); - Notifier::debugMessage(mid, true); - - cout << "INFO: debugging message \"" - << name - << "\"" << endl; + return "Debuging categories: " + "events, " + "threads, " + "gpu, " + "audio, " + "audioverbose, " + "dumpaudio, " + "shaders, " + "shadercode, " + "profile, " + "playback, " + "playbackverbose, " + "cache, " + "mu, " + "muc, " + "compile, " + "dtree, " + "passes, " + "imagefbo, " + "nogpucache, " + "imagefbolog, " + "nodes, " + "plugins"; } -} - -const char* -getDebugCategories() -{ - return "Debuging categories: " - "events, " - "threads, " - "gpu, " - "audio, " - "audioverbose, " - "dumpaudio, " - "shaders, " - "shadercode, " - "profile, " - "playback, " - "playbackverbose, " - "cache, " - "mu, " - "muc, " - "compile, " - "dtree, " - "passes, " - "imagefbo, " - "nogpucache, " - "imagefbolog, " - "nodes, " - "plugins"; -} -int -collectParams(Options::Params& p, const Options::Files& inputFiles, int index) -{ - int count = -1; - for (int i = index; i < inputFiles.size(); i++, count++) + int collectParams(Options::Params& p, const Options::Files& inputFiles, + int index) { - string v = inputFiles[i]; - if (v.substr(0,1) == "+" || v.substr(0,1) == "]") return count; - - string::size_type pos = v.find("="); - if (pos == string::npos) return count; - p.push_back(pair(v.substr(0, pos), v.substr(pos+1, string::npos))); + int count = -1; + for (int i = index; i < inputFiles.size(); i++, count++) + { + string v = inputFiles[i]; + if (v.substr(0, 1) == "+" || v.substr(0, 1) == "]") + return count; + + string::size_type pos = v.find("="); + if (pos == string::npos) + return count; + p.push_back(pair(v.substr(0, pos), + v.substr(pos + 1, string::npos))); + } + return count; } - return count; -} - -int -parseInParams(int argc, char *argv[]) -{ - Options& opts = Options::sharedOptions(); - Options::Files infiles; - for (int i=0; i parts; - stl_ext::tokenize (parts, argv[i], "="); + Options& opts = Options::sharedOptions(); - if (1 == parts.size()) // simple flag - { - opts.muFlags[parts[0]] = "true"; - } - else - if (2 == parts.size()) // name=value flag + for (int i = 0; i < argc; i++) { - opts.muFlags[parts[0]] = parts[1]; - } - else cerr << "ERROR: mal-formed flag: " << argv[i] << endl; - } + vector parts; + stl_ext::tokenize(parts, argv[i], "="); - return 0; -} + if (1 == parts.size()) // simple flag + { + opts.muFlags[parts[0]] = "true"; + } + else if (2 == parts.size()) // name=value flag + { + opts.muFlags[parts[0]] = parts[1]; + } + else + cerr << "ERROR: mal-formed flag: " << argv[i] << endl; + } -int -parseSendEvents(int argc, char *argv[]) -{ - Options& opts = Options::sharedOptions(); + return 0; + } - for (int i = 0; i < argc; i += 2) + int parseSendEvents(int argc, char* argv[]) { - Options::SendExternalEvent e; - e.name = argv[i]; + Options& opts = Options::sharedOptions(); - if (i+1 < argc) e.content = argv[i+1]; + for (int i = 0; i < argc; i += 2) + { + Options::SendExternalEvent e; + e.name = argv[i]; - opts.sendEvents.push_back(e); - // cerr << "parseSendEvents name=" << e.name << " content=" << e.content << endl; - } + if (i + 1 < argc) + e.content = argv[i + 1]; - return 0; -} + opts.sendEvents.push_back(e); + // cerr << "parseSendEvents name=" << e.name << " content=" << + // e.content << endl; + } + return 0; + } -Options& -Options::sharedOptions() -{ - if (!globalOptions) globalOptions = new Options(); - return *globalOptions; -} + Options& Options::sharedOptions() + { + if (!globalOptions) + globalOptions = new Options(); + return *globalOptions; + } -Options::Options() -{ - static const int numLogicalCPUs = - static_cast( TwkUtil::SystemInfo::numCPUs() ); - static const size_t usableMemory = TwkUtil::SystemInfo::usableMemory(); - - displayPriority = -1; - audioPriority = -1; - schedulePolicy = 0; - fps = 0.0; - defaultfps = 24.0; // no command line for this one - useCache = 0; - useLCache = 1; // Use 'Look-Ahead Cache' by default - useNoCache = 0; - showFormats = 0; - fullscreen = 0; - noBorders = 0; - screen = -1; - x = -1; - y = -1; - width = -1; - height = -1; - startupResize = 0; - usecli = 0; - nomb = 0; - bgpattern = 0; - initscript = 0; - scale = 1.0; - sessionType = (char*)""; - resampleMethod = (char*)"area"; - licarg = 0; - maxvram = 64.0; // should be determined at start up - totalcram = 0.2 * (double(usableMemory)/1024.0/1024.0/1024.0); - maxcram = 1.0; // 1 GB - maxlram = 1.0; // 1 GB - maxbwait = 5.0; // seconds - lookback = 25.0; // percent - readerThreads = ( numLogicalCPUs > 4 ) ? std::min( numLogicalCPUs / 4, 4 ) : 1; - workItemThreads = ( numLogicalCPUs > 4 ) ? std::min( numLogicalCPUs / 4, 4 ) : 1; - cacheOutsideRegion = 0; - apple = 0; - allowYUV = 0; - sync = 0; - lqt_decoder = 0; - exrcpus = 0; - dispRedBits = 8; - dispGreenBits = 8; - dispBlueBits = 8; - dispAlphaBits = 8; - networkPort = 0; - networkHost = NULL; - networkTag = NULL; - networkUser = NULL; - networkPerm = -1; - exrRGBA = 0; - exrInherit = 1; - exrNoOneChannel = 0; - exrReadWindowIsDisplayWindow = 0; - exrReadWindow = 3; - exrPlanar3Chan = 0; /* Packed buffers are more optimal. Based on performance tuning */ - exrStripAlpha = 0; - exrConvertYRYBY = 0; - jpegRGBA = 0; - nofloat = 0; - noPBO = 0; - swapScanlines = 0; - prefetch = 1; - useThreadedUpload = 0; - maxbits = 32; - eval = 0; - pyeval = 0; - gamma = 1.0; - brightness = 0.0; - showVersion = 0; - play = 0; - playMode = 0; - loopMode = 0; - showCMS = 0; - cinalt = 0; - cinchroma = 0; - dpxchroma = 0; - cms = 0; - cmsDisplay = 0; - cmsSimulation = 0; - stereoMode = 0; - stereoSwapEyes = 0; - compMode = 0; - layoutMode = 0; - over = 0; - layer = 0; - replace = 0; - topmost = 0; - tile = 0; - wipes = 0; - diff = 0; - noSequence = 0; - inferSequence = 0; - autoRetime = 1; - aframesize = 0; - acachesize = 2048; - nukeSequence = 0; - noRanges = 0; + Options::Options() + { + static const int numLogicalCPUs = + static_cast(TwkUtil::SystemInfo::numCPUs()); + static const size_t usableMemory = TwkUtil::SystemInfo::usableMemory(); + + displayPriority = -1; + audioPriority = -1; + schedulePolicy = 0; + fps = 0.0; + defaultfps = 24.0; // no command line for this one + useCache = 0; + useLCache = 1; // Use 'Look-Ahead Cache' by default + useNoCache = 0; + showFormats = 0; + fullscreen = 0; + noBorders = 0; + screen = -1; + x = -1; + y = -1; + width = -1; + height = -1; + startupResize = 0; + usecli = 0; + nomb = 0; + bgpattern = 0; + initscript = 0; + scale = 1.0; + sessionType = (char*)""; + resampleMethod = (char*)"area"; + licarg = 0; + maxvram = 64.0; // should be determined at start up + totalcram = 0.2 * (double(usableMemory) / 1024.0 / 1024.0 / 1024.0); + maxcram = 1.0; // 1 GB + maxlram = 1.0; // 1 GB + maxbwait = 5.0; // seconds + lookback = 25.0; // percent + readerThreads = + (numLogicalCPUs > 4) ? std::min(numLogicalCPUs / 4, 4) : 1; + workItemThreads = + (numLogicalCPUs > 4) ? std::min(numLogicalCPUs / 4, 4) : 1; + cacheOutsideRegion = 0; + apple = 0; + allowYUV = 0; + sync = 0; + lqt_decoder = 0; + exrcpus = 0; + dispRedBits = 8; + dispGreenBits = 8; + dispBlueBits = 8; + dispAlphaBits = 8; + networkPort = 0; + networkHost = NULL; + networkTag = NULL; + networkUser = NULL; + networkPerm = -1; + exrRGBA = 0; + exrInherit = 1; + exrNoOneChannel = 0; + exrReadWindowIsDisplayWindow = 0; + exrReadWindow = 3; + exrPlanar3Chan = 0; /* Packed buffers are more optimal. Based on + performance tuning */ + exrStripAlpha = 0; + exrConvertYRYBY = 0; + jpegRGBA = 0; + nofloat = 0; + noPBO = 0; + swapScanlines = 0; + prefetch = 1; + useThreadedUpload = 0; + maxbits = 32; + eval = 0; + pyeval = 0; + gamma = 1.0; + brightness = 0.0; + showVersion = 0; + play = 0; + playMode = 0; + loopMode = 0; + showCMS = 0; + cinalt = 0; + cinchroma = 0; + dpxchroma = 0; + cms = 0; + cmsDisplay = 0; + cmsSimulation = 0; + stereoMode = 0; + stereoSwapEyes = 0; + compMode = 0; + layoutMode = 0; + over = 0; + layer = 0; + replace = 0; + topmost = 0; + tile = 0; + wipes = 0; + diff = 0; + noSequence = 0; + inferSequence = 0; + autoRetime = 1; + aframesize = 0; + acachesize = 2048; + nukeSequence = 0; + noRanges = 0; #ifdef PLATFORM_LINUX - audioNice = 0; - audioNoLock = 1; - audioPreRoll = 1; + audioNice = 0; + audioNoLock = 1; + audioPreRoll = 1; #else - audioNice = 0; - audioNoLock = 0; - audioPreRoll = 0; + audioNice = 0; + audioNoLock = 0; + audioPreRoll = 0; #endif - audioScrub = 0; - audioModule = 0; - audioDevice = 0; - audioRate = TWEAK_AUDIO_DEFAULT_SAMPLE_RATE; - audioPrecision = 16; - audioLayout = (int) TwkAudio::Stereo_2; - audioMaxCache = ROUND( usableMemory * - DEFAULT_AUDIO_CACHE_SIZE_IN_SECONDS_PER_GB_OF_USABLE_MEMORY / - ( 1024ULL * 1024ULL * 1024ULL ) ); - audioMinCache = 0.9 * audioMaxCache; - audioGlobalOffset = 0; - audioDeviceLatency = 0; - volume = 1.0; - fileCDL = NULL; - lookCDL = NULL; - fileLUT = NULL; - lookLUT = NULL; - dispLUT = NULL; - preCacheLUT = NULL; - cmapString = NULL; - selectType = NULL; - selectName = NULL; - mediaRepName = NULL; - mediaRepSource = NULL; - noPrefs = 0; - resetPrefs = 0; - useCrashReporter = 0; - encodeURL = 0; - bakeURL = 0; - sRGB = 0; - rec709 = 0; - cinPixel = (char*)"RGB8_PLANAR"; - dpxPixel = (char*)"RGB8_PLANAR"; - mistPixel = (char*)"RGB8_PLANAR"; - - newGLSLlutInterp = 0; + audioScrub = 0; + audioModule = 0; + audioDevice = 0; + audioRate = TWEAK_AUDIO_DEFAULT_SAMPLE_RATE; + audioPrecision = 16; + audioLayout = (int)TwkAudio::Stereo_2; + audioMaxCache = + ROUND(usableMemory + * DEFAULT_AUDIO_CACHE_SIZE_IN_SECONDS_PER_GB_OF_USABLE_MEMORY + / (1024ULL * 1024ULL * 1024ULL)); + audioMinCache = 0.9 * audioMaxCache; + audioGlobalOffset = 0; + audioDeviceLatency = 0; + volume = 1.0; + fileCDL = NULL; + lookCDL = NULL; + fileLUT = NULL; + lookLUT = NULL; + dispLUT = NULL; + preCacheLUT = NULL; + cmapString = NULL; + selectType = NULL; + selectName = NULL; + mediaRepName = NULL; + mediaRepSource = NULL; + noPrefs = 0; + resetPrefs = 0; + useCrashReporter = 0; + encodeURL = 0; + bakeURL = 0; + sRGB = 0; + rec709 = 0; + cinPixel = (char*)"RGB8_PLANAR"; + dpxPixel = (char*)"RGB8_PLANAR"; + mistPixel = (char*)"RGB8_PLANAR"; + + newGLSLlutInterp = 0; #if defined(PLATFORM_LINUX) - vsync = 0; + vsync = 0; #else - vsync = 1; + vsync = 1; #endif - xl = 0; + xl = 0; #ifdef PLATFORM_LINUX - stylusAsMouse = 1; + stylusAsMouse = 1; #else - stylusAsMouse = 0; + stylusAsMouse = 0; #endif - scrubEnable = 1; - clickToPlayEnable = 1; + scrubEnable = 1; + clickToPlayEnable = 1; - qtstyle = 0; - qtcss = 0; - qtdesktop = 1; + qtstyle = 0; + qtcss = 0; + qtdesktop = 1; - view = (char*)""; + view = (char*)""; #ifdef WIN32 - exrIOMethod = 3; /* Memory Map. Based on performance tuning */ - cinIOMethod = 1; - dpxIOMethod = 1; - tgaIOMethod = 1; - tiffIOMethod = 1; - jpegIOMethod = 1; + exrIOMethod = 3; /* Memory Map. Based on performance tuning */ + cinIOMethod = 1; + dpxIOMethod = 1; + tgaIOMethod = 1; + tiffIOMethod = 1; + jpegIOMethod = 1; #else - exrIOMethod = 3; /* Memory Map. Based on performance tuning */ - cinIOMethod = 2; - dpxIOMethod = 2; - tgaIOMethod = 2; - tiffIOMethod = 2; - jpegIOMethod = 0; + exrIOMethod = 3; /* Memory Map. Based on performance tuning */ + cinIOMethod = 2; + dpxIOMethod = 2; + tgaIOMethod = 2; + tiffIOMethod = 2; + jpegIOMethod = 0; #endif - exrIOSize = 61440; - dpxIOSize = 61440; - cinIOSize = 61440; - jpegIOSize = 61440; - tgaIOSize = 61440; - tiffIOSize = 61440; - - exrMaxAsync = 16; - dpxMaxAsync = 16; - tgaMaxAsync = 16; - tiffMaxAsync = 16; - cinMaxAsync = 16; - jpegMaxAsync = 16; - - pixelAspect = 0.0; - stereoOffset = 0.0; - rightEyeStereoOffset = 0.0; - audioOffset = 0.0; - audioOff = 0; - rangeOffset = 0; - rangeStart = numeric_limits::max(); - cutInPoint = numeric_limits::max(); - cutOutPoint = numeric_limits::max(); - noMovieAudio = 0; - cropX0 = 0; - cropX1 = 0; - cropY0 = 0; - cropY1 = 0; - uncropW = 0; - uncropH = 0; - uncropX = 0; - uncropY = 0; - - urlsReuseSession = 1; - noPackages = 0; - delaySessionLoading = 1; - progressiveSourceLoading = evProgressiveSourceLoading.getValue(); - - network = 0; - connectHost = NULL; - connectPort = 0; - networkOnStartup = 0; - - windowType = 0; - - present = false; - presentAudio = -1; - presentDevice = (char*)""; - presentFormat = (char*)""; - presentData = (char*)""; + exrIOSize = 61440; + dpxIOSize = 61440; + cinIOSize = 61440; + jpegIOSize = 61440; + tgaIOSize = 61440; + tiffIOSize = 61440; + + exrMaxAsync = 16; + dpxMaxAsync = 16; + tgaMaxAsync = 16; + tiffMaxAsync = 16; + cinMaxAsync = 16; + jpegMaxAsync = 16; + + pixelAspect = 0.0; + stereoOffset = 0.0; + rightEyeStereoOffset = 0.0; + audioOffset = 0.0; + audioOff = 0; + rangeOffset = 0; + rangeStart = numeric_limits::max(); + cutInPoint = numeric_limits::max(); + cutOutPoint = numeric_limits::max(); + noMovieAudio = 0; + cropX0 = 0; + cropX1 = 0; + cropY0 = 0; + cropY1 = 0; + uncropW = 0; + uncropH = 0; + uncropX = 0; + uncropY = 0; + + urlsReuseSession = 1; + noPackages = 0; + delaySessionLoading = 1; + progressiveSourceLoading = evProgressiveSourceLoading.getValue(); + + network = 0; + connectHost = NULL; + connectPort = 0; + networkOnStartup = 0; + + windowType = 0; + + present = false; + presentAudio = -1; + presentDevice = (char*)""; + presentFormat = (char*)""; + presentData = (char*)""; #ifdef PLATFORM_DARWIN - fontSize1 = 13; - fontSize2 = 10; - useAppleClientStorage = 0; + fontSize1 = 13; + fontSize2 = 10; + useAppleClientStorage = 0; #else - fontSize1 = 10; - fontSize2 = 8; - useAppleClientStorage = 0; + fontSize1 = 10; + fontSize2 = 8; + useAppleClientStorage = 0; #endif - imageFilter = GL_LINEAR; -} - -Options::SourceArgsVector -Options::parseSourceArgs(const Files& inputFiles) -{ - SourceArgsVector sources; - bool inSource = false; - bool needFreshSource = true; - RegEx sequenceSpec("[#@%]"); + imageFilter = GL_LINEAR; + } - for (int i=0; i < inputFiles.size(); i++) + Options::SourceArgsVector Options::parseSourceArgs(const Files& inputFiles) { - const string& arg = inputFiles[i]; + SourceArgsVector sources; + bool inSource = false; + bool needFreshSource = true; + RegEx sequenceSpec("[#@%]"); - if (arg == "[") + for (int i = 0; i < inputFiles.size(); i++) { - if (inSource) + const string& arg = inputFiles[i]; + + if (arg == "[") { - TWK_THROW_STREAM(ReadFailedExc, "Cannot nest source groups"); - } + if (inSource) + { + TWK_THROW_STREAM(ReadFailedExc, + "Cannot nest source groups"); + } - inSource = true; - sources.resize(sources.size() + 1); - sources.back().singleSource = true; - - SourceArgs& a = sources.back(); - - // - // Copy over default per-source values - // - - a.audioOffset = audioOffset; - a.rangeOffset = rangeOffset; - a.rangeStart = rangeStart; - a.noMovieAudio = noMovieAudio; - a.stereoRelativeOffset = stereoOffset; - a.stereoRightOffset = rightEyeStereoOffset; - a.crop[0] = cropX0; - a.crop[1] = cropY0; - a.crop[2] = cropX1; - a.crop[3] = cropY1; - a.uncrop[0] = uncropW; - a.uncrop[1] = uncropH; - a.uncrop[2] = uncropX; - a.uncrop[3] = uncropY; - a.fcdl = fileCDL ? fileCDL : ""; - a.lcdl = lookCDL ? lookCDL : ""; - a.flut = fileLUT ? fileLUT : ""; - a.llut = lookLUT ? lookLUT : ""; - a.pclut = preCacheLUT ? preCacheLUT : ""; - a.cmap = cmapString ? cmapString : ""; - a.selectType = selectType ? selectType : ""; - a.selectName = selectName ? selectName : ""; - a.mediaRepName = mediaRepName ? mediaRepName : ""; - a.mediaRepSource = mediaRepSource ? mediaRepSource : ""; - a.cutIn = cutInPoint; - a.cutOut = cutOutPoint; - a.inparams = inparams; - } - else if (arg == "]") - { - inSource = false; - needFreshSource = true; - } - else if (inSource && arg.size() && arg[0] == '+' && (i+1 < inputFiles.size())) - { - SourceArgs& a = sources.back(); - - // - // First check for per-source args that take no arguement - // - if (arg == "+noMovieAudio" || arg == "+nma") a.noMovieAudio = true; - // - // Then check for per-source args that take at least - // one arguement - // - else if (i+1 < inputFiles.size()) + inSource = true; + sources.resize(sources.size() + 1); + sources.back().singleSource = true; + + SourceArgs& a = sources.back(); + + // + // Copy over default per-source values + // + + a.audioOffset = audioOffset; + a.rangeOffset = rangeOffset; + a.rangeStart = rangeStart; + a.noMovieAudio = noMovieAudio; + a.stereoRelativeOffset = stereoOffset; + a.stereoRightOffset = rightEyeStereoOffset; + a.crop[0] = cropX0; + a.crop[1] = cropY0; + a.crop[2] = cropX1; + a.crop[3] = cropY1; + a.uncrop[0] = uncropW; + a.uncrop[1] = uncropH; + a.uncrop[2] = uncropX; + a.uncrop[3] = uncropY; + a.fcdl = fileCDL ? fileCDL : ""; + a.lcdl = lookCDL ? lookCDL : ""; + a.flut = fileLUT ? fileLUT : ""; + a.llut = lookLUT ? lookLUT : ""; + a.pclut = preCacheLUT ? preCacheLUT : ""; + a.cmap = cmapString ? cmapString : ""; + a.selectType = selectType ? selectType : ""; + a.selectName = selectName ? selectName : ""; + a.mediaRepName = mediaRepName ? mediaRepName : ""; + a.mediaRepSource = mediaRepSource ? mediaRepSource : ""; + a.cutIn = cutInPoint; + a.cutOut = cutOutPoint; + a.inparams = inparams; + } + else if (arg == "]") { - i++; - const char* v = inputFiles[i].c_str(); - - if (arg == "+fps") a.fps = atof(v); - else if (arg == "+volume") a.volume = atof(v); - else if (arg == "+audioOffset" || arg == "+ao") a.audioOffset = atof(v); - else if (arg == "+rangeOffset" || arg == "+ro") a.rangeOffset = atoi(v); - else if (arg == "+rangeStart" || arg == "+rs") a.rangeStart = atoi(v); - else if (arg == "+pixelAspect" || arg == "+pa") a.pixelAspect = atof(v); - else if (arg == "+stereoOffset" || arg == "+so") a.stereoRelativeOffset = atof(v); - else if (arg == "+rightEyeStereoOffset" || arg == "+rso") a.stereoRightOffset = atof(v); - else if (arg == "+fcdl") a.fcdl = v; - else if (arg == "+lcdl") a.lcdl = v; - else if (arg == "+flut") a.flut = v; - else if (arg == "+pclut") a.pclut = v; - else if (arg == "+llut") a.llut = v; - else if (arg == "+cmap") a.cmap = v; - else if (arg == "+select") { a.selectType = v; a.selectName = inputFiles[i+1].c_str(); i++; } - else if (arg == "+mrn" || arg == "+mediaRepName") a.mediaRepName = v; - else if (arg == "+mrs" || arg == "+mediaRepSource") a.mediaRepSource = v; - else if (arg == "+in") a.cutIn = atoi(v); - else if (arg == "+out") a.cutOut = atoi(v); - else if (arg == "+inparams") i += Rv::collectParams(a.inparams, inputFiles, i); - else if (i+4 < inputFiles.size()) + inSource = false; + needFreshSource = true; + } + else if (inSource && arg.size() && arg[0] == '+' + && (i + 1 < inputFiles.size())) + { + SourceArgs& a = sources.back(); + + // + // First check for per-source args that take no arguement + // + if (arg == "+noMovieAudio" || arg == "+nma") + a.noMovieAudio = true; + // + // Then check for per-source args that take at least + // one arguement + // + else if (i + 1 < inputFiles.size()) { - if (arg == "+crop") + i++; + const char* v = inputFiles[i].c_str(); + + if (arg == "+fps") + a.fps = atof(v); + else if (arg == "+volume") + a.volume = atof(v); + else if (arg == "+audioOffset" || arg == "+ao") + a.audioOffset = atof(v); + else if (arg == "+rangeOffset" || arg == "+ro") + a.rangeOffset = atoi(v); + else if (arg == "+rangeStart" || arg == "+rs") + a.rangeStart = atoi(v); + else if (arg == "+pixelAspect" || arg == "+pa") + a.pixelAspect = atof(v); + else if (arg == "+stereoOffset" || arg == "+so") + a.stereoRelativeOffset = atof(v); + else if (arg == "+rightEyeStereoOffset" || arg == "+rso") + a.stereoRightOffset = atof(v); + else if (arg == "+fcdl") + a.fcdl = v; + else if (arg == "+lcdl") + a.lcdl = v; + else if (arg == "+flut") + a.flut = v; + else if (arg == "+pclut") + a.pclut = v; + else if (arg == "+llut") + a.llut = v; + else if (arg == "+cmap") + a.cmap = v; + else if (arg == "+select") { - a.crop[0] = atoi(v); - a.crop[1] = atoi(inputFiles[i+1].c_str()); - a.crop[2] = atoi(inputFiles[i+2].c_str()); - a.crop[3] = atoi(inputFiles[i+3].c_str()); - a.hascrop = true; - i+=3; + a.selectType = v; + a.selectName = inputFiles[i + 1].c_str(); + i++; } - else if (arg == "+uncrop") + else if (arg == "+mrn" || arg == "+mediaRepName") + a.mediaRepName = v; + else if (arg == "+mrs" || arg == "+mediaRepSource") + a.mediaRepSource = v; + else if (arg == "+in") + a.cutIn = atoi(v); + else if (arg == "+out") + a.cutOut = atoi(v); + else if (arg == "+inparams") + i += Rv::collectParams(a.inparams, inputFiles, i); + else if (i + 4 < inputFiles.size()) { - a.uncrop[0] = atoi(v); - a.uncrop[1] = atoi(inputFiles[i+1].c_str()); - a.uncrop[2] = atoi(inputFiles[i+2].c_str()); - a.uncrop[3] = atoi(inputFiles[i+3].c_str()); - - a.hasuncrop = true; - i+=3; + if (arg == "+crop") + { + a.crop[0] = atoi(v); + a.crop[1] = atoi(inputFiles[i + 1].c_str()); + a.crop[2] = atoi(inputFiles[i + 2].c_str()); + a.crop[3] = atoi(inputFiles[i + 3].c_str()); + a.hascrop = true; + i += 3; + } + else if (arg == "+uncrop") + { + a.uncrop[0] = atoi(v); + a.uncrop[1] = atoi(inputFiles[i + 1].c_str()); + a.uncrop[2] = atoi(inputFiles[i + 2].c_str()); + a.uncrop[3] = atoi(inputFiles[i + 3].c_str()); + + a.hasuncrop = true; + i += 3; + } + } + else + { + TWK_THROW_STREAM(ReadFailedExc, + "Unknown flag '" + arg + "' in input"); } - } - else - { - TWK_THROW_STREAM(ReadFailedExc, "Unknown flag '" + arg + "' in input"); } } + else if (!inSource + && (needFreshSource || TwkUtil::Match(sequenceSpec, arg))) + { + sources.resize(sources.size() + 1); + sources.back().files.push_back(arg); + needFreshSource = false; + } + else + { + sources.back().files.push_back(arg); + } } - else if (!inSource && (needFreshSource || TwkUtil::Match(sequenceSpec, arg))) + + if (inSource) { - sources.resize(sources.size() + 1); - sources.back().files.push_back(arg); - needFreshSource = false; + TWK_THROW_STREAM(ReadFailedExc, "Unmatched '[' in input"); } - else + + // + // Convert frame range style to shake style + // + + for (size_t i = 0; i < sources.size(); i++) { - sources.back().files.push_back(arg); + integrateFrameRangeStrings(sources[i].files); } - } - if (inSource) - { - TWK_THROW_STREAM(ReadFailedExc, "Unmatched '[' in input"); + return sources; } - // - // Convert frame range style to shake style - // - - for (size_t i = 0; i < sources.size(); i++) + void Options::integrateFrameRangeStrings(vector& inputFiles) { - integrateFrameRangeStrings(sources[i].files); - } - - return sources; -} - -void -Options::integrateFrameRangeStrings(vector& inputFiles) -{ - vector newInputFiles; + vector newInputFiles; - for (size_t i = 0; i < inputFiles.size(); i++) - { - if (isFrameRange(inputFiles[i]) && i != 0) + for (size_t i = 0; i < inputFiles.size(); i++) { - if (!isFrameRange(inputFiles[i-1])) + if (isFrameRange(inputFiles[i]) && i != 0) { - if (!newInputFiles.empty()) newInputFiles.pop_back(); - newInputFiles.push_back(integrateFrameRange(inputFiles[i-1], inputFiles[i])); + if (!isFrameRange(inputFiles[i - 1])) + { + if (!newInputFiles.empty()) + newInputFiles.pop_back(); + newInputFiles.push_back( + integrateFrameRange(inputFiles[i - 1], inputFiles[i])); + } + else + { + cout << "WARNING: ignoring \"" << inputFiles[i] + << "\" (input " << i + << ") because it looks like a second frame range" + << endl; + } } else { - cout << "WARNING: ignoring \"" << inputFiles[i] - << "\" (input " << i - << ") because it looks like a second frame range" - << endl; + newInputFiles.push_back(inputFiles[i]); } } - else - { - newInputFiles.push_back(inputFiles[i]); - } - } - inputFiles = newInputFiles; -} - -static string -strFromChar (const char* cp) -{ - return (cp) ? string(cp) : string(); -} + inputFiles = newInputFiles; + } -static void -addIfMissing (ostringstream& stream, const string& userString, const char* name, const int value) -{ - if (userString.find(name) == string::npos) stream << " " << name << " " << value; -} + static string strFromChar(const char* cp) + { + return (cp) ? string(cp) : string(); + } -static void -addIfMissing (ostringstream& stream, const string& userString, const char* name, const char* value) -{ - if (userString.find(name) == string::npos) stream << " " << name << " " << value; -} + static void addIfMissing(ostringstream& stream, const string& userString, + const char* name, const int value) + { + if (userString.find(name) == string::npos) + stream << " " << name << " " << value; + } -static void -addIfMissing (ostringstream& stream, const string& userString, const char* name, const float value) -{ - if (userString.find(name) == string::npos) stream << " " << name << " " << value; -} + static void addIfMissing(ostringstream& stream, const string& userString, + const char* name, const char* value) + { + if (userString.find(name) == string::npos) + stream << " " << name << " " << value; + } -void -Options::exportIOEnvVars() const -{ - // - // NOTE: MovieR3D can take MOVIER3D_ARGS env variable, but since - // there currently are no command line options for RED we don't - // need to do anything here. Just let the variable go through - // unchanged. - // - // What's the point of all this env var fiddling? The env var - // holds arguments to not-yet-existing reader/writer objects - // (plugins). When they're created they parse the env var args to - // get their defaults. After that (e.g. prefs) can set attributes - // on the live objects directly. This also allows us to provide - // additional arguments to the readers/writers without having to - // modify the support code directly. - // + static void addIfMissing(ostringstream& stream, const string& userString, + const char* name, const float value) + { + if (userString.find(name) == string::npos) + stream << " " << name << " " << value; + } - ostringstream exr; - ostringstream cin; - ostringstream dpx; - ostringstream jpeg; - ostringstream tif; - ostringstream tga; - ostringstream mistika; - ostringstream ffmpeg; + void Options::exportIOEnvVars() const + { + // + // NOTE: MovieR3D can take MOVIER3D_ARGS env variable, but since + // there currently are no command line options for RED we don't + // need to do anything here. Just let the variable go through + // unchanged. + // + // What's the point of all this env var fiddling? The env var + // holds arguments to not-yet-existing reader/writer objects + // (plugins). When they're created they parse the env var args to + // get their defaults. After that (e.g. prefs) can set attributes + // on the live objects directly. This also allows us to provide + // additional arguments to the readers/writers without having to + // modify the support code directly. + // - TwkApp::Bundle* bundle = TwkApp::Bundle::mainBundle(); + ostringstream exr; + ostringstream cin; + ostringstream dpx; + ostringstream jpeg; + ostringstream tif; + ostringstream tga; + ostringstream mistika; + ostringstream ffmpeg; - string rvexr = strFromChar (getenv("RV_IOEXR_ARGS")); - string rvcin = strFromChar (getenv("RV_IOCIN_ARGS")); - string rvdpx = strFromChar (getenv("RV_IODPX_ARGS")); - string rvjpeg = strFromChar (getenv("RV_IOJPEG_ARGS")); - string rvtif = strFromChar (getenv("RV_IOTIFF_ARGS")); - string rvtga = strFromChar (getenv("RV_IOTARGA_ARGS")); - string rvmist = strFromChar (getenv("RV_MOVIEMISTIKA_ARGS")); - string rvffm = strFromChar (getenv("RV_MOVIEFFMPEG_ARGS")); + TwkApp::Bundle* bundle = TwkApp::Bundle::mainBundle(); - // EXR plugin options + string rvexr = strFromChar(getenv("RV_IOEXR_ARGS")); + string rvcin = strFromChar(getenv("RV_IOCIN_ARGS")); + string rvdpx = strFromChar(getenv("RV_IODPX_ARGS")); + string rvjpeg = strFromChar(getenv("RV_IOJPEG_ARGS")); + string rvtif = strFromChar(getenv("RV_IOTIFF_ARGS")); + string rvtga = strFromChar(getenv("RV_IOTARGA_ARGS")); + string rvmist = strFromChar(getenv("RV_MOVIEMISTIKA_ARGS")); + string rvffm = strFromChar(getenv("RV_MOVIEFFMPEG_ARGS")); - exr << rvexr; + // EXR plugin options - addIfMissing (exr, rvexr, "--rgbaOnly", exrRGBA); - addIfMissing (exr, rvexr, "--inherit", exrInherit); - addIfMissing (exr, rvexr, "--noOneChannel", exrNoOneChannel); - addIfMissing (exr, rvexr, "--readWindowIsDisplayWindow", exrReadWindowIsDisplayWindow); - addIfMissing (exr, rvexr, "--readWindow", exrReadWindow); - addIfMissing (exr, rvexr, "--planar3channel", exrPlanar3Chan); - addIfMissing (exr, rvexr, "--stripAlpha", exrStripAlpha); - addIfMissing (exr, rvexr, "--convertYRYBY", exrConvertYRYBY); - addIfMissing (exr, rvexr, "--ioSize", exrIOSize); - addIfMissing (exr, rvexr, "--ioMethod", exrIOMethod); - addIfMissing (exr, rvexr, "--ioMaxAsync", exrMaxAsync); + exr << rvexr; - bundle->setEnvVar("IOEXR_ARGS", exr.str().c_str(), true); + addIfMissing(exr, rvexr, "--rgbaOnly", exrRGBA); + addIfMissing(exr, rvexr, "--inherit", exrInherit); + addIfMissing(exr, rvexr, "--noOneChannel", exrNoOneChannel); + addIfMissing(exr, rvexr, "--readWindowIsDisplayWindow", + exrReadWindowIsDisplayWindow); + addIfMissing(exr, rvexr, "--readWindow", exrReadWindow); + addIfMissing(exr, rvexr, "--planar3channel", exrPlanar3Chan); + addIfMissing(exr, rvexr, "--stripAlpha", exrStripAlpha); + addIfMissing(exr, rvexr, "--convertYRYBY", exrConvertYRYBY); + addIfMissing(exr, rvexr, "--ioSize", exrIOSize); + addIfMissing(exr, rvexr, "--ioMethod", exrIOMethod); + addIfMissing(exr, rvexr, "--ioMaxAsync", exrMaxAsync); - // CIN plugin options + bundle->setEnvVar("IOEXR_ARGS", exr.str().c_str(), true); - cin << rvcin; + // CIN plugin options - addIfMissing (cin, rvcin, "--format", cinPixel); - addIfMissing (cin, rvcin, "--useChromaticities", cinchroma); - addIfMissing (cin, rvcin, "--ioSize", cinIOSize); - addIfMissing (cin, rvcin, "--ioMethod", cinIOMethod); - addIfMissing (cin, rvcin, "--ioMaxAsync", cinMaxAsync); + cin << rvcin; - bundle->setEnvVar("IOCIN_ARGS", cin.str().c_str(), true); + addIfMissing(cin, rvcin, "--format", cinPixel); + addIfMissing(cin, rvcin, "--useChromaticities", cinchroma); + addIfMissing(cin, rvcin, "--ioSize", cinIOSize); + addIfMissing(cin, rvcin, "--ioMethod", cinIOMethod); + addIfMissing(cin, rvcin, "--ioMaxAsync", cinMaxAsync); - // DPX plugin options + bundle->setEnvVar("IOCIN_ARGS", cin.str().c_str(), true); - dpx << rvdpx; + // DPX plugin options - addIfMissing (dpx, rvdpx, "--format", dpxPixel); - addIfMissing (dpx, rvdpx, "--useChromaticities", dpxchroma); - addIfMissing (dpx, rvdpx, "--ioSize", dpxIOSize); - addIfMissing (dpx, rvdpx, "--ioMethod", dpxIOMethod); - addIfMissing (dpx, rvdpx, "--ioMaxAsync", dpxMaxAsync); + dpx << rvdpx; - bundle->setEnvVar("IODPX_ARGS", dpx.str().c_str(), true); + addIfMissing(dpx, rvdpx, "--format", dpxPixel); + addIfMissing(dpx, rvdpx, "--useChromaticities", dpxchroma); + addIfMissing(dpx, rvdpx, "--ioSize", dpxIOSize); + addIfMissing(dpx, rvdpx, "--ioMethod", dpxIOMethod); + addIfMissing(dpx, rvdpx, "--ioMaxAsync", dpxMaxAsync); - // JPEG plugin options + bundle->setEnvVar("IODPX_ARGS", dpx.str().c_str(), true); - jpeg << rvjpeg; + // JPEG plugin options - addIfMissing (jpeg, rvjpeg, "--ioSize", jpegIOSize); - addIfMissing (jpeg, rvjpeg, "--ioMethod", jpegIOMethod); - addIfMissing (jpeg, rvjpeg, "--ioMaxAsync", jpegMaxAsync); + jpeg << rvjpeg; - bundle->setEnvVar("IOJPEG_ARGS", jpeg.str().c_str(), true); + addIfMissing(jpeg, rvjpeg, "--ioSize", jpegIOSize); + addIfMissing(jpeg, rvjpeg, "--ioMethod", jpegIOMethod); + addIfMissing(jpeg, rvjpeg, "--ioMaxAsync", jpegMaxAsync); - // TIFF plugin options + bundle->setEnvVar("IOJPEG_ARGS", jpeg.str().c_str(), true); - tif << rvtif; + // TIFF plugin options - addIfMissing (tif, rvtif, "--ioSize", tiffIOSize); - addIfMissing (tif, rvtif, "--ioMethod", tiffIOMethod); + tif << rvtif; - bundle->setEnvVar("IOTIFF_ARGS", tif.str().c_str(), true); + addIfMissing(tif, rvtif, "--ioSize", tiffIOSize); + addIfMissing(tif, rvtif, "--ioMethod", tiffIOMethod); - // TARGA plugin options + bundle->setEnvVar("IOTIFF_ARGS", tif.str().c_str(), true); - tga << rvtga; - addIfMissing (tga, rvtga, "--ioSize", tgaIOSize); - addIfMissing (tga, rvtga, "--ioMethod", tgaIOMethod); - addIfMissing (tga, rvtga, "--ioMaxAsync", tgaMaxAsync); + // TARGA plugin options - bundle->setEnvVar("IOTARGA_ARGS", tga.str().c_str(), true); + tga << rvtga; + addIfMissing(tga, rvtga, "--ioSize", tgaIOSize); + addIfMissing(tga, rvtga, "--ioMethod", tgaIOMethod); + addIfMissing(tga, rvtga, "--ioMaxAsync", tgaMaxAsync); - // MISTIKA plugin options + bundle->setEnvVar("IOTARGA_ARGS", tga.str().c_str(), true); - mistika << rvmist; + // MISTIKA plugin options - addIfMissing (mistika, rvmist, "--format", mistPixel); + mistika << rvmist; - bundle->setEnvVar("MOVIEMISTIKA_ARGS", mistika.str().c_str(), true); + addIfMissing(mistika, rvmist, "--format", mistPixel); - // FFMPEG movie plugin options + bundle->setEnvVar("MOVIEMISTIKA_ARGS", mistika.str().c_str(), true); - ffmpeg << rvffm; + // FFMPEG movie plugin options - addIfMissing (ffmpeg, rvffm, "--defaultFPS", defaultfps); - bundle->setEnvVar("MOVIEFFMPEG_ARGS", ffmpeg.str().c_str(), true); -} + ffmpeg << rvffm; -bool -Options::initializeAfterParsing(Options *prefs) -{ - // - // Initialize IPCore prefs from Options - // - - IPCore::Application::OptionMap& optionMap = IPCore::Application::optionMap(); - - optionMap["playMode"] = int(playMode); - optionMap["loopMode"] = int(loopMode); - optionMap["acachesize"] = size_t(acachesize); - optionMap["audioMinCache"] = double(audioMinCache); - optionMap["audioMaxCache"] = double(audioMaxCache); - optionMap["displayPriority"] = size_t(displayPriority); - optionMap["schedulePolicy"] = string(schedulePolicy ? schedulePolicy : ""); - optionMap["workItemThreads"] = int(workItemThreads); - optionMap["progressiveSourceLoading"] = bool(progressiveSourceLoading!=0); - - // - // Initialize IPCore prefs from Env Vars. These may be for testing or - // rare use cases, might "graduate" to real preferences in the future. - // - - if (const char* c = getenv("TWK_MAX_TEXTURE_SIZE")) - { - IPCore::Application::setOptionValue("maxTextureSizeOverride", atoi(c)); + addIfMissing(ffmpeg, rvffm, "--defaultFPS", defaultfps); + bundle->setEnvVar("MOVIEFFMPEG_ARGS", ffmpeg.str().c_str(), true); } - if (getenv("TWK_DISABLE_CACHE_STATS") != NULL) + bool Options::initializeAfterParsing(Options* prefs) { - optionMap["disableCacheStats"] = true; - } + // + // Initialize IPCore prefs from Options + // + + IPCore::Application::OptionMap& optionMap = + IPCore::Application::optionMap(); + + optionMap["playMode"] = int(playMode); + optionMap["loopMode"] = int(loopMode); + optionMap["acachesize"] = size_t(acachesize); + optionMap["audioMinCache"] = double(audioMinCache); + optionMap["audioMaxCache"] = double(audioMaxCache); + optionMap["displayPriority"] = size_t(displayPriority); + optionMap["schedulePolicy"] = + string(schedulePolicy ? schedulePolicy : ""); + optionMap["workItemThreads"] = int(workItemThreads); + optionMap["progressiveSourceLoading"] = + bool(progressiveSourceLoading != 0); + + // + // Initialize IPCore prefs from Env Vars. These may be for testing or + // rare use cases, might "graduate" to real preferences in the future. + // + + if (const char* c = getenv("TWK_MAX_TEXTURE_SIZE")) + { + IPCore::Application::setOptionValue("maxTextureSizeOverride", + atoi(c)); + } + if (getenv("TWK_DISABLE_CACHE_STATS") != NULL) + { + optionMap["disableCacheStats"] = true; + } - // - // Rectify conflicting prefs/args - // + // + // Rectify conflicting prefs/args + // - if (prefs) - { - if (useNoCache) + if (prefs) { - useCache = 0; - useLCache = 0; + if (useNoCache) + { + useCache = 0; + useLCache = 0; + } + else if (useLCache && useCache) + { + if (!prefs->useLCache) + useCache = 0; + else + useLCache = 0; + } + defaultfps = prefs->defaultfps; } - else - if (useLCache && useCache) + + // + // gamma wins over srgb/rec709, and rec709 wins over srgb. + // + + if (gamma != 1.0) { - if (!prefs->useLCache) useCache = 0; - else useLCache = 0; + rec709 = 0; + sRGB = 0; + } + else if (rec709 != 0) + { + sRGB = 0; } - defaultfps = prefs->defaultfps; - } - - // - // gamma wins over srgb/rec709, and rec709 wins over srgb. - // - if (gamma != 1.0) - { - rec709 = 0; - sRGB = 0; - } - else if (rec709 != 0) - { - sRGB = 0; - } + // + // If they want to change the UI they need to supply both qtstyle + // and qtcss + // - // - // If they want to change the UI they need to supply both qtstyle - // and qtcss - // + if (qtcss && !qtstyle) + qtstyle = (char*)"RV"; - if (qtcss && !qtstyle) qtstyle = (char*)"RV"; + // + // Defaults from command line first + // - // - // Defaults from command line first - // + for (size_t i = 0; i < debugKeyWords.size(); i++) + { + debugSwitches(debugKeyWords[i]); + } - for (size_t i = 0; i < debugKeyWords.size(); i++) - { - debugSwitches(debugKeyWords[i]); - } + if (bgpattern) + { + ImageRenderer::BGPattern p = ImageRenderer::Solid0; + + if (!strcmp(bgpattern, "black")) + p = ImageRenderer::Solid0; + else if (!strcmp(bgpattern, "grey18")) + p = ImageRenderer::Solid18; + else if (!strcmp(bgpattern, "grey50")) + p = ImageRenderer::Solid50; + else if (!strcmp(bgpattern, "white")) + p = ImageRenderer::Solid100; + else if (!strcmp(bgpattern, "checker")) + p = ImageRenderer::Checker; + else if (!strcmp(bgpattern, "crosshatch")) + p = ImageRenderer::CrossHatch; + + ImageRenderer::setDefaultBGPattern(p); + } - if (bgpattern) - { - ImageRenderer::BGPattern p = ImageRenderer::Solid0; + ImageRenderer::defaultAllowPBOs(!noPBO); + ImageRenderer::setUseAppleClientStorage(useAppleClientStorage); + DisplayStereoIPNode::setSwapScanlines(swapScanlines); + SystemInfo::setMaxVRAM(size_t(double(maxvram) * 1024.0 * 1024.0)); + if (eval) + RvSession::setInitEval(eval); + if (pyeval) + RvSession::setPyInitEval(pyeval); + if (maxbits != 32) + FormatIPNode::defaultBitDepth = maxbits; + if (nofloat) + FormatIPNode::defaultAllowFP = false; + SoundTrackIPNode::defaultVolume = volume; + FormatIPNode::defaultResampleMethod = resampleMethod; + FileSourceIPNode::defaultOverrideFPS = fps; + FileSourceIPNode::defaultFPS = defaultfps; + SystemInfo::setUseableMemory( + size_t(double(maxcram) * 1024.0 * 1024.0 * 1024.0)); + Session::setUsePreEval(prefetch); + ImageRenderer::setUseThreadedUpload(useThreadedUpload); + Session::setMaxBufferedWaitTime(maxbwait); + Session::setCacheLookBehindFraction(lookback); + Session::setMaxGreedyCacheSize( + size_t(double(maxcram) * 1024.0 * 1024.0 * 1024.0)); + Session::setMaxBufferCacheSize( + size_t(double(maxlram) * 1024.0 * 1024.0 * 1024.0)); + LUTIPNode::newGLSLlutInterp = newGLSLlutInterp; + LayoutGroupIPNode::setDefaultAutoRetime(autoRetime); + StackGroupIPNode::setDefaultAutoRetime(autoRetime); + SequenceGroupIPNode::setDefaultAutoRetime(autoRetime); + IPCore::FBCache::setCacheOutsideRegion(cacheOutsideRegion != 0); + + if (audioOff) + AudioRenderer::setAudioNever(true); + + AudioRenderer::audioModule = audioModule ? audioModule : ""; + + AudioRenderer::RendererParameters audioParams; + audioParams.holdOpen = !audioNice; + audioParams.framesPerBuffer = aframesize; + audioParams.device = audioDevice ? audioDevice : ""; + audioParams.hardwareLock = !audioNoLock; + audioParams.rate = audioRate; + audioParams.preRoll = audioPreRoll; + + // Convert from msecs to secs and reverse the sign. + audioParams.latency = -audioDeviceLatency / 1000.0; + + switch (audioPrecision) + { + case 32: + audioParams.format = TwkAudio::Float32Format; + break; + case -32: + audioParams.format = TwkAudio::Int32Format; + break; + case 24: + audioParams.format = TwkAudio::Int24Format; + break; + default: + case 16: + audioParams.format = TwkAudio::Int16Format; + break; + case 8: + audioParams.format = TwkAudio::Int8Format; + break; + } - if (!strcmp(bgpattern, "black")) p = ImageRenderer::Solid0; - else if (!strcmp(bgpattern, "grey18")) p = ImageRenderer::Solid18; - else if (!strcmp(bgpattern, "grey50")) p = ImageRenderer::Solid50; - else if (!strcmp(bgpattern, "white")) p = ImageRenderer::Solid100; - else if (!strcmp(bgpattern, "checker")) p = ImageRenderer::Checker; - else if (!strcmp(bgpattern, "crosshatch")) p = ImageRenderer::CrossHatch; + audioParams.layout = TwkAudio::Layout(audioLayout); - ImageRenderer::setDefaultBGPattern(p); - } + AudioRenderer::setDefaultParameters(audioParams); + AudioRenderer::initialize(); - ImageRenderer::defaultAllowPBOs(!noPBO); - ImageRenderer::setUseAppleClientStorage(useAppleClientStorage); - DisplayStereoIPNode::setSwapScanlines(swapScanlines); - SystemInfo::setMaxVRAM(size_t(double(maxvram) * 1024.0 * 1024.0)); - if (eval) RvSession::setInitEval(eval); - if (pyeval) RvSession::setPyInitEval(pyeval); - if (maxbits != 32) FormatIPNode::defaultBitDepth = maxbits; - if (nofloat) FormatIPNode::defaultAllowFP = false; - SoundTrackIPNode::defaultVolume = volume; - FormatIPNode::defaultResampleMethod = resampleMethod; - FileSourceIPNode::defaultOverrideFPS = fps; - FileSourceIPNode::defaultFPS = defaultfps; - SystemInfo::setUseableMemory(size_t(double(maxcram) * 1024.0 * 1024.0 * 1024.0)); - Session::setUsePreEval(prefetch); - ImageRenderer::setUseThreadedUpload(useThreadedUpload); - Session::setMaxBufferedWaitTime(maxbwait); - Session::setCacheLookBehindFraction(lookback); - Session::setMaxGreedyCacheSize(size_t(double(maxcram) * 1024.0 * 1024.0 * 1024.0)); - Session::setMaxBufferCacheSize(size_t(double(maxlram) * 1024.0 * 1024.0 * 1024.0)); - LUTIPNode::newGLSLlutInterp = newGLSLlutInterp; - LayoutGroupIPNode::setDefaultAutoRetime(autoRetime); - StackGroupIPNode::setDefaultAutoRetime(autoRetime); - SequenceGroupIPNode::setDefaultAutoRetime(autoRetime); - IPCore::FBCache::setCacheOutsideRegion(cacheOutsideRegion != 0); - - if (audioOff) AudioRenderer::setAudioNever(true); - - AudioRenderer::audioModule = audioModule ? audioModule : ""; - - AudioRenderer::RendererParameters audioParams; - audioParams.holdOpen = !audioNice; - audioParams.framesPerBuffer = aframesize; - audioParams.device = audioDevice ? audioDevice : ""; - audioParams.hardwareLock = !audioNoLock; - audioParams.rate = audioRate; - audioParams.preRoll = audioPreRoll; - - // Convert from msecs to secs and reverse the sign. - audioParams.latency = -audioDeviceLatency / 1000.0; - - switch (audioPrecision) - { - case 32: audioParams.format = TwkAudio::Float32Format; break; - case -32: audioParams.format = TwkAudio::Int32Format; break; - case 24: audioParams.format = TwkAudio::Int24Format; break; - default: - case 16: audioParams.format = TwkAudio::Int16Format; break; - case 8: audioParams.format = TwkAudio::Int8Format; break; - } + if (usecli) + TwkApp::cli(); - audioParams.layout = TwkAudio::Layout(audioLayout); + // + // Expand "macro" arguments + // - AudioRenderer::setDefaultParameters(audioParams); - AudioRenderer::initialize(); + if (over + tile + diff + wipes + layer + topmost + replace > 1) + { + cerr << "ERROR: you can only have one of -wipe, -over, -diff, " + "-replace, -layer, -topmost or -tile" + << endl; + exit(-1); + } - if (usecli) TwkApp::cli(); + if (over) + { + view = (char*)"defaultStack"; + compMode = (char*)"over"; + } - // - // Expand "macro" arguments - // + if (tile) + { + view = (char*)"defaultLayout"; + layoutMode = (char*)"packed"; + } - if (over + tile + diff + wipes + layer + topmost + replace > 1) - { - cerr << "ERROR: you can only have one of -wipe, -over, -diff, -replace, -layer, -topmost or -tile" << endl; - exit(-1); - } + if (diff) + { + view = (char*)"defaultStack"; + compMode = (char*)"difference"; + } - if (over) - { - view = (char*)"defaultStack"; - compMode = (char*)"over"; - } + if (replace) + { + view = (char*)"defaultStack"; + compMode = (char*)"replace"; + } - if (tile) - { - view = (char*)"defaultLayout"; - layoutMode = (char*)"packed"; - } + if (topmost) + { + view = (char*)"defaultStack"; + compMode = (char*)"topmost"; + } - if (diff) - { - view = (char*)"defaultStack"; - compMode = (char*)"difference"; - } + if (layer) + { + view = (char*)"defaultStack"; + compMode = (char*)"layer"; + } - if (replace) - { - view = (char*)"defaultStack"; - compMode = (char*)"replace"; - } + if (sessionType) + { + if (!strcmp(sessionType, "sequence")) + view = (char*)"defaultSequence"; + else if (!strcmp(sessionType, "stack")) + view = (char*)"defaultStack"; + } - if (topmost) - { - view = (char*)"defaultStack"; - compMode = (char*)"topmost"; - } + if (wipes) + { + // Don't set view here because the viewNode may already be + // a stack, in which case we just want to turn on wipes. + // This'll happen in RvApplication. + } - if (layer) - { - view = (char*)"defaultStack"; - compMode = (char*)"layer"; - } + if (stereoMode) + { + DisplayStereoIPNode::setDefaultType(stereoMode); + } - if (sessionType) - { - if (!strcmp(sessionType, "sequence")) view = (char*)"defaultSequence"; - else if (!strcmp(sessionType, "stack")) view = (char*)"defaultStack"; - } + if (compMode) + { + StackIPNode::setDefaultCompType(compMode); + } - if (wipes) - { - // Don't set view here because the viewNode may already be - // a stack, in which case we just want to turn on wipes. - // This'll happen in RvApplication. - } + if (layoutMode) + { + LayoutGroupIPNode::setDefaultMode(layoutMode); + } - if (stereoMode) - { - DisplayStereoIPNode::setDefaultType(stereoMode); - } + if (showFormats) + { + TwkMovie::GenericIO::outputFormats(); + return false; + } - if (compMode) - { - StackIPNode::setDefaultCompType(compMode); - } + exportIOEnvVars(); - if (layoutMode) - { - LayoutGroupIPNode::setDefaultMode(layoutMode); + return true; } - if (showFormats) + void Options::manglePerSourceArgs(char** argv, int argc) { - TwkMovie::GenericIO::outputFormats(); - return false; - } + bool in = false; - exportIOEnvVars(); + // + // if the argument starts with a '-' and is between a '[' and ']' + // argument and it is not a negative number, replace the '-' with + // a '+'. This is trying to convert flags of the form: -foo to + // +foo so that they can be parsed by the Session + // - return true; -} - -void -Options::manglePerSourceArgs(char** argv, int argc) -{ - bool in = false; - - // - // if the argument starts with a '-' and is between a '[' and ']' - // argument and it is not a negative number, replace the '-' with - // a '+'. This is trying to convert flags of the form: -foo to - // +foo so that they can be parsed by the Session - // - - for (int i = 0; i < argc; ++i) - { - char *s = argv[i]; - if (!strcmp(s, "[")) in = true; - else if (!strcmp(s, "]")) in = false; - else if (in && s[0] == '-' && atof(s) >= 0) s[0] = '+'; + for (int i = 0; i < argc; ++i) + { + char* s = argv[i]; + if (!strcmp(s, "[")) + in = true; + else if (!strcmp(s, "]")) + in = false; + else if (in && s[0] == '-' && atof(s) >= 0) + s[0] = '+'; + } } -} - -void -Options::output(ostream& out) -{ - static const char* intfields[] = - { "acachesize", "aframesize", "allowYUV", "apple", "audioNice", "audioLayout", - "audioNoLock", "audioScrub", "audioPreRoll", "audioOff", "audioPrecision", "autoRetime", "bakeURL", "cinIOMethod", - "cinIOSize", "cinMaxAsync", "cinalt", "cinchroma", "connectPort", "cutInPoint", - "cutOutPoint", "diff", "dispAlphaBits", "dispBlueBits", "dispGreenBits", "dispRedBits", - "dpxIOMethod", "dpxIOSize", "dpxMaxAsync", "dpxchroma", "encodeURL", "exrIOMethod", - "exrIOSize", "exrInherit", "exrMaxAsync", "exrNoOneChannel", "exrReadWindow", - "exrPlanar3Chan", "exrStripAlpha", "exrRGBA", "exrcpus", - "newGLSLlutInterp", "fullscreen", "present", "presentAudio", "inferSequence", - "jpegIOMethod", "jpegIOSize", "jpegMaxAsync", - "jpegRGBA", "lqt_decoder", "maxbits", "network", "networkOnStartup", "networkPerm", - "networkPort", "noMovieAudio", "noPBO", "swapScanlines", "noPackages", "noPrefs", "noRanges", "noSequence", - "nofloat", "nomb", "nukeSequence", "over", "play", "playMode", "prefetch", - "useThreadedUpload", "useAppleClientStorage", "progressiveSourceLoading", - "qtdesktop", "rangeOffset", "rangeStart", "readerThreads", "workItemThreads", "rec709", "resetPrefs", "sRGB", - "showCMS", "showFormats", "showVersion", "stylusAsMouse", "sync", "tgaIOMethod", "tgaIOSize", - "tgaMaxAsync", "tiffIOMethod", "tiffIOSize", "tiffMaxAsync", "tile", "urlsReuseSession", - "useCache", "useLCache", "usecli", "vsync", "wipes", "xl", - "noBorders", "screen", "x", "y", "width", "height", "startupResize", "displayPriority", "audioPriority", - "stereoSwap", - NULL }; - - static const char* floatfields[] = - { "audioMaxCache", "audioMinCache", "audioOffset", "audioRate", "brightness", - "cropX0", "cropX1", "cropY0", "cropY1", "defaultfps", "fps", "gamma", - "lookback", "maxbwait", "maxcram", "maxlram", "maxvram", "pixelAspect", "scale", - "stereoOffset", "rightEyeStereoOffset", "totalcram", "uncropH", "uncropW", "uncropX", - "uncropY", "volume", "audioGlobalOffset", "audioDeviceLatency", - NULL - }; - - size_t intoffsets[] = + void Options::output(ostream& out) { - static_cast((char*)(&this->acachesize) - (char*)this), - static_cast((char*)(&this->aframesize) - (char*)this), - static_cast((char*)(&this->allowYUV) - (char*)this), - static_cast((char*)(&this->apple) - (char*)this), - static_cast((char*)(&this->audioNice) - (char*)this), - static_cast((char*)(&this->audioLayout) - (char*)this), - static_cast((char*)(&this->audioNoLock) - (char*)this), - static_cast((char*)(&this->audioScrub) - (char*)this), - static_cast((char*)(&this->audioPreRoll) - (char*)this), - static_cast((char*)(&this->audioOff) - (char*)this), - static_cast((char*)(&this->audioPrecision) - (char*)this), - static_cast((char*)(&this->autoRetime) - (char*)this), - static_cast((char*)(&this->bakeURL) - (char*)this), - static_cast((char*)(&this->cinIOMethod) - (char*)this), - static_cast((char*)(&this->cinIOSize) - (char*)this), - static_cast((char*)(&this->cinMaxAsync) - (char*)this), - static_cast((char*)(&this->cinalt) - (char*)this), - static_cast((char*)(&this->cinchroma) - (char*)this), - static_cast((char*)(&this->connectPort) - (char*)this), - static_cast((char*)(&this->cutInPoint) - (char*)this), - static_cast((char*)(&this->cutOutPoint) - (char*)this), - static_cast((char*)(&this->diff) - (char*)this), - static_cast((char*)(&this->dispAlphaBits) - (char*)this), - static_cast((char*)(&this->dispBlueBits) - (char*)this), - static_cast((char*)(&this->dispGreenBits) - (char*)this), - static_cast((char*)(&this->dispRedBits) - (char*)this), - static_cast((char*)(&this->dpxIOMethod) - (char*)this), - static_cast((char*)(&this->dpxIOSize) - (char*)this), - static_cast((char*)(&this->dpxMaxAsync) - (char*)this), - static_cast((char*)(&this->dpxchroma) - (char*)this), - static_cast((char*)(&this->encodeURL) - (char*)this), - static_cast((char*)(&this->exrIOMethod) - (char*)this), - static_cast((char*)(&this->exrIOSize) - (char*)this), - static_cast((char*)(&this->exrInherit) - (char*)this), - static_cast((char*)(&this->exrMaxAsync) - (char*)this), - static_cast((char*)(&this->exrNoOneChannel) - (char*)this), - static_cast((char*)(&this->exrReadWindowIsDisplayWindow) - (char*)this), - static_cast((char*)(&this->exrReadWindow) - (char*)this), - static_cast((char*)(&this->exrPlanar3Chan) - (char*)this), - static_cast((char*)(&this->exrStripAlpha) - (char*)this), - static_cast((char*)(&this->exrRGBA) - (char*)this), - static_cast((char*)(&this->exrcpus) - (char*)this), - static_cast((char*)(&this->newGLSLlutInterp) - (char*)this), - static_cast((char*)(&this->fullscreen) - (char*)this), - static_cast((char*)(&this->present) - (char*)this), - static_cast((char*)(&this->presentAudio) - (char*)this), - static_cast((char*)(&this->inferSequence) - (char*)this), - static_cast((char*)(&this->jpegIOMethod) - (char*)this), - static_cast((char*)(&this->jpegIOSize) - (char*)this), - static_cast((char*)(&this->jpegMaxAsync) - (char*)this), - static_cast((char*)(&this->jpegRGBA) - (char*)this), - static_cast((char*)(&this->lqt_decoder) - (char*)this), - static_cast((char*)(&this->maxbits) - (char*)this), - static_cast((char*)(&this->network) - (char*)this), - static_cast((char*)(&this->networkOnStartup) - (char*)this), - static_cast((char*)(&this->networkPerm) - (char*)this), - static_cast((char*)(&this->networkPort) - (char*)this), - static_cast((char*)(&this->noMovieAudio) - (char*)this), - static_cast((char*)(&this->noPBO) - (char*)this), - static_cast((char*)(&this->swapScanlines) - (char*)this), - static_cast((char*)(&this->noPackages) - (char*)this), - static_cast((char*)(&this->noPrefs) - (char*)this), - static_cast((char*)(&this->noRanges) - (char*)this), - static_cast((char*)(&this->noSequence) - (char*)this), - static_cast((char*)(&this->nofloat) - (char*)this), - static_cast((char*)(&this->nomb) - (char*)this), - static_cast((char*)(&this->nukeSequence) - (char*)this), - static_cast((char*)(&this->over) - (char*)this), - static_cast((char*)(&this->play) - (char*)this), - static_cast((char*)(&this->playMode) - (char*)this), - static_cast((char*)(&this->loopMode) - (char*)this), - static_cast((char*)(&this->prefetch) - (char*)this), - static_cast((char*)(&this->useThreadedUpload) - (char*)this), - static_cast((char*)(&this->useAppleClientStorage) - (char*)this), - static_cast((char*)(&this->progressiveSourceLoading) - (char*)this), - static_cast((char*)(&this->qtdesktop) - (char*)this), - static_cast((char*)(&this->rangeOffset) - (char*)this), - static_cast((char*)(&this->rangeStart) - (char*)this), - static_cast((char*)(&this->readerThreads) - (char*)this), - static_cast((char*)(&this->workItemThreads) - (char*)this), - static_cast((char*)(&this->rec709) - (char*)this), - static_cast((char*)(&this->resetPrefs) - (char*)this), - static_cast((char*)(&this->sRGB) - (char*)this), - static_cast((char*)(&this->showCMS) - (char*)this), - static_cast((char*)(&this->showFormats) - (char*)this), - static_cast((char*)(&this->showVersion) - (char*)this), - static_cast((char*)(&this->stylusAsMouse) - (char*)this), - static_cast((char*)(&this->sync) - (char*)this), - static_cast((char*)(&this->tgaIOMethod) - (char*)this), - static_cast((char*)(&this->tgaIOSize) - (char*)this), - static_cast((char*)(&this->tgaMaxAsync) - (char*)this), - static_cast((char*)(&this->tiffIOMethod) - (char*)this), - static_cast((char*)(&this->tiffIOSize) - (char*)this), - static_cast((char*)(&this->tiffMaxAsync) - (char*)this), - static_cast((char*)(&this->tile) - (char*)this), - static_cast((char*)(&this->urlsReuseSession) - (char*)this), - static_cast((char*)(&this->useCache) - (char*)this), - static_cast((char*)(&this->useLCache) - (char*)this), - static_cast((char*)(&this->usecli) - (char*)this), - static_cast((char*)(&this->vsync) - (char*)this), - static_cast((char*)(&this->wipes) - (char*)this), - static_cast((char*)(&this->xl) - (char*)this), - static_cast((char*)(&this->noBorders) - (char*)this), - static_cast((char*)(&this->screen) - (char*)this), - static_cast((char*)(&this->x) - (char*)this), - static_cast((char*)(&this->y) - (char*)this), - static_cast((char*)(&this->width) - (char*)this), - static_cast((char*)(&this->height) - (char*)this), - static_cast((char*)(&this->startupResize) - (char*)this), - static_cast((char*)(&this->displayPriority) - (char*)this), - static_cast((char*)(&this->audioPriority) - (char*)this), - static_cast((char*)(&this->stereoSwapEyes) - (char*)this), - 0 - }; - - size_t floatoffsets[] = { - static_cast((char*)(&this->audioMaxCache) - (char*)this), - static_cast((char*)(&this->audioMinCache) - (char*)this), - static_cast((char*)(&this->audioOffset) - (char*)this), - static_cast((char*)(&this->audioRate) - (char*)this), - static_cast((char*)(&this->brightness) - (char*)this), - static_cast((char*)(&this->cropX0) - (char*)this), - static_cast((char*)(&this->cropX1) - (char*)this), - static_cast((char*)(&this->cropY0) - (char*)this), - static_cast((char*)(&this->cropY1) - (char*)this), - static_cast((char*)(&this->defaultfps) - (char*)this), - static_cast((char*)(&this->fps) - (char*)this), - static_cast((char*)(&this->gamma) - (char*)this), - static_cast((char*)(&this->lookback) - (char*)this), - static_cast((char*)(&this->maxbwait) - (char*)this), - static_cast((char*)(&this->maxcram) - (char*)this), - static_cast((char*)(&this->maxlram) - (char*)this), - static_cast((char*)(&this->maxvram) - (char*)this), - static_cast((char*)(&this->pixelAspect) - (char*)this), - static_cast((char*)(&this->scale) - (char*)this), - static_cast((char*)(&this->stereoOffset) - (char*)this), - static_cast((char*)(&this->rightEyeStereoOffset) - (char*)this), - static_cast((char*)(&this->totalcram) - (char*)this), - static_cast((char*)(&this->uncropH) - (char*)this), - static_cast((char*)(&this->uncropW) - (char*)this), - static_cast((char*)(&this->uncropX) - (char*)this), - static_cast((char*)(&this->uncropY) - (char*)this), - static_cast((char*)(&this->volume) - (char*)this), - static_cast((char*)(&this->audioGlobalOffset) - (char*)this), - static_cast((char*)(&this->audioDeviceLatency) - (char*)this), - 0 - }; + static const char* intfields[] = {"acachesize", + "aframesize", + "allowYUV", + "apple", + "audioNice", + "audioLayout", + "audioNoLock", + "audioScrub", + "audioPreRoll", + "audioOff", + "audioPrecision", + "autoRetime", + "bakeURL", + "cinIOMethod", + "cinIOSize", + "cinMaxAsync", + "cinalt", + "cinchroma", + "connectPort", + "cutInPoint", + "cutOutPoint", + "diff", + "dispAlphaBits", + "dispBlueBits", + "dispGreenBits", + "dispRedBits", + "dpxIOMethod", + "dpxIOSize", + "dpxMaxAsync", + "dpxchroma", + "encodeURL", + "exrIOMethod", + "exrIOSize", + "exrInherit", + "exrMaxAsync", + "exrNoOneChannel", + "exrReadWindow", + "exrPlanar3Chan", + "exrStripAlpha", + "exrRGBA", + "exrcpus", + "newGLSLlutInterp", + "fullscreen", + "present", + "presentAudio", + "inferSequence", + "jpegIOMethod", + "jpegIOSize", + "jpegMaxAsync", + "jpegRGBA", + "lqt_decoder", + "maxbits", + "network", + "networkOnStartup", + "networkPerm", + "networkPort", + "noMovieAudio", + "noPBO", + "swapScanlines", + "noPackages", + "noPrefs", + "noRanges", + "noSequence", + "nofloat", + "nomb", + "nukeSequence", + "over", + "play", + "playMode", + "prefetch", + "useThreadedUpload", + "useAppleClientStorage", + "progressiveSourceLoading", + "qtdesktop", + "rangeOffset", + "rangeStart", + "readerThreads", + "workItemThreads", + "rec709", + "resetPrefs", + "sRGB", + "showCMS", + "showFormats", + "showVersion", + "stylusAsMouse", + "sync", + "tgaIOMethod", + "tgaIOSize", + "tgaMaxAsync", + "tiffIOMethod", + "tiffIOSize", + "tiffMaxAsync", + "tile", + "urlsReuseSession", + "useCache", + "useLCache", + "usecli", + "vsync", + "wipes", + "xl", + "noBorders", + "screen", + "x", + "y", + "width", + "height", + "startupResize", + "displayPriority", + "audioPriority", + "stereoSwap", + NULL}; + + static const char* floatfields[] = {"audioMaxCache", + "audioMinCache", + "audioOffset", + "audioRate", + "brightness", + "cropX0", + "cropX1", + "cropY0", + "cropY1", + "defaultfps", + "fps", + "gamma", + "lookback", + "maxbwait", + "maxcram", + "maxlram", + "maxvram", + "pixelAspect", + "scale", + "stereoOffset", + "rightEyeStereoOffset", + "totalcram", + "uncropH", + "uncropW", + "uncropX", + "uncropY", + "volume", + "audioGlobalOffset", + "audioDeviceLatency", + NULL}; + + size_t intoffsets[] = { + static_cast((char*)(&this->acachesize) - (char*)this), + static_cast((char*)(&this->aframesize) - (char*)this), + static_cast((char*)(&this->allowYUV) - (char*)this), + static_cast((char*)(&this->apple) - (char*)this), + static_cast((char*)(&this->audioNice) - (char*)this), + static_cast((char*)(&this->audioLayout) - (char*)this), + static_cast((char*)(&this->audioNoLock) - (char*)this), + static_cast((char*)(&this->audioScrub) - (char*)this), + static_cast((char*)(&this->audioPreRoll) - (char*)this), + static_cast((char*)(&this->audioOff) - (char*)this), + static_cast((char*)(&this->audioPrecision) - (char*)this), + static_cast((char*)(&this->autoRetime) - (char*)this), + static_cast((char*)(&this->bakeURL) - (char*)this), + static_cast((char*)(&this->cinIOMethod) - (char*)this), + static_cast((char*)(&this->cinIOSize) - (char*)this), + static_cast((char*)(&this->cinMaxAsync) - (char*)this), + static_cast((char*)(&this->cinalt) - (char*)this), + static_cast((char*)(&this->cinchroma) - (char*)this), + static_cast((char*)(&this->connectPort) - (char*)this), + static_cast((char*)(&this->cutInPoint) - (char*)this), + static_cast((char*)(&this->cutOutPoint) - (char*)this), + static_cast((char*)(&this->diff) - (char*)this), + static_cast((char*)(&this->dispAlphaBits) - (char*)this), + static_cast((char*)(&this->dispBlueBits) - (char*)this), + static_cast((char*)(&this->dispGreenBits) - (char*)this), + static_cast((char*)(&this->dispRedBits) - (char*)this), + static_cast((char*)(&this->dpxIOMethod) - (char*)this), + static_cast((char*)(&this->dpxIOSize) - (char*)this), + static_cast((char*)(&this->dpxMaxAsync) - (char*)this), + static_cast((char*)(&this->dpxchroma) - (char*)this), + static_cast((char*)(&this->encodeURL) - (char*)this), + static_cast((char*)(&this->exrIOMethod) - (char*)this), + static_cast((char*)(&this->exrIOSize) - (char*)this), + static_cast((char*)(&this->exrInherit) - (char*)this), + static_cast((char*)(&this->exrMaxAsync) - (char*)this), + static_cast((char*)(&this->exrNoOneChannel) - (char*)this), + static_cast((char*)(&this->exrReadWindowIsDisplayWindow) + - (char*)this), + static_cast((char*)(&this->exrReadWindow) - (char*)this), + static_cast((char*)(&this->exrPlanar3Chan) - (char*)this), + static_cast((char*)(&this->exrStripAlpha) - (char*)this), + static_cast((char*)(&this->exrRGBA) - (char*)this), + static_cast((char*)(&this->exrcpus) - (char*)this), + static_cast((char*)(&this->newGLSLlutInterp) - (char*)this), + static_cast((char*)(&this->fullscreen) - (char*)this), + static_cast((char*)(&this->present) - (char*)this), + static_cast((char*)(&this->presentAudio) - (char*)this), + static_cast((char*)(&this->inferSequence) - (char*)this), + static_cast((char*)(&this->jpegIOMethod) - (char*)this), + static_cast((char*)(&this->jpegIOSize) - (char*)this), + static_cast((char*)(&this->jpegMaxAsync) - (char*)this), + static_cast((char*)(&this->jpegRGBA) - (char*)this), + static_cast((char*)(&this->lqt_decoder) - (char*)this), + static_cast((char*)(&this->maxbits) - (char*)this), + static_cast((char*)(&this->network) - (char*)this), + static_cast((char*)(&this->networkOnStartup) - (char*)this), + static_cast((char*)(&this->networkPerm) - (char*)this), + static_cast((char*)(&this->networkPort) - (char*)this), + static_cast((char*)(&this->noMovieAudio) - (char*)this), + static_cast((char*)(&this->noPBO) - (char*)this), + static_cast((char*)(&this->swapScanlines) - (char*)this), + static_cast((char*)(&this->noPackages) - (char*)this), + static_cast((char*)(&this->noPrefs) - (char*)this), + static_cast((char*)(&this->noRanges) - (char*)this), + static_cast((char*)(&this->noSequence) - (char*)this), + static_cast((char*)(&this->nofloat) - (char*)this), + static_cast((char*)(&this->nomb) - (char*)this), + static_cast((char*)(&this->nukeSequence) - (char*)this), + static_cast((char*)(&this->over) - (char*)this), + static_cast((char*)(&this->play) - (char*)this), + static_cast((char*)(&this->playMode) - (char*)this), + static_cast((char*)(&this->loopMode) - (char*)this), + static_cast((char*)(&this->prefetch) - (char*)this), + static_cast((char*)(&this->useThreadedUpload) + - (char*)this), + static_cast((char*)(&this->useAppleClientStorage) + - (char*)this), + static_cast((char*)(&this->progressiveSourceLoading) + - (char*)this), + static_cast((char*)(&this->qtdesktop) - (char*)this), + static_cast((char*)(&this->rangeOffset) - (char*)this), + static_cast((char*)(&this->rangeStart) - (char*)this), + static_cast((char*)(&this->readerThreads) - (char*)this), + static_cast((char*)(&this->workItemThreads) - (char*)this), + static_cast((char*)(&this->rec709) - (char*)this), + static_cast((char*)(&this->resetPrefs) - (char*)this), + static_cast((char*)(&this->sRGB) - (char*)this), + static_cast((char*)(&this->showCMS) - (char*)this), + static_cast((char*)(&this->showFormats) - (char*)this), + static_cast((char*)(&this->showVersion) - (char*)this), + static_cast((char*)(&this->stylusAsMouse) - (char*)this), + static_cast((char*)(&this->sync) - (char*)this), + static_cast((char*)(&this->tgaIOMethod) - (char*)this), + static_cast((char*)(&this->tgaIOSize) - (char*)this), + static_cast((char*)(&this->tgaMaxAsync) - (char*)this), + static_cast((char*)(&this->tiffIOMethod) - (char*)this), + static_cast((char*)(&this->tiffIOSize) - (char*)this), + static_cast((char*)(&this->tiffMaxAsync) - (char*)this), + static_cast((char*)(&this->tile) - (char*)this), + static_cast((char*)(&this->urlsReuseSession) - (char*)this), + static_cast((char*)(&this->useCache) - (char*)this), + static_cast((char*)(&this->useLCache) - (char*)this), + static_cast((char*)(&this->usecli) - (char*)this), + static_cast((char*)(&this->vsync) - (char*)this), + static_cast((char*)(&this->wipes) - (char*)this), + static_cast((char*)(&this->xl) - (char*)this), + static_cast((char*)(&this->noBorders) - (char*)this), + static_cast((char*)(&this->screen) - (char*)this), + static_cast((char*)(&this->x) - (char*)this), + static_cast((char*)(&this->y) - (char*)this), + static_cast((char*)(&this->width) - (char*)this), + static_cast((char*)(&this->height) - (char*)this), + static_cast((char*)(&this->startupResize) - (char*)this), + static_cast((char*)(&this->displayPriority) - (char*)this), + static_cast((char*)(&this->audioPriority) - (char*)this), + static_cast((char*)(&this->stereoSwapEyes) - (char*)this), + 0}; + + size_t floatoffsets[] = { + static_cast((char*)(&this->audioMaxCache) - (char*)this), + static_cast((char*)(&this->audioMinCache) - (char*)this), + static_cast((char*)(&this->audioOffset) - (char*)this), + static_cast((char*)(&this->audioRate) - (char*)this), + static_cast((char*)(&this->brightness) - (char*)this), + static_cast((char*)(&this->cropX0) - (char*)this), + static_cast((char*)(&this->cropX1) - (char*)this), + static_cast((char*)(&this->cropY0) - (char*)this), + static_cast((char*)(&this->cropY1) - (char*)this), + static_cast((char*)(&this->defaultfps) - (char*)this), + static_cast((char*)(&this->fps) - (char*)this), + static_cast((char*)(&this->gamma) - (char*)this), + static_cast((char*)(&this->lookback) - (char*)this), + static_cast((char*)(&this->maxbwait) - (char*)this), + static_cast((char*)(&this->maxcram) - (char*)this), + static_cast((char*)(&this->maxlram) - (char*)this), + static_cast((char*)(&this->maxvram) - (char*)this), + static_cast((char*)(&this->pixelAspect) - (char*)this), + static_cast((char*)(&this->scale) - (char*)this), + static_cast((char*)(&this->stereoOffset) - (char*)this), + static_cast((char*)(&this->rightEyeStereoOffset) + - (char*)this), + static_cast((char*)(&this->totalcram) - (char*)this), + static_cast((char*)(&this->uncropH) - (char*)this), + static_cast((char*)(&this->uncropW) - (char*)this), + static_cast((char*)(&this->uncropX) - (char*)this), + static_cast((char*)(&this->uncropY) - (char*)this), + static_cast((char*)(&this->volume) - (char*)this), + static_cast((char*)(&this->audioGlobalOffset) + - (char*)this), + static_cast((char*)(&this->audioDeviceLatency) + - (char*)this), + 0}; - { - size_t* o = intoffsets; - for (const char** f = intfields; *f; f++, o++) { - int* p = (int*) ((char*)this + *o); - out << "# " << *f << " = " << *p << endl; + size_t* o = intoffsets; + for (const char** f = intfields; *f; f++, o++) + { + int* p = (int*)((char*)this + *o); + out << "# " << *f << " = " << *p << endl; + } } - } - { - size_t* o = floatoffsets; - for (const char** f = floatfields; *f; f++, o++) { - float* p = (float*) ((char*)this + *o); - out << "# " << *f << " = " << *p << endl; + size_t* o = floatoffsets; + for (const char** f = floatfields; *f; f++, o++) + { + float* p = (float*)((char*)this + *o); + out << "# " << *f << " = " << *p << endl; + } } - } #define CHAROUT(x) "# " << #x << " = " << (x ? x : "") << endl - out << CHAROUT(audioDevice) - << CHAROUT(audioModule) - << CHAROUT(bgpattern) - << CHAROUT(cinPixel) - << CHAROUT(cmapString) - << CHAROUT(selectType) - << CHAROUT(selectName) - << CHAROUT(mediaRepName) - << CHAROUT(mediaRepSource) - << CHAROUT(cms) - << CHAROUT(cmsDisplay) - << CHAROUT(cmsSimulation) - << CHAROUT(compMode) - << CHAROUT(connectHost) - << CHAROUT(dispLUT) - << CHAROUT(dpxPixel) - << CHAROUT(eval) - << CHAROUT(fileCDL) - << CHAROUT(fileLUT) - << CHAROUT(initscript) - << CHAROUT(layoutMode) - << CHAROUT(licarg) - << CHAROUT(lookCDL) - << CHAROUT(lookLUT) - << CHAROUT(mistPixel) - << CHAROUT(networkHost) - << CHAROUT(networkTag) - << CHAROUT(preCacheLUT) - << CHAROUT(presentData) - << CHAROUT(presentDevice) - << CHAROUT(presentFormat) - << CHAROUT(qtcss) - << CHAROUT(qtstyle) - << CHAROUT(resampleMethod) - << CHAROUT(schedulePolicy) - << CHAROUT(sessionType) - << CHAROUT(stereoMode) - << CHAROUT(view) - << CHAROUT(windowType); - - for (int i = 0; i < sendEvents.size(); ++i) - { - out << CHAROUT(sendEvents[i].name.c_str()) - << CHAROUT(sendEvents[i].content.c_str()); + out << CHAROUT(audioDevice) << CHAROUT(audioModule) + << CHAROUT(bgpattern) << CHAROUT(cinPixel) << CHAROUT(cmapString) + << CHAROUT(selectType) << CHAROUT(selectName) + << CHAROUT(mediaRepName) << CHAROUT(mediaRepSource) << CHAROUT(cms) + << CHAROUT(cmsDisplay) << CHAROUT(cmsSimulation) + << CHAROUT(compMode) << CHAROUT(connectHost) << CHAROUT(dispLUT) + << CHAROUT(dpxPixel) << CHAROUT(eval) << CHAROUT(fileCDL) + << CHAROUT(fileLUT) << CHAROUT(initscript) << CHAROUT(layoutMode) + << CHAROUT(licarg) << CHAROUT(lookCDL) << CHAROUT(lookLUT) + << CHAROUT(mistPixel) << CHAROUT(networkHost) << CHAROUT(networkTag) + << CHAROUT(preCacheLUT) << CHAROUT(presentData) + << CHAROUT(presentDevice) << CHAROUT(presentFormat) + << CHAROUT(qtcss) << CHAROUT(qtstyle) << CHAROUT(resampleMethod) + << CHAROUT(schedulePolicy) << CHAROUT(sessionType) + << CHAROUT(stereoMode) << CHAROUT(view) << CHAROUT(windowType); + + for (int i = 0; i < sendEvents.size(); ++i) + { + out << CHAROUT(sendEvents[i].name.c_str()) + << CHAROUT(sendEvents[i].content.c_str()); + } } -} -} // +} // namespace Rv diff --git a/src/lib/app/RvApp/PyCommandsModule.cpp b/src/lib/app/RvApp/PyCommandsModule.cpp index 660374dbb..619cc4741 100644 --- a/src/lib/app/RvApp/PyCommandsModule.cpp +++ b/src/lib/app/RvApp/PyCommandsModule.cpp @@ -1,9 +1,9 @@ // // Copyright (c) 2011 Tweak Software. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// // #include @@ -15,20 +15,19 @@ #include #include -namespace Rv { +namespace Rv +{ using namespace std; using namespace TwkApp; using namespace IPCore; - static PyObject* - badArgument() + static PyObject* badArgument() { PyErr_SetString(PyExc_Exception, "Bad argument"); return NULL; } - static PyObject * - data(PyObject *self, PyObject* args) + static PyObject* data(PyObject* self, PyObject* args) { RvSession* s = RvSession::currentRvSession(); @@ -43,23 +42,23 @@ namespace Rv { } } - static PyObject * - insertCreatePixelBlock(PyObject *self, PyObject* args) + static PyObject* insertCreatePixelBlock(PyObject* self, PyObject* args) { RvSession* s = RvSession::currentRvSession(); PyEventObject* event; - if (!PyArg_ParseTuple(args, "O!", TwkApp::pyEventType(),&event)) return NULL; + if (!PyArg_ParseTuple(args, "O!", TwkApp::pyEventType(), &event)) + return NULL; if (const PixelBlockTransferEvent* pe = - dynamic_cast(event->event)) + dynamic_cast(event->event)) { const RvGraph::Sources& sources = s->rvgraph().imageSources(); - for (size_t i=0; i < sources.size(); i++) + for (size_t i = 0; i < sources.size(); i++) { if (ImageSourceIPNode* node = - dynamic_cast(sources[i])) + dynamic_cast(sources[i])) { size_t index = node->mediaIndex(pe->media()); @@ -67,12 +66,10 @@ namespace Rv { { try { - node->insertPixels(pe->view(), - pe->layer(), - pe->frame(), - pe->x(), pe->y(), pe->width(), pe->height(), - pe->pixels(), - pe->size()); + node->insertPixels(pe->view(), pe->layer(), + pe->frame(), pe->x(), pe->y(), + pe->width(), pe->height(), + pe->pixels(), pe->size()); } catch (PixelBlockSizeMismatchExc& exc) { @@ -97,25 +94,15 @@ namespace Rv { return Py_None; } - static PyMethodDef localmethods[] ={ + static PyMethodDef localmethods[] = { - { "data", - data, - METH_NOARGS, - "return session data object." }, + {"data", data, METH_NOARGS, "return session data object."}, - { "insertCreatePixelBlock", - insertCreatePixelBlock, - METH_VARARGS, - "insert block of pixels into image source." }, + {"insertCreatePixelBlock", insertCreatePixelBlock, METH_VARARGS, + "insert block of pixels into image source."}, - { NULL } - }; + {NULL}}; - void* - pyRvAppCommands() - { - return (void*)localmethods; - } + void* pyRvAppCommands() { return (void*)localmethods; } -} // Rv +} // namespace Rv diff --git a/src/lib/app/RvApp/RvApp/CommandsModule.h b/src/lib/app/RvApp/RvApp/CommandsModule.h index 78705c176..59233302e 100644 --- a/src/lib/app/RvApp/RvApp/CommandsModule.h +++ b/src/lib/app/RvApp/RvApp/CommandsModule.h @@ -1,9 +1,9 @@ // // Copyright (c) 2013 Tweak Software // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// // #ifndef __RvApp__CommandsModule__h__ #define __RvApp__CommandsModule__h__ @@ -12,12 +12,13 @@ #include #include -namespace Rv { +namespace Rv +{ -void initCommands(Mu::MuLangContext* c=0); -Mu::Function* sessionFunction(const char*); -void makeSessionDataFunction(Mu::Function*); + void initCommands(Mu::MuLangContext* c = 0); + Mu::Function* sessionFunction(const char*); + void makeSessionDataFunction(Mu::Function*); -} // Rv +} // namespace Rv #endif // __RvApp__CommandsModule__h__ diff --git a/src/lib/app/RvApp/RvApp/FileSpaceLinearizeIPNode.h b/src/lib/app/RvApp/RvApp/FileSpaceLinearizeIPNode.h index 7af755d81..2c59f04c3 100644 --- a/src/lib/app/RvApp/RvApp/FileSpaceLinearizeIPNode.h +++ b/src/lib/app/RvApp/RvApp/FileSpaceLinearizeIPNode.h @@ -1,64 +1,64 @@ //****************************************************************************** -// Copyright (c) 2005 Tweak Inc. +// Copyright (c) 2005 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #ifndef __IPGraph__FileSpaceLinearizeIPNode__h__ #define __IPGraph__FileSpaceLinearizeIPNode__h__ #include #include -namespace IPCore { +namespace IPCore +{ -// -// FileSpaceLinearizeIPNode -// -// Convert from file to (linear) working space. Don't use this node -// in new applications. This is for RV backwards compatibility. -// + // + // FileSpaceLinearizeIPNode + // + // Convert from file to (linear) working space. Don't use this node + // in new applications. This is for RV backwards compatibility. + // -class FileSpaceLinearizeIPNode : public LUTIPNode -{ - public: - FileSpaceLinearizeIPNode(const std::string& name, - const NodeDefinition* def, - IPGraph* graph, - GroupIPNode* group = 0); - - virtual ~FileSpaceLinearizeIPNode(); + class FileSpaceLinearizeIPNode : public LUTIPNode + { + public: + FileSpaceLinearizeIPNode(const std::string& name, + const NodeDefinition* def, IPGraph* graph, + GroupIPNode* group = 0); + + virtual ~FileSpaceLinearizeIPNode(); + + virtual IPImage* evaluate(const Context&); - virtual IPImage* evaluate(const Context&); + void setLogLin(int); + void setSRGB(int); + void setRec709(int); + void setFileGamma(float); - void setLogLin(int); - void setSRGB(int); - void setRec709(int); - void setFileGamma(float); + private: + void evaluateOne(IPImage* img, const Context& context); - private: - void evaluateOne(IPImage* img, const Context& context); - - private: - IntProperty* m_colorAlphaType; - IntProperty* m_colorLogType; - IntProperty* m_cineonWhite; - IntProperty* m_cineonBlack; - IntProperty* m_cineonBreakPoint; - IntProperty* m_colorYUV; - IntProperty* m_colorsRGB2Linear; - IntProperty* m_colorRec7092Linear; - FloatProperty* m_colorFileGamma; - IntProperty* m_colorActive; - IntProperty* m_colorIgnoreChromaticities; - IntProperty* m_CDLactive; - Vec3fProperty* m_CDLslope; - Vec3fProperty* m_CDLoffset; - Vec3fProperty* m_CDLpower; - FloatProperty* m_CDLsaturation; - IntProperty* m_CDLnoclamp; -}; + private: + IntProperty* m_colorAlphaType; + IntProperty* m_colorLogType; + IntProperty* m_cineonWhite; + IntProperty* m_cineonBlack; + IntProperty* m_cineonBreakPoint; + IntProperty* m_colorYUV; + IntProperty* m_colorsRGB2Linear; + IntProperty* m_colorRec7092Linear; + FloatProperty* m_colorFileGamma; + IntProperty* m_colorActive; + IntProperty* m_colorIgnoreChromaticities; + IntProperty* m_CDLactive; + Vec3fProperty* m_CDLslope; + Vec3fProperty* m_CDLoffset; + Vec3fProperty* m_CDLpower; + FloatProperty* m_CDLsaturation; + IntProperty* m_CDLnoclamp; + }; -} // Rv +} // namespace IPCore #endif // __IPGraph__FileSpaceLinearizeIPNode__h__ diff --git a/src/lib/app/RvApp/RvApp/FormatIPNode.h b/src/lib/app/RvApp/RvApp/FormatIPNode.h index cd5720874..7d8609dbd 100644 --- a/src/lib/app/RvApp/RvApp/FormatIPNode.h +++ b/src/lib/app/RvApp/RvApp/FormatIPNode.h @@ -1,9 +1,9 @@ //****************************************************************************** -// Copyright (c) 2005 Tweak Inc. +// Copyright (c) 2005 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #ifndef __IPGraph__FormatIPNode__h__ #define __IPGraph__FormatIPNode__h__ @@ -13,100 +13,99 @@ #include #include -namespace IPCore { - -// -// class FormatIPNode -// -// Converts inputs into formats that can be used by the ImageRenderer -// - -class FormatIPNode : public IPNode +namespace IPCore { - public: - typedef TwkFBAux::Interpolation Interpolation; - typedef TwkFB::FrameBuffer::DataType DataType; - struct Params + // + // class FormatIPNode + // + // Converts inputs into formats that can be used by the ImageRenderer + // + + class FormatIPNode : public IPNode { - bool floatOk; - float scale; - int xfit; - int yfit; - int xresize; - int yresize; - int maxBitDepth; - DataType bestIntegral; - DataType bestFloat; - bool crop; - int cropX0; - int cropY0; - int cropX1; - int cropY1; - int leftCrop; - int rightCrop; - int topCrop; - int bottomCrop; - bool uncrop; - int uncropWidth; - int uncropHeight; - int uncropX; - int uncropY; - Interpolation method; - }; + public: + typedef TwkFBAux::Interpolation Interpolation; + typedef TwkFB::FrameBuffer::DataType DataType; - FormatIPNode(const std::string& name, - const NodeDefinition* def, - IPGraph*, - GroupIPNode* group=0); - virtual ~FormatIPNode(); + struct Params + { + bool floatOk; + float scale; + int xfit; + int yfit; + int xresize; + int yresize; + int maxBitDepth; + DataType bestIntegral; + DataType bestFloat; + bool crop; + int cropX0; + int cropY0; + int cropX1; + int cropY1; + int leftCrop; + int rightCrop; + int topCrop; + int bottomCrop; + bool uncrop; + int uncropWidth; + int uncropHeight; + int uncropX; + int uncropY; + Interpolation method; + }; - virtual IPImage* evaluate(const Context&); - virtual IPImageID* evaluateIdentifier(const Context&); + FormatIPNode(const std::string& name, const NodeDefinition* def, + IPGraph*, GroupIPNode* group = 0); + virtual ~FormatIPNode(); - Params params() const; + virtual IPImage* evaluate(const Context&); + virtual IPImageID* evaluateIdentifier(const Context&); - virtual ImageStructureInfo imageStructureInfo(const Context&) const; - virtual void propertyChanged(const Property*); + Params params() const; - void setFitResolution(int w, int h); - void setResizeResolution(int w, int h); - void setCrop(int x0, int y0, int x1, int y1); - void setUncrop(int w, int h, int x, int y); + virtual ImageStructureInfo imageStructureInfo(const Context&) const; + virtual void propertyChanged(const Property*); - static int defaultBitDepth; - static bool defaultAllowFP; - static std::string defaultResampleMethod; + void setFitResolution(int w, int h); + void setResizeResolution(int w, int h); + void setCrop(int x0, int y0, int x1, int y1); + void setUncrop(int w, int h, int x, int y); - protected: - virtual void outputDisconnect(IPNode*); + static int defaultBitDepth; + static bool defaultAllowFP; + static std::string defaultResampleMethod; - private: - IntProperty* m_xfit; - IntProperty* m_yfit; - IntProperty* m_xresize; - IntProperty* m_yresize; - FloatProperty* m_scale; - StringProperty* m_resampleMethod; - IntProperty* m_maxBitDepth; - IntProperty* m_allowFloatingPoint; - IntProperty* m_cropActive; - IntProperty* m_xmin; - IntProperty* m_xmax; - IntProperty* m_ymin; - IntProperty* m_ymax; - IntProperty* m_leftCrop; - IntProperty* m_rightCrop; - IntProperty* m_topCrop; - IntProperty* m_bottomCrop; - IntProperty* m_cropManip; - IntProperty* m_uncropActive; - IntProperty* m_uncropWidth; - IntProperty* m_uncropHeight; - IntProperty* m_uncropX; - IntProperty* m_uncropY; -}; + protected: + virtual void outputDisconnect(IPNode*); + + private: + IntProperty* m_xfit; + IntProperty* m_yfit; + IntProperty* m_xresize; + IntProperty* m_yresize; + FloatProperty* m_scale; + StringProperty* m_resampleMethod; + IntProperty* m_maxBitDepth; + IntProperty* m_allowFloatingPoint; + IntProperty* m_cropActive; + IntProperty* m_xmin; + IntProperty* m_xmax; + IntProperty* m_ymin; + IntProperty* m_ymax; + IntProperty* m_leftCrop; + IntProperty* m_rightCrop; + IntProperty* m_topCrop; + IntProperty* m_bottomCrop; + IntProperty* m_cropManip; + IntProperty* m_uncropActive; + IntProperty* m_uncropWidth; + IntProperty* m_uncropHeight; + IntProperty* m_uncropX; + IntProperty* m_uncropY; + }; -} // Rv +} // namespace IPCore #endif // __IPGraph__FormatIPNode__h__ diff --git a/src/lib/app/RvApp/RvApp/Options.h b/src/lib/app/RvApp/RvApp/Options.h index 29c63cae6..c8ab7c6b7 100644 --- a/src/lib/app/RvApp/RvApp/Options.h +++ b/src/lib/app/RvApp/RvApp/Options.h @@ -1,9 +1,9 @@ // // Copyright (c) 2013 Tweak Software // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// // #ifndef __RV__Options__h__ #define __RV__Options__h__ @@ -13,541 +13,667 @@ #include #include -namespace Rv { - -// -// This is for use with the libarg parser. The MACRO below is -// provided as an arg_parse function argument. This should contain -// logic and arguments common to all implementations. This struct -// should probably not be used anywhere in RvApp (eventhough it lives -// here). -// - -struct Options +namespace Rv { - typedef std::vector StringVector; - typedef std::map StringMap; - typedef std::vector Files; - typedef std::deque > Params; - struct SourceArgs + // + // This is for use with the libarg parser. The MACRO below is + // provided as an arg_parse function argument. This should contain + // logic and arguments common to all implementations. This struct + // should probably not be used anywhere in RvApp (eventhough it lives + // here). + // + + struct Options { - SourceArgs() : audioOffset(0), rangeOffset(0), volume(1), fps(0), - pixelAspect(0), stereoRelativeOffset(0), stereoRightOffset(0), - hascrop(false), hasuncrop(false), singleSource (false), - noMovieAudio(false) + typedef std::vector StringVector; + typedef std::map StringMap; + typedef std::vector Files; + typedef std::deque> Params; + + struct SourceArgs + { + SourceArgs() + : audioOffset(0) + , rangeOffset(0) + , volume(1) + , fps(0) + , pixelAspect(0) + , stereoRelativeOffset(0) + , stereoRightOffset(0) + , hascrop(false) + , hasuncrop(false) + , singleSource(false) + , noMovieAudio(false) { - cutIn = (std::numeric_limits::max)(); + cutIn = (std::numeric_limits::max)(); cutOut = (std::numeric_limits::max)(); rangeStart = (std::numeric_limits::max)(); } - StringVector files; - float audioOffset; - int rangeOffset; - int rangeStart; - float volume; - float fps; - bool hascrop; - bool singleSource; - bool noMovieAudio; - float crop[4]; - bool hasuncrop; - float uncrop[4]; - float pixelAspect; - float stereoRelativeOffset; - float stereoRightOffset; - int cutIn; - int cutOut; - std::string fcdl; - std::string lcdl; - std::string flut; - std::string pclut; - std::string llut; - std::string cmap; - std::string selectName; - std::string selectType; - std::string mediaRepName; - std::string mediaRepSource; - Params inparams; + StringVector files; + float audioOffset; + int rangeOffset; + int rangeStart; + float volume; + float fps; + bool hascrop; + bool singleSource; + bool noMovieAudio; + float crop[4]; + bool hasuncrop; + float uncrop[4]; + float pixelAspect; + float stereoRelativeOffset; + float stereoRightOffset; + int cutIn; + int cutOut; + std::string fcdl; + std::string lcdl; + std::string flut; + std::string pclut; + std::string llut; + std::string cmap; + std::string selectName; + std::string selectType; + std::string mediaRepName; + std::string mediaRepSource; + Params inparams; + }; + + typedef std::vector SourceArgsVector; + + struct SendExternalEvent + { + std::string name; + std::string content; + }; + + typedef std::vector SendExternalEventVector; + + Options(); + + // + // Use this, don't make your own Options object + // + + static Options& sharedOptions(); + + // + // Call this prior to calling arg_parse with argv + // + + static void manglePerSourceArgs(char** argv, int argc); + + // + // Call this before you start your app up. It may act on some of the + // option state and exit (for example show formats). It will also + // convert the inputFiles into SourceArgsVector + // + + bool initializeAfterParsing(Options* prefs = 0); + + // + // Set IO env variable arguments from the options + // + + void exportIOEnvVars() const; + + // + // Find seperate frame ranges + // + + void integrateFrameRangeStrings(std::vector&); + + // + // Parse an input file list into SourceArgs. Files is a bit deceiving, + // it can actullay contain groupings "[" and "]" as well as per-source + // args premanged from manglePerSourceArgs() like +fps, etc. The + // parsed per-source args are in the structs along with the actual + // final file list with arguments stripped. + // + + SourceArgsVector parseSourceArgs(const StringVector&); + + // + // Output as ASCII data. Each line is preceeded by "#" character + // + + void output(std::ostream&); + + // + // The state + // + + float fps; + float defaultfps; + int useCache; + int useLCache; + int useNoCache; + int showFormats; + int fullscreen; + int usecli; + int nomb; + char* bgpattern; + int nukeSequence; + int noRanges; + char* initscript; + float scale; + char* windowType; + char* sessionType; + char* resampleMethod; + char* licarg; + float maxvram; + float totalcram; + float maxcram; + float maxlram; + float maxbwait; + float lookback; + int cacheOutsideRegion; + int noPBO; + int swapScanlines; + int prefetch; + int useAppleClientStorage; + int useThreadedUpload; + int readerThreads; + int workItemThreads; + int apple; + int allowYUV; + int sync; + int lqt_decoder; + int exrcpus; + int networkPort; + int dispRedBits; + int dispGreenBits; + int dispBlueBits; + int dispAlphaBits; + char* networkHost; + std::string networkHostBuf; + char* networkTag; + std::string networkTagBuf; + int networkPerm; + char* networkUser; + int exrRGBA; + int exrIOMethod; + int exrIOSize; + int exrMaxAsync; + int exrInherit; + int exrNoOneChannel; + int exrReadWindowIsDisplayWindow; + int exrReadWindow; + int exrPlanar3Chan; + int exrStripAlpha; + int exrConvertYRYBY; + int jpegRGBA; + int jpegIOMethod; + int jpegIOSize; + int jpegMaxAsync; + int nofloat; + int maxbits; + int audioOff; + int audioNoLock; + int audioNice; + int audioScrub; + int audioPreRoll; + char* audioModule; + char* audioDevice; + float audioRate; + int audioPrecision; + int audioLayout; + float audioMinCache; + float audioMaxCache; + float audioGlobalOffset; + float audioDeviceLatency; + float volume; + char* eval; + char* pyeval; + float gamma; + float brightness; + int showVersion; + int play; + int playMode; + int loopMode; + int showCMS; + int cinalt; + int cinchroma; + int dpxchroma; + int cinIOMethod; + int cinIOSize; + int cinMaxAsync; + int dpxIOMethod; + int dpxIOSize; + int dpxMaxAsync; + int tgaIOMethod; + int tgaIOSize; + int tgaMaxAsync; + int tiffIOMethod; + int tiffIOSize; + int tiffMaxAsync; + int aframesize; + int acachesize; + char* cms; + char* cmsDisplay; + char* cmsSimulation; + char* stereoMode; + char* compMode; + char* layoutMode; + int stereoSwapEyes; + int over; + int replace; + int topmost; + int layer; + int tile; + int diff; + int wipes; + int noSequence; + int inferSequence; + int autoRetime; + StringVector inputFiles; + char* fileCDL; + char* lookCDL; + char* fileLUT; + char* preCacheLUT; + char* lookLUT; + char* dispLUT; + char* cmapString; + char* selectType; + char* selectName; + char* mediaRepName; + char* mediaRepSource; + int noPrefs; + int resetPrefs; + int useCrashReporter; + int encodeURL; + int bakeURL; + int sRGB; + int rec709; + char* cinPixel; + char* dpxPixel; + char* mistPixel; + int newGLSLlutInterp; + int vsync; + char* qtstyle; + char* qtcss; + int qtdesktop; + int xl; + int network; + char* connectHost; + int connectPort; + int networkOnStartup; + int stylusAsMouse; + int scrubEnable; + int clickToPlayEnable; + int urlsReuseSession; + int noPackages; + int delaySessionLoading; + int progressiveSourceLoading; + StringVector debugKeyWords; + StringMap muFlags; + char* view; + int imageFilter; + + float pixelAspect; + int rangeOffset; + int rangeStart; + int cutInPoint; + int cutOutPoint; + int noMovieAudio; + float stereoOffset; + float rightEyeStereoOffset; + float audioOffset; + float cropX0; + float cropY0; + float cropX1; + float cropY1; + float uncropW; + float uncropH; + float uncropX; + float uncropY; + Params inparams; + + int x; + int y; + int width; + int height; + int screen; + int startupResize; + int noBorders; + int displayPriority; + int audioPriority; + char* schedulePolicy; + + char* presentDevice; + char* presentFormat; + char* presentData; + int present; + int presentAudio; + int fontSize1; + int fontSize2; + + SendExternalEventVector sendEvents; }; - typedef std::vector SourceArgsVector; - - struct SendExternalEvent - { - std::string name; - std::string content; - }; - - typedef std::vector SendExternalEventVector; - - Options(); - - // - // Use this, don't make your own Options object - // - - static Options& sharedOptions(); - - // - // Call this prior to calling arg_parse with argv - // - - static void manglePerSourceArgs(char** argv, int argc); - - // - // Call this before you start your app up. It may act on some of the - // option state and exit (for example show formats). It will also - // convert the inputFiles into SourceArgsVector - // - - bool initializeAfterParsing(Options* prefs = 0); - - // - // Set IO env variable arguments from the options - // - - void exportIOEnvVars() const; - - // - // Find seperate frame ranges - // - - void integrateFrameRangeStrings(std::vector&); - - // - // Parse an input file list into SourceArgs. Files is a bit deceiving, - // it can actullay contain groupings "[" and "]" as well as per-source - // args premanged from manglePerSourceArgs() like +fps, etc. The - // parsed per-source args are in the structs along with the actual - // final file list with arguments stripped. - // - - SourceArgsVector parseSourceArgs(const StringVector&); - - // - // Output as ASCII data. Each line is preceeded by "#" character - // - - void output(std::ostream&); - - // - // The state - // + int collectParameters(Options::Params&, const Options::Files&, int); + int parseInParams(int, char**); + int parseDebugKeyWords(int, char**); + int parseMuFlags(int, char**); + int parseSendEvents(int, char**); + const char* getDebugCategories(); - float fps; - float defaultfps; - int useCache; - int useLCache; - int useNoCache; - int showFormats; - int fullscreen; - int usecli; - int nomb; - char* bgpattern; - int nukeSequence; - int noRanges; - char* initscript; - float scale; - char* windowType; - char* sessionType; - char* resampleMethod; - char* licarg; - float maxvram; - float totalcram; - float maxcram; - float maxlram; - float maxbwait; - float lookback; - int cacheOutsideRegion; - int noPBO; - int swapScanlines; - int prefetch; - int useAppleClientStorage; - int useThreadedUpload; - int readerThreads; - int workItemThreads; - int apple; - int allowYUV; - int sync; - int lqt_decoder; - int exrcpus; - int networkPort; - int dispRedBits; - int dispGreenBits; - int dispBlueBits; - int dispAlphaBits; - char* networkHost; - std::string networkHostBuf; - char* networkTag; - std::string networkTagBuf; - int networkPerm; - char* networkUser; - int exrRGBA; - int exrIOMethod; - int exrIOSize; - int exrMaxAsync; - int exrInherit; - int exrNoOneChannel; - int exrReadWindowIsDisplayWindow; - int exrReadWindow; - int exrPlanar3Chan; - int exrStripAlpha; - int exrConvertYRYBY; - int jpegRGBA; - int jpegIOMethod; - int jpegIOSize; - int jpegMaxAsync; - int nofloat; - int maxbits; - int audioOff; - int audioNoLock; - int audioNice; - int audioScrub; - int audioPreRoll; - char* audioModule; - char* audioDevice; - float audioRate; - int audioPrecision; - int audioLayout; - float audioMinCache; - float audioMaxCache; - float audioGlobalOffset; - float audioDeviceLatency; - float volume; - char* eval; - char* pyeval; - float gamma; - float brightness; - int showVersion; - int play; - int playMode; - int loopMode; - int showCMS; - int cinalt; - int cinchroma; - int dpxchroma; - int cinIOMethod; - int cinIOSize; - int cinMaxAsync; - int dpxIOMethod; - int dpxIOSize; - int dpxMaxAsync; - int tgaIOMethod; - int tgaIOSize; - int tgaMaxAsync; - int tiffIOMethod; - int tiffIOSize; - int tiffMaxAsync; - int aframesize; - int acachesize; - char* cms; - char* cmsDisplay; - char* cmsSimulation; - char* stereoMode; - char* compMode; - char* layoutMode; - int stereoSwapEyes; - int over; - int replace; - int topmost; - int layer; - int tile; - int diff; - int wipes; - int noSequence; - int inferSequence; - int autoRetime; - StringVector inputFiles; - char* fileCDL; - char* lookCDL; - char* fileLUT; - char* preCacheLUT; - char* lookLUT; - char* dispLUT; - char* cmapString; - char* selectType; - char* selectName; - char* mediaRepName; - char* mediaRepSource; - int noPrefs; - int resetPrefs; - int useCrashReporter; - int encodeURL; - int bakeURL; - int sRGB; - int rec709; - char* cinPixel; - char* dpxPixel; - char* mistPixel; - int newGLSLlutInterp; - int vsync; - char* qtstyle; - char* qtcss; - int qtdesktop; - int xl; - int network; - char* connectHost; - int connectPort; - int networkOnStartup; - int stylusAsMouse; - int scrubEnable; - int clickToPlayEnable; - int urlsReuseSession; - int noPackages; - int delaySessionLoading; - int progressiveSourceLoading; - StringVector debugKeyWords; - StringMap muFlags; - char* view; - int imageFilter; - - float pixelAspect; - int rangeOffset; - int rangeStart; - int cutInPoint; - int cutOutPoint; - int noMovieAudio; - float stereoOffset; - float rightEyeStereoOffset; - float audioOffset; - float cropX0; - float cropY0; - float cropX1; - float cropY1; - float uncropW; - float uncropH; - float uncropX; - float uncropY; - Params inparams; - - int x; - int y; - int width; - int height; - int screen; - int startupResize; - int noBorders; - int displayPriority; - int audioPriority; - char* schedulePolicy; - - char* presentDevice; - char* presentFormat; - char* presentData; - int present; - int presentAudio; - int fontSize1; - int fontSize2; - - SendExternalEventVector sendEvents; -}; - -int collectParameters(Options::Params&, const Options::Files&, int); -int parseInParams(int, char**); -int parseDebugKeyWords(int, char**); -int parseMuFlags(int, char**); -int parseSendEvents(int, char**); -const char* getDebugCategories(); - -} // Rv +} // namespace Rv // // This should be one of the arguments to arg_parse // -#define RV_ARG_EXAMPLES \ - "", "Usage: RV movie and image sequence viewer", \ - "", "", \ - "", " One File: rv foo.jpg", \ - "", " This Directory: rv .", \ - "", " Other Directory: rv /path/to/dir", \ - "", " Image Sequence w/Audio: rv [ in.#.tif in.wav ]", \ - "", " Stereo w/Audio: rv [ left.#.tif right.#.tif in.wav ]", \ - "", " Stereo Movies: rv [ left.mov right.mov ]", \ - "", " Stereo Movie (from rvio): rv stereo.mov", \ - "", " Cuts Sequenced: rv cut1.mov cut2.#.exr cut3.mov", \ - "", " Stereo Cuts Sequenced: rv [ l1.mov r1.mov ] [ l2.mov r2.mov ]", \ - "", " Forced Anamorphic: rv [ -pa 2.0 fullaperture.#.dpx ]", \ - "", " Compare: rv -wipe a.exr b.exr", \ - "", " Difference: rv -diff a.exr b.exr", \ - "", " Slap Comp Over: rv -over a.exr b.exr", \ - "", " Tile Images: rv -tile *.jpg", \ - "", " Cache + Play Movie: rv -l -play foo.mov", \ - "", " Cache Images to Examine: rv -c big.#.exr", \ - "", " Fullscreen on 2nd monitor: rv -fullscreen -screen 1", \ - "", " Select Source View: rv [ in.exr -select view right ] ", \ - "", " Select Source Layer: rv [ in.exr -select layer light1.diffuse ] (single-view source)", \ - "", " Select Source Layer: rv [ in.exr -select layer left,light1.diffuse ] (multi-view source)", \ - "", " Select Source Channel: rv [ in.exr -select channel R ] (single-view, single-layer source)", \ - "", " Select Source Channel: rv [ in.exr -select channel left,Diffuse,R ] (multi-view, multi-layer source)" \ - -#define RV_ARG_SEQUENCE_HELP \ - "", "Image Sequence Numbering", \ - "", "", \ - "", " Frames 1 to 100 no padding: image.1-100@.jpg", \ - "", " Frames 1 to 100 padding 4: image.1-100#.jpg -or- image.1-100@@@@.jpg", \ - "", " Frames 1 to 100 padding 5: image.1-100@@@@@.jpg", \ - "", " Frames -100 to -200 padding 4: image.-100--200#jpg", \ - "", " printf style padding 4: image.%%04d.jpg", \ - "", " printf style w/range: image.%%04d.jpg 1-100", \ - "", " printf no padding w/range: image.%%d.jpg 1-100", \ - "", " Complicated no pad 1 to 100: image_887f1-100@_982.tif", \ - "", " Stereo pair (left,right): image.#.%%V.tif", \ - "", " Stereo pair (L,R): image.#.%%v.tif", \ - "", " All Frames, padding 4: image.#.jpg", \ - "", " All Frames in Sequence: image.*.jpg", \ - "", " All Frames in Directory: /path/to/directory", \ - "", " All Frames in current dir: ." - -#define RV_ARG_SOURCE_OPTIONS(opt) \ - "", "Per-source arguments (inside [ and ] restricts to that source only)", \ - "", "", \ - "-pa %f", &opt.pixelAspect, "Per-source pixel aspect ratio", \ - "-ro %d", &opt.rangeOffset, "Per-source range offset", \ - "-rs %d", &opt.rangeStart, "Per-source range start", \ - "-fps %f", &opt.fps, "Per-source or global fps", \ - "-ao %f", &opt.audioOffset, "Per-source audio offset in seconds", \ - "-so %f", &opt.stereoOffset, "Per-source stereo relative eye offset", \ - "-rso %f", &opt.rightEyeStereoOffset, "Per-source stereo right eye offset", \ - "-volume %f", &opt.volume, "Per-source or global audio volume (default=%.2g)", opt.volume, \ - "-fcdl %S", &opt.fileCDL, "Per-source file CDL", \ - "-lcdl %S", &opt.lookCDL, "Per-source look CDL", \ - "-flut %S", &opt.fileLUT, "Per-source file LUT", \ - "-llut %S", &opt.lookLUT, "Per-source look LUT", \ - "-pclut %S", &opt.preCacheLUT, "Per-source pre-cache software LUT", \ - "-cmap %S", &opt.cmapString, "Per-source channel mapping (channel names, separated by ',')", \ - "-select %S %S", &opt.selectType, &opt.selectName, "Per-source view/layer/channel selection", \ - "-mediaRepName %S", &opt.mediaRepName, "Per-source media representation name", \ - "-mediaRepSource %S", &opt.mediaRepSource, "The source for which to add the source media representation", \ - "-crop %d %d %d %d", &opt.cropX0, &opt.cropY0, &opt.cropX1, &opt.cropY1, "Per-source crop (xmin, ymin, xmax, ymax)", \ - "-uncrop %d %d %d %d", &opt.uncropW, &opt.uncropH, &opt.uncropX, &opt.uncropY, "Per-source uncrop (width, height, xoffset, yoffset)", \ - "-in %d", &opt.cutInPoint, "Per-source cut-in frame", \ - "-out %d", &opt.cutOutPoint, "Per-source cut-out frame", \ - "-noMovieAudio", ARG_FLAG(&opt.noMovieAudio), "Disable source movie's baked-in audio", \ - "-inparams", ARG_SUBR(&Rv::parseInParams), "Source specific input parameters" - -#define RV_ARG_PARSE_OPTIONS(opt) \ - "-c", ARG_FLAG(&opt.useCache), "Use region frame cache", \ - "-l", ARG_FLAG(&opt.useLCache), "Use look-ahead cache", \ - "-nc", ARG_FLAG(&opt.useNoCache), "Use no caching", \ - "-s %f", &opt.scale, "Image scale reduction", \ - "-ns", ARG_FLAG(&opt.nukeSequence), "Nuke style sequence notation (deprecated and ignored -- no longer needed)", \ - "-noRanges", ARG_FLAG(&opt.noRanges), "No separate frame ranges (i.e. 1-10 will be considered a file)", \ - "-sessionType %S", &opt.sessionType, "Session type (sequence, stack) (deprecated, use -view)", \ - "-stereo %S", &opt.stereoMode, "Stereo mode (hardware, checker, scanline, anaglyph, lumanaglyph, left, right, pair, mirror, hsqueezed, vsqueezed)", \ - "-stereoSwap %d", &opt.stereoSwapEyes, "Swap left and right eyes stereo display (0 == no, 1 == yes, default=%d)", opts.stereoSwapEyes, \ - "-vsync %d", &opt.vsync, "Video Sync (1 = on, 0 = off, default = %d)", opts.vsync, \ - "-comp %S", &opt.compMode, "Composite mode (over, add, difference, replace, topmost)", \ - "-layout %S", &opt.layoutMode, "Layout mode (packed, row, column, manual)", \ - "-over", ARG_FLAG(&opt.over), "Same as -comp over -view defaultStack", \ - "-diff", ARG_FLAG(&opt.diff), "Same as -comp difference -view defaultStack", \ - "-replace", ARG_FLAG(&opt.replace), "Same as -comp replace -view defaultStack", \ - "-topmost", ARG_FLAG(&opt.topmost), "Same as -comp topmost -view defaultStack", \ - "-layer", ARG_FLAG(&opt.layer), "Same as -comp topmost -view defaultStack, with strict frame ranges", \ - "-tile", ARG_FLAG(&opt.tile), "Same as -layout packed -view defaultLayout", \ - "-wipe", ARG_FLAG(&opt.wipes), "Same as -over with wipes enabled", \ - "-view %S", &opt.view, "Start with a particular view", \ - "-noSequence", ARG_FLAG(&opt.noSequence), "Don't contract files into sequences", \ - "-inferSequence", ARG_FLAG(&opt.inferSequence), "Infer sequences from one file", \ - "-autoRetime %d", &opt.autoRetime, "Automatically retime conflicting media fps in sequences and stacks (1 = on, 0 = off, default = %d)", opts.autoRetime, \ - "-rthreads %d", &opt.readerThreads, "Number of reader threads (default=%d)", opts.readerThreads, \ - "-workItemThreads %d", &opt.workItemThreads, "Number of work item threads (default=%d)", opts.workItemThreads, \ - "-progressiveSourceLoading %d", &opt.progressiveSourceLoading, "Use asynchronous source loading, default=0 (off)", \ - "-fullscreen", ARG_FLAG(&opt.fullscreen), "Start in fullscreen mode", \ - "-present", ARG_FLAG(&opt.present), "Start in presentation mode (using presentation device)", \ - "-presentAudio %d", &opt.presentAudio, "Use presentation audio device in presentation mode (1 = on, 0 = off)", \ - "-presentDevice %S", &opt.presentDevice, "Presentation mode device", \ - "-presentVideoFormat %S", &opt.presentFormat, "Presentation mode override video format (device specific)", \ - "-presentDataFormat %S", &opt.presentData, "Presentation mode override data format (device specific)", \ - "-screen %d", &opt.screen, "Start on screen (0, 1, 2, ...)", \ - "-noBorders", ARG_FLAG(&opt.noBorders), "No window manager decorations", \ - "-geometry %d %d [%d %d]", &opt.x, &opt.y, &opt.width, &opt.height, "Start geometry X, Y, W, H", \ - "-fitMedia", ARG_FLAG(&opt.startupResize), "Fit the window to the first media shown", \ - "-init %S", &opt.initscript, "Override init script", \ - "-nofloat", ARG_FLAG(&opt.nofloat), "Turn off floating point by default", \ - "-maxbits %d", &opt.maxbits, "Maximum default bit depth (default=%d)", opt.maxbits, \ - "-gamma %f", &opt.gamma, "Set display gamma (default=%g)", opt.gamma, \ - "-sRGB", ARG_FLAG(&opt.sRGB), "Display using linear -> sRGB conversion", \ - "-rec709", ARG_FLAG(&opt.rec709), "Display using linear -> Rec 709 conversion", \ - "-dlut %S", &opt.dispLUT, "Apply display LUT", \ - "-brightness %f", &opt.brightness, "Set display relative brightness in stops (default=%g)", opt.brightness, \ - "-resampleMethod %S", &opt.resampleMethod, "Resampling method (area, linear, cubic, nearest, default=%s)", opt.resampleMethod, \ - "-eval %S", &opt.eval, "Evaluate Mu expression at every session start", \ - "-pyeval %S", &opt.pyeval, "Evaluate Python expression at every session start", \ - "-nomb", ARG_FLAG(&opt.nomb), "Hide menu bar on start up", \ - "-play", ARG_FLAG(&opt.play), "Play on startup", \ - "-playMode %d", &opt.playMode, "Playback mode (0=Context dependent, 1=Play all frames, 2=Realtime, default=%d)", opt.playMode, \ - "-loopMode %d", &opt.loopMode, "Playback loop mode (0=Loop, 1=Play Once, 2=Ping-Pong, default=%d)", opt.loopMode, \ - "-cli", ARG_FLAG(&opt.usecli), "Mu command line interface", \ - "-vram %f", &opt.maxvram, "VRAM usage limit in Mb, default = %f", opt.maxvram, \ - "-cram %f", &opt.maxcram, "Max region cache RAM usage in Gb, (%.2gGb available, default %.2gGb)", opt.totalcram, opt.maxcram, \ - "-lram %f", &opt.maxlram, "Max look-ahead cache RAM usage in Gb, (%.2gGb available, default %.2gGb)", opt.totalcram, opt.maxlram, \ - "-noPBO", ARG_FLAG(&opt.noPBO), "Prevent use of GL PBOs for pixel transfer", \ - "-prefetch", ARG_FLAG(&opt.prefetch), "Prefetch images for rendering", \ - "-useAppleClientStorage", ARG_FLAG(&opt.useAppleClientStorage), "Use APPLE_client_storage extension", \ - "-useThreadedUpload", ARG_FLAG(&opt.useThreadedUpload), "Use threading for texture uploading/downloading if possible", \ - "-bwait %f", &opt.maxbwait, "Max buffer wait time in cached seconds, default %.1f", opt.maxbwait, \ - "-lookback %f", &opt.lookback, "Percentage of the lookahead cache reserved for frames behind the playhead, default %g", opt.lookback, \ - "-yuv", ARG_FLAG(&opt.allowYUV), "Assume YUV hardware conversion", \ - "-noaudio", ARG_FLAG(&opt.audioOff), "Turn off audio", \ - "-audiofs %d", &opt.aframesize, "Use fixed audio frame size (results are hardware dependant ... try 512)", \ - "-audioCachePacket %d", &opt.acachesize, "Audio cache packet size in samples (default=%d)", opt.acachesize, \ - "-audioMinCache %f", &opt.audioMinCache, "Audio cache min size in seconds (default=%f)", opt.audioMinCache, \ - "-audioMaxCache %f", &opt.audioMaxCache, "Audio cache max size in seconds (default=%f)", opt.audioMaxCache, \ - "-audioModule %S", &opt.audioModule, "Use specific audio module", \ - "-audioDevice %S", &opt.audioDevice, "Use specific audio device", \ - "-audioRate %f", &opt.audioRate, "Use specific output audio rate (default=ask hardware)", \ - "-audioPrecision %d", &opt.audioPrecision, "Use specific output audio precision (default=%d)", opt.audioPrecision, \ - "-audioNice %d", &opt.audioNice, "Close audio device when not playing (may cause problems on some hardware) default=%d", opt.audioNice, \ - "-audioNoLock %d", &opt.audioNoLock, "Do not use hardware audio/video syncronization (use software instead, default=%d)", opt.audioNoLock, \ - "-audioPreRoll %d", &opt.audioPreRoll, "Preroll audio on device open (Linux only; default=%d)", opt.audioPreRoll, \ - "-audioGlobalOffset %f", &opt.audioGlobalOffset, "Global audio offset in seconds", \ - "-audioDeviceLatency %f", &opt.audioDeviceLatency, "Audio device latency compensation in milliseconds", \ - "-bg %S", &opt.bgpattern, "Background pattern (default=black, white, grey18, grey50, checker, crosshatch)", \ - "-formats", ARG_FLAG(&opt.showFormats), "Show all supported image and movie formats", \ - "-apple", ARG_FLAG(&opt.apple), "Use Quicktime and NSImage libraries (on OS X)", \ - "-cinalt", ARG_FLAG(&opt.cinalt), "Use alternate Cineon/DPX readers", \ - "-exrcpus %d", &opt.exrcpus, "EXR thread count (default=%d)", opt.exrcpus, \ - "-exrRGBA", ARG_FLAG(&opt.exrRGBA), "EXR Always read as RGBA (default=false)", \ - "-exrInherit", ARG_FLAG(&opt.exrInherit), "EXR guess channel inheritance (default=false)", \ - "-exrNoOneChannel", ARG_FLAG(&opt.exrNoOneChannel), "EXR never use one channel planar images (default=false)", \ - "-exrIOMethod %d [%d]", &opt.exrIOMethod, &opt.exrIOSize, "EXR I/O Method (0=standard, 1=buffered, 2=unbuffered, 3=MemoryMap, 4=AsyncBuffered, 5=AsyncUnbuffered, default=%d) and optional chunk size (default=%d)", opts.exrIOMethod, opts.exrIOSize, \ - "-exrReadWindowIsDisplayWindow", ARG_FLAG(&opts.exrReadWindowIsDisplayWindow), "EXR read window is display window (default=false)", \ - "-exrReadWindow %d", &opt.exrReadWindow, "EXR Read Window Method (0=Data, 1=Display, 2=Union, 3=Data inside Display, default=%d)", opts.exrReadWindow, \ - "-jpegRGBA", ARG_FLAG(&opt.jpegRGBA), "Make JPEG four channel RGBA on read (default=no, use RGB or YUV)", \ - "-jpegIOMethod %d [%d]", &opt.jpegIOMethod, &opt.jpegIOSize, "JPEG I/O Method (0=standard, 1=buffered, 2=unbuffered, 3=MemoryMap, 4=AsyncBuffered, 5=AsyncUnbuffered, default=%d) and optional chunk size (default=%d)", opts.exrIOMethod, opts.exrIOSize, \ - "-cinpixel %S", &opt.cinPixel, "Cineon pixel storage (default=%s)", opt.cinPixel, \ - "-cinchroma", ARG_FLAG(&opt.cinchroma), "Use Cineon chromaticity values (for default reader only)", \ - "-cinIOMethod %d [%d]", &opt.cinIOMethod, &opt.cinIOSize, "Cineon I/O Method (0=standard, 1=buffered, 2=unbuffered, 3=MemoryMap, 4=AsyncBuffered, 5=AsyncUnbuffered, default=%d) and optional chunk size (default=%d)", opts.cinIOMethod, opts.cinIOSize, \ - "-dpxpixel %S", &opt.dpxPixel, "DPX pixel storage (default=%s)", opt.dpxPixel, \ - "-dpxchroma", ARG_FLAG(&opt.dpxchroma), "Use DPX chromaticity values (for default reader only)", \ - "-dpxIOMethod %d [%d]", &opt.dpxIOMethod, &opt.dpxIOSize, "DPX I/O Method (0=standard, 1=buffered, 2=unbuffered, 3=MemoryMap, 4=AsyncBuffered, 5=AsyncUnbuffered, default=%d) and optional chunk size (default=%d)", opts.dpxIOMethod, opts.dpxIOSize, \ - "-tgaIOMethod %d [%d]", &opt.tgaIOMethod, &opt.tgaIOSize, "TARGA I/O Method (0=standard, 1=buffered, 2=unbuffered, 3=MemoryMap, 4=AsyncBuffered, 5=AsyncUnbuffered, default=%d) and optional chunk size (default=%d)", opts.tgaIOMethod, opts.tgaIOSize, \ - "-tiffIOMethod %d [%d]", &opt.tiffIOMethod, &opt.tiffIOSize, "TIFF I/O Method (0=standard, 1=buffered, 2=unbuffered, 3=MemoryMap, 4=AsyncBuffered, 5=AsyncUnbuffered, default=%d) and optional chunk size (default=%d)", opts.tgaIOMethod, opts.tgaIOSize, \ - "-lic %S", &opt.licarg, "Use specific license file", \ - "-noPrefs", ARG_FLAG(&opt.noPrefs), "Ignore preferences", \ - "-resetPrefs", ARG_FLAG(&opt.resetPrefs), "Reset preferences to default values", \ - "-qtcss %S", &opt.qtcss, "Use QT style sheet for UI", \ - "-qtstyle %S", &opt.qtstyle, "Use QT style", \ - "-qtdesktop %d", &opt.qtdesktop, "QT desktop aware, default=1 (on)", \ - "-xl", ARG_FLAG(&opt.xl), "Aggressively absorb screen space for large media", \ - "-mouse %d", &opt.stylusAsMouse, "Force tablet/stylus events to be treated as a mouse events, default=0 (off)", \ - "-network", ARG_FLAG(&opt.network), "Start networking", \ - "-networkPort %d", &opt.networkPort, "Port for networking", \ - "-networkHost %S", &opt.networkHost, "Alternate host/address for incoming connections", \ - "-networkTag %S", &opt.networkTag, "Tag to mark automatically saved port file", \ - "-networkConnect %S [%d]", &opt.connectHost, &opt.connectPort, "Start networking and connect to host at port", \ - "-networkUser %S", &opt.networkUser, "User for network", \ - "-networkPerm %d", &opt.networkPerm, "Default network connection permission (0=Ask, 1=Allow, 2=Deny, default=0)", \ - "-reuse %d", &opt.urlsReuseSession, "Try to re-use the current session for incoming URLs (1 = reuse session, 0 = new session, default = %d)", opt.urlsReuseSession, \ - "-nopackages", ARG_FLAG(&opt.noPackages), "Don't load any packages at startup (for debugging)", \ - "-encodeURL", ARG_FLAG(&opt.encodeURL), "Encode the command line as an rvlink URL, print, and exit", \ - "-bakeURL", ARG_FLAG(&opt.bakeURL), "Fully bake the command line as an rvlink URL, print, and exit", \ - "-sendEvent", ARG_SUBR(&Rv::parseSendEvents), "Send external events e.g. -sendEvent 'name' 'content'", \ - "-flags", ARG_SUBR(&Rv::parseMuFlags), "Arbitrary flags (flag, or 'name=value') for use in Mu code",\ - "-debug", ARG_SUBR(&Rv::parseDebugKeyWords), Rv::getDebugCategories(), \ - "-version", ARG_FLAG(&opt.showVersion), "Show RV version number" +#define RV_ARG_EXAMPLES \ + "", "Usage: RV movie and image sequence viewer", "", "", "", \ + " One File: rv foo.jpg", "", \ + " This Directory: rv .", "", \ + " Other Directory: rv /path/to/dir", "", \ + " Image Sequence w/Audio: rv [ in.#.tif in.wav ]", "", \ + " Stereo w/Audio: rv [ left.#.tif right.#.tif in.wav ]", \ + "", " Stereo Movies: rv [ left.mov right.mov ]", "", \ + " Stereo Movie (from rvio): rv stereo.mov", "", \ + " Cuts Sequenced: rv cut1.mov cut2.#.exr cut3.mov", "", \ + " Stereo Cuts Sequenced: rv [ l1.mov r1.mov ] [ l2.mov r2.mov " \ + "]", \ + "", " Forced Anamorphic: rv [ -pa 2.0 fullaperture.#.dpx ]", \ + "", " Compare: rv -wipe a.exr b.exr", "", \ + " Difference: rv -diff a.exr b.exr", "", \ + " Slap Comp Over: rv -over a.exr b.exr", "", \ + " Tile Images: rv -tile *.jpg", "", \ + " Cache + Play Movie: rv -l -play foo.mov", "", \ + " Cache Images to Examine: rv -c big.#.exr", "", \ + " Fullscreen on 2nd monitor: rv -fullscreen -screen 1", "", \ + " Select Source View: rv [ in.exr -select view right ] ", "", \ + " Select Source Layer: rv [ in.exr -select layer " \ + "light1.diffuse ] (single-view source)", \ + "", \ + " Select Source Layer: rv [ in.exr -select layer " \ + "left,light1.diffuse ] (multi-view source)", \ + "", \ + " Select Source Channel: rv [ in.exr -select channel R ] " \ + " (single-view, single-layer source)", \ + "", \ + " Select Source Channel: rv [ in.exr -select channel " \ + "left,Diffuse,R ] (multi-view, multi-layer source)" + +#define RV_ARG_SEQUENCE_HELP \ + "", "Image Sequence Numbering", "", "", "", \ + " Frames 1 to 100 no padding: image.1-100@.jpg", "", \ + " Frames 1 to 100 padding 4: image.1-100#.jpg -or- " \ + "image.1-100@@@@.jpg", \ + "", " Frames 1 to 100 padding 5: image.1-100@@@@@.jpg", "", \ + " Frames -100 to -200 padding 4: image.-100--200#jpg", "", \ + " printf style padding 4: image.%%04d.jpg", "", \ + " printf style w/range: image.%%04d.jpg 1-100", "", \ + " printf no padding w/range: image.%%d.jpg 1-100", "", \ + " Complicated no pad 1 to 100: image_887f1-100@_982.tif", "", \ + " Stereo pair (left,right): image.#.%%V.tif", "", \ + " Stereo pair (L,R): image.#.%%v.tif", "", \ + " All Frames, padding 4: image.#.jpg", "", \ + " All Frames in Sequence: image.*.jpg", "", \ + " All Frames in Directory: /path/to/directory", "", \ + " All Frames in current dir: ." + +#define RV_ARG_SOURCE_OPTIONS(opt) \ + "", "Per-source arguments (inside [ and ] restricts to that source only)", \ + "", "", "-pa %f", &opt.pixelAspect, "Per-source pixel aspect ratio", \ + "-ro %d", &opt.rangeOffset, "Per-source range offset", "-rs %d", \ + &opt.rangeStart, "Per-source range start", "-fps %f", &opt.fps, \ + "Per-source or global fps", "-ao %f", &opt.audioOffset, \ + "Per-source audio offset in seconds", "-so %f", &opt.stereoOffset, \ + "Per-source stereo relative eye offset", "-rso %f", \ + &opt.rightEyeStereoOffset, "Per-source stereo right eye offset", \ + "-volume %f", &opt.volume, \ + "Per-source or global audio volume (default=%.2g)", opt.volume, \ + "-fcdl %S", &opt.fileCDL, "Per-source file CDL", "-lcdl %S", \ + &opt.lookCDL, "Per-source look CDL", "-flut %S", &opt.fileLUT, \ + "Per-source file LUT", "-llut %S", &opt.lookLUT, \ + "Per-source look LUT", "-pclut %S", &opt.preCacheLUT, \ + "Per-source pre-cache software LUT", "-cmap %S", &opt.cmapString, \ + "Per-source channel mapping (channel names, separated by ',')", \ + "-select %S %S", &opt.selectType, &opt.selectName, \ + "Per-source view/layer/channel selection", "-mediaRepName %S", \ + &opt.mediaRepName, "Per-source media representation name", \ + "-mediaRepSource %S", &opt.mediaRepSource, \ + "The source for which to add the source media representation", \ + "-crop %d %d %d %d", &opt.cropX0, &opt.cropY0, &opt.cropX1, \ + &opt.cropY1, "Per-source crop (xmin, ymin, xmax, ymax)", \ + "-uncrop %d %d %d %d", &opt.uncropW, &opt.uncropH, &opt.uncropX, \ + &opt.uncropY, "Per-source uncrop (width, height, xoffset, yoffset)", \ + "-in %d", &opt.cutInPoint, "Per-source cut-in frame", "-out %d", \ + &opt.cutOutPoint, "Per-source cut-out frame", "-noMovieAudio", \ + ARG_FLAG(&opt.noMovieAudio), "Disable source movie's baked-in audio", \ + "-inparams", ARG_SUBR(&Rv::parseInParams), \ + "Source specific input parameters" + +#define RV_ARG_PARSE_OPTIONS(opt) \ + "-c", ARG_FLAG(&opt.useCache), "Use region frame cache", "-l", \ + ARG_FLAG(&opt.useLCache), "Use look-ahead cache", "-nc", \ + ARG_FLAG(&opt.useNoCache), "Use no caching", "-s %f", &opt.scale, \ + "Image scale reduction", "-ns", ARG_FLAG(&opt.nukeSequence), \ + "Nuke style sequence notation (deprecated and ignored -- no longer " \ + "needed)", \ + "-noRanges", ARG_FLAG(&opt.noRanges), \ + "No separate frame ranges (i.e. 1-10 will be considered a file)", \ + "-sessionType %S", &opt.sessionType, \ + "Session type (sequence, stack) (deprecated, use -view)", \ + "-stereo %S", &opt.stereoMode, \ + "Stereo mode (hardware, checker, scanline, anaglyph, lumanaglyph, " \ + "left, right, pair, mirror, hsqueezed, vsqueezed)", \ + "-stereoSwap %d", &opt.stereoSwapEyes, \ + "Swap left and right eyes stereo display (0 == no, 1 == yes, " \ + "default=%d)", \ + opts.stereoSwapEyes, "-vsync %d", &opt.vsync, \ + "Video Sync (1 = on, 0 = off, default = %d)", opts.vsync, "-comp %S", \ + &opt.compMode, \ + "Composite mode (over, add, difference, replace, topmost)", \ + "-layout %S", &opt.layoutMode, \ + "Layout mode (packed, row, column, manual)", "-over", \ + ARG_FLAG(&opt.over), "Same as -comp over -view defaultStack", "-diff", \ + ARG_FLAG(&opt.diff), "Same as -comp difference -view defaultStack", \ + "-replace", ARG_FLAG(&opt.replace), \ + "Same as -comp replace -view defaultStack", "-topmost", \ + ARG_FLAG(&opt.topmost), "Same as -comp topmost -view defaultStack", \ + "-layer", ARG_FLAG(&opt.layer), \ + "Same as -comp topmost -view defaultStack, with strict frame ranges", \ + "-tile", ARG_FLAG(&opt.tile), \ + "Same as -layout packed -view defaultLayout", "-wipe", \ + ARG_FLAG(&opt.wipes), "Same as -over with wipes enabled", "-view %S", \ + &opt.view, "Start with a particular view", "-noSequence", \ + ARG_FLAG(&opt.noSequence), "Don't contract files into sequences", \ + "-inferSequence", ARG_FLAG(&opt.inferSequence), \ + "Infer sequences from one file", "-autoRetime %d", &opt.autoRetime, \ + "Automatically retime conflicting media fps in sequences and stacks " \ + "(1 = on, 0 = off, default = %d)", \ + opts.autoRetime, "-rthreads %d", &opt.readerThreads, \ + "Number of reader threads (default=%d)", opts.readerThreads, \ + "-workItemThreads %d", &opt.workItemThreads, \ + "Number of work item threads (default=%d)", opts.workItemThreads, \ + "-progressiveSourceLoading %d", &opt.progressiveSourceLoading, \ + "Use asynchronous source loading, default=0 (off)", "-fullscreen", \ + ARG_FLAG(&opt.fullscreen), "Start in fullscreen mode", "-present", \ + ARG_FLAG(&opt.present), \ + "Start in presentation mode (using presentation device)", \ + "-presentAudio %d", &opt.presentAudio, \ + "Use presentation audio device in presentation mode (1 = on, 0 = " \ + "off)", \ + "-presentDevice %S", &opt.presentDevice, "Presentation mode device", \ + "-presentVideoFormat %S", &opt.presentFormat, \ + "Presentation mode override video format (device specific)", \ + "-presentDataFormat %S", &opt.presentData, \ + "Presentation mode override data format (device specific)", \ + "-screen %d", &opt.screen, "Start on screen (0, 1, 2, ...)", \ + "-noBorders", ARG_FLAG(&opt.noBorders), \ + "No window manager decorations", "-geometry %d %d [%d %d]", &opt.x, \ + &opt.y, &opt.width, &opt.height, "Start geometry X, Y, W, H", \ + "-fitMedia", ARG_FLAG(&opt.startupResize), \ + "Fit the window to the first media shown", "-init %S", \ + &opt.initscript, "Override init script", "-nofloat", \ + ARG_FLAG(&opt.nofloat), "Turn off floating point by default", \ + "-maxbits %d", &opt.maxbits, "Maximum default bit depth (default=%d)", \ + opt.maxbits, "-gamma %f", &opt.gamma, \ + "Set display gamma (default=%g)", opt.gamma, "-sRGB", \ + ARG_FLAG(&opt.sRGB), "Display using linear -> sRGB conversion", \ + "-rec709", ARG_FLAG(&opt.rec709), \ + "Display using linear -> Rec 709 conversion", "-dlut %S", \ + &opt.dispLUT, "Apply display LUT", "-brightness %f", &opt.brightness, \ + "Set display relative brightness in stops (default=%g)", \ + opt.brightness, "-resampleMethod %S", &opt.resampleMethod, \ + "Resampling method (area, linear, cubic, nearest, default=%s)", \ + opt.resampleMethod, "-eval %S", &opt.eval, \ + "Evaluate Mu expression at every session start", "-pyeval %S", \ + &opt.pyeval, "Evaluate Python expression at every session start", \ + "-nomb", ARG_FLAG(&opt.nomb), "Hide menu bar on start up", "-play", \ + ARG_FLAG(&opt.play), "Play on startup", "-playMode %d", &opt.playMode, \ + "Playback mode (0=Context dependent, 1=Play all frames, 2=Realtime, " \ + "default=%d)", \ + opt.playMode, "-loopMode %d", &opt.loopMode, \ + "Playback loop mode (0=Loop, 1=Play Once, 2=Ping-Pong, default=%d)", \ + opt.loopMode, "-cli", ARG_FLAG(&opt.usecli), \ + "Mu command line interface", "-vram %f", &opt.maxvram, \ + "VRAM usage limit in Mb, default = %f", opt.maxvram, "-cram %f", \ + &opt.maxcram, \ + "Max region cache RAM usage in Gb, (%.2gGb available, default " \ + "%.2gGb)", \ + opt.totalcram, opt.maxcram, "-lram %f", &opt.maxlram, \ + "Max look-ahead cache RAM usage in Gb, (%.2gGb available, default " \ + "%.2gGb)", \ + opt.totalcram, opt.maxlram, "-noPBO", ARG_FLAG(&opt.noPBO), \ + "Prevent use of GL PBOs for pixel transfer", "-prefetch", \ + ARG_FLAG(&opt.prefetch), "Prefetch images for rendering", \ + "-useAppleClientStorage", ARG_FLAG(&opt.useAppleClientStorage), \ + "Use APPLE_client_storage extension", "-useThreadedUpload", \ + ARG_FLAG(&opt.useThreadedUpload), \ + "Use threading for texture uploading/downloading if possible", \ + "-bwait %f", &opt.maxbwait, \ + "Max buffer wait time in cached seconds, default %.1f", opt.maxbwait, \ + "-lookback %f", &opt.lookback, \ + "Percentage of the lookahead cache reserved for frames behind the " \ + "playhead, default %g", \ + opt.lookback, "-yuv", ARG_FLAG(&opt.allowYUV), \ + "Assume YUV hardware conversion", "-noaudio", ARG_FLAG(&opt.audioOff), \ + "Turn off audio", "-audiofs %d", &opt.aframesize, \ + "Use fixed audio frame size (results are hardware dependant ... try " \ + "512)", \ + "-audioCachePacket %d", &opt.acachesize, \ + "Audio cache packet size in samples (default=%d)", opt.acachesize, \ + "-audioMinCache %f", &opt.audioMinCache, \ + "Audio cache min size in seconds (default=%f)", opt.audioMinCache, \ + "-audioMaxCache %f", &opt.audioMaxCache, \ + "Audio cache max size in seconds (default=%f)", opt.audioMaxCache, \ + "-audioModule %S", &opt.audioModule, "Use specific audio module", \ + "-audioDevice %S", &opt.audioDevice, "Use specific audio device", \ + "-audioRate %f", &opt.audioRate, \ + "Use specific output audio rate (default=ask hardware)", \ + "-audioPrecision %d", &opt.audioPrecision, \ + "Use specific output audio precision (default=%d)", \ + opt.audioPrecision, "-audioNice %d", &opt.audioNice, \ + "Close audio device when not playing (may cause problems on some " \ + "hardware) default=%d", \ + opt.audioNice, "-audioNoLock %d", &opt.audioNoLock, \ + "Do not use hardware audio/video syncronization (use software " \ + "instead, default=%d)", \ + opt.audioNoLock, "-audioPreRoll %d", &opt.audioPreRoll, \ + "Preroll audio on device open (Linux only; default=%d)", \ + opt.audioPreRoll, "-audioGlobalOffset %f", &opt.audioGlobalOffset, \ + "Global audio offset in seconds", "-audioDeviceLatency %f", \ + &opt.audioDeviceLatency, \ + "Audio device latency compensation in milliseconds", "-bg %S", \ + &opt.bgpattern, \ + "Background pattern (default=black, white, grey18, grey50, checker, " \ + "crosshatch)", \ + "-formats", ARG_FLAG(&opt.showFormats), \ + "Show all supported image and movie formats", "-apple", \ + ARG_FLAG(&opt.apple), "Use Quicktime and NSImage libraries (on OS X)", \ + "-cinalt", ARG_FLAG(&opt.cinalt), "Use alternate Cineon/DPX readers", \ + "-exrcpus %d", &opt.exrcpus, "EXR thread count (default=%d)", \ + opt.exrcpus, "-exrRGBA", ARG_FLAG(&opt.exrRGBA), \ + "EXR Always read as RGBA (default=false)", "-exrInherit", \ + ARG_FLAG(&opt.exrInherit), \ + "EXR guess channel inheritance (default=false)", "-exrNoOneChannel", \ + ARG_FLAG(&opt.exrNoOneChannel), \ + "EXR never use one channel planar images (default=false)", \ + "-exrIOMethod %d [%d]", &opt.exrIOMethod, &opt.exrIOSize, \ + "EXR I/O Method (0=standard, 1=buffered, 2=unbuffered, 3=MemoryMap, " \ + "4=AsyncBuffered, 5=AsyncUnbuffered, default=%d) and optional chunk " \ + "size (default=%d)", \ + opts.exrIOMethod, opts.exrIOSize, "-exrReadWindowIsDisplayWindow", \ + ARG_FLAG(&opts.exrReadWindowIsDisplayWindow), \ + "EXR read window is display window (default=false)", \ + "-exrReadWindow %d", &opt.exrReadWindow, \ + "EXR Read Window Method (0=Data, 1=Display, 2=Union, 3=Data inside " \ + "Display, default=%d)", \ + opts.exrReadWindow, "-jpegRGBA", ARG_FLAG(&opt.jpegRGBA), \ + "Make JPEG four channel RGBA on read (default=no, use RGB or YUV)", \ + "-jpegIOMethod %d [%d]", &opt.jpegIOMethod, &opt.jpegIOSize, \ + "JPEG I/O Method (0=standard, 1=buffered, 2=unbuffered, 3=MemoryMap, " \ + "4=AsyncBuffered, 5=AsyncUnbuffered, default=%d) and optional chunk " \ + "size (default=%d)", \ + opts.exrIOMethod, opts.exrIOSize, "-cinpixel %S", &opt.cinPixel, \ + "Cineon pixel storage (default=%s)", opt.cinPixel, "-cinchroma", \ + ARG_FLAG(&opt.cinchroma), \ + "Use Cineon chromaticity values (for default reader only)", \ + "-cinIOMethod %d [%d]", &opt.cinIOMethod, &opt.cinIOSize, \ + "Cineon I/O Method (0=standard, 1=buffered, 2=unbuffered, " \ + "3=MemoryMap, 4=AsyncBuffered, 5=AsyncUnbuffered, default=%d) and " \ + "optional chunk size (default=%d)", \ + opts.cinIOMethod, opts.cinIOSize, "-dpxpixel %S", &opt.dpxPixel, \ + "DPX pixel storage (default=%s)", opt.dpxPixel, "-dpxchroma", \ + ARG_FLAG(&opt.dpxchroma), \ + "Use DPX chromaticity values (for default reader only)", \ + "-dpxIOMethod %d [%d]", &opt.dpxIOMethod, &opt.dpxIOSize, \ + "DPX I/O Method (0=standard, 1=buffered, 2=unbuffered, 3=MemoryMap, " \ + "4=AsyncBuffered, 5=AsyncUnbuffered, default=%d) and optional chunk " \ + "size (default=%d)", \ + opts.dpxIOMethod, opts.dpxIOSize, "-tgaIOMethod %d [%d]", \ + &opt.tgaIOMethod, &opt.tgaIOSize, \ + "TARGA I/O Method (0=standard, 1=buffered, 2=unbuffered, " \ + "3=MemoryMap, 4=AsyncBuffered, 5=AsyncUnbuffered, default=%d) and " \ + "optional chunk size (default=%d)", \ + opts.tgaIOMethod, opts.tgaIOSize, "-tiffIOMethod %d [%d]", \ + &opt.tiffIOMethod, &opt.tiffIOSize, \ + "TIFF I/O Method (0=standard, 1=buffered, 2=unbuffered, 3=MemoryMap, " \ + "4=AsyncBuffered, 5=AsyncUnbuffered, default=%d) and optional chunk " \ + "size (default=%d)", \ + opts.tgaIOMethod, opts.tgaIOSize, "-lic %S", &opt.licarg, \ + "Use specific license file", "-noPrefs", ARG_FLAG(&opt.noPrefs), \ + "Ignore preferences", "-resetPrefs", ARG_FLAG(&opt.resetPrefs), \ + "Reset preferences to default values", "-qtcss %S", &opt.qtcss, \ + "Use QT style sheet for UI", "-qtstyle %S", &opt.qtstyle, \ + "Use QT style", "-qtdesktop %d", &opt.qtdesktop, \ + "QT desktop aware, default=1 (on)", "-xl", ARG_FLAG(&opt.xl), \ + "Aggressively absorb screen space for large media", "-mouse %d", \ + &opt.stylusAsMouse, \ + "Force tablet/stylus events to be treated as a mouse events, " \ + "default=0 (off)", \ + "-network", ARG_FLAG(&opt.network), "Start networking", \ + "-networkPort %d", &opt.networkPort, "Port for networking", \ + "-networkHost %S", &opt.networkHost, \ + "Alternate host/address for incoming connections", "-networkTag %S", \ + &opt.networkTag, "Tag to mark automatically saved port file", \ + "-networkConnect %S [%d]", &opt.connectHost, &opt.connectPort, \ + "Start networking and connect to host at port", "-networkUser %S", \ + &opt.networkUser, "User for network", "-networkPerm %d", \ + &opt.networkPerm, \ + "Default network connection permission (0=Ask, 1=Allow, 2=Deny, " \ + "default=0)", \ + "-reuse %d", &opt.urlsReuseSession, \ + "Try to re-use the current session for incoming URLs (1 = reuse " \ + "session, 0 = new session, default = %d)", \ + opt.urlsReuseSession, "-nopackages", ARG_FLAG(&opt.noPackages), \ + "Don't load any packages at startup (for debugging)", "-encodeURL", \ + ARG_FLAG(&opt.encodeURL), \ + "Encode the command line as an rvlink URL, print, and exit", \ + "-bakeURL", ARG_FLAG(&opt.bakeURL), \ + "Fully bake the command line as an rvlink URL, print, and exit", \ + "-sendEvent", ARG_SUBR(&Rv::parseSendEvents), \ + "Send external events e.g. -sendEvent 'name' 'content'", "-flags", \ + ARG_SUBR(&Rv::parseMuFlags), \ + "Arbitrary flags (flag, or 'name=value') for use in Mu code", \ + "-debug", ARG_SUBR(&Rv::parseDebugKeyWords), Rv::getDebugCategories(), \ + "-version", ARG_FLAG(&opt.showVersion), "Show RV version number" #endif // __RV__Options__h__ diff --git a/src/lib/app/RvApp/RvApp/PyCommandsModule.h b/src/lib/app/RvApp/RvApp/PyCommandsModule.h index b1d760470..69ce47c69 100644 --- a/src/lib/app/RvApp/RvApp/PyCommandsModule.h +++ b/src/lib/app/RvApp/RvApp/PyCommandsModule.h @@ -1,18 +1,19 @@ // -// Copyright (c) 2011 Tweak Software. +// Copyright (c) 2011 Tweak Software. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// // #ifndef __RvApp__PyCommandsModule__h__ #define __RvApp__PyCommandsModule__h__ #include -namespace Rv { +namespace Rv +{ -void* pyRvAppCommands(); + void* pyRvAppCommands(); -} // Rv +} // namespace Rv #endif // __RvApp__PyCommandsModule__h__ diff --git a/src/lib/app/RvApp/RvApp/RvGraph.h b/src/lib/app/RvApp/RvApp/RvGraph.h index 2807263c0..3d70ffd6a 100644 --- a/src/lib/app/RvApp/RvApp/RvGraph.h +++ b/src/lib/app/RvApp/RvApp/RvGraph.h @@ -1,9 +1,9 @@ //****************************************************************************** -// Copyright (c) 2007 Tweak Inc. +// Copyright (c) 2007 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #ifndef __RvApp__RvGraph__h__ #define __RvApp__RvGraph__h__ @@ -11,116 +11,135 @@ #include -namespace IPCore { -class FileSourceIPNode; -class ImageSourceIPNode; -class LayoutGroupIPNode; -class SequenceGroupIPNode; -class SourceGroupIPNode; -class SourceIPNode; -class StackGroupIPNode; -} - -namespace Rv { - -// -// RvGraph -// -// This class controls the IPNode graph. It also owns one or more -// evaluation threads which are the only threads allowed to evaluate -// the graph. The RvGraph can also cache results and guarantee that -// pixels will be available for a certain amount of time. -// - -class RvGraph : public IPCore::IPGraph +namespace IPCore +{ + class FileSourceIPNode; + class ImageSourceIPNode; + class LayoutGroupIPNode; + class SequenceGroupIPNode; + class SourceGroupIPNode; + class SourceIPNode; + class StackGroupIPNode; +} // namespace IPCore + +namespace Rv { - public: - typedef std::vector Sources; - typedef boost::signals2::signal FastAddSourceChangedSignal; - - RvGraph(const IPCore::NodeManager*); - ~RvGraph(); // - // Create a sparse node from the given node. This will share prop - // data via referencing + // RvGraph // - - virtual TwkContainer::PropertyContainer* sparseContainer(IPCore::IPNode*); - - virtual void initializeIPTree(const VideoModules&); - virtual void removeNode(IPCore::IPNode*); - virtual IPCore::DisplayGroupIPNode* newDisplayGroup(const std::string& nodeName, - const TwkApp::VideoDevice* d = 0); - virtual IPCore::OutputGroupIPNode* newOutputGroup(const std::string& nodeName, - const TwkApp::VideoDevice* d = 0); - - const Sources& imageSources() const { return m_imageSources; } - IPCore::SourceIPNode* addSource(const std::string& nodeType, - const std::string& nodeName="", - const std::string& mediaRepName="", - IPCore::SourceIPNode* mediaRepSisterSrcNode=nullptr); - - // Fast add source mechanism which postpones the default views' inputs - // connection until all the new sources have been added to prevent O(n^2) - void connectNewSourcesToDefaultViews(); - - // Scope of the fast add source mechanism which postpones the default views' - // inputs connection until all the new sources have been added - void addSourceBegin() - { - int newFastAddSourceEnabled = ++m_fastAddSourceEnabled; - - m_fastAddSourceChangedSignal(true, newFastAddSourceEnabled); - } - void addSourceEnd() - { - int newFastAddSourceEnabled = --m_fastAddSourceEnabled; - - if(newFastAddSourceEnabled == 0) - connectNewSourcesToDefaultViews(); - - m_fastAddSourceChangedSignal(false, newFastAddSourceEnabled); - } - bool isFastAddSourceEnabled() const { return m_fastAddSourceEnabled>0; } - - // gives access to the signal call when fastAddSourceEnabled changed + // This class controls the IPNode graph. It also owns one or more + // evaluation threads which are the only threads allowed to evaluate + // the graph. The RvGraph can also cache results and guarantee that + // pixels will be available for a certain amount of time. // - FastAddSourceChangedSignal& fastAddSourceChangedSignal() { return m_fastAddSourceChangedSignal; } - // Scope guard of the same fast add source mechanism - class FastAddSourceGuard + class RvGraph : public IPCore::IPGraph { public: - explicit FastAddSourceGuard( RvGraph& rvgraph ) : m_rvgraph( rvgraph ) - { - m_rvgraph.addSourceBegin(); - } - ~FastAddSourceGuard() - { - m_rvgraph.addSourceEnd(); - } - private: - RvGraph& m_rvgraph; - }; - - protected: - IPCore::SourceGroupIPNode* newSourceGroup(const std::string& nodeName, IPCore::SourceIPNode*); - IPCore::SourceIPNode* newSource(const std::string& nodeName, - const std::string& nodeType, - const std::string& mediaRepName); - void setupSource(IPCore::SourceIPNode*, IPCore::SourceIPNode* mediaRepSisterSrcNode); - - private: - Sources m_imageSources; - IPCore::SequenceGroupIPNode* m_sequenceNode; - IPCore::StackGroupIPNode* m_stackNode; - IPCore::LayoutGroupIPNode* m_layoutNode; - IPCore::IPNode::IPNodes m_newSources; - std::atomic m_fastAddSourceEnabled{0}; - FastAddSourceChangedSignal m_fastAddSourceChangedSignal; -}; - -} // Rv + typedef std::vector Sources; + typedef boost::signals2::signal + FastAddSourceChangedSignal; + + RvGraph(const IPCore::NodeManager*); + ~RvGraph(); + + // + // Create a sparse node from the given node. This will share prop + // data via referencing + // + + virtual TwkContainer::PropertyContainer* + sparseContainer(IPCore::IPNode*); + + virtual void initializeIPTree(const VideoModules&); + virtual void removeNode(IPCore::IPNode*); + virtual IPCore::DisplayGroupIPNode* + newDisplayGroup(const std::string& nodeName, + const TwkApp::VideoDevice* d = 0); + virtual IPCore::OutputGroupIPNode* + newOutputGroup(const std::string& nodeName, + const TwkApp::VideoDevice* d = 0); + + const Sources& imageSources() const { return m_imageSources; } + + IPCore::SourceIPNode* + addSource(const std::string& nodeType, const std::string& nodeName = "", + const std::string& mediaRepName = "", + IPCore::SourceIPNode* mediaRepSisterSrcNode = nullptr); + + // Fast add source mechanism which postpones the default views' inputs + // connection until all the new sources have been added to prevent + // O(n^2) + void connectNewSourcesToDefaultViews(); + + // Scope of the fast add source mechanism which postpones the default + // views' inputs connection until all the new sources have been added + void addSourceBegin() + { + int newFastAddSourceEnabled = ++m_fastAddSourceEnabled; + + m_fastAddSourceChangedSignal(true, newFastAddSourceEnabled); + } + + void addSourceEnd() + { + int newFastAddSourceEnabled = --m_fastAddSourceEnabled; + + if (newFastAddSourceEnabled == 0) + connectNewSourcesToDefaultViews(); + + m_fastAddSourceChangedSignal(false, newFastAddSourceEnabled); + } + + bool isFastAddSourceEnabled() const + { + return m_fastAddSourceEnabled > 0; + } + + // gives access to the signal call when fastAddSourceEnabled changed + // + FastAddSourceChangedSignal& fastAddSourceChangedSignal() + { + return m_fastAddSourceChangedSignal; + } + + // Scope guard of the same fast add source mechanism + class FastAddSourceGuard + { + public: + explicit FastAddSourceGuard(RvGraph& rvgraph) + : m_rvgraph(rvgraph) + { + m_rvgraph.addSourceBegin(); + } + + ~FastAddSourceGuard() { m_rvgraph.addSourceEnd(); } + + private: + RvGraph& m_rvgraph; + }; + + protected: + IPCore::SourceGroupIPNode* newSourceGroup(const std::string& nodeName, + IPCore::SourceIPNode*); + IPCore::SourceIPNode* newSource(const std::string& nodeName, + const std::string& nodeType, + const std::string& mediaRepName); + void setupSource(IPCore::SourceIPNode*, + IPCore::SourceIPNode* mediaRepSisterSrcNode); + + private: + Sources m_imageSources; + IPCore::SequenceGroupIPNode* m_sequenceNode; + IPCore::StackGroupIPNode* m_stackNode; + IPCore::LayoutGroupIPNode* m_layoutNode; + IPCore::IPNode::IPNodes m_newSources; + std::atomic m_fastAddSourceEnabled{0}; + FastAddSourceChangedSignal m_fastAddSourceChangedSignal; + }; + +} // namespace Rv #endif // __RvApp__RvGraph__h__ diff --git a/src/lib/app/RvApp/RvApp/RvNodeDefinitions.h b/src/lib/app/RvApp/RvApp/RvNodeDefinitions.h index dd4577859..ab6919b19 100644 --- a/src/lib/app/RvApp/RvApp/RvNodeDefinitions.h +++ b/src/lib/app/RvApp/RvApp/RvNodeDefinitions.h @@ -1,85 +1,88 @@ // -// Copyright (c) 2013 Tweak Software. +// Copyright (c) 2013 Tweak Software. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// // #ifndef __RvApp__RvNodeDefinitions__h__ #define __RvApp__RvNodeDefinitions__h__ #include #include -namespace Rv { +namespace Rv +{ -void addRvNodeDefinitions(IPCore::NodeManager*); + void addRvNodeDefinitions(IPCore::NodeManager*); -// -// Scale on all nodes -// + // + // Scale on all nodes + // -void setScaleOnAll(const IPCore::IPGraph& graph, float scale); + void setScaleOnAll(const IPCore::IPGraph& graph, float scale); -// -// Log->Lin on all nodes -// + // + // Log->Lin on all nodes + // -void setLogLinOnAll(const IPCore::IPGraph& graph, bool, int); + void setLogLinOnAll(const IPCore::IPGraph& graph, bool, int); -// -// sRGB->Lin on all nodes -// + // + // sRGB->Lin on all nodes + // -void setSRGBLinOnAll(const IPCore::IPGraph& graph, bool); -// + void setSRGBLinOnAll(const IPCore::IPGraph& graph, bool); + // -// 709->Lin on all nodes -// + // 709->Lin on all nodes + // -void setRec709LinOnAll(const IPCore::IPGraph& graph, bool); + void setRec709LinOnAll(const IPCore::IPGraph& graph, bool); -// -// Gamma (const IPCore::IPGraph& graph, interactive) on all nodes -// + // + // Gamma (const IPCore::IPGraph& graph, interactive) on all nodes + // -void setGammaOnAll(const IPCore::IPGraph& graph, float gamma); + void setGammaOnAll(const IPCore::IPGraph& graph, float gamma); -// -// Gamma (const IPCore::IPGraph& graph, file) on all nodes -// + // + // Gamma (const IPCore::IPGraph& graph, file) on all nodes + // -void setFileGammaOnAll(const IPCore::IPGraph& graph, float gamma); + void setFileGammaOnAll(const IPCore::IPGraph& graph, float gamma); -// -// Exposure on all nodes -// + // + // Exposure on all nodes + // -void setFileExposureOnAll(const IPCore::IPGraph& graph, float exposure); + void setFileExposureOnAll(const IPCore::IPGraph& graph, float exposure); -// -// Orientation on all nodes -// + // + // Orientation on all nodes + // -void setFlipFlopOnAll(const IPCore::IPGraph& graph, bool setFlip, bool flip, bool setFlop, bool flop); + void setFlipFlopOnAll(const IPCore::IPGraph& graph, bool setFlip, bool flip, + bool setFlop, bool flop); -// -// -// - -void setChannelMapOnAll(const IPCore::IPGraph& graph, const std::vector& ch); + // + // + // -// -// sets FormatIPNode's xfit and yfit on all inputs -// + void setChannelMapOnAll(const IPCore::IPGraph& graph, + const std::vector& ch); -void fitAllInputs(const IPCore::IPGraph& graph, int w, int h); + // + // sets FormatIPNode's xfit and yfit on all inputs + // -// -// sets FormatIPNode's xresize and yresize on all inputs -// + void fitAllInputs(const IPCore::IPGraph& graph, int w, int h); + + // + // sets FormatIPNode's xresize and yresize on all inputs + // -void resizeAllInputs(const IPCore::IPGraph& graph, int w, int h); + void resizeAllInputs(const IPCore::IPGraph& graph, int w, int h); -} // Rv +} // namespace Rv #endif // __RvApp__RvNodeDefinitions__h__ diff --git a/src/lib/app/RvApp/RvApp/RvSession.h b/src/lib/app/RvApp/RvApp/RvSession.h index bd03fddb6..c37aaab4c 100644 --- a/src/lib/app/RvApp/RvApp/RvSession.h +++ b/src/lib/app/RvApp/RvApp/RvSession.h @@ -1,9 +1,9 @@ //****************************************************************************** -// Copyright (c) 2005 Tweak Inc. +// Copyright (c) 2005 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #ifndef __RVApp__RvSession__h__ #define __RVApp__RvSession__h__ @@ -15,408 +15,416 @@ #include #include -namespace Mu { -class CallEnvironment; -} - -namespace IPCore { -class IPNode; -class SourceIPNode; -class SequenceIPNode; -class SwitchIPNode; +namespace Mu +{ + class CallEnvironment; } -namespace Rv { -class LoadState; - -// -// class Session -// -// This object represents the "document" in as much as Rv has a -// "document". The Session can be a single image, a movie, an edit, a -// composite, etc, etc. -// - -class RvSession : public IPCore::Session +namespace IPCore { - public: - // - // Types - // - - typedef std::vector Sources; - - // - // Constructors - // - - RvSession(); - virtual ~RvSession(); - - void postInitialize(); - - const RvGraph& rvgraph() const { return *static_cast(m_graph); } - RvGraph& rvgraph() { return *static_cast(m_graph); } - - // - // Takes a file list and calls read with sequences created from - // it. Calls read() below with addContents=true. It will throw if - // any file in files is unreadable, but only AFTER trying to read - // all of them. - // - // If a set of files in the file list is bracket by files named - // '[' and ']' (without nesting) the files are "grouped". In that - // case all of the file sources in the group are put into an - // input source together. This is used, for example, to make - // stereo pairs. - // - // Its an error to have unmatched '[' or ']' names. If that - // happens, the function will throw a read error. - // - // throws AllReadFailedExc (if none of the files worked) - // ReadFailedExc (if some of the files worked) - // - - void readUnorganizedFileList(const StringVector& files, - bool doProcessOpts=false, - bool merge=false, - const std::string& tag=""); + class IPNode; + class SourceIPNode; + class SequenceIPNode; + class SwitchIPNode; +} // namespace IPCore - // - // Replaces contents with filename or if addContents==true then - // add the contents of the file instead of replacing. You should - // throw out of here if the read failed. - // - - virtual void read(const std::string& filename, const ReadRequest&); - - // - // Write contents to filename or if partial==true, then write - // only some of the data. (This is interpreted by the document - // sub-class.) Normally this would mean: write selection - // only. you should throw out of here if the write fails. - // +namespace Rv +{ + class LoadState; + + // + // class Session + // + // This object represents the "document" in as much as Rv has a + // "document". The Session can be a single image, a movie, an edit, a + // composite, etc, etc. + // + + class RvSession : public IPCore::Session + { + public: + // + // Types + // + + typedef std::vector Sources; + + // + // Constructors + // + + RvSession(); + virtual ~RvSession(); + + void postInitialize(); + + const RvGraph& rvgraph() const + { + return *static_cast(m_graph); + } + + RvGraph& rvgraph() { return *static_cast(m_graph); } + + // + // Takes a file list and calls read with sequences created from + // it. Calls read() below with addContents=true. It will throw if + // any file in files is unreadable, but only AFTER trying to read + // all of them. + // + // If a set of files in the file list is bracket by files named + // '[' and ']' (without nesting) the files are "grouped". In that + // case all of the file sources in the group are put into an + // input source together. This is used, for example, to make + // stereo pairs. + // + // Its an error to have unmatched '[' or ']' names. If that + // happens, the function will throw a read error. + // + // throws AllReadFailedExc (if none of the files worked) + // ReadFailedExc (if some of the files worked) + // + + void readUnorganizedFileList(const StringVector& files, + bool doProcessOpts = false, + bool merge = false, + const std::string& tag = ""); + + // + // Replaces contents with filename or if addContents==true then + // add the contents of the file instead of replacing. You should + // throw out of here if the read failed. + // + + virtual void read(const std::string& filename, const ReadRequest&); + + // + // Write contents to filename or if partial==true, then write + // only some of the data. (This is interpreted by the document + // sub-class.) Normally this would mean: write selection + // only. you should throw out of here if the write fails. + // + + virtual void write(const std::string& filename, const WriteRequest&); + + // + // Similar, but does not change the filename of the session + // + + void saveACopyAs(const char* filename, bool partial = false, + bool compressed = false, bool sparse = true); + + virtual void makeActive(); + virtual void clear(); + virtual void render(); + + bool isEmpty() const; + + // + // If the user has set the view size (from Mu) we may not want + // to do it ourselves. + // + void setUserHasSetViewSize(bool v) { m_userHasSetViewSize = v; }; + + bool userHasSetViewSize() { return m_userHasSetViewSize; }; + + // + // Source material. Some methods add a bunch of media paths as a + // single source. This is useful for making stereo sources for example. + // Set the name if you are reading the source from a file, otherwise + // it'll be created programmatically. + // + + IPCore::SourceIPNode* addSourceWithTag(const StringVector& files, + std::string tag, + std::string nodeName = "", + std::string mediaRepName = ""); + IPCore::SourceIPNode* addSource(std::string, Options::SourceArgs& sargs, + std::string nodeName = ""); + IPCore::SourceIPNode* addSource(const StringVector&, + Options::SourceArgs& sargs, + std::string nodeName = "", + std::string nodeType = "RVFileSource", + std::string mediaRepName = "", + std::string mediaRepSource = ""); + IPCore::SourceIPNode* addImageSource(const std::string&, + const TwkMovie::MovieInfo&); + + void newMediaLoaded(IPCore::SourceIPNode*); + + // + // Delete a node. This can be a source (group) node or whatever + // + + virtual void deleteNode(IPCore::IPNode*); + + // + // Add another media path to the current source (for stereo, etc) you + // can pass "" for sourceName to use the "current" source ala pre 3.8.7 + // + + IPCore::SourceIPNode* addToSourceHelper(const std::string&, + StringVector files, + Options::SourceArgs& sargs); + + void addToSource(const std::string& sourceName, + const std::string& filename, + const std::string& tag = ""); + + // + // Relocate lost media files. + // - virtual void write(const std::string& filename, const WriteRequest&); + void relocateSource(const std::string& oldFilename, + const std::string& newFilename, + const std::string& sourceNode = ""); - // - // Similar, but does not change the filename of the session - // + // + // Set all the media in a particular source + // - void saveACopyAs(const char* filename, - bool partial=false, - bool compressed=false, - bool sparse=true); + void setSourceMedia(const std::string& sourceNode, + const StringVector& files, const std::string& tag); + // + // Add a media representation to an existing source specified by + // srcNodeName + // - virtual void makeActive(); - virtual void clear(); - virtual void render(); + IPCore::SourceIPNode* addSourceMediaRep( + const std::string& srcNodeName, const std::string& mediaRepName, + const StringVector& mediaRepPaths, const std::string& tag); - bool isEmpty() const; - - // - // If the user has set the view size (from Mu) we may not want - // to do it ourselves. - // - void setUserHasSetViewSize (bool v) { m_userHasSetViewSize = v; }; - bool userHasSetViewSize() { return m_userHasSetViewSize; }; + // + // Set the active input of the Switch node specified or the ones + // associated with the specified source node to the given media + // representation specified by name. + // - // - // Source material. Some methods add a bunch of media paths as a - // single source. This is useful for making stereo sources for example. - // Set the name if you are reading the source from a file, otherwise - // it'll be created programmatically. - // + void setActiveSourceMediaRep(const std::string& srcNodeOrSwitchNodeName, + const std::string& mediaRepName, + const std::string& tag); - IPCore::SourceIPNode* addSourceWithTag(const StringVector& files, - std::string tag, - std::string nodeName="", - std::string mediaRepName=""); - IPCore::SourceIPNode* addSource(std::string, - Options::SourceArgs& sargs, - std::string nodeName=""); - IPCore::SourceIPNode* addSource(const StringVector&, - Options::SourceArgs& sargs, - std::string nodeName="", - std::string nodeType="RVFileSource", - std::string mediaRepName="", - std::string mediaRepSource=""); - IPCore::SourceIPNode* addImageSource(const std::string&, - const TwkMovie::MovieInfo&); - - void newMediaLoaded(IPCore::SourceIPNode*); + // + // Returns the name of the media representation currently selected by + // the Switch Group corresponding to the given RVFileSource node. + // - // - // Delete a node. This can be a source (group) node or whatever - // + std::string sourceMediaRep(const std::string& srcNodeOrSwitchNodeName); - virtual void deleteNode(IPCore::IPNode*); + // + // Returns the names of the media representations available for the + // Switch Group corresponding to the given RVFileSource node or + // RVSwitch node. Also optionally returns the source nodes associated + // with these media reps. + // - // - // Add another media path to the current source (for stereo, etc) you - // can pass "" for sourceName to use the "current" source ala pre 3.8.7 - // + void sourceMediaReps(const std::string& srcNodeOrSwitchNodeName, + StringVector& sourceMediaReps, + StringVector* sourceNodes = nullptr); - IPCore::SourceIPNode* addToSourceHelper(const std::string&, - StringVector files, - Options::SourceArgs& sargs); + // + // Returns the source media rep switch node associated with the source + // if any + // - void addToSource(const std::string& sourceName, - const std::string& filename, - const std::string& tag=""); + std::string sourceMediaRepSwitchNode(const std::string& srcNodeName); - // - // Relocate lost media files. - // + // + // Returns the source media rep's switch node's first input associated + // with the source if any + // - void relocateSource(const std::string& oldFilename, - const std::string& newFilename, - const std::string& sourceNode = ""); + std::string sourceMediaRepSourceNode(const std::string& srcNodeName); - // - // Set all the media in a particular source - // + // + // Mu code to run on initialization + // - void setSourceMedia(const std::string& sourceNode, - const StringVector& files, - const std::string& tag); + static void setInitEval(const std::string& s) { m_initEval = s; } + static std::string initEval() { return m_initEval; } - // - // Add a media representation to an existing source specified by srcNodeName - // + static void setPyInitEval(const std::string& s) { m_pyInitEval = s; } - IPCore::SourceIPNode* addSourceMediaRep(const std::string& srcNodeName, - const std::string& mediaRepName, - const StringVector& mediaRepPaths, - const std::string& tag); + static std::string pyInitEval() { return m_pyInitEval; } - // - // Set the active input of the Switch node specified or the ones associated - // with the specified source node to the given media representation - // specified by name. - // + // + // Sources / Nodes + // - void setActiveSourceMediaRep(const std::string& srcNodeOrSwitchNodeName, - const std::string& mediaRepName, - const std::string& tag); + const Sources& sources() const { return rvgraph().imageSources(); } + std::string currentSourceName() const; - // - // Returns the name of the media representation currently selected by the - // Switch Group corresponding to the given RVFileSource node. - // + // + // "Top" FB -- not really useful anymore + // - std::string sourceMediaRep(const std::string& srcNodeOrSwitchNodeName); - + const TwkFB::FrameBuffer* currentFB() const; - // - // Returns the names of the media representations available for the Switch - // Group corresponding to the given RVFileSource node or RVSwitch node. - // Also optionally returns the source nodes associated with these media reps. - // + // + // FB for one of the current sources + // - void sourceMediaReps(const std::string& srcNodeOrSwitchNodeName, - StringVector& sourceMediaReps, - StringVector* sourceNodes = nullptr); - + const TwkFB::FrameBuffer* currentFB(const std::string&) const; - // - // Returns the source media rep switch node associated with the source if any - // + // + // Same syntax as currentFB but returns a SourceNode + // - std::string sourceMediaRepSwitchNode(const std::string& srcNodeName); - + IPCore::SourceIPNode* sourceNode(const std::string&) const; - // - // Returns the source media rep's switch node's first input associated with the source if any - // + // + // Same syntax as currentFB but returns a SwitchNode + // - std::string sourceMediaRepSourceNode(const std::string& srcNodeName); - + IPCore::SwitchIPNode* switchNode(const std::string&) const; - // - // Mu code to run on initialization - // + // + // Data + // - static void setInitEval(const std::string& s) { m_initEval = s; } - static std::string initEval() { return m_initEval; } + Mu::Object* data() const { return m_data; } - static void setPyInitEval(const std::string& s) { m_pyInitEval = s; } - static std::string pyInitEval() { return m_pyInitEval; } + void* pyData() const { return m_pydata; } - // - // Sources / Nodes - // + static RvSession* currentRvSession() + { + return static_cast(IPCore::Session::currentSession()); + } - const Sources& sources() const { return rvgraph().imageSources(); } - std::string currentSourceName() const; + // + // Set scaling on all transform nodes. Used by linux + // version command line argument. + // - // - // "Top" FB -- not really useful anymore - // + void setScaleOnAll(float scale); - const TwkFB::FrameBuffer* currentFB() const; + // + // LUTs + // - // - // FB for one of the current sources - // + void readCDL(std::string, const std::string& node, + bool activate = false); + void readLUT(std::string, const std::string& node, + bool activate = false); + void readLUTOnAll(std::string, const std::string& nodeType, + bool activate = true); - const TwkFB::FrameBuffer* currentFB(const std::string&) const; + std::string lookupMuFlag(std::string key); - // - // Same syntax as currentFB but returns a SourceNode - // + // + // Loading status + // - IPCore::SourceIPNode* sourceNode(const std::string&) const; + int loadCount(); + int loadTotal(); + // + // Override + // - // - // Same syntax as currentFB but returns a SwitchNode - // + virtual void findProperty(PropertyVector& props, + const std::string& name); + virtual void findCurrentNodesByTypeName(NodeVector& nodes, + const std::string& typeName); + virtual void findNodesByTypeName(NodeVector& nodes, + const std::string& typeName); - IPCore::SwitchIPNode* switchNode(const std::string&) const; + virtual IPCore::IPNode* newNode(const std::string& typeName, + const std::string& nodeName); + virtual void setRendererType(const std::string&); - // - // Data - // + virtual void readProfile(const std::string& filename, + IPCore::IPNode* node, const WriteRequest&); - Mu::Object* data() const { return m_data; } - void* pyData() const { return m_pydata; } + protected: + virtual void readGTO(const std::string& filename, bool merge, + Options::SourceArgs& sargs); + void readEDL(const char* filename); + void readGTOSessionContainer(PropertyContainer*); - static RvSession* currentRvSession() - { return static_cast(IPCore::Session::currentSession()); } + void applyRvSessionSpecificOptions(); - // - // Set scaling on all transform nodes. Used by linux - // version command line argument. - // + void checkForStereoPaths(const std::string&, StringVector&); - void setScaleOnAll(float scale); + void readSource(const std::string& filename, Options::SourceArgs& sargs, + bool addContents, bool addToExistingSource, + const std::string& tag = "", bool merge = false); - // - // LUTs - // + void readSourceHelper(StringVector files, Options::SourceArgs& sargs, + bool addContents, bool addToExistingSource); - void readCDL(std::string, const std::string& node, bool activate=false); - void readLUT(std::string, const std::string& node, bool activate=false); - void readLUTOnAll(std::string, const std::string& nodeType, bool activate=true); + void continueLoading(); + void applySingleSourceArgs(Options::SourceArgs& sargs, + IPCore::SourceIPNode* node); - std::string lookupMuFlag (std::string key); + void processOptionsAfterSourcesLoaded(bool hadLoadError = false); - // - // Loading status - // + void buildFileList(const StringVector& files, std::string tag, + StringVector& collected); + std::vector + findSourcesByMedia(const std::string& filename, + const std::string& sourceNode = ""); + std::vector + findSwitchIPNodes(const std::string& srcNodeOrSwitchNodeName); - int loadCount(); - int loadTotal(); + void setSequenceEvents(); + void unsetSequenceEvents(); + void setSequenceIPNode(IPCore::SequenceIPNode* newSequenceIPNode); + void onSequenceChanging(); + void onSequenceChanged(); + void onGraphFastAddSourceChanged(bool begin, + int newFastAddSourceEnabled); + void onGraphMediaSetEmpty(); + void onGraphNodeWillRemove(IPCore::IPNode* node); - // - // Override - // + private: + Mu::Object* m_data; + void* m_pydata; + bool m_loadingError; + std::string m_loadingErrorString; + Mu::CallEnvironment* m_callEnv; + StringMap m_muFlags; + LoadState* m_loadState; + int m_gtoSourceTotal; + int m_gtoSourceCount; + bool m_userHasSetViewSize; + + // The source node which gives its fps to the graph. + // Normally the first source inserted in the graph. + IPCore::SourceIPNode* m_conductorSource; + + /// sequence IP node of the graph + IPCore::SequenceIPNode* m_sequenceIPNode{nullptr}; + + /// source IP node that contains the play head when the sequence + /// node starts its layout + int m_currentSourceIndex{-1}; + + /// the range info of the source that contains the play head + /// at the beginning of the layout + IPCore::IPNode::ImageRangeInfo m_currentSourceRangeInfo; + + /// offset of the source that contains the playhead at the beginning + /// of the layout + int m_currentSourceOffset{0}; - virtual void findProperty(PropertyVector& props, const std::string& name); - virtual void findCurrentNodesByTypeName(NodeVector& nodes, const std::string& typeName); - virtual void findNodesByTypeName(NodeVector& nodes, const std::string& typeName); - - virtual IPCore::IPNode* newNode(const std::string& typeName, const std::string& nodeName); - - virtual void setRendererType(const std::string&); - - virtual void readProfile(const std::string& filename, - IPCore::IPNode* node, - const WriteRequest&); - - protected: - virtual void readGTO(const std::string& filename, bool merge, Options::SourceArgs& sargs); - void readEDL(const char* filename); - void readGTOSessionContainer(PropertyContainer*); - - void applyRvSessionSpecificOptions(); - - void checkForStereoPaths(const std::string&, StringVector&); - - void readSource(const std::string& filename, - Options::SourceArgs& sargs, - bool addContents, - bool addToExistingSource, - const std::string& tag="", - bool merge=false); - - void readSourceHelper(StringVector files, - Options::SourceArgs& sargs, - bool addContents, - bool addToExistingSource); - - - void continueLoading(); - void applySingleSourceArgs(Options::SourceArgs& sargs, IPCore::SourceIPNode* node); - - void processOptionsAfterSourcesLoaded(bool hadLoadError=false); - - void buildFileList(const StringVector& files, std::string tag, StringVector& collected); - std::vector findSourcesByMedia(const std::string& filename, - const std::string& sourceNode = ""); - std::vector findSwitchIPNodes(const std::string& srcNodeOrSwitchNodeName); - - void setSequenceEvents(); - void unsetSequenceEvents(); - void setSequenceIPNode(IPCore::SequenceIPNode* newSequenceIPNode); - void onSequenceChanging(); - void onSequenceChanged(); - void onGraphFastAddSourceChanged(bool begin, int newFastAddSourceEnabled); - void onGraphMediaSetEmpty(); - void onGraphNodeWillRemove(IPCore::IPNode * node); - - private: - Mu::Object* m_data; - void* m_pydata; - bool m_loadingError; - std::string m_loadingErrorString; - Mu::CallEnvironment* m_callEnv; - StringMap m_muFlags; - LoadState* m_loadState; - int m_gtoSourceTotal; - int m_gtoSourceCount; - bool m_userHasSetViewSize; - - // The source node which gives its fps to the graph. - // Normally the first source inserted in the graph. - IPCore::SourceIPNode* m_conductorSource; - - /// sequence IP node of the graph - IPCore::SequenceIPNode* m_sequenceIPNode {nullptr}; - - /// source IP node that contains the play head when the sequence - /// node starts its layout - int m_currentSourceIndex {-1}; - - /// the range info of the source that contains the play head - /// at the beginning of the layout - IPCore::IPNode::ImageRangeInfo m_currentSourceRangeInfo; - - /// offset of the source that contains the playhead at the beginning - /// of the layout - int m_currentSourceOffset {0}; - - /// next sequence layout is the first one - bool m_firstSequenceChange {true}; - - boost::signals2::connection m_fastAddSourceChangedConnection; - boost::signals2::connection m_mediaLoadingSetEmptyConnection; - boost::signals2::connection m_nodeWillRemoveConnection; - - static std::string m_initEval; - static std::string m_pyInitEval; - public: - static Session* m_currentSession; -}; - - -} // Rv + /// next sequence layout is the first one + bool m_firstSequenceChange{true}; + + boost::signals2::connection m_fastAddSourceChangedConnection; + boost::signals2::connection m_mediaLoadingSetEmptyConnection; + boost::signals2::connection m_nodeWillRemoveConnection; + + static std::string m_initEval; + static std::string m_pyInitEval; + + public: + static Session* m_currentSession; + }; + +} // namespace Rv #endif // __RVApp__RvSession__h__ - - diff --git a/src/lib/app/RvApp/RvApp/RvViewGroupIPNode.h b/src/lib/app/RvApp/RvApp/RvViewGroupIPNode.h index 7f22a05ff..8e597b7da 100644 --- a/src/lib/app/RvApp/RvApp/RvViewGroupIPNode.h +++ b/src/lib/app/RvApp/RvApp/RvViewGroupIPNode.h @@ -1,35 +1,32 @@ // -// Copyright (c) 2010 Tweak Software. +// Copyright (c) 2010 Tweak Software. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// // #ifndef __RvApp__RvViewGroupIPNode__h__ #define __RvApp__RvViewGroupIPNode__h__ #include #include - -namespace Rv { - -using namespace IPCore; - -class RvViewGroupIPNode : public ViewGroupIPNode +namespace Rv { - public: - RvViewGroupIPNode(const std::string& name, - const NodeDefinition* def, - IPGraph* graph, - GroupIPNode* group=0) : ViewGroupIPNode(name, def, graph, group) {}; + using namespace IPCore; - virtual ~RvViewGroupIPNode(); + class RvViewGroupIPNode : public ViewGroupIPNode + { + public: + RvViewGroupIPNode(const std::string& name, const NodeDefinition* def, + IPGraph* graph, GroupIPNode* group = 0) + : ViewGroupIPNode(name, def, graph, group) {}; - virtual IPImage* evaluate(const Context&); -}; + virtual ~RvViewGroupIPNode(); + virtual IPImage* evaluate(const Context&); + }; -} // Rv +} // namespace Rv #endif // __IPCore__ViewGroupIPNode__h__ diff --git a/src/lib/app/RvApp/RvGraph.cpp b/src/lib/app/RvApp/RvGraph.cpp index d70fbdd68..218bc2913 100644 --- a/src/lib/app/RvApp/RvGraph.cpp +++ b/src/lib/app/RvApp/RvGraph.cpp @@ -1,9 +1,9 @@ // -// Copyright (c) 2012 Tweak Software. +// Copyright (c) 2012 Tweak Software. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// // #include #include @@ -47,7 +47,7 @@ #include #include -#include +#include #include #include @@ -56,14 +56,15 @@ #include #endif -namespace Rv { -using namespace IPCore; -using namespace std; -using namespace TwkMath; -using namespace TwkUtil; -using namespace TwkContainer; -using namespace TwkAudio; -using namespace boost; +namespace Rv +{ + using namespace IPCore; + using namespace std; + using namespace TwkMath; + using namespace TwkUtil; + using namespace TwkContainer; + using namespace TwkAudio; + using namespace boost; #ifdef PLATFORM_WINDOWS #define PAD "%06d" @@ -71,448 +72,491 @@ using namespace boost; #define PAD "%06zd" #endif -// Note that the new fast add source mechanism postpones the default views -// input connection until all the new sources have been added. -// Note that this mechanism was put in place so that we end up with an O(n) -// complexity instead of O(n^2) with respect to the number of added sources -// This mechanism is enabled by default. -// However the following environment variable can be used if one suspects -// that an issue originates from this specific mechanism. -static ENVVAR_BOOL( evUseFastAddSource, "RV_USE_FAST_ADD_SOURCE", true ); - -// Defines the default value of the autoEDL mode for the RVSwitchGroup node -static ENVVAR_INT( evMediaRepSwitchAutoEDL, "RV_MEDIA_REP_SWITCH_AUTO_EDL", 0 ); - -//---------------------------------------------------------------------- - -RvGraph::RvGraph(const NodeManager* nodeManager) - : IPGraph(nodeManager), - m_sequenceNode(0), - m_stackNode(0), - m_layoutNode(0) -{ -} - -RvGraph::~RvGraph() -{ -} - -void -RvGraph::removeNode(IPNode* n) -{ - IPGraph::removeNode(n); - - if (n == m_sequenceNode) m_sequenceNode = 0; - if (n == m_stackNode) m_stackNode = 0; - if (n == m_layoutNode) m_layoutNode = 0; - - Sources::iterator s = find(m_imageSources.begin(), m_imageSources.end(), n); - if (s != m_imageSources.end()) m_imageSources.erase(s); -} - -void -RvGraph::initializeIPTree(const VideoModules& modules) -{ - lockAudioFill(); - finishAudioThread(); - unlockAudioFill(); - - m_topologyChanged = true; - - if (m_cacheMode != NeverCache) + // Note that the new fast add source mechanism postpones the default views + // input connection until all the new sources have been added. + // Note that this mechanism was put in place so that we end up with an O(n) + // complexity instead of O(n^2) with respect to the number of added sources + // This mechanism is enabled by default. + // However the following environment variable can be used if one suspects + // that an issue originates from this specific mechanism. + static ENVVAR_BOOL(evUseFastAddSource, "RV_USE_FAST_ADD_SOURCE", true); + + // Defines the default value of the autoEDL mode for the RVSwitchGroup node + static ENVVAR_INT(evMediaRepSwitchAutoEDL, "RV_MEDIA_REP_SWITCH_AUTO_EDL", + 0); + + //---------------------------------------------------------------------- + + RvGraph::RvGraph(const NodeManager* nodeManager) + : IPGraph(nodeManager) + , m_sequenceNode(0) + , m_stackNode(0) + , m_layoutNode(0) { - setCachingMode(NeverCache, 1, 2, 1, 2, 1, 1, 24.0); - finishCachingThread(); } - // - // Unhook all inputs. This will prevent the need for recursive - // deletion -- at least at the top level. - // + RvGraph::~RvGraph() {} - for (NodeMap::iterator i = m_viewNodeMap.begin(); - i != m_viewNodeMap.end(); - ++i) + void RvGraph::removeNode(IPNode* n) { - IPNode* n = i->second; - n->willDelete(); - n->disconnectInputs(); + IPGraph::removeNode(n); + + if (n == m_sequenceNode) + m_sequenceNode = 0; + if (n == m_stackNode) + m_stackNode = 0; + if (n == m_layoutNode) + m_layoutNode = 0; + + Sources::iterator s = + find(m_imageSources.begin(), m_imageSources.end(), n); + if (s != m_imageSources.end()) + m_imageSources.erase(s); } - // - // Delete all nodes until none are left, but first set the view node - // to the last node. If we don't do this, once we delete the view node - // we will reset it to the next node and repeat that until we reach - // the end. Each time we do this is will re-evaluate the graph, which - // is needlessly costly since we are about to delete all nodes. - // - if (!m_viewNodeMap.empty()) + void RvGraph::initializeIPTree(const VideoModules& modules) { - setViewNode(m_viewNodeMap.rbegin()->second); - } - while (!m_viewNodeMap.empty()) - { - IPNode* n = m_viewNodeMap.begin()->second; - delete n; - } - - m_imageSources.clear(); - m_displayGroups.clear(); + lockAudioFill(); + finishAudioThread(); + unlockAudioFill(); - m_rootNode = 0; - m_sequenceNode = 0; - m_stackNode = 0; - m_layoutNode = 0; - m_viewNode = 0; + m_topologyChanged = true; - m_nodeMap.clear(); - m_viewNodeMap.clear(); - m_defaultViewsMap.clear(); - - m_rootNode = newNode("Root", "root"); - m_sessionNode = newNodeOfType("RVSession", "rv"); - m_sequenceNode = newNodeOfType("RVSequenceGroup", "defaultSequence"); - m_stackNode = newNodeOfType("RVStackGroup", "defaultStack"); - m_layoutNode = newNodeOfType("RVLayoutGroup", "defaultLayout"); - m_viewGroupNode = newNodeOfType("RVViewGroup", "viewGroup"); - m_defaultOutputGroup = newOutputGroup("defaultOutputGroup"); - - m_viewNode = m_sequenceNode; - - m_sequenceNode->declareProperty("ui.name", QObject::tr("Default Sequence").toStdString().c_str()); - m_stackNode->declareProperty("ui.name", "Default Stack"); - m_layoutNode->declareProperty("ui.name", "Default Layout"); + if (m_cacheMode != NeverCache) + { + setCachingMode(NeverCache, 1, 2, 1, 2, 1, 1, 24.0); + finishCachingThread(); + } - m_volume = m_viewGroupNode->soundtrackNode()->property("audio.volume"); - m_balance = m_viewGroupNode->soundtrackNode()->property("audio.balance"); - m_mute = m_viewGroupNode->soundtrackNode()->property("audio.mute"); - m_audioSoftClamp = m_viewGroupNode->soundtrackNode()->property("audio.softClamp"); - m_audioOffset = m_viewGroupNode->soundtrackNode()->property("audio.offset"); - m_audioOffset2 = m_viewGroupNode->soundtrackNode()->property("audio.internalOffset"); + // + // Unhook all inputs. This will prevent the need for recursive + // deletion -- at least at the top level. + // - m_defaultViewsMap[m_sequenceNode->name()] = m_sequenceNode; - m_defaultViewsMap[m_stackNode->name()] = m_stackNode; - m_defaultViewsMap[m_layoutNode->name()] = m_layoutNode; + for (NodeMap::iterator i = m_viewNodeMap.begin(); + i != m_viewNodeMap.end(); ++i) + { + IPNode* n = i->second; + n->willDelete(); + n->disconnectInputs(); + } - m_viewNodeMap[m_sequenceNode->name()] = m_sequenceNode; - m_viewNodeMap[m_stackNode->name()] = m_stackNode; - m_viewNodeMap[m_layoutNode->name()] = m_layoutNode; + // + // Delete all nodes until none are left, but first set the view node + // to the last node. If we don't do this, once we delete the view node + // we will reset it to the next node and repeat that until we reach + // the end. Each time we do this is will re-evaluate the graph, which + // is needlessly costly since we are about to delete all nodes. + // + if (!m_viewNodeMap.empty()) + { + setViewNode(m_viewNodeMap.rbegin()->second); + } + while (!m_viewNodeMap.empty()) + { + IPNode* n = m_viewNodeMap.begin()->second; + delete n; + } - m_viewGroupNode->setInputs1(m_viewNode); + m_imageSources.clear(); + m_displayGroups.clear(); + + m_rootNode = 0; + m_sequenceNode = 0; + m_stackNode = 0; + m_layoutNode = 0; + m_viewNode = 0; + + m_nodeMap.clear(); + m_viewNodeMap.clear(); + m_defaultViewsMap.clear(); + + m_rootNode = newNode("Root", "root"); + m_sessionNode = newNodeOfType("RVSession", "rv"); + m_sequenceNode = newNodeOfType("RVSequenceGroup", + "defaultSequence"); + m_stackNode = + newNodeOfType("RVStackGroup", "defaultStack"); + m_layoutNode = + newNodeOfType("RVLayoutGroup", "defaultLayout"); + m_viewGroupNode = + newNodeOfType("RVViewGroup", "viewGroup"); + m_defaultOutputGroup = newOutputGroup("defaultOutputGroup"); + + m_viewNode = m_sequenceNode; + + m_sequenceNode->declareProperty( + "ui.name", QObject::tr("Default Sequence").toStdString().c_str()); + m_stackNode->declareProperty("ui.name", + "Default Stack"); + m_layoutNode->declareProperty("ui.name", + "Default Layout"); + + m_volume = m_viewGroupNode->soundtrackNode()->property( + "audio.volume"); + m_balance = m_viewGroupNode->soundtrackNode()->property( + "audio.balance"); + m_mute = m_viewGroupNode->soundtrackNode()->property( + "audio.mute"); + m_audioSoftClamp = + m_viewGroupNode->soundtrackNode()->property( + "audio.softClamp"); + m_audioOffset = + m_viewGroupNode->soundtrackNode()->property( + "audio.offset"); + m_audioOffset2 = + m_viewGroupNode->soundtrackNode()->property( + "audio.internalOffset"); + + m_defaultViewsMap[m_sequenceNode->name()] = m_sequenceNode; + m_defaultViewsMap[m_stackNode->name()] = m_stackNode; + m_defaultViewsMap[m_layoutNode->name()] = m_layoutNode; + + m_viewNodeMap[m_sequenceNode->name()] = m_sequenceNode; + m_viewNodeMap[m_stackNode->name()] = m_stackNode; + m_viewNodeMap[m_layoutNode->name()] = m_layoutNode; + + m_viewGroupNode->setInputs1(m_viewNode); + + m_defaultOutputGroup->setInputs1(m_viewGroupNode); + setPhysicalDevicesInternal(modules); + + m_rootNode->appendInput(m_viewGroupNode->waveformNode()); + } - m_defaultOutputGroup->setInputs1(m_viewGroupNode); - setPhysicalDevicesInternal(modules); + DisplayGroupIPNode* + RvGraph::newDisplayGroup(const std::string& nodeName, + const TwkApp::VideoDevice* device) + { + const Options& opts = Options::sharedOptions(); - m_rootNode->appendInput(m_viewGroupNode->waveformNode()); -} + DisplayGroupIPNode* group = + newNodeOfType("RVDisplayGroup", nodeName); + if (group) + { + group->setPhysicalVideoDevice(device); -DisplayGroupIPNode* -RvGraph::newDisplayGroup(const std::string& nodeName, const TwkApp::VideoDevice* device) -{ - const Options& opts = Options::sharedOptions(); + if (IPNode* dispNode = + group->displayPipelineNode()->findNodeInPipelineByTypeName( + "RVDisplayColor")) + { + dispNode->setProperty("color.gamma", opts.gamma); + dispNode->setProperty("color.sRGB", opts.sRGB); + dispNode->setProperty("color.Rec709", opts.rec709); + dispNode->setProperty("color.brightness", + opts.brightness); + } + } - DisplayGroupIPNode* group = newNodeOfType("RVDisplayGroup", nodeName); + return group; + } - if (group) + OutputGroupIPNode* + RvGraph::newOutputGroup(const std::string& nodeName, + const TwkApp::VideoDevice* device) { - group->setPhysicalVideoDevice(device); + OutputGroupIPNode* group = + newNodeOfType("RVOutputGroup", nodeName); + if (group) + group->setPhysicalVideoDevice(device); + return group; + } - if (IPNode* dispNode = - group->displayPipelineNode()->findNodeInPipelineByTypeName("RVDisplayColor")) + TwkContainer::PropertyContainer* RvGraph::sparseContainer(IPNode* node) + { + if (dynamic_cast(node)) { - dispNode->setProperty("color.gamma", opts.gamma); - dispNode->setProperty("color.sRGB", opts.sRGB); - dispNode->setProperty("color.Rec709", opts.rec709); - dispNode->setProperty("color.brightness", opts.brightness); + return node->shallowCopy(); } + return IPGraph::sparseContainer(node); } - return group; -} - -OutputGroupIPNode* -RvGraph::newOutputGroup(const std::string& nodeName, const TwkApp::VideoDevice* device) -{ - OutputGroupIPNode* group = newNodeOfType("RVOutputGroup", nodeName); - if (group) group->setPhysicalVideoDevice(device); - return group; -} - -TwkContainer::PropertyContainer* -RvGraph::sparseContainer(IPNode* node) -{ - if (dynamic_cast(node)) - { - return node->shallowCopy(); - } - return IPGraph::sparseContainer(node); -} - -SourceIPNode* -RvGraph::addSource( - const std::string& nodeType, - const std::string& nodeName, - const std::string& mediaRepName, - IPCore::SourceIPNode* mediaRepSisterSrcNode -) -{ - // Alternating between 2 colors makes it easier to see each individual - // added source. - static bool zoneFlip = false; - zoneFlip = !zoneFlip; - HOP_ZONE( zoneFlip ? HOP_ZONE_COLOR_10 :HOP_ZONE_COLOR_11 ); - HOP_PROF_DYN_NAME( - std::string(std::string("RvGraph::addSource(nodeType=") + nodeType + - std::string(") ") + nodeName).c_str()); - - // - // Build the IP tree for this source. Make sure that the - // caching/evaluation thread is suspended before doing - // anything. - // - - string finalName = nodeName; - - if (finalName.empty()) + SourceIPNode* + RvGraph::addSource(const std::string& nodeType, const std::string& nodeName, + const std::string& mediaRepName, + IPCore::SourceIPNode* mediaRepSisterSrcNode) { - char temp[256]; - size_t n = m_imageSources.size(); - sprintf(temp, "sourceGroup" PAD "_source", n); + // Alternating between 2 colors makes it easier to see each individual + // added source. + static bool zoneFlip = false; + zoneFlip = !zoneFlip; + HOP_ZONE(zoneFlip ? HOP_ZONE_COLOR_10 : HOP_ZONE_COLOR_11); + HOP_PROF_DYN_NAME( + std::string(std::string("RvGraph::addSource(nodeType=") + nodeType + + std::string(") ") + nodeName) + .c_str()); - finalName = temp; - } + // + // Build the IP tree for this source. Make sure that the + // caching/evaluation thread is suspended before doing + // anything. + // - if (finalName.find("_source") == string::npos) - { - cerr << "ERROR: malformed source name: " << finalName << endl; - } + string finalName = nodeName; - SourceIPNode* source = newSource(finalName, nodeType, mediaRepName); - setupSource(source, mediaRepSisterSrcNode); + if (finalName.empty()) + { + char temp[256]; + size_t n = m_imageSources.size(); + sprintf(temp, "sourceGroup" PAD "_source", n); - return source; -} + finalName = temp; + } -// Fast add source mechanism which postpones the default views' inputs -// connection until all the new sources have been added. -// Note that this mechanism was put in place so that we end up with an O(n) -// complexity instead of O(n^2) with respect to the number of added sources -// This mechanism is enabled by default but can be disabled with an -// environment variable for emergency/debugging purpose. -void -RvGraph::connectNewSourcesToDefaultViews() -{ - HOP_PROF_FUNC(); + if (finalName.find("_source") == string::npos) + { + cerr << "ERROR: malformed source name: " << finalName << endl; + } - if ( !evUseFastAddSource.getValue() || m_newSources.empty() ) - { - return; + SourceIPNode* source = newSource(finalName, nodeType, mediaRepName); + setupSource(source, mediaRepSisterSrcNode); + + return source; } - for (NodeMap::iterator i = m_defaultViewsMap.begin(); - i != m_defaultViewsMap.end(); - ++i) + // Fast add source mechanism which postpones the default views' inputs + // connection until all the new sources have been added. + // Note that this mechanism was put in place so that we end up with an O(n) + // complexity instead of O(n^2) with respect to the number of added sources + // This mechanism is enabled by default but can be disabled with an + // environment variable for emergency/debugging purpose. + void RvGraph::connectNewSourcesToDefaultViews() { - HOP_PROF_DYN_NAME( - std::string( - std::string("RvGraph::updateDefaultViewsWithNewSources() - setInputs - ") + - i->first ).c_str() ); - - IPNode* layer = i->second; - IPNode::IPNodes inputs(layer->inputs().size() + m_newSources.size()); - copy(layer->inputs().begin(), layer->inputs().end(), inputs.begin()); - copy(m_newSources.begin(), m_newSources.end(), inputs.begin()+layer->inputs().size()); - HOP_ZONE( HOP_ZONE_COLOR_12 ); - layer->setInputs(inputs); - } + HOP_PROF_FUNC(); - m_newSources.clear(); -} + if (!evUseFastAddSource.getValue() || m_newSources.empty()) + { + return; + } -void -RvGraph::setupSource(SourceIPNode* source, IPCore::SourceIPNode* mediaRepSisterSrcNode) -{ - HOP_PROF_FUNC(); + for (NodeMap::iterator i = m_defaultViewsMap.begin(); + i != m_defaultViewsMap.end(); ++i) + { + HOP_PROF_DYN_NAME( + std::string( + std::string("RvGraph::updateDefaultViewsWithNewSources() - " + "setInputs - ") + + i->first) + .c_str()); - string name = source->name(); - name = name.substr(0, name.find("_source")); + IPNode* layer = i->second; + IPNode::IPNodes inputs(layer->inputs().size() + + m_newSources.size()); + copy(layer->inputs().begin(), layer->inputs().end(), + inputs.begin()); + copy(m_newSources.begin(), m_newSources.end(), + inputs.begin() + layer->inputs().size()); + HOP_ZONE(HOP_ZONE_COLOR_12); + layer->setInputs(inputs); + } - m_imageSources.push_back(source); + m_newSources.clear(); + } - SourceGroupIPNode* sourceGroup = newSourceGroup(name, source); + void RvGraph::setupSource(SourceIPNode* source, + IPCore::SourceIPNode* mediaRepSisterSrcNode) + { + HOP_PROF_FUNC(); - m_viewNodeMap[sourceGroup->name()] = sourceGroup; + string name = source->name(); + name = name.substr(0, name.find("_source")); - // Are we adding a media representation ? - SwitchGroupIPNode* switchGroup = nullptr; - if (mediaRepSisterSrcNode || !source->mediaRepName().empty()) - { - // Make sure that the media is not loaded by default when adding a media - // representation as we only want to load it when the media representation - // is actually used - if (mediaRepSisterSrcNode) - { - source->setMediaActive(false); + m_imageSources.push_back(source); - // Is there an already existing switch group already connected to the sister source node ? - switchGroup = dynamic_cast( - findNodeAssociatedWith(mediaRepSisterSrcNode->group(), "RVSwitchGroup")); - } - - // If there is no existing switch group already then allocate one - if (!switchGroup) - { - const NodeDefinition* def = m_nodeManager->definition("RVSwitchGroup"); - if (!def) - { - TWK_THROW_EXC_STREAM("Could not find RVSwitchGroup node definition"); - } + SourceGroupIPNode* sourceGroup = newSourceGroup(name, source); - switchGroup = new SwitchGroupIPNode(name+"_switchGroup", def, this); - switchGroup->switchNode()->setProperty( - "mode.autoEDL", evMediaRepSwitchAutoEDL.getValue() ); + m_viewNodeMap[sourceGroup->name()] = sourceGroup; + // Are we adding a media representation ? + SwitchGroupIPNode* switchGroup = nullptr; + if (mediaRepSisterSrcNode || !source->mediaRepName().empty()) + { + // Make sure that the media is not loaded by default when adding a + // media representation as we only want to load it when the media + // representation is actually used if (mediaRepSisterSrcNode) { - switchGroup->setInputs2(mediaRepSisterSrcNode->group(), sourceGroup); + source->setMediaActive(false); + + // Is there an already existing switch group already connected + // to the sister source node ? + switchGroup = + dynamic_cast(findNodeAssociatedWith( + mediaRepSisterSrcNode->group(), "RVSwitchGroup")); } - else + + // If there is no existing switch group already then allocate one + if (!switchGroup) { - switchGroup->setInputs1(sourceGroup); - } + const NodeDefinition* def = + m_nodeManager->definition("RVSwitchGroup"); + if (!def) + { + TWK_THROW_EXC_STREAM( + "Could not find RVSwitchGroup node definition"); + } - m_viewNodeMap[switchGroup->name()] = switchGroup; + switchGroup = + new SwitchGroupIPNode(name + "_switchGroup", def, this); + switchGroup->switchNode()->setProperty( + "mode.autoEDL", evMediaRepSwitchAutoEDL.getValue()); - // Adjust the view nodes accordingly - if (evUseFastAddSource.getValue() && isFastAddSourceEnabled()) - { - // Fast add source mechanism which postpones the default views' inputs - // connection until all the new sources have been added to prevent O(n^2) if (mediaRepSisterSrcNode) { - std::replace(m_newSources.begin(), m_newSources.end(), static_cast(mediaRepSisterSrcNode->group()), static_cast(switchGroup)); + switchGroup->setInputs2(mediaRepSisterSrcNode->group(), + sourceGroup); } else { - m_newSources.push_back(static_cast(switchGroup)); + switchGroup->setInputs1(sourceGroup); } - } - else - { - // - // Connect all of the default view nodes. - // - - IPNode::IPNodes inputs(1); - for (NodeMap::iterator i = m_defaultViewsMap.begin(); - i != m_defaultViewsMap.end(); - ++i) - { - HOP_PROF_DYN_NAME( - std::string( - std::string("RvGraph::setupSource - setInputs - ") + - i->first ).c_str() ); - IPNode* layer = i->second; + m_viewNodeMap[switchGroup->name()] = switchGroup; + + // Adjust the view nodes accordingly + if (evUseFastAddSource.getValue() && isFastAddSourceEnabled()) + { + // Fast add source mechanism which postpones the default + // views' inputs connection until all the new sources have + // been added to prevent O(n^2) if (mediaRepSisterSrcNode) { - inputs.resize(layer->inputs().size()); - for (size_t i = 0; i < inputs.size(); i++) - { - inputs[i] = (layer->inputs()[i] == mediaRepSisterSrcNode->group()) ? switchGroup : layer->inputs()[i]; - } + std::replace(m_newSources.begin(), m_newSources.end(), + static_cast( + mediaRepSisterSrcNode->group()), + static_cast(switchGroup)); } else { - inputs.resize(layer->inputs().size() + 1); - copy(layer->inputs().begin(), layer->inputs().end(), inputs.begin()); - inputs.back() = switchGroup; + m_newSources.push_back( + static_cast(switchGroup)); + } + } + else + { + // + // Connect all of the default view nodes. + // + + IPNode::IPNodes inputs(1); + for (NodeMap::iterator i = m_defaultViewsMap.begin(); + i != m_defaultViewsMap.end(); ++i) + { + HOP_PROF_DYN_NAME( + std::string( + std::string( + "RvGraph::setupSource - setInputs - ") + + i->first) + .c_str()); + + IPNode* layer = i->second; + if (mediaRepSisterSrcNode) + { + inputs.resize(layer->inputs().size()); + for (size_t i = 0; i < inputs.size(); i++) + { + inputs[i] = (layer->inputs()[i] + == mediaRepSisterSrcNode->group()) + ? switchGroup + : layer->inputs()[i]; + } + } + else + { + inputs.resize(layer->inputs().size() + 1); + copy(layer->inputs().begin(), layer->inputs().end(), + inputs.begin()); + inputs.back() = switchGroup; + } + HOP_ZONE(HOP_ZONE_COLOR_12); + layer->setInputs(inputs); } - HOP_ZONE( HOP_ZONE_COLOR_12 ); - layer->setInputs(inputs); } + + m_topologyChanged = true; + } + else + { + switchGroup->appendInput(sourceGroup); } - m_topologyChanged = true; + return; + } + + if (evUseFastAddSource.getValue() && isFastAddSourceEnabled()) + { + // Fast add source mechanism which postpones the default views' + // inputs connection until all the new sources have been added to + // prevent O(n^2) + m_newSources.push_back(sourceGroup); } else { - switchGroup->appendInput(sourceGroup); + // + // Connect all of the default view nodes. + // + + IPNode::IPNodes inputs(1); + for (NodeMap::iterator i = m_defaultViewsMap.begin(); + i != m_defaultViewsMap.end(); ++i) + { + HOP_PROF_DYN_NAME( + std::string( + std::string("RvGraph::setupSource - setInputs - ") + + i->first) + .c_str()); + + IPNode* layer = i->second; + inputs.resize(layer->inputs().size() + 1); + copy(layer->inputs().begin(), layer->inputs().end(), + inputs.begin()); + inputs.back() = sourceGroup; + HOP_ZONE(HOP_ZONE_COLOR_12); + layer->setInputs(inputs); + } } - - return; - } - if (evUseFastAddSource.getValue() && isFastAddSourceEnabled()) - { - // Fast add source mechanism which postpones the default views' inputs - // connection until all the new sources have been added to prevent O(n^2) - m_newSources.push_back(sourceGroup); + m_frameCacheInvalid = true; + m_topologyChanged = true; } - else - { - // - // Connect all of the default view nodes. - // - IPNode::IPNodes inputs(1); - for (NodeMap::iterator i = m_defaultViewsMap.begin(); - i != m_defaultViewsMap.end(); - ++i) + SourceIPNode* RvGraph::newSource(const std::string& nodeName, + const std::string& nodeType, + const std::string& mediaRepName) + { + SourceIPNode* source = 0; + if (const NodeDefinition* def = m_nodeManager->definition(nodeType)) { - HOP_PROF_DYN_NAME( - std::string( - std::string("RvGraph::setupSource - setInputs - ") + - i->first ).c_str() ); - - IPNode* layer = i->second; - inputs.resize(layer->inputs().size() + 1); - copy(layer->inputs().begin(), layer->inputs().end(), inputs.begin()); - inputs.back() = sourceGroup; - HOP_ZONE( HOP_ZONE_COLOR_12 ); - layer->setInputs(inputs); + if (nodeType == "RVImageSource") + { + ImageSourceIPNode* sipn = new ImageSourceIPNode( + nodeName, def, this, NULL, mediaRepName); + source = dynamic_cast(sipn); + } + else if (nodeType == "RVFileSource") + { + FileSourceIPNode* sipn = new FileSourceIPNode( + nodeName, def, this, NULL, mediaRepName); + source = dynamic_cast(sipn); + } } - } - m_frameCacheInvalid = true; - m_topologyChanged = true; -} + return source; + } -SourceIPNode* -RvGraph::newSource(const std::string& nodeName, - const std::string& nodeType, - const std::string& mediaRepName) -{ - SourceIPNode* source = 0; - if (const NodeDefinition* def = m_nodeManager->definition(nodeType)) + SourceGroupIPNode* RvGraph::newSourceGroup(const std::string& nodeName, + SourceIPNode* snode) { - if (nodeType == "RVImageSource") + if (const NodeDefinition* def = + m_nodeManager->definition("RVSourceGroup")) { - ImageSourceIPNode* sipn = new ImageSourceIPNode(nodeName, def, this, NULL, mediaRepName); - source = dynamic_cast(sipn); + return new SourceGroupIPNode(nodeName, def, snode, this); } - else if (nodeType == "RVFileSource") + else { - FileSourceIPNode* sipn = new FileSourceIPNode(nodeName, def, this, NULL, mediaRepName); - source = dynamic_cast(sipn); + return 0; } } - return source; -} - -SourceGroupIPNode* -RvGraph::newSourceGroup(const std::string& nodeName, SourceIPNode* snode) -{ - if (const NodeDefinition* def = m_nodeManager->definition("RVSourceGroup")) - { - return new SourceGroupIPNode(nodeName, def, snode, this); - } - else - { - return 0; - } -} - -} // Rv +} // namespace Rv diff --git a/src/lib/app/RvApp/RvNodeDefinitions.cpp b/src/lib/app/RvApp/RvNodeDefinitions.cpp index 16e6ca189..574574c51 100644 --- a/src/lib/app/RvApp/RvNodeDefinitions.cpp +++ b/src/lib/app/RvApp/RvNodeDefinitions.cpp @@ -1,9 +1,9 @@ // // Copyright (c) 2013 Tweak Software. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// // #include #include @@ -56,733 +56,659 @@ #include #include -namespace Rv { -using namespace std; -using namespace IPCore; +namespace Rv +{ + using namespace std; + using namespace IPCore; + + namespace + { + typedef TwkContainer::StringProperty StringProperty; + typedef IPGraph::FloatProperty FloatProperty; + typedef IPGraph::IntProperty IntProperty; -namespace { -typedef TwkContainer::StringProperty StringProperty; -typedef IPGraph::FloatProperty FloatProperty; -typedef IPGraph::IntProperty IntProperty; + int compiledPreLUTSize = 0; -int compiledPreLUTSize = 0; -int getCompiledPreLUTSize() -{ - if (compiledPreLUTSize == 0) + int getCompiledPreLUTSize() + { + if (compiledPreLUTSize == 0) + { + compiledPreLUTSize = 2048; + if (const char* var = getenv("RV_COMPILED_PRELUT_SIZE")) + { + compiledPreLUTSize = atoi(var); + cerr << "INFO: custom preLUT size: " << compiledPreLUTSize + << endl; + } + } + return compiledPreLUTSize; + } + + } // namespace + + void addRvNodeDefinitions(NodeManager* m) { - compiledPreLUTSize = 2048; - if (const char* var = getenv("RV_COMPILED_PRELUT_SIZE")) + NodeDefinition::ByteVector emptyIcon; + + addICCNodeDefinitions(m); + bool usingICC = false; + char* ignoreICC = getenv("RV_IGNORE_ICC_PROFILE"); + if (ignoreICC) + usingICC = (strcmp(ignoreICC, "0") == 0); + + m->addDefinition(new NodeDefinition("Adaptor", 1, false, "adaptor", + newIPNode, "", "", + emptyIcon, false)); + + m->addDefinition(new NodeDefinition("Root", 1, false, "root", + newIPNode, "", "", + emptyIcon, false)); + + // RvSession protocolVersion is overwritten in the session write request + m->addDefinition(new NodeDefinition( + "RVSession", 4, false, "session", newIPNode, + "Session container", "", emptyIcon, false)); + { - compiledPreLUTSize = atoi(var); - cerr << "INFO: custom preLUT size: " << compiledPreLUTSize << endl; + NodeDefinition* def = + new NodeDefinition("RVSequenceGroup", 1, true, "sequenceGroup", + newIPNode, + "Plays back inputs by EDL", "", emptyIcon); + + def->declareProperty("defaults.sequenceType", + "RVSequence"); + def->declareProperty("defaults.retimeType", + "RVRetime"); + def->declareProperty("defaults.paintType", + "RVPaint"); + m->addDefinition(def); } - } - return compiledPreLUTSize; -} -} // close empty namespace + { + NodeDefinition* def = + new NodeDefinition("RVStackGroup", 1, true, "stackGroup", + newIPNode, + "Stacks inputs in time", "", emptyIcon); + + def->declareProperty("defaults.stackType", + "RVStack"); + def->declareProperty("defaults.transformType", + "RVTransform2D"); + def->declareProperty("defaults.retimeType", + "RVRetime"); + def->declareProperty("defaults.paintType", + "RVPaint"); + m->addDefinition(def); + } -void addRvNodeDefinitions(NodeManager* m) -{ - NodeDefinition::ByteVector emptyIcon; + { + NodeDefinition* def = new NodeDefinition( + "RVFolderGroup", 1, true, "folderGroup", + newIPNode, + "Multipurpose collection of nodes", "", emptyIcon); + + def->declareProperty("folder.switch", "RVSwitch"); + def->declareProperty("folder.stack", + "RVStackGroup"); + def->declareProperty("folder.layout", + "RVLayoutGroup"); + m->addDefinition(def); + } + { + NodeDefinition* def = new NodeDefinition( + "RVLayoutGroup", 1, true, "layoutGroup", + newIPNode, + "Visaully layout inputs in various ways", "", emptyIcon); + + def->declareProperty("defaults.stackType", + "RVStack"); + def->declareProperty("defaults.transformType", + "RVTransform2D"); + def->declareProperty("defaults.retimeType", + "RVRetime"); + def->declareProperty("defaults.paintType", + "RVPaint"); + m->addDefinition(def); + } - addICCNodeDefinitions(m); - bool usingICC = false; - char* ignoreICC = getenv("RV_IGNORE_ICC_PROFILE"); - if (ignoreICC) usingICC = (strcmp(ignoreICC,"0") == 0); + { + NodeDefinition* def = new NodeDefinition( + "RVRetimeGroup", 1, true, "retimeGroup", + newIPNode, + "Change input FPS, duration, or offset", "", emptyIcon); + + def->declareProperty("defaults.retimeType", + "RVRetime"); + def->declareProperty("defaults.paintType", + "RVPaint"); + m->addDefinition(def); + } - m->addDefinition(new NodeDefinition("Adaptor", 1, false, - "adaptor", - newIPNode, - "", "", emptyIcon, - false)); + { + NodeDefinition* def = new NodeDefinition( + "RVSwitchGroup", 1, true, "switchGroup", + newIPNode, "Select one of several inputs", + "", emptyIcon); + + def->declareProperty("defaults.switchType", + "RVSwitch"); + m->addDefinition(def); + } - m->addDefinition(new NodeDefinition("Root", 1, false, - "root", - newIPNode, - "", "", emptyIcon, - false)); + m->addDefinition(new NodeDefinition("RVRetime", 1, false, "retime", + newIPNode, "", "", + emptyIcon, false)); + m->addDefinition(new NodeDefinition( + "RVSwitch", 1, false, "switch", newIPNode, + "Select one of several inputs", "", emptyIcon, false)); - // RvSession protocolVersion is overwritten in the session write request - m->addDefinition(new NodeDefinition("RVSession", 4, false, - "session", - newIPNode, - "Session container", - "", - emptyIcon, - false)); + { + NodeDefinition* def = new NodeDefinition( + "RVColorPipelineGroup", 1, true, "pipeline", + newIPNode, + "Managed Single Input Pipeline for Source Color", "", emptyIcon, + false); + + def->declareProperty("defaults.pipeline", + "RVColor"); + m->addDefinition(def); + } - { - NodeDefinition* def = new NodeDefinition("RVSequenceGroup", 1, true, - "sequenceGroup", - newIPNode, - "Plays back inputs by EDL", - "", - emptyIcon); - - def->declareProperty("defaults.sequenceType", "RVSequence"); - def->declareProperty("defaults.retimeType", "RVRetime"); - def->declareProperty("defaults.paintType", "RVPaint"); - m->addDefinition(def); - } + { + NodeDefinition* def = new NodeDefinition( + "RVLookPipelineGroup", 1, true, "pipeline", + newIPNode, + "Managed Single Input Pipeline for Source Look", "", emptyIcon, + false); + + def->declareProperty("defaults.pipeline", + "RVLookLUT"); + m->addDefinition(def); + } + { + NodeDefinition* def = new NodeDefinition( + "RVLinearizePipelineGroup", 1, true, "pipeline", + newIPNode, + "Managed Single Input Pipeline for Source Linearization", "", + emptyIcon, false); + + vector linearizeDefaults; + linearizeDefaults.push_back("RVLinearize"); + if (usingICC) + linearizeDefaults.push_back("ICCLinearizeTransform"); + linearizeDefaults.push_back("RVLensWarp"); + def->declareProperty("defaults.pipeline", + linearizeDefaults); + m->addDefinition(def); + } - { - NodeDefinition* def = new NodeDefinition("RVStackGroup", 1, true, - "stackGroup", - newIPNode, - "Stacks inputs in time", - "", - emptyIcon); - - def->declareProperty("defaults.stackType", "RVStack"); - def->declareProperty("defaults.transformType", "RVTransform2D"); - def->declareProperty("defaults.retimeType", "RVRetime"); - def->declareProperty("defaults.paintType", "RVPaint"); - m->addDefinition(def); - } + { + NodeDefinition* def = + new NodeDefinition("RVDisplayPipelineGroup", 1, true, + "pipeline", newIPNode, + "Managed Single Input Pipeline for Display", + "", emptyIcon, false); + + vector displayDefaults; + if (usingICC) + displayDefaults.push_back("ICCDisplayTransform"); + displayDefaults.push_back("RVDisplayColor"); + def->declareProperty("defaults.pipeline", + displayDefaults); + m->addDefinition(def); + } - { - NodeDefinition* def = new NodeDefinition("RVFolderGroup", 1, true, - "folderGroup", - newIPNode, - "Multipurpose collection of nodes", - "", - emptyIcon); - - def->declareProperty("folder.switch", "RVSwitch"); - def->declareProperty("folder.stack", "RVStackGroup"); - def->declareProperty("folder.layout", "RVLayoutGroup"); - m->addDefinition(def); - } + { + NodeDefinition* def = new NodeDefinition( + "RVViewPipelineGroup", 1, true, "pipeline", + newIPNode, + "Managed Single Input Pipeline for View Group", "", emptyIcon, + false); + + // + // View pipeline is empty by default. + // + def->declareProperty("defaults.pipeline"); + m->addDefinition(def); + } - { - NodeDefinition* def = new NodeDefinition("RVLayoutGroup", 1, true, - "layoutGroup", - newIPNode, - "Visaully layout inputs in various ways", - "", - emptyIcon); - - def->declareProperty("defaults.stackType", "RVStack"); - def->declareProperty("defaults.transformType", "RVTransform2D"); - def->declareProperty("defaults.retimeType", "RVRetime"); - def->declareProperty("defaults.paintType", "RVPaint"); - m->addDefinition(def); - } + m->addDefinition(new NodeDefinition( + "PipelineGroup", 1, true, "pipeline", + newIPNode, "Managed Single Input Pipeline", "", + emptyIcon, true)); - { - NodeDefinition* def = new NodeDefinition("RVRetimeGroup", 1, true, - "retimeGroup", - newIPNode, - "Change input FPS, duration, or offset", - "", - emptyIcon); - - def->declareProperty("defaults.retimeType", "RVRetime"); - def->declareProperty("defaults.paintType", "RVPaint"); - m->addDefinition(def); - } + m->addDefinition(new NodeDefinition("RVCache", 1, false, "cache", + newIPNode, "", "", + emptyIcon, false)); + m->addDefinition(new NodeDefinition("RVCacheLUT", 1, false, "cacheLUT", + newIPNode, "", "", + emptyIcon, false)); - { - NodeDefinition* def = new NodeDefinition("RVSwitchGroup", 1, true, - "switchGroup", - newIPNode, - "Select one of several inputs", - "", - emptyIcon); - - def->declareProperty("defaults.switchType", "RVSwitch"); - m->addDefinition(def); - } + m->addDefinition(new NodeDefinition( + "RVChannelMap", 1, false, "channelMap", newIPNode, + "", "", emptyIcon, false)); - m->addDefinition(new NodeDefinition("RVRetime", 1, false, - "retime", - newIPNode, - "", "", emptyIcon, - false)); + m->addDefinition(new NodeDefinition("RVColor", 2, false, "color", + newIPNode, "", "", + emptyIcon, true)); - m->addDefinition(new NodeDefinition("RVSwitch", 1, false, - "switch", - newIPNode, - "Select one of several inputs", - "", - emptyIcon, - false)); + m->addDefinition(new NodeDefinition("RVCDL", 1, false, "color", + newIPNode, "", "", + emptyIcon, true)); - { - NodeDefinition* def = new NodeDefinition("RVColorPipelineGroup", 1, true, - "pipeline", - newIPNode, - "Managed Single Input Pipeline for Source Color", - "", - emptyIcon, - false); - - def->declareProperty("defaults.pipeline", "RVColor"); - m->addDefinition(def); - } + m->addDefinition(new NodeDefinition( + "RVDispTransform2D", 1, false, "dispTransform2D", + newIPNode, "", "", emptyIcon, false)); - { - NodeDefinition* def = new NodeDefinition("RVLookPipelineGroup", 1, true, - "pipeline", - newIPNode, - "Managed Single Input Pipeline for Source Look", - "", - emptyIcon, - false); - - def->declareProperty("defaults.pipeline", "RVLookLUT"); - m->addDefinition(def); - } + { + NodeDefinition* def = new NodeDefinition( + "RVDisplayColor", 1, false, "displayColor", + newIPNode, "", "", emptyIcon, false); - { - NodeDefinition* def = new NodeDefinition("RVLinearizePipelineGroup", 1, true, - "pipeline", - newIPNode, - "Managed Single Input Pipeline for Source Linearization", - "", - emptyIcon, - false); - - vector linearizeDefaults; - linearizeDefaults.push_back("RVLinearize"); - if (usingICC) linearizeDefaults.push_back("ICCLinearizeTransform"); - linearizeDefaults.push_back("RVLensWarp"); - def->declareProperty("defaults.pipeline", linearizeDefaults); - m->addDefinition(def); - } + def->declareProperty("defaults.preLUTSize", + getCompiledPreLUTSize()); + m->addDefinition(def); + } - { - NodeDefinition* def = new NodeDefinition("RVDisplayPipelineGroup", 1, true, - "pipeline", - newIPNode, - "Managed Single Input Pipeline for Display", - "", - emptyIcon, - false); - - vector displayDefaults; - if (usingICC) displayDefaults.push_back("ICCDisplayTransform"); - displayDefaults.push_back("RVDisplayColor"); - def->declareProperty("defaults.pipeline", displayDefaults); - m->addDefinition(def); - } + { + NodeDefinition* def = new NodeDefinition( + "RVDisplayGroup", 1, true, "displayGroup", + newIPNode, "", "", emptyIcon, false); + + def->declareProperty("defaults.stereoType", + "RVDisplayStereo"); + def->declareProperty("defaults.pipelineType", + "RVDisplayPipelineGroup"); + m->addDefinition(def); + } - { - NodeDefinition* def = new NodeDefinition("RVViewPipelineGroup", 1, true, - "pipeline", - newIPNode, - "Managed Single Input Pipeline for View Group", - "", - emptyIcon, - false); - - // - // View pipeline is empty by default. - // - def->declareProperty("defaults.pipeline"); - m->addDefinition(def); - } + { + NodeDefinition* def = new NodeDefinition( + "RVOutputGroup", 1, true, "outputGroup", + newIPNode, "", "", emptyIcon, false); + + def->declareProperty("defaults.stereoType", + "RVDisplayStereo"); + def->declareProperty("defaults.pipelineType", + "RVDisplayPipelineGroup"); + m->addDefinition(def); + } - m->addDefinition(new NodeDefinition("PipelineGroup", 1, true, - "pipeline", - newIPNode, - "Managed Single Input Pipeline", - "", - emptyIcon, - true)); - - m->addDefinition(new NodeDefinition("RVCache", 1, false, - "cache", - newIPNode, - "", "", emptyIcon, - false)); - - m->addDefinition(new NodeDefinition("RVCacheLUT", 1, false, - "cacheLUT", - newIPNode, - "", "", emptyIcon, - false)); - - m->addDefinition(new NodeDefinition("RVChannelMap", 1, false, - "channelMap", - newIPNode, - "", "", emptyIcon, - false)); - - m->addDefinition(new NodeDefinition("RVColor", 2, false, - "color", - newIPNode, - "", "", emptyIcon, - true)); - - m->addDefinition(new NodeDefinition("RVCDL", 1, false, - "color", - newIPNode, - "", "", emptyIcon, - true)); - - m->addDefinition(new NodeDefinition("RVDispTransform2D", 1, false, - "dispTransform2D", - newIPNode, - "", "", emptyIcon, - false)); + { + NodeDefinition* def = new NodeDefinition( + "RVViewGroup", 1, true, "viewGroup", + newIPNode, "", "", emptyIcon, false); + + def->declareProperty("defaults.soundtrackType", + "RVSoundTrack"); + def->declareProperty("defaults.dispTransformType", + "RVDispTransform2D"); + def->declareProperty("defaults.waveformType", + "AudioWaveform"); + def->declareProperty("defaults.pipelineType", + "RVViewPipelineGroup"); + m->addDefinition(def); + } - { - NodeDefinition* def = new NodeDefinition("RVDisplayColor", 1, false, - "displayColor", - newIPNode, - "", "", emptyIcon, - false); - - def->declareProperty("defaults.preLUTSize", getCompiledPreLUTSize()); - m->addDefinition(def); - } + m->addDefinition(new NodeDefinition( + "RVDisplayStereo", 1, false, "displayStereo", + newIPNode, "", "", emptyIcon, false)); - { - NodeDefinition* def = new NodeDefinition("RVDisplayGroup", 1, true, - "displayGroup", - newIPNode, - "", "", emptyIcon, - false); - - def->declareProperty("defaults.stereoType", "RVDisplayStereo"); - def->declareProperty("defaults.pipelineType", "RVDisplayPipelineGroup"); - m->addDefinition(def); - } + { + NodeDefinition* def = new NodeDefinition( + "RVFileSource", 1, false, "fileSource", + newIPNode, "", "", emptyIcon, false); + + Rv::Options& opts = Rv::Options::sharedOptions(); + def->declareProperty( + "defaults.progressiveSourceLoading", + opts.progressiveSourceLoading); + def->declareProperty("defaults.missingMovieProc", + "error"); + m->addDefinition(def); + } - { - NodeDefinition* def = new NodeDefinition("RVOutputGroup", 1, true, - "outputGroup", - newIPNode, - "", "", emptyIcon, - false); - - def->declareProperty("defaults.stereoType", "RVDisplayStereo"); - def->declareProperty("defaults.pipelineType", "RVDisplayPipelineGroup"); - m->addDefinition(def); - } + m->addDefinition(new NodeDefinition( + "RVImageSource", 1, false, "imageSource", + newIPNode, "", "", emptyIcon, false)); - { - NodeDefinition* def = new NodeDefinition("RVViewGroup", 1, true, - "viewGroup", - newIPNode, - "", "", emptyIcon, - false); - - def->declareProperty("defaults.soundtrackType", "RVSoundTrack"); - def->declareProperty("defaults.dispTransformType", "RVDispTransform2D"); - def->declareProperty("defaults.waveformType", "AudioWaveform"); - def->declareProperty("defaults.pipelineType", "RVViewPipelineGroup"); - m->addDefinition(def); - } + m->addDefinition(new NodeDefinition("RVFormat", 1, false, "format", + newIPNode, "", "", + emptyIcon, false)); + { + NodeDefinition* def = new NodeDefinition( + "RVLinearize", 1, false, "linearize", + newIPNode, "", "", emptyIcon, false); - m->addDefinition(new NodeDefinition("RVDisplayStereo", 1, false, - "displayStereo", - newIPNode, - "", "", emptyIcon, - false)); + def->declareProperty("defaults.preLUTSize", + getCompiledPreLUTSize()); + m->addDefinition(def); + } - { - NodeDefinition* def = new NodeDefinition("RVFileSource", 1, false, - "fileSource", - newIPNode, - "", "", emptyIcon, - false); - - Rv::Options& opts = Rv::Options::sharedOptions(); - def->declareProperty("defaults.progressiveSourceLoading", opts.progressiveSourceLoading); - def->declareProperty("defaults.missingMovieProc", "error"); - m->addDefinition(def); - } + m->addDefinition(new NodeDefinition("RVLensWarp", 1, false, "lensWarp", + newIPNode, "", "", + emptyIcon, false)); - m->addDefinition(new NodeDefinition("RVImageSource", 1, false, - "imageSource", - newIPNode, - "", "", emptyIcon, - false)); + m->addDefinition(new NodeDefinition( + "RVUnsharpMask", 1, false, "unsharpMask", + newIPNode, "", "", emptyIcon, true)); - m->addDefinition(new NodeDefinition("RVFormat", 1, false, - "format", - newIPNode, - "", "", emptyIcon, - false)); + m->addDefinition(new NodeDefinition("RVLookLUT", 1, false, "look", + newIPNode, "", "", + emptyIcon, false)); - { - NodeDefinition* def = new NodeDefinition("RVLinearize", 1, false, - "linearize", - newIPNode, - "", "", emptyIcon, - false); - - def->declareProperty("defaults.preLUTSize", getCompiledPreLUTSize()); - m->addDefinition(def); - } + m->addDefinition(new NodeDefinition( + "RVPrimaryConvert", 1, false, "primaryConvert", + newIPNode, "", "", emptyIcon, true)); - m->addDefinition(new NodeDefinition("RVLensWarp", 1, false, - "lensWarp", - newIPNode, - "", "", emptyIcon, - false)); + { + NodeDefinition* def = new NodeDefinition("OCIO", 1, false, "OCIO", + newIPNode, "", + "", emptyIcon, true); - m->addDefinition(new NodeDefinition("RVUnsharpMask", 1, false, - "unsharpMask", - newIPNode, - "", "", emptyIcon, - true)); + def->declareProperty("defaults.function", "color"); + m->addDefinition(def); + } - m->addDefinition(new NodeDefinition("RVLookLUT", 1, false, - "look", - newIPNode, - "", "", emptyIcon, - false)); + { + NodeDefinition* def = new NodeDefinition( + "OCIODisplay", 1, false, "OCIODisplay", newIPNode, + "", "", emptyIcon, true); - m->addDefinition(new NodeDefinition("RVPrimaryConvert", 1, false, - "primaryConvert", - newIPNode, - "", "", emptyIcon, - true)); + def->declareProperty("defaults.function", + "display"); + m->addDefinition(def); + } + { + NodeDefinition* def = new NodeDefinition( + "OCIOLook", 1, false, "OCIOLook", newIPNode, "", "", + emptyIcon, true); - { - NodeDefinition* def = new NodeDefinition("OCIO", 1, false, - "OCIO", - newIPNode, - "", "", emptyIcon, - true); - - def->declareProperty("defaults.function", "color"); - m->addDefinition(def); - } + def->declareProperty("defaults.function", "look"); + m->addDefinition(def); + } - { - NodeDefinition* def = new NodeDefinition("OCIODisplay", 1, false, - "OCIODisplay", - newIPNode, - "", "", emptyIcon, - true); - - def->declareProperty("defaults.function", "display"); - m->addDefinition(def); - } + { + NodeDefinition* def = new NodeDefinition( + "OCIOFile", 1, false, "OCIOFile", newIPNode, "", "", + emptyIcon, true); - { - NodeDefinition* def = new NodeDefinition("OCIOLook", 1, false, - "OCIOLook", - newIPNode, - "", "", emptyIcon, - true); - - def->declareProperty("defaults.function", "look"); - m->addDefinition(def); - } + def->declareProperty("defaults.function", "color"); + m->addDefinition(def); + } - { - NodeDefinition* def = new NodeDefinition("OCIOFile", 1, false, - "OCIOFile", - newIPNode, - "", "", emptyIcon, - true); - - def->declareProperty("defaults.function", "color"); - m->addDefinition(def); - } + { + NodeDefinition* def = new NodeDefinition( + "SYNLinearize", 1, false, "sclin", newIPNode, "", + "", emptyIcon, true); - { - NodeDefinition* def = new NodeDefinition("SYNLinearize", 1, false, - "sclin", - newIPNode, - "", "", emptyIcon, - true); - - def->declareProperty("defaults.function", "synlinearize"); - m->addDefinition(def); - } + def->declareProperty("defaults.function", + "synlinearize"); + m->addDefinition(def); + } - { - NodeDefinition* def = new NodeDefinition("SYNDisplay", 1, false, - "scdsp", - newIPNode, - "", "", emptyIcon, - true); - - def->declareProperty("defaults.function", "syndisplay"); - m->addDefinition(def); - } + { + NodeDefinition* def = new NodeDefinition( + "SYNDisplay", 1, false, "scdsp", newIPNode, "", "", + emptyIcon, true); - m->addDefinition(new NodeDefinition("RVOverlay", 1, false, - "overlay", - newIPNode, - "", "", emptyIcon, - false)); + def->declareProperty("defaults.function", + "syndisplay"); + m->addDefinition(def); + } - m->addDefinition(new NodeDefinition("RVPaint", 3, false, - "paint", - newIPNode, - "", "", emptyIcon, - false)); + m->addDefinition(new NodeDefinition("RVOverlay", 1, false, "overlay", + newIPNode, "", "", + emptyIcon, false)); - m->addDefinition(new NodeDefinition("RVSequence", 1, false, - "sequence", - newIPNode, - "", "", emptyIcon, - false)); + m->addDefinition(new NodeDefinition("RVPaint", 3, false, "paint", + newIPNode, "", "", + emptyIcon, false)); - { - NodeDefinition* def = new NodeDefinition("RVSoundTrack", 1, false, - "soundTrack", - newIPNode, - "", "", emptyIcon, - false); - - // NOTE: differs from core SoundTrack - def->declareProperty("defaults.softClamp", 1); - m->addDefinition(def); - } + m->addDefinition(new NodeDefinition("RVSequence", 1, false, "sequence", + newIPNode, "", "", + emptyIcon, false)); - { - NodeDefinition* def = new NodeDefinition("RVSourceGroup", 1, true, - "sourceGroup", - newIPNode, - "", "", emptyIcon); - - def->declareProperty("defaults.preCacheLUTType", "RVCacheLUT"); - def->declareProperty("defaults.formatType", "RVFormat"); - def->declareProperty("defaults.channelMapType", "RVChannelMap"); - def->declareProperty("defaults.cacheType", "RVCache"); - def->declareProperty("defaults.paintType", "RVPaint"); - def->declareProperty("defaults.overlayType", "RVOverlay"); - def->declareProperty("defaults.colorPipelineType", "RVColorPipelineGroup"); - def->declareProperty("defaults.linearizePipelineType", "RVLinearizePipelineGroup"); - def->declareProperty("defaults.lookPipelineType", "RVLookPipelineGroup"); - def->declareProperty("defaults.stereoType", "RVSourceStereo"); - def->declareProperty("defaults.transformType", "RVTransform2D"); - def->declareProperty("defaults.cropType", ""); - m->addDefinition(def); - } + { + NodeDefinition* def = new NodeDefinition( + "RVSoundTrack", 1, false, "soundTrack", + newIPNode, "", "", emptyIcon, false); - m->addDefinition(new NodeDefinition("RVSourceStereo", 1, false, - "sourceStereo", - newIPNode, - "", "", emptyIcon, - false)); - - m->addDefinition(new NodeDefinition("RVStack", 1, false, - "stack", - newIPNode, - "", "", emptyIcon, - false)); - - m->addDefinition(new NodeDefinition("RVTransform2D", 1, false, - "transform2D", - newIPNode, - "", "", emptyIcon, - false)); - - m->addDefinition(new NodeDefinition("AudioWaveform", 1, false, - "audioWaveform", - newIPNode, - "", "", emptyIcon, - false)); - - m->addDefinition(new NodeDefinition("Dynamic", 1, true, - "dynamic", - newIPNode, - "", "", emptyIcon)); - -} - -void -setScaleOnAll(const IPGraph& graph, float scale) -{ - const IPGraph::NodeMap& nodeMap = graph.nodeMap(); + // NOTE: differs from core SoundTrack + def->declareProperty("defaults.softClamp", 1); + m->addDefinition(def); + } + + { + NodeDefinition* def = new NodeDefinition( + "RVSourceGroup", 1, true, "sourceGroup", + newIPNode, "", "", emptyIcon); + + def->declareProperty("defaults.preCacheLUTType", + "RVCacheLUT"); + def->declareProperty("defaults.formatType", + "RVFormat"); + def->declareProperty("defaults.channelMapType", + "RVChannelMap"); + def->declareProperty("defaults.cacheType", + "RVCache"); + def->declareProperty("defaults.paintType", + "RVPaint"); + def->declareProperty("defaults.overlayType", + "RVOverlay"); + def->declareProperty("defaults.colorPipelineType", + "RVColorPipelineGroup"); + def->declareProperty( + "defaults.linearizePipelineType", "RVLinearizePipelineGroup"); + def->declareProperty("defaults.lookPipelineType", + "RVLookPipelineGroup"); + def->declareProperty("defaults.stereoType", + "RVSourceStereo"); + def->declareProperty("defaults.transformType", + "RVTransform2D"); + def->declareProperty("defaults.cropType", ""); + m->addDefinition(def); + } + + m->addDefinition(new NodeDefinition( + "RVSourceStereo", 1, false, "sourceStereo", + newIPNode, "", "", emptyIcon, false)); + + m->addDefinition(new NodeDefinition("RVStack", 1, false, "stack", + newIPNode, "", "", + emptyIcon, false)); + + m->addDefinition(new NodeDefinition( + "RVTransform2D", 1, false, "transform2D", + newIPNode, "", "", emptyIcon, false)); + + m->addDefinition(new NodeDefinition( + "AudioWaveform", 1, false, "audioWaveform", + newIPNode, "", "", emptyIcon, false)); + + m->addDefinition(new NodeDefinition("Dynamic", 1, true, "dynamic", + newIPNode, "", "", + emptyIcon)); + } - for (IPGraph::NodeMap::const_iterator i = nodeMap.begin(); - i != nodeMap.end(); - ++i) + void setScaleOnAll(const IPGraph& graph, float scale) { - if (FormatIPNode* node = dynamic_cast((*i).second)) + const IPGraph::NodeMap& nodeMap = graph.nodeMap(); + + for (IPGraph::NodeMap::const_iterator i = nodeMap.begin(); + i != nodeMap.end(); ++i) { - if (FloatProperty* fp = - node->property("geometry", "scale")) + if (FormatIPNode* node = dynamic_cast((*i).second)) { - fp->front() = scale; + if (FloatProperty* fp = + node->property("geometry", "scale")) + { + fp->front() = scale; + } } } } -} - -void -setLogLinOnAll(const IPGraph& graph, bool val, int type) -{ - const IPGraph::NodeMap& nodeMap = graph.nodeMap(); - for (IPGraph::NodeMap::const_iterator i = nodeMap.begin(); - i != nodeMap.end(); - ++i) + void setLogLinOnAll(const IPGraph& graph, bool val, int type) { - if (FileSpaceLinearizeIPNode* node = dynamic_cast((*i).second)) + const IPGraph::NodeMap& nodeMap = graph.nodeMap(); + + for (IPGraph::NodeMap::const_iterator i = nodeMap.begin(); + i != nodeMap.end(); ++i) { - node->setLogLin(val ? type : 0); + if (FileSpaceLinearizeIPNode* node = + dynamic_cast((*i).second)) + { + node->setLogLin(val ? type : 0); + } } } -} -void -setSRGBLinOnAll(const IPGraph& graph, bool val) -{ - const IPGraph::NodeMap& nodeMap = graph.nodeMap(); - - for (IPGraph::NodeMap::const_iterator i = nodeMap.begin(); - i != nodeMap.end(); - ++i) + void setSRGBLinOnAll(const IPGraph& graph, bool val) { - if (FileSpaceLinearizeIPNode* node = dynamic_cast((*i).second)) + const IPGraph::NodeMap& nodeMap = graph.nodeMap(); + + for (IPGraph::NodeMap::const_iterator i = nodeMap.begin(); + i != nodeMap.end(); ++i) { - node->setSRGB(1); + if (FileSpaceLinearizeIPNode* node = + dynamic_cast((*i).second)) + { + node->setSRGB(1); + } } } -} -void -setRec709LinOnAll(const IPGraph& graph, bool val) -{ - const IPGraph::NodeMap& nodeMap = graph.nodeMap(); - - for (IPGraph::NodeMap::const_iterator i = nodeMap.begin(); - i != nodeMap.end(); - ++i) + void setRec709LinOnAll(const IPGraph& graph, bool val) { - if (FileSpaceLinearizeIPNode* node = dynamic_cast((*i).second)) + const IPGraph::NodeMap& nodeMap = graph.nodeMap(); + + for (IPGraph::NodeMap::const_iterator i = nodeMap.begin(); + i != nodeMap.end(); ++i) { - node->setRec709(1); + if (FileSpaceLinearizeIPNode* node = + dynamic_cast((*i).second)) + { + node->setRec709(1); + } } } -} - -void -setGammaOnAll(const IPGraph& graph, float gamma) -{ - const IPGraph::NodeMap& nodeMap = graph.nodeMap(); - for (IPGraph::NodeMap::const_iterator i = nodeMap.begin(); - i != nodeMap.end(); - ++i) + void setGammaOnAll(const IPGraph& graph, float gamma) { - if (ColorIPNode* node = dynamic_cast((*i).second)) + const IPGraph::NodeMap& nodeMap = graph.nodeMap(); + + for (IPGraph::NodeMap::const_iterator i = nodeMap.begin(); + i != nodeMap.end(); ++i) { - node->setGamma(gamma); + if (ColorIPNode* node = dynamic_cast((*i).second)) + { + node->setGamma(gamma); + } } } -} - -void -setFileGammaOnAll(const IPGraph& graph, float gamma) -{ - const IPGraph::NodeMap& nodeMap = graph.nodeMap(); - for (IPGraph::NodeMap::const_iterator i = nodeMap.begin(); - i != nodeMap.end(); - ++i) + void setFileGammaOnAll(const IPGraph& graph, float gamma) { - if (FileSpaceLinearizeIPNode* node = dynamic_cast((*i).second)) + const IPGraph::NodeMap& nodeMap = graph.nodeMap(); + + for (IPGraph::NodeMap::const_iterator i = nodeMap.begin(); + i != nodeMap.end(); ++i) { - node->setFileGamma(gamma); + if (FileSpaceLinearizeIPNode* node = + dynamic_cast((*i).second)) + { + node->setFileGamma(gamma); + } } } -} -void -setFileExposureOnAll(const IPGraph& graph, float e) -{ - const IPGraph::NodeMap& nodeMap = graph.nodeMap(); - - for (IPGraph::NodeMap::const_iterator i = nodeMap.begin(); - i != nodeMap.end(); - ++i) + void setFileExposureOnAll(const IPGraph& graph, float e) { - if (ColorIPNode* node = dynamic_cast((*i).second)) + const IPGraph::NodeMap& nodeMap = graph.nodeMap(); + + for (IPGraph::NodeMap::const_iterator i = nodeMap.begin(); + i != nodeMap.end(); ++i) { - node->setExposure(e); + if (ColorIPNode* node = dynamic_cast((*i).second)) + { + node->setExposure(e); + } } } -} -void -setFlipFlopOnAll(const IPGraph& graph, bool setFlip, bool flip, - bool setFlop, bool flop) -{ - const IPGraph::NodeMap& nodeMap = graph.nodeMap(); - - for (IPGraph::NodeMap::const_iterator i = nodeMap.begin(); - i != nodeMap.end(); - ++i) + void setFlipFlopOnAll(const IPGraph& graph, bool setFlip, bool flip, + bool setFlop, bool flop) { - if (Transform2DIPNode* node = dynamic_cast((*i).second)) + const IPGraph::NodeMap& nodeMap = graph.nodeMap(); + + for (IPGraph::NodeMap::const_iterator i = nodeMap.begin(); + i != nodeMap.end(); ++i) { - if (setFlip) node->setFlip(flip); - if (setFlop) node->setFlop(flop); + if (Transform2DIPNode* node = + dynamic_cast((*i).second)) + { + if (setFlip) + node->setFlip(flip); + if (setFlop) + node->setFlop(flop); + } } } -} - -void -setChannelMapOnAll(const IPGraph& graph, const vector& chmap) -{ - const IPGraph::NodeMap& nodeMap = graph.nodeMap(); - for (IPGraph::NodeMap::const_iterator i = nodeMap.begin(); - i != nodeMap.end(); - ++i) + void setChannelMapOnAll(const IPGraph& graph, const vector& chmap) { - if (ChannelMapIPNode* node = dynamic_cast((*i).second)) - { - node->setChannelMap(chmap); - } + const IPGraph::NodeMap& nodeMap = graph.nodeMap(); - if (FileSourceIPNode* node = dynamic_cast((*i).second)) + for (IPGraph::NodeMap::const_iterator i = nodeMap.begin(); + i != nodeMap.end(); ++i) { - node->setReadAllChannels(true); + if (ChannelMapIPNode* node = + dynamic_cast((*i).second)) + { + node->setChannelMap(chmap); + } + + if (FileSourceIPNode* node = + dynamic_cast((*i).second)) + { + node->setReadAllChannels(true); + } } } -} - -void -fitAllInputs(const IPGraph& graph, int w, int h) -{ - const IPGraph::NodeMap& nodeMap = graph.nodeMap(); - - for (IPGraph::NodeMap::const_iterator i = nodeMap.begin(); - i != nodeMap.end(); - ++i) + void fitAllInputs(const IPGraph& graph, int w, int h) { - if (FormatIPNode* node = dynamic_cast((*i).second)) + const IPGraph::NodeMap& nodeMap = graph.nodeMap(); + + for (IPGraph::NodeMap::const_iterator i = nodeMap.begin(); + i != nodeMap.end(); ++i) { - node->setFitResolution(w, h); + if (FormatIPNode* node = dynamic_cast((*i).second)) + { + node->setFitResolution(w, h); + } } } -} -void -resizeAllInputs(const IPGraph& graph, int w, int h) -{ - const IPGraph::NodeMap& nodeMap = graph.nodeMap(); - - for (IPGraph::NodeMap::const_iterator i = nodeMap.begin(); - i != nodeMap.end(); - ++i) + void resizeAllInputs(const IPGraph& graph, int w, int h) { - if (FormatIPNode* node = dynamic_cast((*i).second)) + const IPGraph::NodeMap& nodeMap = graph.nodeMap(); + + for (IPGraph::NodeMap::const_iterator i = nodeMap.begin(); + i != nodeMap.end(); ++i) { - node->setResizeResolution(w, h); + if (FormatIPNode* node = dynamic_cast((*i).second)) + { + node->setResizeResolution(w, h); + } } } -} -} // Rv +} // namespace Rv diff --git a/src/lib/app/RvApp/RvSession.cpp b/src/lib/app/RvApp/RvSession.cpp index 9b4eb2663..b7a8dd11c 100644 --- a/src/lib/app/RvApp/RvSession.cpp +++ b/src/lib/app/RvApp/RvSession.cpp @@ -1,9 +1,9 @@ // // Copyright (c) 2012 Tweak Software. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// // #include #include @@ -92,9 +92,7 @@ #include - -template -inline T mod( const T &a, const T &by ) +template inline T mod(const T& a, const T& by) { T rem = a % by; return rem < T(0) ? rem + by : rem; @@ -105,3941 +103,4194 @@ inline T mod( const T &a, const T &by ) // float worstFpsError = 0.0; -namespace Rv { +namespace Rv +{ #if 0 -#define DB_GENERAL 0x01 -#define DB_EDGES 0x02 -#define DB_ALL 0xff +#define DB_GENERAL 0x01 +#define DB_EDGES 0x02 +#define DB_ALL 0xff // #define DB_LEVEL (DB_ALL & (~ DB_EDGES)) -#define DB_LEVEL DB_ALL - -#define DB(x) if (DB_GENERAL & DB_LEVEL) cerr << "Session: " << x << endl -#define DBL(level, x) if (level & DB_LEVEL) cerr << "Session: " << x << endl +#define DB_LEVEL DB_ALL + +#define DB(x) \ + if (DB_GENERAL & DB_LEVEL) \ + cerr << "Session: " << x << endl +#define DBL(level, x) \ + if (level & DB_LEVEL) \ + cerr << "Session: " << x << endl #else #define DB(x) #define DBL(level, x) #endif -using namespace TwkMovie; -using namespace TwkMath; -using namespace TwkApp; -using namespace TwkUtil; -using namespace TwkContainer; -using namespace Mu; -using namespace std; -using namespace IPCore; -using namespace boost; + using namespace TwkMovie; + using namespace TwkMath; + using namespace TwkApp; + using namespace TwkUtil; + using namespace TwkContainer; + using namespace Mu; + using namespace std; + using namespace IPCore; + using namespace boost; -std::string RvSession::m_initEval; -std::string RvSession::m_pyInitEval; + std::string RvSession::m_initEval; + std::string RvSession::m_pyInitEval; -static RegEx oldContainerNameRE("^([a-zA-Z0-9]+[^0-9])([0-9][0-9][0-9])$"); -static bool debugGC = false; -static std::string defaultSequenceSequenceIPNodeName("defaultSequence_sequence"); + static RegEx oldContainerNameRE("^([a-zA-Z0-9]+[^0-9])([0-9][0-9][0-9])$"); + static bool debugGC = false; + static std::string + defaultSequenceSequenceIPNodeName("defaultSequence_sequence"); -static ENVVAR_BOOL( evUseSequenceEventsTracking, "RV_USE_SEQUENCE_EVENTS_TRACKING", true ); + static ENVVAR_BOOL(evUseSequenceEventsTracking, + "RV_USE_SEQUENCE_EVENTS_TRACKING", true); -namespace { -static bool firstTime = true; + namespace + { + static bool firstTime = true; -bool -checkForDirFiles(string filename, bool noSeq, SequenceNameList* files) -{ + bool checkForDirFiles(string filename, bool noSeq, + SequenceNameList* files) + { #ifdef PLATFORM_WINDOWS - if (filename.size() && filename[filename.size() - 1] == '/') - { - filename.erase(filename.size() - 1, 1); - } + if (filename.size() && filename[filename.size() - 1] == '/') + { + filename.erase(filename.size() - 1, 1); + } #endif #ifdef _MSC_VER - struct _stat64 sb; + struct _stat64 sb; #else - struct stat sb; + struct stat sb; #endif - memset(&sb, 0, sizeof(sb)); - int err = TwkUtil::stat(filename.c_str(), &sb); + memset(&sb, 0, sizeof(sb)); + int err = TwkUtil::stat(filename.c_str(), &sb); - bool isDir = false; - if (!err && sb.st_mode & S_IFDIR) - // - // Pattern is a directory, so unpack possibly into multiple - // sources (or multiple layers) here. - // - { - isDir = true; - SequenceNameList seqs = sequencesInDirectory(filename, - noSeq ? FalseSequencePredicate : GlobalExtensionPredicate); + bool isDir = false; + if (!err && sb.st_mode & S_IFDIR) + // + // Pattern is a directory, so unpack possibly into multiple + // sources (or multiple layers) here. + // + { + isDir = true; + SequenceNameList seqs = sequencesInDirectory( + filename, + noSeq ? FalseSequencePredicate : GlobalExtensionPredicate); - for (int i=0; i < seqs.size(); i++) - { - if (seqs[i][0] == '.') continue; - string fullname = filename + "/" + seqs[i]; - files->push_back(fullname); - } - } - else files->push_back(filename); + for (int i = 0; i < seqs.size(); i++) + { + if (seqs[i][0] == '.') + continue; + string fullname = filename + "/" + seqs[i]; + files->push_back(fullname); + } + } + else + files->push_back(filename); - return isDir; -} + return isDir; + } -// Returns true if the specified source arguments has initialized (non default) -// cut points. Otherwise returns false. -bool hasCutPoints(const Options::SourceArgs& sargs) -{ - // Note that the default cutIn is initialized with either plus or minus - // numeric_limits::max() depending on where it is initialized - // cutOut on the other hand is always initialized with the plus version. - return sargs.cutIn!=-numeric_limits::max() && - sargs.cutIn!=numeric_limits::max() && - sargs.cutOut!=numeric_limits::max(); -} + // Returns true if the specified source arguments has initialized (non + // default) cut points. Otherwise returns false. + bool hasCutPoints(const Options::SourceArgs& sargs) + { + // Note that the default cutIn is initialized with either plus or + // minus numeric_limits::max() depending on where it is + // initialized cutOut on the other hand is always initialized with + // the plus version. + return sargs.cutIn != -numeric_limits::max() + && sargs.cutIn != numeric_limits::max() + && sargs.cutOut != numeric_limits::max(); + } -} // empty namespace - -RvSession::RvSession() - : Session(new RvGraph(IPCore::Application::instance()->nodeManager())), - m_loadingError(false), - m_data(0), - m_pydata(0), - m_callEnv(new TwkApp::CallEnv(this)), - m_loadState(0), - m_gtoSourceCount(0), - m_gtoSourceTotal(0), - m_userHasSetViewSize(false), - m_conductorSource(nullptr) -{ - Options& opts = Options::sharedOptions(); - m_realtime = (opts.playMode == 2); - m_playMode = static_cast(opts.loopMode); + } // namespace - if (firstTime) + RvSession::RvSession() + : Session(new RvGraph(IPCore::Application::instance()->nodeManager())) + , m_loadingError(false) + , m_data(0) + , m_pydata(0) + , m_callEnv(new TwkApp::CallEnv(this)) + , m_loadState(0) + , m_gtoSourceCount(0) + , m_gtoSourceTotal(0) + , m_userHasSetViewSize(false) + , m_conductorSource(nullptr) { - // - // Initialize nodes here -- at this point we know that GL has - // been initialized which is currently required for node - // initialization. - // - - IPCore::Application::setOptionValueFromEnvironment("nodePath", "TWK_NODE_PLUGIN_PATH"); - IPCore::Application::setOptionValueFromEnvironment("nodeDefinitionOverride", "TWK_NODE_DEFINITION_OVERRIDE"); - addRvNodeDefinitions(IPCore::Application::instance()->nodeManager()); - IPCore::Application::instance()->loadOptionNodeDefinitions(); - firstTime = false; - } - - m_mediaLoadingSetEmptyConnection = graph().mediaLoadingSetEmptySignal().connect(boost::bind(&RvSession::onGraphMediaSetEmpty, this)); + Options& opts = Options::sharedOptions(); + m_realtime = (opts.playMode == 2); + m_playMode = static_cast(opts.loopMode); - // register the signal to detecting removing of node in the graphe - m_nodeWillRemoveConnection = graph().nodeWillRemoveSignal().connect(boost::bind(&RvSession::onGraphNodeWillRemove, this, std::placeholders::_1)); + if (firstTime) + { + // + // Initialize nodes here -- at this point we know that GL has + // been initialized which is currently required for node + // initialization. + // - // - // register the signal to detect fastAddSourceEnabled in the graphe - auto rvGraph = dynamic_cast(&graph()); - if (rvGraph) - m_fastAddSourceChangedConnection = rvGraph->fastAddSourceChangedSignal().connect(boost::bind(&RvSession::onGraphFastAddSourceChanged, this, std::placeholders::_1, std::placeholders::_2)); + IPCore::Application::setOptionValueFromEnvironment( + "nodePath", "TWK_NODE_PLUGIN_PATH"); + IPCore::Application::setOptionValueFromEnvironment( + "nodeDefinitionOverride", "TWK_NODE_DEFINITION_OVERRIDE"); + addRvNodeDefinitions( + IPCore::Application::instance()->nodeManager()); + IPCore::Application::instance()->loadOptionNodeDefinitions(); + firstTime = false; + } - graph().clear(); + m_mediaLoadingSetEmptyConnection = + graph().mediaLoadingSetEmptySignal().connect( + boost::bind(&RvSession::onGraphMediaSetEmpty, this)); - if (getenv("RV_DEBUG_GC")) debugGC = true; + // register the signal to detecting removing of node in the graphe + m_nodeWillRemoveConnection = graph().nodeWillRemoveSignal().connect( + boost::bind(&RvSession::onGraphNodeWillRemove, this, + std::placeholders::_1)); - applyRvSessionSpecificOptions(); -} + // + // register the signal to detect fastAddSourceEnabled in the graphe + auto rvGraph = dynamic_cast(&graph()); + if (rvGraph) + m_fastAddSourceChangedConnection = + rvGraph->fastAddSourceChangedSignal().connect( + boost::bind(&RvSession::onGraphFastAddSourceChanged, this, + std::placeholders::_1, std::placeholders::_2)); -RvSession::~RvSession() -{ - m_fastAddSourceChangedConnection.disconnect(); - m_mediaLoadingSetEmptyConnection.disconnect(); - m_nodeWillRemoveConnection.disconnect(); + graph().clear(); - if (m_data) m_data->releaseExternal(); - m_data = 0; + if (getenv("RV_DEBUG_GC")) + debugGC = true; - // - // Force a GC so we can hopefully remove any unwanted objects - // + applyRvSessionSpecificOptions(); + } - Mu::GarbageCollector::collect(); + RvSession::~RvSession() + { + m_fastAddSourceChangedConnection.disconnect(); + m_mediaLoadingSetEmptyConnection.disconnect(); + m_nodeWillRemoveConnection.disconnect(); - // - // Same with python - // + if (m_data) + m_data->releaseExternal(); + m_data = 0; - disposeOfPythonObject(m_pydata); + // + // Force a GC so we can hopefully remove any unwanted objects + // - // - // let the scripting stuff leak. There are timing issues with - // deletion. Hopefully at this point its all gone anyway. - // + Mu::GarbageCollector::collect(); - ((TwkApp::CallEnv*)m_callEnv)->invalidate(); - //delete m_callEnv; -} + // + // Same with python + // -void -RvSession::makeActive() -{ - Session::m_currentSession = this; - muProcess()->setCallEnv(m_callEnv); - Session::makeActive(); -} + disposeOfPythonObject(m_pydata); + // + // let the scripting stuff leak. There are timing issues with + // deletion. Hopefully at this point its all gone anyway. + // -void -RvSession::clear() -{ - Session::clear(); - m_loadingErrorString = ""; - m_loadingError = false; - m_conductorSource = nullptr; - m_sequenceIPNode = nullptr; + ((TwkApp::CallEnv*)m_callEnv)->invalidate(); + // delete m_callEnv; + } - if (!m_beingDeleted) + void RvSession::makeActive() { - applyRvSessionSpecificOptions(); + Session::m_currentSession = this; + muProcess()->setCallEnv(m_callEnv); + Session::makeActive(); } -} -void -RvSession::render() -{ - Session::render(); - - try + void RvSession::clear() { - continueLoading(); + Session::clear(); + m_loadingErrorString = ""; + m_loadingError = false; + m_conductorSource = nullptr; + m_sequenceIPNode = nullptr; + + if (!m_beingDeleted) + { + applyRvSessionSpecificOptions(); + } } - catch (const std::exception& exc) + + void RvSession::render() { - cerr << "ERROR: " << exc.what() << endl; + Session::render(); + + try + { + continueLoading(); + } + catch (const std::exception& exc) + { + cerr << "ERROR: " << exc.what() << endl; + } + catch (...) + { + cerr << "ERROR: Unknown Exception" << endl; + } } - catch (...) + + void RvSession::applyRvSessionSpecificOptions() { - cerr << "ERROR: Unknown Exception" << endl; - } -} + Options& opts = Options::sharedOptions(); -void -RvSession::applyRvSessionSpecificOptions() -{ - Options& opts = Options::sharedOptions(); + if (opts.noSequence) + m_noSequences = true; + if (opts.scale != 1.0) + setScaleOnAll(opts.scale); + setFPS(opts.defaultfps); + if (opts.fullscreen) + fullScreenMode(true); + setRendererType("Composite"); - if (opts.noSequence) m_noSequences = true; - if (opts.scale != 1.0) setScaleOnAll(opts.scale); - setFPS(opts.defaultfps); - if (opts.fullscreen) fullScreenMode(true); - setRendererType("Composite"); + if (opts.readerThreads > 0 && opts.readerThreads <= 32) + { + graph().setNumEvalThreads(opts.readerThreads); + } - if (opts.readerThreads > 0 && - opts.readerThreads <= 32) - { - graph().setNumEvalThreads(opts.readerThreads); + if (!strcmp(opts.sessionType, "sequence")) + { + setSessionType(SequenceSession); + } + else if (!strcmp(opts.sessionType, "stack")) + { + setSessionType(StackSession); + } + + setGlobalAudioOffset(opts.audioGlobalOffset); + setGlobalSwapEyes(opts.stereoSwapEyes != 0); + + m_muFlags = opts.muFlags; } - if (!strcmp(opts.sessionType, "sequence")) + std::string RvSession::lookupMuFlag(std::string key) { - setSessionType(SequenceSession); + StringMap::iterator i = m_muFlags.find(key); + if (i == m_muFlags.end()) + return ""; + else + return i->second; } - else if (!strcmp(opts.sessionType, "stack")) + + class LoadState { - setSessionType(StackSession); - } + public: + LoadState(RvSession* s, Options::SourceArgsVector& sav, bool noSeq, + bool dpo, bool mg, string tg); - setGlobalAudioOffset(opts.audioGlobalOffset); - setGlobalSwapEyes(opts.stereoSwapEyes != 0); + bool isLoading() + { + return (!m_sav.empty() && m_savIndex < m_sav.size()); + } - m_muFlags = opts.muFlags; -} + int loadCount() { return isLoading() ? m_loadCount : 0; } + int loadTotal() { return m_totalCount; } -std::string -RvSession::lookupMuFlag(std::string key) -{ - StringMap::iterator i = m_muFlags.find(key); - if (i == m_muFlags.end()) return ""; - else return i->second; -} + void storeCacheMode(RvSession::CachingMode m) { m_cacheMode = m; } + RvSession::CachingMode cacheMode() { return m_cacheMode; } + bool doProcessOpts() { return m_doProcessOpts; } -class LoadState -{ - public: - LoadState( - RvSession* s, - Options::SourceArgsVector& sav, - bool noSeq, - bool dpo, - bool mg, - string tg); - - bool isLoading() { return (!m_sav.empty() && m_savIndex < m_sav.size()); } - int loadCount() { return isLoading() ? m_loadCount : 0; } - int loadTotal() { return m_totalCount; } - void storeCacheMode(RvSession::CachingMode m) - { m_cacheMode = m; } - RvSession::CachingMode - cacheMode() { return m_cacheMode; } - bool doProcessOpts() { return m_doProcessOpts; } - bool merge() { return m_merge; } - string tag() { return m_tag; } - IPCore::ReadFailedExc& readExc() { return m_rexc; } - int numSourcesRead() { return (m_session->sources().size() - m_nPreexistingSources); } - int lastLoadedIndex() { return m_lastLoadedSourceIndex; } - - bool timeToLoad(); - void nextPattern (string& pattern, Options::SourceArgs& sargs, bool& addLayer); - bool nextPatternIsLayer (Options::SourceArgs& sargs) - { return (m_perSourceIndex != 0 && sargs.singleSource); } - - private: - RvSession* m_session; - Options::SourceArgsVector m_sav; - int m_savIndex; - int m_tryCount; - vector m_perSourcePatterns; - int m_perSourceIndex; - int m_loadCount; - int m_totalCount; - RvSession::CachingMode m_cacheMode; - bool m_doProcessOpts; - bool m_merge; - string m_tag; - IPCore::ReadFailedExc m_rexc; - int m_nPreexistingSources; - int m_lastLoadedSourceIndex; -}; - -LoadState::LoadState ( - RvSession* s, - Options::SourceArgsVector &sav, - bool noSeq, - bool dpo, - bool mg, - string tg) : - m_session(s), - m_sav(sav), - m_savIndex(0), - m_perSourceIndex(0), - m_lastLoadedSourceIndex(0), - m_tryCount(0), - m_loadCount(0), - m_totalCount(0), - m_cacheMode(RvSession::NeverCache), - m_doProcessOpts(dpo), - m_merge(mg), - m_tag(tg), - m_rexc("") -{ - m_nPreexistingSources = m_session->sources().size(); + bool merge() { return m_merge; } - for (int q = 0; q < m_sav.size(); q++) - { - const Options::SourceArgs& sargs = m_sav[q]; - const Options::Files& files = sargs.files; - SequenceNameList inputPatterns, inputPatternsOrig = sequencesInFileList(files, - noSeq ? FalseSequencePredicate : GlobalExtensionPredicate); + string tag() { return m_tag; } - // - // Need to check for directories - // + IPCore::ReadFailedExc& readExc() { return m_rexc; } + + int numSourcesRead() + { + return (m_session->sources().size() - m_nPreexistingSources); + } + + int lastLoadedIndex() { return m_lastLoadedSourceIndex; } + + bool timeToLoad(); + void nextPattern(string& pattern, Options::SourceArgs& sargs, + bool& addLayer); + + bool nextPatternIsLayer(Options::SourceArgs& sargs) + { + return (m_perSourceIndex != 0 && sargs.singleSource); + } - for (int p = 0; p < inputPatternsOrig.size(); ++p) + private: + RvSession* m_session; + Options::SourceArgsVector m_sav; + int m_savIndex; + int m_tryCount; + vector m_perSourcePatterns; + int m_perSourceIndex; + int m_loadCount; + int m_totalCount; + RvSession::CachingMode m_cacheMode; + bool m_doProcessOpts; + bool m_merge; + string m_tag; + IPCore::ReadFailedExc m_rexc; + int m_nPreexistingSources; + int m_lastLoadedSourceIndex; + }; + + LoadState::LoadState(RvSession* s, Options::SourceArgsVector& sav, + bool noSeq, bool dpo, bool mg, string tg) + : m_session(s) + , m_sav(sav) + , m_savIndex(0) + , m_perSourceIndex(0) + , m_lastLoadedSourceIndex(0) + , m_tryCount(0) + , m_loadCount(0) + , m_totalCount(0) + , m_cacheMode(RvSession::NeverCache) + , m_doProcessOpts(dpo) + , m_merge(mg) + , m_tag(tg) + , m_rexc("") + { + m_nPreexistingSources = m_session->sources().size(); + + for (int q = 0; q < m_sav.size(); q++) { - string filename = inputPatternsOrig[p]; - bool isDir = checkForDirFiles(filename, noSeq, &inputPatterns); + const Options::SourceArgs& sargs = m_sav[q]; + const Options::Files& files = sargs.files; + SequenceNameList inputPatterns, + inputPatternsOrig = sequencesInFileList( + files, + noSeq ? FalseSequencePredicate : GlobalExtensionPredicate); // - // If the directory contained no media, use informative but - // non-existent name and itself and let it explode later. + // Need to check for directories // - if (isDir && inputPatterns.size() == 0) + + for (int p = 0; p < inputPatternsOrig.size(); ++p) { - string fullname = filename + "/" + "emptyDirectory"; - inputPatterns.push_back(fullname); + string filename = inputPatternsOrig[p]; + bool isDir = checkForDirFiles(filename, noSeq, &inputPatterns); + + // + // If the directory contained no media, use informative but + // non-existent name and itself and let it explode later. + // + if (isDir && inputPatterns.size() == 0) + { + string fullname = filename + "/" + "emptyDirectory"; + inputPatterns.push_back(fullname); + } } - } - m_perSourcePatterns.push_back(inputPatterns); - m_totalCount += inputPatterns.size(); + m_perSourcePatterns.push_back(inputPatterns); + m_totalCount += inputPatterns.size(); + } } -} -bool -LoadState::timeToLoad() -{ - if (!isLoading()) return false; - - bool ret = (m_loadCount == 0) ? (m_tryCount == 3) : (m_tryCount % 2 == 1); - ++m_tryCount; - - return ret; -} - -void -LoadState::nextPattern (string& pattern, Options::SourceArgs& sargs, bool& addLayer) -{ - sargs = m_sav[m_savIndex]; - addLayer = m_perSourceIndex != 0 && sargs.singleSource; - m_lastLoadedSourceIndex = m_perSourceIndex; + bool LoadState::timeToLoad() + { + if (!isLoading()) + return false; - SequenceNameList& patterns = m_perSourcePatterns[m_savIndex]; - pattern = patterns[m_perSourceIndex++]; + bool ret = + (m_loadCount == 0) ? (m_tryCount == 3) : (m_tryCount % 2 == 1); + ++m_tryCount; - if (m_perSourceIndex >= patterns.size()) - { - ++m_savIndex; - m_perSourceIndex = 0; + return ret; } - ++m_loadCount; -} + void LoadState::nextPattern(string& pattern, Options::SourceArgs& sargs, + bool& addLayer) + { + sargs = m_sav[m_savIndex]; + addLayer = m_perSourceIndex != 0 && sargs.singleSource; + m_lastLoadedSourceIndex = m_perSourceIndex; -int -RvSession::loadCount() -{ - return m_readingGTO ? m_gtoSourceCount : (m_loadState ? m_loadState->loadCount() : 0); -} + SequenceNameList& patterns = m_perSourcePatterns[m_savIndex]; + pattern = patterns[m_perSourceIndex++]; -int -RvSession::loadTotal() -{ - return m_readingGTO ? m_gtoSourceTotal : (m_loadState ? m_loadState->loadTotal() : 0); -} + if (m_perSourceIndex >= patterns.size()) + { + ++m_savIndex; + m_perSourceIndex = 0; + } -void -RvSession::continueLoading() -{ - if (!m_loadState || !m_loadState->timeToLoad() || m_readingGTO) return; + ++m_loadCount; + } - HOP_ZONE( HOP_ZONE_COLOR_10 ); - HOP_PROF_FUNC(); + int RvSession::loadCount() + { + return m_readingGTO ? m_gtoSourceCount + : (m_loadState ? m_loadState->loadCount() : 0); + } - // - // If we're caching at the moment, turn it off, but remember what mode - // it is so we can turn it back on later. - // - if (m_cacheMode != NeverCache) + int RvSession::loadTotal() { - m_loadState->storeCacheMode(m_cacheMode); - setCaching(NeverCache); + return m_readingGTO ? m_gtoSourceTotal + : (m_loadState ? m_loadState->loadTotal() : 0); } - // - // On the other hand, if the session is empty, remember the preferred - // caching mode and turn _that_ on later. - // - if (sources().empty()) + + void RvSession::continueLoading() { - Options& opts = Options::sharedOptions(); + if (!m_loadState || !m_loadState->timeToLoad() || m_readingGTO) + return; - if (opts.useCache) m_loadState->storeCacheMode(RvSession::GreedyCache); - else if (opts.useLCache) m_loadState->storeCacheMode(RvSession::BufferCache); - } + HOP_ZONE(HOP_ZONE_COLOR_10); + HOP_PROF_FUNC(); + + // + // If we're caching at the moment, turn it off, but remember what mode + // it is so we can turn it back on later. + // + if (m_cacheMode != NeverCache) + { + m_loadState->storeCacheMode(m_cacheMode); + setCaching(NeverCache); + } + // + // On the other hand, if the session is empty, remember the preferred + // caching mode and turn _that_ on later. + // + if (sources().empty()) + { + Options& opts = Options::sharedOptions(); - string pattern; - Options::SourceArgs sargs; - bool addLayer = false; + if (opts.useCache) + m_loadState->storeCacheMode(RvSession::GreedyCache); + else if (opts.useLCache) + m_loadState->storeCacheMode(RvSession::BufferCache); + } - m_loadState->nextPattern (pattern, sargs, addLayer); - const char *file = pattern.c_str(); + string pattern; + Options::SourceArgs sargs; + bool addLayer = false; - int oldFrame = currentFrame(); + m_loadState->nextPattern(pattern, sargs, addLayer); + const char* file = pattern.c_str(); - SourceIPNode* node = 0; - try - { - readSource(file, sargs, true, addLayer, m_loadState->tag(), m_loadState->merge()); + int oldFrame = currentFrame(); - cout << "INFO: " - << ((addLayer) ? "+ " : "") - << file << endl; - } - catch (TwkExc::Exception& exc) - { - m_loadState->readExc() << exc.str() - << " (" << m_loadState->lastLoadedIndex() << ") " - << endl; - } - catch (std::exception& exc) - { - m_loadState->readExc() << exc.what() - << " while reading " - << file - << " (" << m_loadState->lastLoadedIndex() << ") " - << endl; - } - catch (...) - { - m_loadState->readExc() << "Unknown Exception while reading " << file - << " (" << m_loadState->lastLoadedIndex() << ") " + SourceIPNode* node = 0; + try + { + readSource(file, sargs, true, addLayer, m_loadState->tag(), + m_loadState->merge()); + + cout << "INFO: " << ((addLayer) ? "+ " : "") << file << endl; + } + catch (TwkExc::Exception& exc) + { + m_loadState->readExc() + << exc.str() << " (" << m_loadState->lastLoadedIndex() << ") " << endl; - } + } + catch (std::exception& exc) + { + m_loadState->readExc() + << exc.what() << " while reading " << file << " (" + << m_loadState->lastLoadedIndex() << ") " << endl; + } + catch (...) + { + m_loadState->readExc() + << "Unknown Exception while reading " << file << " (" + << m_loadState->lastLoadedIndex() << ") " << endl; + } - setViewNode(viewNodeName()); - askForRedraw(); + setViewNode(viewNodeName()); + askForRedraw(); - if (m_loadState->isLoading()) - { - setFrameInternal(oldFrame); - } - else - { - if (m_loadState->loadTotal() > 1) + if (m_loadState->isLoading()) { - rvgraph().addSourceEnd(); + setFrameInternal(oldFrame); } + else + { + if (m_loadState->loadTotal() > 1) + { + rvgraph().addSourceEnd(); + } - IPCore::ReadFailedExc rexc = m_loadState->readExc(); - int numRead = m_loadState->numSourcesRead(); - bool doProcessOpts = m_loadState->doProcessOpts(); - CachingMode mode = m_loadState->cacheMode(); + IPCore::ReadFailedExc rexc = m_loadState->readExc(); + int numRead = m_loadState->numSourcesRead(); + bool doProcessOpts = m_loadState->doProcessOpts(); + CachingMode mode = m_loadState->cacheMode(); - delete m_loadState; - m_loadState = 0; + delete m_loadState; + m_loadState = 0; - if (mode != NeverCache) setCaching(mode); + if (mode != NeverCache) + setCaching(mode); - if (doProcessOpts) processOptionsAfterSourcesLoaded(rexc.str() != ""); + if (doProcessOpts) + processOptionsAfterSourcesLoaded(rexc.str() != ""); - // Note: It was decided to trigger the after-progressive-proxy-loading - // event even when progressive source loading is disabled - userGenericEvent("after-progressive-proxy-loading", ""); + // Note: It was decided to trigger the + // after-progressive-proxy-loading event even when progressive + // source loading is disabled + userGenericEvent("after-progressive-proxy-loading", ""); - // We delay the after-progressive-loading event after all the sources are loaded - if (!m_graph->isMediaLoading()) - userGenericEvent("after-progressive-loading", ""); + // We delay the after-progressive-loading event after all the + // sources are loaded + if (!m_graph->isMediaLoading()) + userGenericEvent("after-progressive-loading", ""); - if (rexc.str() != "") - { - if (numRead == 0) + if (rexc.str() != "") { - m_loadingError = true; - m_loadingErrorString = rexc.str(); - TWK_THROW_STREAM(AllReadFailedExc, rexc.str()); + if (numRead == 0) + { + m_loadingError = true; + m_loadingErrorString = rexc.str(); + TWK_THROW_STREAM(AllReadFailedExc, rexc.str()); + } + else + throw rexc; } - else throw rexc; } } -} -void -RvSession::readUnorganizedFileList(const StringVector& infiles, - bool doProcessOpts, - bool merge, - const string& tag) -{ - int rvFileCount = 0; - for (int i = 0; i < infiles.size(); ++i) if (string(extension(infiles[i])) == "rv") ++rvFileCount; + void RvSession::readUnorganizedFileList(const StringVector& infiles, + bool doProcessOpts, bool merge, + const string& tag) + { + int rvFileCount = 0; + for (int i = 0; i < infiles.size(); ++i) + if (string(extension(infiles[i])) == "rv") + ++rvFileCount; - if (rvFileCount > 1) merge = true; + if (rvFileCount > 1) + merge = true; - // PROGLOAD this func should take tag for when called from mu - Options::SourceArgsVector insources = Options::sharedOptions().parseSourceArgs(infiles); + // PROGLOAD this func should take tag for when called from mu + Options::SourceArgsVector insources = + Options::sharedOptions().parseSourceArgs(infiles); - int nexisting = sources().size(); + int nexisting = sources().size(); - // - // NOTE: the exception is created but will not be used unless an - // error occurs. Each round of reading results in another line of - // exception message being appended to the exception stream - // + // + // NOTE: the exception is created but will not be used unless an + // error occurs. Each round of reading results in another line of + // exception message being appended to the exception stream + // - IPCore::ReadFailedExc rexc(""); - m_loadingError = false; - int group = 0; - int item = 0; + IPCore::ReadFailedExc rexc(""); + m_loadingError = false; + int group = 0; + int item = 0; - if (Options::sharedOptions().delaySessionLoading) - { - if (!insources.empty()) + if (Options::sharedOptions().delaySessionLoading) { - if (m_loadState) cerr << "ERROR: already have load state!\n" << endl; - m_loadState = new LoadState(this, insources, m_noSequences, doProcessOpts, merge, tag); - - if (m_loadState->loadTotal() > 1) + if (!insources.empty()) { - rvgraph().addSourceBegin(); - } + if (m_loadState) + cerr << "ERROR: already have load state!\n" << endl; + m_loadState = new LoadState(this, insources, m_noSequences, + doProcessOpts, merge, tag); - userGenericEvent("before-progressive-loading", ""); + if (m_loadState->loadTotal() > 1) + { + rvgraph().addSourceBegin(); + } - // Note: It was decided to trigger the before-progressive-proxy-loading - // event even when progressive source loading is disabled - userGenericEvent("before-progressive-proxy-loading", ""); - } - else if (doProcessOpts) - { - processOptionsAfterSourcesLoaded(); - setViewNode(viewNodeName(), true); + userGenericEvent("before-progressive-loading", ""); + + // Note: It was decided to trigger the + // before-progressive-proxy-loading event even when progressive + // source loading is disabled + userGenericEvent("before-progressive-proxy-loading", ""); + } + else if (doProcessOpts) + { + processOptionsAfterSourcesLoaded(); + setViewNode(viewNodeName(), true); + } } - } - else - { - for (int q=0; q < insources.size(); q++) + else { - Options::SourceArgs& sargs = insources[q]; - const Options::Files& files = sargs.files; - SequenceNameList inputPatterns = sequencesInFileList(files, - m_noSequences ? FalseSequencePredicate : GlobalExtensionPredicate); - - for (int i=0; i < inputPatterns.size(); i++) + for (int q = 0; q < insources.size(); q++) { - const char *file = inputPatterns[i].c_str(); + Options::SourceArgs& sargs = insources[q]; + const Options::Files& files = sargs.files; + SequenceNameList inputPatterns = sequencesInFileList( + files, m_noSequences ? FalseSequencePredicate + : GlobalExtensionPredicate); - try + for (int i = 0; i < inputPatterns.size(); i++) { - bool addLayer = i != 0 && sargs.singleSource; + const char* file = inputPatterns[i].c_str(); + + try + { + bool addLayer = i != 0 && sargs.singleSource; - readSource(file, sargs, true, addLayer, "", merge); + readSource(file, sargs, true, addLayer, "", merge); - cout << "INFO: " - << ((addLayer) ? "+ " : "") - << inputPatterns[i] << endl; - } - catch (TwkExc::Exception& exc) - { - rexc << exc.str() << " (" << i << ") " << endl; + cout << "INFO: " << ((addLayer) ? "+ " : "") + << inputPatterns[i] << endl; + } + catch (TwkExc::Exception& exc) + { + rexc << exc.str() << " (" << i << ") " << endl; + } + catch (std::exception& exc) + { + rexc << exc.what() << " while reading " << file << " (" + << i << ") " << endl; + } + catch (...) + { + rexc << "Unknown Exception while reading " << file + << " (" << i << ") " << endl; + } } - catch (std::exception& exc) + } + + if (rexc.str() != "") + { + int nread = sources().size() - nexisting; + + if (nread == 0) { - rexc << exc.what() - << " while reading " - << file - << " (" << i << ") " - << endl; + m_loadingError = true; + m_loadingErrorString = rexc.str(); + TWK_THROW_STREAM(AllReadFailedExc, rexc.str()); } - catch (...) + else { - rexc << "Unknown Exception while reading " << file - << " (" << i << ") " - << endl; + throw rexc; } } + + if (doProcessOpts) + processOptionsAfterSourcesLoaded(); + + setViewNode(viewNodeName(), true); } + } - if (rexc.str() != "") - { - int nread = sources().size() - nexisting; + void RvSession::processOptionsAfterSourcesLoaded(bool hadLoadError) + { + Options& opts = Options::sharedOptions(); + + // + // Some session parameters need to be set after the read + // - if (nread == 0) + if (opts.scale != 1.0) + setScaleOnAll(opts.scale); + opts.scale = 1.0; // use it only once + + if (opts.dispLUT) + { + try { - m_loadingError = true; - m_loadingErrorString = rexc.str(); - TWK_THROW_STREAM(AllReadFailedExc, rexc.str()); + readLUT(opts.dispLUT, "#RVDisplayColor", true); } - else + catch (std::exception& exc) { - throw rexc; + cerr << "ERROR: " << exc.what() << endl; } } - if (doProcessOpts) processOptionsAfterSourcesLoaded(); - - setViewNode(viewNodeName(), true); - } -} - -void -RvSession::processOptionsAfterSourcesLoaded(bool hadLoadError) -{ - Options& opts = Options::sharedOptions(); - - // - // Some session parameters need to be set after the read - // - - if (opts.scale != 1.0) setScaleOnAll(opts.scale); - opts.scale = 1.0; // use it only once - - if (opts.dispLUT) - { - try - { - readLUT(opts.dispLUT, "#RVDisplayColor", true); - } - catch (std::exception& exc) - { - cerr << "ERROR: " << exc.what() << endl; - } - } - - if (opts.fileLUT) - { - try - { - readLUTOnAll(opts.fileLUT, "RVLinearize", true); - } - catch (std::exception& exc) + if (opts.fileLUT) { - cerr << "ERROR: " << exc.what() << endl; + try + { + readLUTOnAll(opts.fileLUT, "RVLinearize", true); + } + catch (std::exception& exc) + { + cerr << "ERROR: " << exc.what() << endl; + } } - } - if (opts.lookLUT) - { - try - { - readLUTOnAll(opts.lookLUT, "RVLookLUT", true); - } - catch (std::exception& exc) + if (opts.lookLUT) { - cerr << "ERROR: " << exc.what() << endl; + try + { + readLUTOnAll(opts.lookLUT, "RVLookLUT", true); + } + catch (std::exception& exc) + { + cerr << "ERROR: " << exc.what() << endl; + } } - } - if (opts.view && *opts.view) - { - if (!setViewNode(opts.view)) + if (opts.view && *opts.view) { - cerr << "ERROR: view not found \"" << opts.view << "\"" << endl; + if (!setViewNode(opts.view)) + { + cerr << "ERROR: view not found \"" << opts.view << "\"" << endl; + } } - } - if (opts.wipes) - { - StackGroupIPNode* stackNode = dynamic_cast (graph().viewNode()); - if (!stackNode) + if (opts.wipes) { - setViewNode ("defaultStack"); - stackNode = (StackGroupIPNode *) graph().viewNode(); + StackGroupIPNode* stackNode = + dynamic_cast(graph().viewNode()); + if (!stackNode) + { + setViewNode("defaultStack"); + stackNode = (StackGroupIPNode*)graph().viewNode(); + } + TwkContainer::IntProperty* ip = + stackNode->createProperty( + "ui.wipes"); + ip->resize(1); + ip->front() = 1; + stackNode->propertyChanged(ip); + + StackIPNode* compNode = stackNode->stackNode(); + TwkContainer::StringProperty* sp = + stackNode->createProperty( + "composite.type"); + sp->resize(1); + sp->front() = "over"; + compNode->propertyChanged(sp); } - TwkContainer::IntProperty* ip = - stackNode->createProperty("ui.wipes"); - ip->resize(1); - ip->front() = 1; - stackNode->propertyChanged(ip); - StackIPNode* compNode = stackNode->stackNode(); - TwkContainer::StringProperty* sp = - stackNode->createProperty("composite.type"); - sp->resize(1); - sp->front() = "over"; - compNode->propertyChanged(sp); - } + // + // These can cause problems if they are allowed to start *before* + // we know the GL capabilities. The queryGL() function above may + // indicate that certain pixel formats are (not) preferred. If + // the caching threads get there first, they can make bad + // assumptions about the image format + // - // - // These can cause problems if they are allowed to start *before* - // we know the GL capabilities. The queryGL() function above may - // indicate that certain pixel formats are (not) preferred. If - // the caching threads get there first, they can make bad - // assumptions about the image format - // + if (opts.useCache) + setCaching(RvSession::GreedyCache); + else if (opts.useLCache) + setCaching(RvSession::BufferCache); - if (opts.useCache) setCaching(RvSession::GreedyCache); - else if (opts.useLCache) setCaching(RvSession::BufferCache); + // setFrame(1); - //setFrame(1); + if (opts.play && !hadLoadError) + { + if (m_cacheMode == BufferCache) + { + play(); + m_bufferWait = true; + } + else + play(); + } - if (opts.play && !hadLoadError) - { - if (m_cacheMode == BufferCache) { play(); m_bufferWait = true; } - else play(); - } + string mu = initEval(); + // cerr << "newRvSessionFromFiles mu '" << mu << "'" << endl; - string mu = initEval(); - // cerr << "newRvSessionFromFiles mu '" << mu << "'" << endl; + if (mu != "") + { + // Empty stored mu code now, otherwise we can recurse if the code + // creates a session. - if (mu != "") - { - // Empty stored mu code now, otherwise we can recurse if the code - // creates a session. + setInitEval(""); - setInitEval(""); + string output = + TwkApp::muEval(muContext(), muProcess(), muModuleList(), + mu.c_str(), "Command line eval"); - string output = TwkApp::muEval(muContext(), - muProcess(), - muModuleList(), - mu.c_str(), - "Command line eval"); + if ("string => \"noprint\"" != output) + { + cout << "INFO: eval returned: " << output << endl; + } + } - if ("string => \"noprint\"" != output) + // Send external events and their corresponding content. + for (int i = 0; i < opts.sendEvents.size(); ++i) { - cout << "INFO: eval returned: " << output << endl; + const Options::SendExternalEvent& e = opts.sendEvents[i]; + userGenericEvent("external-" + e.name, e.content); } } - // Send external events and their corresponding content. - for (int i = 0; i < opts.sendEvents.size(); ++i) + void RvSession::applySingleSourceArgs(Options::SourceArgs& sargs, + SourceIPNode* node) { - const Options::SendExternalEvent &e = opts.sendEvents[i]; - userGenericEvent("external-" + e.name, e.content); - } -} - -void -RvSession::applySingleSourceArgs (Options::SourceArgs& sargs, SourceIPNode* node) -{ - if (!node) return; + if (!node) + return; - if (sargs.cutIn != numeric_limits::max()) - { - if (IntProperty *p = node->property("cut.in")) + if (sargs.cutIn != numeric_limits::max()) { - p->front() = sargs.cutIn; - node->propertyChanged(p); + if (IntProperty* p = node->property("cut.in")) + { + p->front() = sargs.cutIn; + node->propertyChanged(p); + } } - } - if (sargs.cutOut != numeric_limits::max()) - { - if (IntProperty *p = node->property("cut.out")) + if (sargs.cutOut != numeric_limits::max()) { - p->front() = sargs.cutOut; - node->propertyChanged(p); + if (IntProperty* p = node->property("cut.out")) + { + p->front() = sargs.cutOut; + node->propertyChanged(p); + } } - } - if (sargs.fps != 0) - { - if (FloatProperty *p = node->property("group.fps")) + if (sargs.fps != 0) { - p->front() = sargs.fps; - node->propertyChanged(p); - } - - // - // If we only have one source loaded, the default views have adopted - // the "wrong" fps (ie the one from before we set it with this - // option), so adjust them. BUT, not if the user specified a session - // FPS on the command line, since the defaultViews should not adopt an - // FPS anyway. - // + if (FloatProperty* p = node->property("group.fps")) + { + p->front() = sargs.fps; + node->propertyChanged(p); + } - Options& opts = Options::sharedOptions(); + // + // If we only have one source loaded, the default views have + // adopted the "wrong" fps (ie the one from before we set it with + // this option), so adjust them. BUT, not if the user specified a + // session FPS on the command line, since the defaultViews should + // not adopt an FPS anyway. + // - if (sources().size() == 1 && opts.fps == 0.0) - { - setFPS(sargs.fps); - const IPGraph::NodeMap& vnodes = graph().viewableNodes(); + Options& opts = Options::sharedOptions(); - for (IPGraph::NodeMap::const_iterator i = vnodes.begin(); i != vnodes.end(); ++i) + if (sources().size() == 1 && opts.fps == 0.0) { - if (graph().isDefaultView((*i).first)) copySessionStateToNode((*i).second); + setFPS(sargs.fps); + const IPGraph::NodeMap& vnodes = graph().viewableNodes(); + + for (IPGraph::NodeMap::const_iterator i = vnodes.begin(); + i != vnodes.end(); ++i) + { + if (graph().isDefaultView((*i).first)) + copySessionStateToNode((*i).second); + } } } - } - if (sargs.volume != -1) - { - if (FloatProperty *p = node->property("group.volume")) + if (sargs.volume != -1) { - p->front() = sargs.volume; - node->propertyChanged(p); + if (FloatProperty* p = + node->property("group.volume")) + { + p->front() = sargs.volume; + node->propertyChanged(p); + } } - } - if (sargs.audioOffset != 0) - { - if (FloatProperty *p = node->property("group.audioOffset")) + if (sargs.audioOffset != 0) { - p->front() = sargs.audioOffset; - node->propertyChanged(p); + if (FloatProperty* p = + node->property("group.audioOffset")) + { + p->front() = sargs.audioOffset; + node->propertyChanged(p); + } } - } - if (sargs.rangeOffset != 0) - { - if (IntProperty *p = node->property("group.rangeOffset")) + if (sargs.rangeOffset != 0) { - p->front() = sargs.rangeOffset; - node->propertyChanged(p); + if (IntProperty* p = + node->property("group.rangeOffset")) + { + p->front() = sargs.rangeOffset; + node->propertyChanged(p); + } } - } - if (sargs.rangeStart != numeric_limits::max()) - { - IntProperty* p = node->createProperty("group.rangeStart"); - p->resize(1); - node->newPropertyCreated(p); - p->front() = sargs.rangeStart; - node->propertyChanged(p); - } - - if (sargs.noMovieAudio) - { - if (IntProperty *p = node->property("group.noMovieAudio")) + if (sargs.rangeStart != numeric_limits::max()) { - p->front() = 1; + IntProperty* p = + node->createProperty("group.rangeStart"); + p->resize(1); + node->newPropertyCreated(p); + p->front() = sargs.rangeStart; node->propertyChanged(p); } - } - if (sargs.stereoRelativeOffset != 0.0) - { - if (SourceStereoIPNode* snode = - dynamic_cast(graph().findNodeAssociatedWith(node, "RVSourceStereo"))) + if (sargs.noMovieAudio) { - if (FloatProperty *p = snode->property("stereo.relativeOffset")) + if (IntProperty* p = + node->property("group.noMovieAudio")) { - p->front() = sargs.stereoRelativeOffset; - snode->propertyChanged(p); + p->front() = 1; + node->propertyChanged(p); } } - } - if (sargs.stereoRightOffset != 0.0) - { - if (SourceStereoIPNode* snode = - dynamic_cast(graph().findNodeAssociatedWith(node, "RVSourceStereo"))) + if (sargs.stereoRelativeOffset != 0.0) { - if (FloatProperty *p = snode->property("stereo.rightOffset")) + if (SourceStereoIPNode* snode = dynamic_cast( + graph().findNodeAssociatedWith(node, "RVSourceStereo"))) { - p->front() = sargs.stereoRightOffset; - snode->propertyChanged(p); + if (FloatProperty* p = + snode->property("stereo.relativeOffset")) + { + p->front() = sargs.stereoRelativeOffset; + snode->propertyChanged(p); + } } } - } - if (sargs.pixelAspect != 0.0) - { - if (LensWarpIPNode* lnode = - dynamic_cast(graph().findNodeAssociatedWith(node, "RVLensWarp"))) + if (sargs.stereoRightOffset != 0.0) { - if (FloatProperty* p = lnode->property("warp.pixelAspectRatio")) + if (SourceStereoIPNode* snode = dynamic_cast( + graph().findNodeAssociatedWith(node, "RVSourceStereo"))) { - p->front() = sargs.pixelAspect; - lnode->propertyChanged(p); + if (FloatProperty* p = + snode->property("stereo.rightOffset")) + { + p->front() = sargs.stereoRightOffset; + snode->propertyChanged(p); + } } } - } - - // - // XXX All the below changes do not generate events, and so cannot be - // remote synced at the moment - // - - if (sargs.selectType != "" && sargs.selectName != "") - { - StringVector parts; - algorithm::split(parts, sargs.selectName, is_any_of(string(","))); - if (sargs.selectType == "view") - { - StringVector v(2); - v[0] = "view"; - v[1] = parts[0]; - node->setProperty("request.imageComponent", v); - } - else - if (sargs.selectType == "layer") + if (sargs.pixelAspect != 0.0) { - StringVector v(3); - v[0] = "layer"; - v[1] = (parts.size() > 1) ? parts[0] : ""; - v[2] = (parts.size() > 1) ? parts[1] : sargs.selectName; - node->setProperty("request.imageComponent", v); + if (LensWarpIPNode* lnode = dynamic_cast( + graph().findNodeAssociatedWith(node, "RVLensWarp"))) + { + if (FloatProperty* p = + lnode->property("warp.pixelAspectRatio")) + { + p->front() = sargs.pixelAspect; + lnode->propertyChanged(p); + } + } } - else - if (sargs.selectType == "channel") + + // + // XXX All the below changes do not generate events, and so cannot be + // remote synced at the moment + // + + if (sargs.selectType != "" && sargs.selectName != "") { - StringVector v(4); - v[0] = "channel"; - v[1] = (parts.size() > 2) ? parts[0] : ""; - v[2] = (parts.size() > 2) ? parts[1] : ""; - v[3] = (parts.size() > 2) ? parts[2] : sargs.selectName; - node->setProperty("request.imageComponent", v); + StringVector parts; + algorithm::split(parts, sargs.selectName, is_any_of(string(","))); + + if (sargs.selectType == "view") + { + StringVector v(2); + v[0] = "view"; + v[1] = parts[0]; + node->setProperty("request.imageComponent", v); + } + else if (sargs.selectType == "layer") + { + StringVector v(3); + v[0] = "layer"; + v[1] = (parts.size() > 1) ? parts[0] : ""; + v[2] = (parts.size() > 1) ? parts[1] : sargs.selectName; + node->setProperty("request.imageComponent", v); + } + else if (sargs.selectType == "channel") + { + StringVector v(4); + v[0] = "channel"; + v[1] = (parts.size() > 2) ? parts[0] : ""; + v[2] = (parts.size() > 2) ? parts[1] : ""; + v[3] = (parts.size() > 2) ? parts[2] : sargs.selectName; + node->setProperty("request.imageComponent", v); + } } - } - if (sargs.cmap != "") - { - if (ChannelMapIPNode* cmapnode = - dynamic_cast(graph().findNodeAssociatedWith(node, "RVChannelMap"))) + if (sargs.cmap != "") { - StringVector chans; - stl_ext::tokenize(chans, sargs.cmap, ","); - cmapnode->setChannelMap(chans); - if ( (chans.size() > 1) || ((sargs.selectType == "") && (sargs.selectName == "")) ) + if (ChannelMapIPNode* cmapnode = dynamic_cast( + graph().findNodeAssociatedWith(node, "RVChannelMap"))) { - node->setProperty("request.readAllChannels", 1); + StringVector chans; + stl_ext::tokenize(chans, sargs.cmap, ","); + cmapnode->setChannelMap(chans); + if ((chans.size() > 1) + || ((sargs.selectType == "") && (sargs.selectName == ""))) + { + node->setProperty("request.readAllChannels", + 1); + } } } - } - if (sargs.fcdl != "") - { - if (PipelineGroupIPNode* pipeGroup = - dynamic_cast(node->group()->memberByType("RVLinearizePipelineGroup"))) + if (sargs.fcdl != "") { - if (FileSpaceLinearizeIPNode* cdlnode = - dynamic_cast(pipeGroup->memberByType("RVLinearize"))) + if (PipelineGroupIPNode* pipeGroup = + dynamic_cast( + node->group()->memberByType( + "RVLinearizePipelineGroup"))) { - readCDL(sargs.fcdl, cdlnode->name(), true); + if (FileSpaceLinearizeIPNode* cdlnode = + dynamic_cast( + pipeGroup->memberByType("RVLinearize"))) + { + readCDL(sargs.fcdl, cdlnode->name(), true); + } } } - } - if (sargs.lcdl != "") - { - if (PipelineGroupIPNode* pipeGroup = - dynamic_cast(node->group()->memberByType("RVColorPipelineGroup"))) + if (sargs.lcdl != "") { - if (ColorIPNode* cdlnode = - dynamic_cast(pipeGroup->memberByType("RVColor"))) + if (PipelineGroupIPNode* pipeGroup = + dynamic_cast( + node->group()->memberByType("RVColorPipelineGroup"))) { - readCDL(sargs.lcdl, cdlnode->name(), true); + if (ColorIPNode* cdlnode = dynamic_cast( + pipeGroup->memberByType("RVColor"))) + { + readCDL(sargs.lcdl, cdlnode->name(), true); + } } } - } - if (sargs.flut != "") - { - if (PipelineGroupIPNode* pipeGroup = - dynamic_cast(node->group()->memberByType("RVLinearizePipelineGroup"))) + if (sargs.flut != "") { - if (LUTIPNode* lutnode = - dynamic_cast(pipeGroup->memberByType("RVLinearize"))) + if (PipelineGroupIPNode* pipeGroup = + dynamic_cast( + node->group()->memberByType( + "RVLinearizePipelineGroup"))) { - readLUT(sargs.flut, lutnode->name(), true); + if (LUTIPNode* lutnode = dynamic_cast( + pipeGroup->memberByType("RVLinearize"))) + { + readLUT(sargs.flut, lutnode->name(), true); + } } } - } - if (sargs.pclut != "") - { - if (LUTIPNode* lutnode = - dynamic_cast(graph().findNodeAssociatedWith(node, "RVCacheLUT"))) + if (sargs.pclut != "") { - readLUT(sargs.pclut, lutnode->name(), true); + if (LUTIPNode* lutnode = dynamic_cast( + graph().findNodeAssociatedWith(node, "RVCacheLUT"))) + { + readLUT(sargs.pclut, lutnode->name(), true); + } } - } - if (sargs.llut != "") - { - if (PipelineGroupIPNode* pipeGroup = - dynamic_cast(node->group()->memberByType("RVLookPipelineGroup"))) + if (sargs.llut != "") { - if (LUTIPNode* lutnode = - dynamic_cast(pipeGroup->memberByType("RVLookLUT"))) + if (PipelineGroupIPNode* pipeGroup = + dynamic_cast( + node->group()->memberByType("RVLookPipelineGroup"))) { - readLUT(sargs.llut, lutnode->name(), true); + if (LUTIPNode* lutnode = dynamic_cast( + pipeGroup->memberByType("RVLookLUT"))) + { + readLUT(sargs.llut, lutnode->name(), true); + } } } - } - if (sargs.hascrop || sargs.hasuncrop) - { - if (FormatIPNode* fnode = - dynamic_cast(graph().findNodeAssociatedWith(node, "RVFormat"))) + if (sargs.hascrop || sargs.hasuncrop) { - if (sargs.hascrop) fnode->setCrop(int(sargs.crop[0]), - int(sargs.crop[1]), - int(sargs.crop[2]), - int(sargs.crop[3])); - - if (sargs.hasuncrop) fnode->setUncrop(int(sargs.uncrop[0]), - int(sargs.uncrop[1]), - int(sargs.uncrop[2]), - int(sargs.uncrop[3])); + if (FormatIPNode* fnode = dynamic_cast( + graph().findNodeAssociatedWith(node, "RVFormat"))) + { + if (sargs.hascrop) + fnode->setCrop(int(sargs.crop[0]), int(sargs.crop[1]), + int(sargs.crop[2]), int(sargs.crop[3])); + + if (sargs.hasuncrop) + fnode->setUncrop(int(sargs.uncrop[0]), int(sargs.uncrop[1]), + int(sargs.uncrop[2]), + int(sargs.uncrop[3])); + } } } -} - -void -RvSession::read(const string& filename, const ReadRequest& request) -{ - const bool addContents = request.optionValue("append", false); - const string tag = request.optionValue("tag", ""); - - Options::SourceArgs sargs; - readSource(filename, sargs, addContents, false, tag); -} - -void -RvSession::readSourceHelper(StringVector files, - Options::SourceArgs& sargs, - bool addContents, - bool addToExistingSource) -{ - if (!addContents) clear(); + void RvSession::read(const string& filename, const ReadRequest& request) { - RvGraph::FastAddSourceGuard fastAddSourceGuard(rvgraph()); + const bool addContents = request.optionValue("append", false); + const string tag = request.optionValue("tag", ""); - if (addToExistingSource) addToSourceHelper("", files, sargs); - else for (int i=0; i < files.size(); i++) addSource(files[i], sargs); + Options::SourceArgs sargs; + readSource(filename, sargs, addContents, false, tag); } - // We need to update the frame range here because the FastAddSourceGuard set - // the inputs of the SequenceIPNode after the RvSession::newMediaLoaded is - // called for the last source. - updateRange(); -} + void RvSession::readSourceHelper(StringVector files, + Options::SourceArgs& sargs, + bool addContents, bool addToExistingSource) + { + if (!addContents) + clear(); -void -RvSession::readSource(const std::string& infilename, - Options::SourceArgs& sargs, - bool addContents, - bool addToExistingSource, - const string& tag, - bool merge) -{ - HOP_PROF_DYN_NAME( - std::string(std::string("RvSession::readSource : ") + - infilename).c_str()); + { + RvGraph::FastAddSourceGuard fastAddSourceGuard(rvgraph()); - string filename = pathConform(IPCore::Application::mapFromVar(infilename)); - string eventContents = filename + ";;" + tag; - string newfilename = userGenericEvent("incoming-source-path", eventContents); + if (addToExistingSource) + addToSourceHelper("", files, sargs); + else + for (int i = 0; i < files.size(); i++) + addSource(files[i], sargs); + } - if (newfilename != "") - { - filename = newfilename; + // We need to update the frame range here because the FastAddSourceGuard + // set the inputs of the SequenceIPNode after the + // RvSession::newMediaLoaded is called for the last source. + updateRange(); } - SequenceNameList files; - if (checkForDirFiles(filename, m_noSequences, &files)) + void RvSession::readSource(const std::string& infilename, + Options::SourceArgs& sargs, bool addContents, + bool addToExistingSource, const string& tag, + bool merge) { - readSourceHelper(files, sargs, addContents, addToExistingSource); - } - else - { - // - // If its a single file, add it. If its an RV file then read - // it and reconstruct the session from that. - // + HOP_PROF_DYN_NAME( + std::string(std::string("RvSession::readSource : ") + infilename) + .c_str()); - string ext = extension(filename); + string filename = + pathConform(IPCore::Application::mapFromVar(infilename)); + string eventContents = filename + ";;" + tag; + string newfilename = + userGenericEvent("incoming-source-path", eventContents); - if (ext == "rv") + if (newfilename != "") { - readGTO(filename.c_str(), merge, sargs); + filename = newfilename; } - else if (ext == "rvedl") + + SequenceNameList files; + if (checkForDirFiles(filename, m_noSequences, &files)) { - readEDL(filename.c_str()); + readSourceHelper(files, sargs, addContents, addToExistingSource); } - else if (isStereoSequence(filename)) + else { - StringVector movies; - checkForStereoPaths(filename, movies); + // + // If its a single file, add it. If its an RV file then read + // it and reconstruct the session from that. + // + + string ext = extension(filename); - if (movies.size() == 2) + if (ext == "rv") + { + readGTO(filename.c_str(), merge, sargs); + } + else if (ext == "rvedl") + { + readEDL(filename.c_str()); + } + else if (isStereoSequence(filename)) { - if (!addContents) clear(); + StringVector movies; + checkForStereoPaths(filename, movies); - if (addToExistingSource) addToSourceHelper("", movies, sargs); - else addSource(movies, sargs); + if (movies.size() == 2) + { + if (!addContents) + clear(); + + if (addToExistingSource) + addToSourceHelper("", movies, sargs); + else + addSource(movies, sargs); + } + else + TWK_THROW_STREAM(IPCore::ReadFailedExc, + "Cannot access stereo media " << filename); + } + else + { + StringVector movies; + movies.push_back(filename); + readSourceHelper(movies, sargs, addContents, + addToExistingSource); } - else TWK_THROW_STREAM(IPCore::ReadFailedExc, "Cannot access stereo media " << filename); - } - else - { - StringVector movies; - movies.push_back(filename); - readSourceHelper(movies, sargs, addContents, addToExistingSource); } } -} - - -void -RvSession::addToSource(const string& srcNode, - const string& infilename, - const string& tag) -{ - string filename = pathConform(IPCore::Application::mapFromVar(infilename)); - string eventContents = filename + ";;" + tag; - string newfilename = userGenericEvent("incoming-source-path", eventContents); - if (newfilename != "") + void RvSession::addToSource(const string& srcNode, const string& infilename, + const string& tag) { - filename = newfilename; - } - - // - // If it's a directory, and there's one sequence in the - // directory, try to add that. - // + string filename = + pathConform(IPCore::Application::mapFromVar(infilename)); + string eventContents = filename + ";;" + tag; + string newfilename = + userGenericEvent("incoming-source-path", eventContents); - SequenceNameList files; - if (checkForDirFiles(filename, false, &files)) - { - if (files.size() == 1) - { - filename = files[0]; - } - else if (files.size() == 0) + if (newfilename != "") { - TWK_THROW_STREAM(IPCore::ReadFailedExc, "Direcory contains no media"); + filename = newfilename; } - else - { - TWK_THROW_STREAM(IPCore::ReadFailedExc, "Direcory contains too many sequences"); - } - } - - StringVector movies; - checkForStereoPaths(filename, movies); - Options::SourceArgs sargs; - if (movies.size()) addToSourceHelper(srcNode, movies, sargs); -} - -SourceIPNode* -RvSession::addToSourceHelper(const string& srcNode, StringVector movies, - Options::SourceArgs& sargs) -{ - SourceIPNode* node = 0; - if (movies.empty()) return 0; - if (srcNode == "") - { - const RvGraph::Sources& sources = rvgraph().imageSources(); - if (sources.empty()) return 0; // - // Want to add to the source we just added, so that's the - // last one in this list. + // If it's a directory, and there's one sequence in the + // directory, try to add that. // - node = sources[sources.size() - 1]; - } - else node = sourceNode(srcNode); - if (!node) return 0; + SequenceNameList files; + if (checkForDirFiles(filename, false, &files)) + { + if (files.size() == 1) + { + filename = files[0]; + } + else if (files.size() == 0) + { + TWK_THROW_STREAM(IPCore::ReadFailedExc, + "Direcory contains no media"); + } + else + { + TWK_THROW_STREAM(IPCore::ReadFailedExc, + "Direcory contains too many sequences"); + } + } - // - // Store input parameters - // + StringVector movies; + checkForStereoPaths(filename, movies); + Options::SourceArgs sargs; + if (movies.size()) + addToSourceHelper(srcNode, movies, sargs); + } - if (FileSourceIPNode* fsipn = dynamic_cast(node)) + SourceIPNode* RvSession::addToSourceHelper(const string& srcNode, + StringVector movies, + Options::SourceArgs& sargs) { - fsipn->storeInputParameters(sargs.inparams); - } + SourceIPNode* node = 0; + if (movies.empty()) + return 0; - // - // Set the media on the source - // + if (srcNode == "") + { + const RvGraph::Sources& sources = rvgraph().imageSources(); + if (sources.empty()) + return 0; + // + // Want to add to the source we just added, so that's the + // last one in this list. + // + node = sources[sources.size() - 1]; + } + else + node = sourceNode(srcNode); - StringProperty* movie = node->property("media.movie"); - for (int i = 0; i < movies.size(); ++i) movie->push_back(movies[i]); - node->propertyChanged(movie); + if (!node) + return 0; - // - // Apply any source args - // + // + // Store input parameters + // + + if (FileSourceIPNode* fsipn = dynamic_cast(node)) + { + fsipn->storeInputParameters(sargs.inparams); + } - applySingleSourceArgs(sargs, node); + // + // Set the media on the source + // - // - // Send the user an event - // + StringProperty* movie = node->property("media.movie"); + for (int i = 0; i < movies.size(); ++i) + movie->push_back(movies[i]); + node->propertyChanged(movie); - ostringstream str; - str << node->name() << ";;RVSource" << ";;" << movies[0]; - userGenericEvent("source-modified", str.str()); + // + // Apply any source args + // - return node; -} + applySingleSourceArgs(sargs, node); -void -RvSession::buildFileList(const StringVector& files, string tag, StringVector& collected) -{ - for (int i = 0; i < files.size(); i++) - { - string filename = pathConform(IPCore::Application::mapFromVar(files[i])); - string eventContents = filename + ";;" + tag; - string newfilename = userGenericEvent("incoming-source-path", eventContents); + // + // Send the user an event + // - if (newfilename != "") filename = newfilename; + ostringstream str; + str << node->name() << ";;RVSource" << ";;" << movies[0]; + userGenericEvent("source-modified", str.str()); - checkForStereoPaths(filename, collected); + return node; } -} -SourceIPNode* -RvSession::addSourceWithTag(const StringVector& files, string tag, string nodeName, string mediaRepName) -{ - Options::SourceArgs sargs; - if (!files.empty()) + void RvSession::buildFileList(const StringVector& files, string tag, + StringVector& collected) { - StringVector sourceArgs; - sourceArgs.push_back("["); - for (int i=0; iname(), mediaReps); - if (any_of(mediaReps.begin(), mediaReps.end(), [&](const string& elem) {return elem == mediaRepName;})) + if (mediaRepSource == "last") { - TWK_THROW_EXC_STREAM("ERROR: Source media representation name already exists: " << mediaRepName << endl); + const RvGraph::Sources& sources = rvgraph().imageSources(); + if (sources.empty()) + return 0; + // + // Want to add to the source we just added, so that's the + // last one in this list. + // + mediaRepLinkedSrcNode = sources[sources.size() - 1]; } - } - } + else + { + mediaRepLinkedSrcNode = sourceNode(mediaRepSource); + } + if (!mediaRepLinkedSrcNode) + TWK_THROW_EXC_STREAM( + "ERROR: Could not find specified source node" << endl); - SourceIPNode* source = rvgraph().addSource(nodeType, nodeName, mediaRepName, mediaRepLinkedSrcNode); + // Make sure the media rep name does not already exists + if (mediaRepLinkedSrcNode) + { + StringVector mediaReps; + sourceMediaReps(mediaRepLinkedSrcNode->name(), mediaReps); + if (any_of(mediaReps.begin(), mediaReps.end(), + [&](const string& elem) + { return elem == mediaRepName; })) + { + TWK_THROW_EXC_STREAM("ERROR: Source media representation " + "name already exists: " + << mediaRepName << endl); + } + } + } - // - // Set the media on the source - // + SourceIPNode* source = rvgraph().addSource( + nodeType, nodeName, mediaRepName, mediaRepLinkedSrcNode); - source->mediaChangedSignal().connect(boost::bind(&RvSession::newMediaLoaded, this, source)); - StringProperty* movie = source->property("media.movie"); - for (int i = 0; i < movies.size(); ++i) movie->push_back (movies[i]); + // + // Set the media on the source + // - // - // Store input parameters - // - // Note that the FileSourceIPNode::storeInputParameters() must be called - // before the 'source->propertyChanged(movie)' below otherwise those input - // parameters might be missed entirely by FileSourceIPNode::openMovieTask() - // (which is executed in a worker thread) or reset cookies which might lead - // to file access errors such as : - // 'Could not locate "https://.../mp4". Relocate source to fix' - // + source->mediaChangedSignal().connect( + boost::bind(&RvSession::newMediaLoaded, this, source)); + StringProperty* movie = source->property("media.movie"); + for (int i = 0; i < movies.size(); ++i) + movie->push_back(movies[i]); - if (FileSourceIPNode* fsipn = dynamic_cast(source)) - { - fsipn->storeInputParameters(sargs.inparams); - } + // + // Store input parameters + // + // Note that the FileSourceIPNode::storeInputParameters() must be + // called before the 'source->propertyChanged(movie)' below otherwise + // those input parameters might be missed entirely by + // FileSourceIPNode::openMovieTask() (which is executed in a worker + // thread) or reset cookies which might lead to file access errors such + // as : 'Could not locate "https://.../mp4". Relocate source to fix' + // - // Set the proxy parameters based on the per-source command-line flags if - // any were specified. These are not essential per say but really improves - // the user experience in progressive source loading mode. - // For example, the following SG fields are provided via these per-source - // command-line flags (+in,+out,+fps) when a user on a ShotGrid site selects - // 'Play in RV' or 'Play in Screening Room for RV': - // sg_first_frame/sg_last_frame/sg_uploaded_movie_frame_rate - if (hasCutPoints(sargs)) - { - source->declareProperty("proxy.range", Vec2i(sargs.cutIn, sargs.cutOut)); - } - if (sargs.fps!=0.0) - { - source->declareProperty("proxy.fps", sargs.fps); - } + if (FileSourceIPNode* fsipn = dynamic_cast(source)) + { + fsipn->storeInputParameters(sargs.inparams); + } - source->propertyChanged(movie); + // Set the proxy parameters based on the per-source command-line flags + // if any were specified. These are not essential per say but really + // improves the user experience in progressive source loading mode. For + // example, the following SG fields are provided via these per-source + // command-line flags (+in,+out,+fps) when a user on a ShotGrid site + // selects 'Play in RV' or 'Play in Screening Room for RV': + // sg_first_frame/sg_last_frame/sg_uploaded_movie_frame_rate + if (hasCutPoints(sargs)) + { + source->declareProperty( + "proxy.range", Vec2i(sargs.cutIn, sargs.cutOut)); + } + if (sargs.fps != 0.0) + { + source->declareProperty("proxy.fps", sargs.fps); + } + source->propertyChanged(movie); - // - // Send the user an event - // + // + // Send the user an event + // - userGenericEvent("new-node", source->name()); + userGenericEvent("new-node", source->name()); - // - // Handle new-source event - // + // + // Handle new-source event + // - ostringstream nscontents; - string media = (movies.size() > 0) ? movies[0] : ""; - nscontents << source->name() << ";;RVSource;;" << media; - userGenericEvent("new-source", nscontents.str()); + ostringstream nscontents; + string media = (movies.size() > 0) ? movies[0] : ""; + nscontents << source->name() << ";;RVSource;;" << media; + userGenericEvent("new-source", nscontents.str()); - // - // Check and see if stereo needs to be turned on - // + // + // Check and see if stereo needs to be turned on + // - IPGraph::NodeVector nodes; - graph().findNodesByTypeName(nodes, "RVDisplayStereo"); + IPGraph::NodeVector nodes; + graph().findNodesByTypeName(nodes, "RVDisplayStereo"); - if (!nodes.empty()) - { - if (DisplayStereoIPNode* stereo = dynamic_cast(nodes.front())) + if (!nodes.empty()) { - if (stereo->stereoType() == "hardware") send(stereoHardwareOnMessage()); - else send(stereoHardwareOffMessage()); + if (DisplayStereoIPNode* stereo = + dynamic_cast(nodes.front())) + { + if (stereo->stereoType() == "hardware") + send(stereoHardwareOnMessage()); + else + send(stereoHardwareOffMessage()); + } } - } - // - // Apply any source args - // - - applySingleSourceArgs(sargs, source); + // + // Apply any source args + // - return source; -} + applySingleSourceArgs(sargs, source); -SourceIPNode* -RvSession::addImageSource(const string& mediaName, const MovieInfo& info) -{ - StringVector movies(1); - movies.front() = mediaName; - Options::SourceArgs sargs; - SourceIPNode* sipn = addSource(movies, sargs, "", "RVImageSource"); - ImageSourceIPNode* source = dynamic_cast(sipn); - source->set(mediaName, info); - - return source; -} + return source; + } -void -RvSession::newMediaLoaded(SourceIPNode* node) -{ - if (SourceGroupIPNode* group = dynamic_cast(node->group())) + SourceIPNode* RvSession::addImageSource(const string& mediaName, + const MovieInfo& info) { - // - // If there isn't a name already give it one - // + StringVector movies(1); + movies.front() = mediaName; + Options::SourceArgs sargs; + SourceIPNode* sipn = addSource(movies, sargs, "", "RVImageSource"); + ImageSourceIPNode* source = dynamic_cast(sipn); + source->set(mediaName, info); - if (!(group->property("ui.name"))) group->setUINameFromMedia(); + return source; + } - const RvGraph::Sources& sources = rvgraph().imageSources(); - Options& opts = Options::sharedOptions(); - if (opts.playMode == 0 && sources.size() == 1 && node->hasAudio()) + void RvSession::newMediaLoaded(SourceIPNode* node) + { + if (SourceGroupIPNode* group = + dynamic_cast(node->group())) { - m_realtime = true; - } + // + // If there isn't a name already give it one + // - // - // Notify the source node to avoid a dead lock - // - node->onNewMediaComplete(); + if (!(group->property("ui.name"))) + group->setUINameFromMedia(); - // - // Handle source-group-complete event - // + const RvGraph::Sources& sources = rvgraph().imageSources(); + Options& opts = Options::sharedOptions(); + if (opts.playMode == 0 && sources.size() == 1 && node->hasAudio()) + { + m_realtime = true; + } + + // + // Notify the source node to avoid a dead lock + // + node->onNewMediaComplete(); - ostringstream sgccontents; - string action = node->updateAction(); - sgccontents << group->name() << ";;" << action; + // + // Handle source-group-complete event + // - if (Options::sharedOptions().progressiveSourceLoading) - { - if (action != "modified") - userGenericEvent("source-group-proxy-complete", sgccontents.str()); + ostringstream sgccontents; + string action = node->updateAction(); + sgccontents << group->name() << ";;" << action; + + if (Options::sharedOptions().progressiveSourceLoading) + { + if (action != "modified") + userGenericEvent("source-group-proxy-complete", + sgccontents.str()); + else + userGenericEvent("source-group-complete", + sgccontents.str()); + } else + { + // Note: It was decided to trigger the + // source-group-proxy-complete event even when progressive + // source loading is disabled + userGenericEvent("source-group-proxy-complete", + sgccontents.str()); + userGenericEvent("source-group-complete", sgccontents.str()); - } - else - { - // Note: It was decided to trigger the source-group-proxy-complete - // event even when progressive source loading is disabled - userGenericEvent("source-group-proxy-complete", sgccontents.str()); + } - userGenericEvent("source-group-complete", sgccontents.str()); - } + if ((sources.size() == 1 && action == "new") + || m_conductorSource == node) + { + updateRange(); + m_inc = graph().root()->imageRangeInfo().inc; - if ( (sources.size() == 1 && action == "new") || m_conductorSource == node) - { - updateRange(); - m_inc = graph().root()->imageRangeInfo().inc; + if (m_conductorSource == nullptr) + { + // We want to change the playhead only during the first load + m_frame = rangeStart(); + } - if (m_conductorSource == nullptr) - { - // We want to change the playhead only during the first load - m_frame = rangeStart(); + m_fps = sources.front()->imageRangeInfo().fps; + m_conductorSource = node; } - m_fps = sources.front()->imageRangeInfo().fps; - m_conductorSource = node; - } - - if (m_gtoSourceCount == m_gtoSourceTotal) - { - updateRange(); - if (graph().hasAudio()) ensureAudioRenderer(); + if (m_gtoSourceCount == m_gtoSourceTotal) + { + updateRange(); + if (graph().hasAudio()) + ensureAudioRenderer(); + } } } -} - -vector -RvSession::findSourcesByMedia(const string& filename, const string& node) -{ - vector sources; - if (node == "") + vector + RvSession::findSourcesByMedia(const string& filename, const string& node) { - NodeVector nodes; - graph().findNodesByTypeName(nodes, "RVFileSource"); + vector sources; - for (NodeVector::iterator i = nodes.begin(); i != nodes.end(); ++i) + if (node == "") { - if (FileSourceIPNode* n = dynamic_cast(*i)) + NodeVector nodes; + graph().findNodesByTypeName(nodes, "RVFileSource"); + + for (NodeVector::iterator i = nodes.begin(); i != nodes.end(); ++i) { - if (n->filename() == filename) sources.push_back(n); + if (FileSourceIPNode* n = dynamic_cast(*i)) + { + if (n->filename() == filename) + sources.push_back(n); + } } } - } - else - { - if (IPNode* ipn = graph().findNode(node)) + else { - if (FileSourceIPNode* n = dynamic_cast(ipn)) + if (IPNode* ipn = graph().findNode(node)) { - if (n->filename() == filename) sources.push_back(n); + if (FileSourceIPNode* n = dynamic_cast(ipn)) + { + if (n->filename() == filename) + sources.push_back(n); + } } } - } - - return sources; -} - -void -RvSession::relocateSource(const string& oldFilename, - const string& newFilename, - const string& srcNode) -{ - string newF = pathConform(IPCore::Application::mapFromVar(newFilename)); - vector sources = findSourcesByMedia(oldFilename, srcNode); + return sources; + } - for (int i = 0; i < sources.size(); ++i) + void RvSession::relocateSource(const string& oldFilename, + const string& newFilename, + const string& srcNode) { - FileSourceIPNode* source = sources[i]; - - ostringstream mrcontents; - mrcontents << source->name() << ";;" << oldFilename << ";;" << newF; - userGenericEvent("media-relocated", mrcontents.str()); - - StringProperty* movie = source->property("media.movie"); - movie->front() = newFilename; - IntProperty* mediaActive = source->property("media.active"); - mediaActive->front() = 1; - source->propertyChanged(movie); + string newF = pathConform(IPCore::Application::mapFromVar(newFilename)); - ostringstream nscontents; - nscontents << source->name() << ";;RVSource;;" << newFilename; - userGenericEvent("new-source", nscontents.str()); + vector sources = + findSourcesByMedia(oldFilename, srcNode); + for (int i = 0; i < sources.size(); ++i) + { + FileSourceIPNode* source = sources[i]; + + ostringstream mrcontents; + mrcontents << source->name() << ";;" << oldFilename << ";;" << newF; + userGenericEvent("media-relocated", mrcontents.str()); + + StringProperty* movie = + source->property("media.movie"); + movie->front() = newFilename; + IntProperty* mediaActive = + source->property("media.active"); + mediaActive->front() = 1; + source->propertyChanged(movie); + + ostringstream nscontents; + nscontents << source->name() << ";;RVSource;;" << newFilename; + userGenericEvent("new-source", nscontents.str()); + } } -} - -void -RvSession::setSourceMedia(const std::string& srcNode, - const StringVector& files, - const std::string& tag) -{ - if (IPNode* node = graph().findNode(srcNode)) + void RvSession::setSourceMedia(const std::string& srcNode, + const StringVector& files, + const std::string& tag) { - StringVector mediaFiles; - buildFileList(files, tag, mediaFiles); - if (!mediaFiles.empty()) + + if (IPNode* node = graph().findNode(srcNode)) { - if (FileSourceIPNode* fsipn = dynamic_cast(node)) + StringVector mediaFiles; + buildFileList(files, tag, mediaFiles); + if (!mediaFiles.empty()) { - const bool isProgressiveLoadingEnabled = fsipn->hasProgressiveSourceLoading(); - fsipn->setProgressiveSourceLoading(false); - - fsipn->clearMedia(); - StringProperty* movie = fsipn->property("media.movie"); - movie->resize(0); - for (int i = 0; i < mediaFiles.size(); ++i) movie->push_back(mediaFiles[i]); - IntProperty* mediaActive = fsipn->property("media.active"); - mediaActive->front() = 1; - fsipn->propertyChanged(movie); + if (FileSourceIPNode* fsipn = + dynamic_cast(node)) + { + const bool isProgressiveLoadingEnabled = + fsipn->hasProgressiveSourceLoading(); + fsipn->setProgressiveSourceLoading(false); + + fsipn->clearMedia(); + StringProperty* movie = + fsipn->property("media.movie"); + movie->resize(0); + for (int i = 0; i < mediaFiles.size(); ++i) + movie->push_back(mediaFiles[i]); + IntProperty* mediaActive = + fsipn->property("media.active"); + mediaActive->front() = 1; + fsipn->propertyChanged(movie); - ostringstream nscontents; - string media = (mediaFiles.size() > 0) ? mediaFiles[0] : ""; - nscontents << srcNode << ";;RVSource;;" << media; - userGenericEvent("new-source", nscontents.str()); + ostringstream nscontents; + string media = (mediaFiles.size() > 0) ? mediaFiles[0] : ""; + nscontents << srcNode << ";;RVSource;;" << media; + userGenericEvent("new-source", nscontents.str()); - ostringstream smscontents; - smscontents << srcNode << ";;" << tag; - userGenericEvent("source-media-set", smscontents.str()); + ostringstream smscontents; + smscontents << srcNode << ";;" << tag; + userGenericEvent("source-media-set", smscontents.str()); - fsipn->setProgressiveSourceLoading(isProgressiveLoadingEnabled); - } - else - { - TWK_THROW_EXC_STREAM("Bad node type " << srcNode); + fsipn->setProgressiveSourceLoading( + isProgressiveLoadingEnabled); + } + else + { + TWK_THROW_EXC_STREAM("Bad node type " << srcNode); + } } } - } - else - { - TWK_THROW_STREAM(IPCore::ReadFailedExc, "Can't find node " << srcNode); + else + { + TWK_THROW_STREAM(IPCore::ReadFailedExc, + "Can't find node " << srcNode); + } } -} - -SourceIPNode* -RvSession::addSourceMediaRep(const std::string& srcNodeName, - const std::string& mediaRepName, - const StringVector& mediaRepPathsAndOptionsArg, - const std::string& tag) -{ - Options::SourceArgs sargs; - if (!mediaRepPathsAndOptionsArg.empty()) + SourceIPNode* RvSession::addSourceMediaRep( + const std::string& srcNodeName, const std::string& mediaRepName, + const StringVector& mediaRepPathsAndOptionsArg, const std::string& tag) { - StringVector sourceArgs; - sourceArgs.push_back("["); - for (int i=0; igroup()!=nullptr && - switchNode->group()->protocol() == "RVSwitchGroup"; -} + auto result = + addSource(mediaRepPaths, sargs, "" /*nodeName*/, + "RVFileSource" /*nodeType*/, mediaRepName, srcNodeName); -// Find and return the Switch node(s) associated with the specified source node name if any -vector -RvSession::findSwitchIPNodes(const string& srcNodeOrSwitchNodeName) -{ - vector switchNodes; - - NodeVector nodes; - if (srcNodeOrSwitchNodeName == "") - { - findCurrentNodesByTypeName(nodes, "RVSwitch"); + return result; } - else if (srcNodeOrSwitchNodeName == "all") + + // Returns true if the switch node as parameter belongs to an RVSwitchGroup + static bool isGroupedSwitchNode(SwitchIPNode const* const switchNode) { - graph().findNodesByTypeName(nodes, "RVSwitch"); + return switchNode && switchNode->group() != nullptr + && switchNode->group()->protocol() == "RVSwitchGroup"; } - else if (IPNode* srcNode = graph().findNode(srcNodeOrSwitchNodeName)) + + // Find and return the Switch node(s) associated with the specified source + // node name if any + vector + RvSession::findSwitchIPNodes(const string& srcNodeOrSwitchNodeName) { - SwitchIPNode* switchNode = dynamic_cast(srcNode); - if (!switchNode && srcNode->group()) + vector switchNodes; + + NodeVector nodes; + if (srcNodeOrSwitchNodeName == "") + { + findCurrentNodesByTypeName(nodes, "RVSwitch"); + } + else if (srcNodeOrSwitchNodeName == "all") + { + graph().findNodesByTypeName(nodes, "RVSwitch"); + } + else if (IPNode* srcNode = graph().findNode(srcNodeOrSwitchNodeName)) { - switchNode = dynamic_cast( - graph().findNodeAssociatedWith(srcNode->group(), "RVSwitch")); + SwitchIPNode* switchNode = dynamic_cast(srcNode); + if (!switchNode && srcNode->group()) + { + switchNode = + dynamic_cast(graph().findNodeAssociatedWith( + srcNode->group(), "RVSwitch")); + } + + // Make sure that the switch node (if any) is part of a switch group + if (switchNode && isGroupedSwitchNode(switchNode)) + { + switchNodes.push_back(switchNode); + } } - // Make sure that the switch node (if any) is part of a switch group - if (switchNode && isGroupedSwitchNode(switchNode)) + for (NodeVector::iterator i = nodes.begin(); i != nodes.end(); ++i) { - switchNodes.push_back(switchNode); + // Make sure that the switch node (if any) is part of a switch group + SwitchIPNode* switchNode = dynamic_cast(*i); + if (switchNode && isGroupedSwitchNode(switchNode)) + { + switchNodes.push_back(switchNode); + } } + + return switchNodes; } - for (NodeVector::iterator i = nodes.begin(); i != nodes.end(); ++i) + // Find and return the source group node corresponding to the requested + // source media representation if any + static SourceGroupIPNode* sourceGroupFromSwitchInput(IPNode* switchInput) { - // Make sure that the switch node (if any) is part of a switch group - SwitchIPNode* switchNode = dynamic_cast(*i); - if (switchNode && isGroupedSwitchNode(switchNode)) + if (AdaptorIPNode* adaptor = dynamic_cast(switchInput)) { - switchNodes.push_back(switchNode); + switchInput = adaptor->groupInputNode(); + } + if (SourceGroupIPNode* srcGroup = + dynamic_cast(switchInput)) + { + return srcGroup; } - } - return switchNodes; -} + return nullptr; + } -// Find and return the source group node corresponding to the requested source -// media representation if any -static SourceGroupIPNode* -sourceGroupFromSwitchInput(IPNode* switchInput) -{ - if (AdaptorIPNode* adaptor = dynamic_cast(switchInput)) + // Find and return the source node corresponding to the requested source + // media representation if any + static SourceIPNode* sourceFromSwitchInput(IPNode* switchInput) { - switchInput = adaptor->groupInputNode(); - } - if (SourceGroupIPNode* srcGroup = dynamic_cast(switchInput)) - { - return srcGroup; - } - - return nullptr; -} - -// Find and return the source node corresponding to the requested source media -// representation if any -static SourceIPNode* -sourceFromSwitchInput(IPNode* switchInput) -{ - if (SourceGroupIPNode* srcGroup = sourceGroupFromSwitchInput(switchInput)) - { - if (FileSourceIPNode* srcNode = - dynamic_cast(srcGroup->memberByType("RVFileSource"))) - { - return srcNode; - } - if (ImageSourceIPNode* srcNode = - dynamic_cast(srcGroup->memberByType("RVImageSource"))) + if (SourceGroupIPNode* srcGroup = + sourceGroupFromSwitchInput(switchInput)) { - return srcNode; - } - } - - return nullptr; -} - -// Finds and returns the source group corresponding to the requested source -// media representation if any -static SourceGroupIPNode* -findSourceGroupMediaRep(SwitchIPNode* switchNode, const std::string& mediaRepName, SourceIPNode*& out_srcNode) -{ - for (int i = 0; i < switchNode->inputs().size(); ++i) - { - if (SourceIPNode* srcNode = sourceFromSwitchInput(switchNode->inputs()[i])) - { - if (srcNode->mediaRepName() == mediaRepName) + if (FileSourceIPNode* srcNode = dynamic_cast( + srcGroup->memberByType("RVFileSource"))) + { + return srcNode; + } + if (ImageSourceIPNode* srcNode = dynamic_cast( + srcGroup->memberByType("RVImageSource"))) { - out_srcNode = srcNode; - return dynamic_cast(srcNode->group()); + return srcNode; } } - } - return nullptr; -} + return nullptr; + } -// Returns the currently selected source media representation's name -std::string RvSession::sourceMediaRep( - const string& srcNodeOrSwitchNodeName -) -{ - // Find the Switch node associated with the specified switch or source node if any - SwitchIPNode* switchNode = this->switchNode(srcNodeOrSwitchNodeName); - if (!switchNode) + // Finds and returns the source group corresponding to the requested source + // media representation if any + static SourceGroupIPNode* + findSourceGroupMediaRep(SwitchIPNode* switchNode, + const std::string& mediaRepName, + SourceIPNode*& out_srcNode) { - std::vector switchNodes = findSwitchIPNodes(srcNodeOrSwitchNodeName); - if (!switchNodes.empty()) + for (int i = 0; i < switchNode->inputs().size(); ++i) { - switchNode = switchNodes[0]; + if (SourceIPNode* srcNode = + sourceFromSwitchInput(switchNode->inputs()[i])) + { + if (srcNode->mediaRepName() == mediaRepName) + { + out_srcNode = srcNode; + return dynamic_cast(srcNode->group()); + } + } } - } - // If there is no associated switch nodes then it means there is only a - // single source media representation - SourceIPNode* srcNode = nullptr; - if (!switchNode) - { - srcNode = sourceNode(srcNodeOrSwitchNodeName); - } - else - { - srcNode = sourceFromSwitchInput(switchNode->activeInput()); + return nullptr; } - return srcNode ? srcNode->mediaRepName() : ""; -} - -// Finds and returns the Source Media Representation names available -void RvSession::sourceMediaReps( - const string& srcNodeOrSwitchNodeName, - StringVector& sourceMediaReps, - StringVector* sourceNodes /* = nullptr */ -) -{ - sourceMediaReps.clear(); - if (sourceNodes) sourceNodes->clear(); - - // Find the Switch node associated with the specified switch or source node if any - SwitchIPNode* switchNode = this->switchNode(srcNodeOrSwitchNodeName); - if (!switchNode) + // Returns the currently selected source media representation's name + std::string RvSession::sourceMediaRep(const string& srcNodeOrSwitchNodeName) { - std::vector switchNodes = findSwitchIPNodes(srcNodeOrSwitchNodeName); - if (!switchNodes.empty()) + // Find the Switch node associated with the specified switch or source + // node if any + SwitchIPNode* switchNode = this->switchNode(srcNodeOrSwitchNodeName); + if (!switchNode) { - switchNode = switchNodes[0]; + std::vector switchNodes = + findSwitchIPNodes(srcNodeOrSwitchNodeName); + if (!switchNodes.empty()) + { + switchNode = switchNodes[0]; + } } - } - // If there is no associated switch nodes then it means there is only a - // single source media representation - if (!switchNode) - { - SourceIPNode* srcNode = sourceNode(srcNodeOrSwitchNodeName); - if (srcNode) + // If there is no associated switch nodes then it means there is only a + // single source media representation + SourceIPNode* srcNode = nullptr; + if (!switchNode) { - sourceMediaReps.push_back(srcNode->mediaRepName()); - if (sourceNodes) sourceNodes->push_back(srcNode->name()); + srcNode = sourceNode(srcNodeOrSwitchNodeName); } - return; - } - - for (size_t i = 0; i < switchNode->inputs().size(); ++i) - { - if (SourceIPNode* srcNode = sourceFromSwitchInput(switchNode->inputs()[i])) + else { - sourceMediaReps.push_back(srcNode->mediaRepName()); - if (sourceNodes) sourceNodes->push_back(srcNode->name()); + srcNode = sourceFromSwitchInput(switchNode->activeInput()); } - } -} -// Returns the source media rep switch node associated with the source if any -std::string RvSession::sourceMediaRepSwitchNode( - const string& srcNodeName -) -{ - // Find the Switch node(s) associated with the specified source node if any - std::vector switchNodes = findSwitchIPNodes(srcNodeName); - - return switchNodes.empty() ? "" : switchNodes[0]->name(); -} - -// Returns the source media rep's switch node's first input associated with the source if any -std::string RvSession::sourceMediaRepSourceNode( - const string& srcNodeName -) -{ - // Find the Switch node(s) associated with the specified source node if any - std::vector switchNodes = findSwitchIPNodes(srcNodeName); - - // If there is no associated switch nodes then it means there is only a - // single source media representation - if (!switchNodes.empty() && switchNodes[0]->inputs().size()>=1) - { - SourceIPNode* srcNode = sourceFromSwitchInput(switchNodes[0]->inputs()[0]); - if (srcNode) - { - return srcNode->name(); - } + return srcNode ? srcNode->mediaRepName() : ""; } - return ""; -} - -void -RvSession::setActiveSourceMediaRep(const std::string& srcNodeOrSwitchNodeName, - const std::string& mediaRepName, - const std::string& tag) -{ - // Find the Switch node associated with the specified switch or source node if any - vector switchNodes; - SwitchIPNode* switchNode = this->switchNode(srcNodeOrSwitchNodeName); - if (switchNode) - { - switchNodes.push_back(switchNode); - } - else + // Finds and returns the Source Media Representation names available + void RvSession::sourceMediaReps(const string& srcNodeOrSwitchNodeName, + StringVector& sourceMediaReps, + StringVector* sourceNodes /* = nullptr */ + ) { - switchNodes = findSwitchIPNodes(srcNodeOrSwitchNodeName); - } + sourceMediaReps.clear(); + if (sourceNodes) + sourceNodes->clear(); - // Nothing to do if there isn't any - if (switchNodes.empty()) - { - if (srcNodeOrSwitchNodeName!="" && srcNodeOrSwitchNodeName!="all") + // Find the Switch node associated with the specified switch or source + // node if any + SwitchIPNode* switchNode = this->switchNode(srcNodeOrSwitchNodeName); + if (!switchNode) { - // Log an error but only if the requested media rep to activate is - // not the currently active one - SourceIPNode* srcNode = sourceNode(srcNodeOrSwitchNodeName); - if (!srcNode || srcNode->mediaRepName()!=mediaRepName) + std::vector switchNodes = + findSwitchIPNodes(srcNodeOrSwitchNodeName); + if (!switchNodes.empty()) { - TWK_THROW_STREAM(IPCore::ReadFailedExc, "Can't find switch node associated with source node " - << srcNodeOrSwitchNodeName << " to select the '" << mediaRepName << "' media representation."); + switchNode = switchNodes[0]; } } - return; - } - - // Swap media for all the specified switch node(s) - for( const auto& switchNode : switchNodes ) - { - if (SourceIPNode* activeSrcNode = sourceFromSwitchInput(switchNode->activeInput())) + // If there is no associated switch nodes then it means there is only a + // single source media representation + if (!switchNode) { - // Select the requested media representation if this not the currently selected one. - if (activeSrcNode->mediaRepName() != mediaRepName) + SourceIPNode* srcNode = sourceNode(srcNodeOrSwitchNodeName); + if (srcNode) { - SourceIPNode* newSrcNode = nullptr; - if (SourceGroupIPNode* newSrcGroup = findSourceGroupMediaRep(switchNode, mediaRepName, newSrcNode)) - { - if (StringProperty *switchInputProp = switchNode->property("output.input")) - { - if ((*switchInputProp)[0]!=newSrcGroup->name()) - { - // Select the new source group - switchNode->propertyWillChange(switchInputProp); - (*switchInputProp)[0]=newSrcGroup->name(); - switchNode->propertyChanged(switchInputProp); - - ostringstream eventContents; - eventContents << newSrcNode->name() << ";;" << newSrcNode->mediaRepName() << ";;" - << activeSrcNode->name() << ";;" << activeSrcNode->mediaRepName(); - userGenericEvent("source-media-rep-activated", eventContents.str()); - } - } - } - else - { - if (srcNodeOrSwitchNodeName!="" && srcNodeOrSwitchNodeName!="all") - { - TWK_THROW_STREAM(IPCore::ReadFailedExc, - "Can't find source group associated with " - << srcNodeOrSwitchNodeName << " to select the '" - << mediaRepName << "' media representation."); - } - else - { - // Otherwise, make sure the active source node's media is active - // Note that this will trigger the multiple source media fallback - // mechanism if the current source cannot be activated (ie if it - // is not available) - activeSrcNode->setMediaActive(true); - } - } + sourceMediaReps.push_back(srcNode->mediaRepName()); + if (sourceNodes) + sourceNodes->push_back(srcNode->name()); } - // Otherwise make sure the active source node's media is active - else + return; + } + + for (size_t i = 0; i < switchNode->inputs().size(); ++i) + { + if (SourceIPNode* srcNode = + sourceFromSwitchInput(switchNode->inputs()[i])) { - activeSrcNode->setMediaActive(true); + sourceMediaReps.push_back(srcNode->mediaRepName()); + if (sourceNodes) + sourceNodes->push_back(srcNode->name()); } } } -} -void -RvSession::write(const string& infilename, const WriteRequest& request) -{ - const string filename = pathConform(infilename); - const string ext = extension(filename); - const bool writeAsCopy = request.optionValue("writeAsCopy", false); - - if (ext == "rv") + // Returns the source media rep switch node associated with the source if + // any + std::string RvSession::sourceMediaRepSwitchNode(const string& srcNodeName) { - // - // Make a new WriteRequest based on what we get that has - // internal options set to write an rv style session file - // - - WriteRequest newRequest = request; + // Find the Switch node(s) associated with the specified source node if + // any + std::vector switchNodes = findSwitchIPNodes(srcNodeName); - // - // If there's an ImageSourceIPNode in the session than force - // the use of compressed binary output - // + return switchNodes.empty() ? "" : switchNodes[0]->name(); + } - const IPGraph::NodeMap& nodeMap = graph().nodeMap(); - bool bigFile = false; + // Returns the source media rep's switch node's first input associated with + // the source if any + std::string RvSession::sourceMediaRepSourceNode(const string& srcNodeName) + { + // Find the Switch node(s) associated with the specified source node if + // any + std::vector switchNodes = findSwitchIPNodes(srcNodeName); - for (NodeMap::const_iterator i = nodeMap.begin(); - i != nodeMap.end(); - ++i) + // If there is no associated switch nodes then it means there is only a + // single source media representation + if (!switchNodes.empty() && switchNodes[0]->inputs().size() >= 1) { - IPNode* n = i->second; - if (dynamic_cast(n)) bigFile = true; + SourceIPNode* srcNode = + sourceFromSwitchInput(switchNodes[0]->inputs()[0]); + if (srcNode) + { + return srcNode->name(); + } } - // - // Set the RV specific write options - // - - newRequest.setOption("writerID", string("RV")); - newRequest.setOption("sessionProtocol", string("RVSession")); - newRequest.setOption("sessionProtocolVersion", 4); - newRequest.setOption("sessionName", string("rv")); - newRequest.setOption("version", 2); - if (bigFile) newRequest.setOption("compressed", true); - - // - // Output pre events - // - - if (writeAsCopy) userGenericEvent("before-session-write-copy", filename); - else userGenericEvent("before-session-write", filename); - - // - // Call the generic session writer - // - - Session::write(filename, newRequest); - setFileName(filename.c_str()); - - // - // post write events - // - - if (writeAsCopy) userGenericEvent("after-session-write-copy", filename); - else userGenericEvent("after-session-write", filename); + return ""; } - else - { - Session::write(infilename, request); - } -} -struct FrameBufferFinder -{ - FrameBufferFinder() : fbImage(0) {} - const IPImage* fbImage; - - void operator () (IPImage* i) + void RvSession::setActiveSourceMediaRep( + const std::string& srcNodeOrSwitchNodeName, + const std::string& mediaRepName, const std::string& tag) { - if (fbImage) return; - if (i->destination != IPImage::OutputTexture) + // Find the Switch node associated with the specified switch or source + // node if any + vector switchNodes; + SwitchIPNode* switchNode = this->switchNode(srcNodeOrSwitchNodeName); + if (switchNode) { - fbImage = i; + switchNodes.push_back(switchNode); } - } -}; - -const TwkFB::FrameBuffer* -RvSession::currentFB() const -{ - FrameBufferFinder finder; - foreach_ip (m_displayImage, finder); - return finder.fbImage ? finder.fbImage->fb : 0; -} - -SourceIPNode* -RvSession::sourceNode(const std::string& sourceName) const -{ - StringVector tokens; - stl_ext::tokenize(tokens, sourceName, "./"); - - if (!tokens.empty()) - { - if (IPNode* node = graph().findNode(tokens.front())) + else { - if (SourceIPNode* source = dynamic_cast(node)) - { - return source; - } + switchNodes = findSwitchIPNodes(srcNodeOrSwitchNodeName); } - } - - return 0; -} -SwitchIPNode* -RvSession::switchNode(const std::string& switchNodeName) const -{ - StringVector tokens; - stl_ext::tokenize(tokens, switchNodeName, "./"); - - if (!tokens.empty()) - { - if (IPNode* node = graph().findNode(tokens.front())) + // Nothing to do if there isn't any + if (switchNodes.empty()) { - if (SwitchIPNode* switchNode = dynamic_cast(node)) + if (srcNodeOrSwitchNodeName != "" + && srcNodeOrSwitchNodeName != "all") { - return switchNode; + // Log an error but only if the requested media rep to activate + // is not the currently active one + SourceIPNode* srcNode = sourceNode(srcNodeOrSwitchNodeName); + if (!srcNode || srcNode->mediaRepName() != mediaRepName) + { + TWK_THROW_STREAM( + IPCore::ReadFailedExc, + "Can't find switch node associated with source node " + << srcNodeOrSwitchNodeName << " to select the '" + << mediaRepName << "' media representation."); + } } - } - } - return 0; -} - -const TwkFB::FrameBuffer* -RvSession::currentFB(const std::string& sourceName) const -{ - if (m_displayImage) - { - StringVector tokens; - stl_ext::tokenize(tokens, sourceName, "/"); + return; + } - for (size_t i = 0; i < m_displayFBStatus.size(); i++) + // Swap media for all the specified switch node(s) + for (const auto& switchNode : switchNodes) { - if (TwkFB::FrameBuffer* fb = m_displayFBStatus[i].fb) + if (SourceIPNode* activeSrcNode = + sourceFromSwitchInput(switchNode->activeInput())) { - string n = fb->attribute("RVSource"); - - if (n == sourceName) - { - return fb; - } - else + // Select the requested media representation if this not the + // currently selected one. + if (activeSrcNode->mediaRepName() != mediaRepName) { - StringVector stokens; - stl_ext::tokenize(stokens, n, "/"); - - if (stokens.size() >= tokens.size()) + SourceIPNode* newSrcNode = nullptr; + if (SourceGroupIPNode* newSrcGroup = + findSourceGroupMediaRep(switchNode, mediaRepName, + newSrcNode)) { - bool matches = true; - - for (size_t q = 0; q < tokens.size(); q++) + if (StringProperty* switchInputProp = + switchNode->property( + "output.input")) { - if (stokens[q] != tokens[q]) + if ((*switchInputProp)[0] != newSrcGroup->name()) { - matches = false; - break; + // Select the new source group + switchNode->propertyWillChange(switchInputProp); + (*switchInputProp)[0] = newSrcGroup->name(); + switchNode->propertyChanged(switchInputProp); + + ostringstream eventContents; + eventContents << newSrcNode->name() << ";;" + << newSrcNode->mediaRepName() + << ";;" << activeSrcNode->name() + << ";;" + << activeSrcNode->mediaRepName(); + userGenericEvent("source-media-rep-activated", + eventContents.str()); } } - - if (matches) return fb; } - } - } - } - - // - // If user passed in a simple name, and we did not find a match above, - // look again and return fb if leading substr matches. - // - - if (tokens.size() == 1) - { - for (size_t i = 0; i < m_displayFBStatus.size(); i++) - { - if (TwkFB::FrameBuffer* fb = m_displayFBStatus[i].fb) - { - string n = fb->attribute("RVSource"); - - if (sourceName.compare(0, string::npos, n, 0, sourceName.size()) == 0) + else { - return fb; + if (srcNodeOrSwitchNodeName != "" + && srcNodeOrSwitchNodeName != "all") + { + TWK_THROW_STREAM( + IPCore::ReadFailedExc, + "Can't find source group associated with " + << srcNodeOrSwitchNodeName + << " to select the '" << mediaRepName + << "' media representation."); + } + else + { + // Otherwise, make sure the active source node's + // media is active Note that this will trigger the + // multiple source media fallback mechanism if the + // current source cannot be activated (ie if it is + // not available) + activeSrcNode->setMediaActive(true); + } } } + // Otherwise make sure the active source node's media is active + else + { + activeSrcNode->setMediaActive(true); + } } } } - return 0; -} - -bool -RvSession::isEmpty() const -{ - return rvgraph().imageSources().empty(); -} - - -void -RvSession::postInitialize() -{ - if (Function* F = sessionFunction("initialize")) + void RvSession::write(const string& infilename, const WriteRequest& request) { - makeActive(); - Context::ArgumentVector v; - TypedValue tv = TwkApp::muContext()->evalFunction(TwkApp::muProcess(), F, v); + const string filename = pathConform(infilename); + const string ext = extension(filename); + const bool writeAsCopy = + request.optionValue("writeAsCopy", false); - if (m_data = (Object*)tv._value._Pointer) + if (ext == "rv") { - m_data->retainExternal(); - } - } - - // - // Same thing but with python - // - - m_pydata = callPythonFunction("initialize"); + // + // Make a new WriteRequest based on what we get that has + // internal options set to write an rv style session file + // - userGenericEvent("state-intialized", ""); - userGenericEvent("state-initialized", ""); + WriteRequest newRequest = request; - // - // Mu setup - // + // + // If there's an ImageSourceIPNode in the session than force + // the use of compressed binary output + // - if (Function* F = sessionFunction("setup")) - { - makeActive(); - Context::ArgumentVector v; - TwkApp::muContext()->evalFunction(TwkApp::muProcess(), F, v); - } + const IPGraph::NodeMap& nodeMap = graph().nodeMap(); + bool bigFile = false; - // - // Same thing but with python - // + for (NodeMap::const_iterator i = nodeMap.begin(); + i != nodeMap.end(); ++i) + { + IPNode* n = i->second; + if (dynamic_cast(n)) + bigFile = true; + } - void* ignored = callPythonFunction("setup"); - disposeOfPythonObject(ignored); + // + // Set the RV specific write options + // - // - // Mu init / command-line eval - // + newRequest.setOption("writerID", string("RV")); + newRequest.setOption("sessionProtocol", string("RVSession")); + newRequest.setOption("sessionProtocolVersion", 4); + newRequest.setOption("sessionName", string("rv")); + newRequest.setOption("version", 2); + if (bigFile) + newRequest.setOption("compressed", true); - if (m_initEval != "") - { - string output = muEval(muContext(), - muProcess(), - muModuleList(), - m_initEval.c_str(), - "Command line eval"); + // + // Output pre events + // - if ("string => \"noprint\"" != output) - { - cout << "INFO: eval returned: " << output << endl; - } - m_initEval.clear(); - } + if (writeAsCopy) + userGenericEvent("before-session-write-copy", filename); + else + userGenericEvent("before-session-write", filename); - // - // Same thing but with python - // + // + // Call the generic session writer + // - if (m_pyInitEval != "") - { - TwkApp::evalPython(m_pyInitEval.c_str()); - } -} + Session::write(filename, newRequest); + setFileName(filename.c_str()); -string -RvSession::currentSourceName() const -{ - string name; + // + // post write events + // - try - { - if (!currentFB()) - { - name = "Untitled.rv"; + if (writeAsCopy) + userGenericEvent("after-session-write-copy", filename); + else + userGenericEvent("after-session-write", filename); } else { - name = currentFB()->attribute("Sequence"); + Session::write(infilename, request); } } - catch (...) - { - name = "?"; - } - - return name; -} - - -//---------------------------------------------------------------------- -void -RvSession::readGTOSessionContainer(PropertyContainer* pc) -{ - - StringProperty* vnp = pc->property("session.viewNode"); - StringProperty* sp = pc->property("session.sources"); - IntProperty* mp = pc->property("session.marks"); - IntProperty* tp = pc->property("session.type"); - Vec2iProperty* rp = pc->property("session.range"); - Vec2iProperty* iop = pc->property("session.region"); - FloatProperty* fpsp = pc->property("session.fps"); - IntProperty* rtp = pc->property("session.realtime"); - IntProperty* incp = pc->property("session.inc"); - IntProperty* fp = pc->property("session.currentFrame"); - IntProperty* bg = pc->property("session.background"); - - if (sp) + struct FrameBufferFinder { - // - // Backwards compat - // - - Options::SourceArgs sargs; - for (int i=0; i < sp->size(); i++) + FrameBufferFinder() + : fbImage(0) { - addSource((*sp)[i], sargs); - cout << "INFO: added " << (*sp)[i] << endl; } - } - - for (int i=0; mp && i < mp->size(); i++) - { - markFrame((*mp)[i]); - } - if (fpsp && !fpsp->empty()) setFPS(fpsp->front()); - if (rtp && !rtp->empty()) setRealtime(rtp->front() ? true : false); - if (incp && !incp->empty()) setInc(incp->front()); - if (rp && !rp->empty()) setRangeStart(rp->front().x); - if (rp && !rp->empty()) setRangeEnd(rp->front().y); - if (iop && !iop->empty()) setInPoint(iop->front().x); - if (iop && !iop->empty()) setOutPoint(iop->front().y); + const IPImage* fbImage; - if (vnp && !vnp->empty()) - { - setViewNode(vnp->front(), true); - } + void operator()(IPImage* i) + { + if (fbImage) + return; + if (i->destination != IPImage::OutputTexture) + { + fbImage = i; + } + } + }; - if (bg && !bg->empty()) + const TwkFB::FrameBuffer* RvSession::currentFB() const { - m_renderer->setBGPattern((ImageRenderer::BGPattern)bg->front()); + FrameBufferFinder finder; + foreach_ip(m_displayImage, finder); + return finder.fbImage ? finder.fbImage->fb : 0; } -} - -namespace { - -void -makeTopLevelSet(PropertyContainer* connections, - GTOReader::Containers& containers, - set& topLevelSet) -{ - StringProperty* lhs = connections ? connections->property("evaluation.lhs") : 0; - StringProperty* rhs = connections ? connections->property("evaluation.rhs") : 0; - StringPairProperty* cons = connections ? connections->property("evaluation.connections") : 0; - StringProperty* top = connections ? connections->property("top.nodes") : 0; - if (top) + SourceIPNode* RvSession::sourceNode(const std::string& sourceName) const { - std::copy(top->valueContainer().begin(), - top->valueContainer().end(), - std::inserter(topLevelSet, topLevelSet.begin())); - } + StringVector tokens; + stl_ext::tokenize(tokens, sourceName, "./"); - if (lhs && rhs) - { - std::copy(lhs->valueContainer().begin(), - lhs->valueContainer().end(), - std::inserter(topLevelSet, topLevelSet.begin())); + if (!tokens.empty()) + { + if (IPNode* node = graph().findNode(tokens.front())) + { + if (SourceIPNode* source = dynamic_cast(node)) + { + return source; + } + } + } - std::copy(rhs->valueContainer().begin(), - rhs->valueContainer().end(), - std::inserter(topLevelSet, topLevelSet.begin())); + return 0; } - if (cons) + SwitchIPNode* RvSession::switchNode(const std::string& switchNodeName) const { - const StringPairProperty::container_type& array = cons->valueContainer(); + StringVector tokens; + stl_ext::tokenize(tokens, switchNodeName, "./"); - for (size_t i = 0; i < array.size(); i++) + if (!tokens.empty()) { - topLevelSet.insert(array[i].first); - topLevelSet.insert(array[i].second); + if (IPNode* node = graph().findNode(tokens.front())) + { + if (SwitchIPNode* switchNode = + dynamic_cast(node)) + { + return switchNode; + } + } } + + return 0; } - for (size_t i = 0; i < containers.size(); i++) + const TwkFB::FrameBuffer* + RvSession::currentFB(const std::string& sourceName) const { - PropertyContainer* pc = containers[i]; - string name = TwkContainer::name(pc); - - if (pc->property("ui.name")) + if (m_displayImage) { - // - // If ui.name *and* has no _ in the name (meaning its one of ours?) - // + StringVector tokens; + stl_ext::tokenize(tokens, sourceName, "/"); - if (name.find("_") == string::npos) topLevelSet.insert(name); - } - } -} + for (size_t i = 0; i < m_displayFBStatus.size(); i++) + { + if (TwkFB::FrameBuffer* fb = m_displayFBStatus[i].fb) + { + string n = fb->attribute("RVSource"); -void -inputsForNode(PropertyContainer* connections, - IPGraph& graph, - const string& name, - IPGraph::IPNodes& inputs) -{ - if (!connections) return; + if (n == sourceName) + { + return fb; + } + else + { + StringVector stokens; + stl_ext::tokenize(stokens, n, "/"); - StringProperty* lhs = connections->property("evaluation.lhs"); - StringProperty* rhs = connections->property("evaluation.rhs"); - StringPairProperty* cons = connections->property("evaluation.connections"); + if (stokens.size() >= tokens.size()) + { + bool matches = true; - if (!cons) - { - if (!lhs || !rhs || lhs->size() != rhs->size()) return; - } + for (size_t q = 0; q < tokens.size(); q++) + { + if (stokens[q] != tokens[q]) + { + matches = false; + break; + } + } - inputs.clear(); + if (matches) + return fb; + } + } + } + } - if (cons) - { - for (size_t i = 0; i < cons->size(); i++) - { - const pair& arrow = (*cons)[i]; + // + // If user passed in a simple name, and we did not find a match + // above, look again and return fb if leading substr matches. + // - if (arrow.second == name) + if (tokens.size() == 1) { - if (IPNode* n = graph.findNode(arrow.first)) + for (size_t i = 0; i < m_displayFBStatus.size(); i++) { - inputs.push_back(n); - } - else - { - cout << "WARNING: could not find node " - << arrow.first << " when trying to connect inputs for " - << name - << endl; + if (TwkFB::FrameBuffer* fb = m_displayFBStatus[i].fb) + { + string n = fb->attribute("RVSource"); + + if (sourceName.compare(0, string::npos, n, 0, + sourceName.size()) + == 0) + { + return fb; + } + } } } } + + return 0; } - else + + bool RvSession::isEmpty() const { return rvgraph().imageSources().empty(); } + + void RvSession::postInitialize() { - for (size_t i = 0; i < rhs->size(); i++) + if (Function* F = sessionFunction("initialize")) { - if ((*rhs)[i] == name) + makeActive(); + Context::ArgumentVector v; + TypedValue tv = + TwkApp::muContext()->evalFunction(TwkApp::muProcess(), F, v); + + if (m_data = (Object*)tv._value._Pointer) { - if (IPNode* n = graph.findNode((*lhs)[i])) - { - inputs.push_back(n); - } - else - { - cout << "WARNING: could not find node " - << (*lhs)[i] << " when trying to connect inputs for " - << name - << endl; - } + m_data->retainExternal(); } } - } -} -typedef set NameSet; -typedef map NameMap; + // + // Same thing but with python + // -#ifdef PLATFORM_WINDOWS -#define PAD "%06d" -#else -#define PAD "%06zd" -#endif + m_pydata = callPythonFunction("initialize"); -string -uniqueName (string name, NameSet& disallowedNames) -{ - static char buf[16]; - static RegEx endRE("(.*[^0-9])([0-9]+)"); - static RegEx midRE("(.*[^0-9])([0-9][0-9][0-9][0-9][0-9][0-9])([^0-9].*)"); + userGenericEvent("state-intialized", ""); + userGenericEvent("state-initialized", ""); - if (disallowedNames.count(name) > 0) - { // - // Find a 6-zero-padded number in the middle. + // Mu setup // - Match midMatch(midRE, name); - if (midMatch) + if (Function* F = sessionFunction("setup")) { - string finalName; - istringstream istr (midMatch.subStr(1)); - int n; - istr >> n; - do - { - ++n; - sprintf (buf, PAD, size_t(n)); - ostringstream str; - str << midMatch.subStr(0) << buf << midMatch.subStr(2); - finalName = str.str(); - } - while (disallowedNames.count (finalName) > 0); - - return finalName; + makeActive(); + Context::ArgumentVector v; + TwkApp::muContext()->evalFunction(TwkApp::muProcess(), F, v); } // - // Find a possibly zero-padded number on the end. + // Same thing but with python + // + + void* ignored = callPythonFunction("setup"); + disposeOfPythonObject(ignored); + + // + // Mu init / command-line eval // - Match endMatch(endRE, name); - if (endMatch) + if (m_initEval != "") { - string finalName; - istringstream istr (endMatch.subStr(1)); - int n; - istr >> n; - do + string output = muEval(muContext(), muProcess(), muModuleList(), + m_initEval.c_str(), "Command line eval"); + + if ("string => \"noprint\"" != output) { - ++n; - sprintf (buf, PAD, size_t(n)); - ostringstream str; - str << endMatch.subStr(0) << buf; - finalName = str.str(); + cout << "INFO: eval returned: " << output << endl; } - while (disallowedNames.count (finalName) > 0); - - return finalName; + m_initEval.clear(); } // - // Fallback: add a number to the end and recurse + // Same thing but with python // - ostringstream str; - str << name << "000002"; - return uniqueName(str.str(), disallowedNames); - } - - return name; -} - -void -uniqifyContainerNames (GTOReader::Containers& containers, NameSet& existingNames) -{ - NameSet origNames; - NameSet conflictingNames; - NameMap newNameMap; - - // - // run through containers that correspond to top-level nodes, identify those that - // conflict with existingNames - // - - for (size_t i = 0; i < containers.size(); i++) - { - PropertyContainer* pc = containers[i]; - - if (protocol(pc) == "RVSession") continue; - - string nm = TwkContainer::name(pc); - if (nm.find('_') == string::npos && existingNames.count(nm)) + if (m_pyInitEval != "") { - conflictingNames.insert(nm); + TwkApp::evalPython(m_pyInitEval.c_str()); } - origNames.insert(nm); } - // - // for every conflicting top-level name, choose a new name (same type!) that isn't - // in either the original list, or the new one. - // - - - NameSet disallowedNames = existingNames; - disallowedNames.insert (origNames.begin(), origNames.end()); - - for (NameSet::iterator i = conflictingNames.begin(); i != conflictingNames.end(); ++i) + string RvSession::currentSourceName() const { + string name; - string newName = uniqueName (*i, disallowedNames); + try + { + if (!currentFB()) + { + name = "Untitled.rv"; + } + else + { + name = currentFB()->attribute("Sequence"); + } + } + catch (...) + { + name = "?"; + } - newNameMap[*i] = newName; - disallowedNames.insert (newName); + return name; } - // - // run through all containers, add mappings for non-top-level containers, - // based on the mapping for the corresponding top-level container(s). - // + //---------------------------------------------------------------------- - for (size_t i = 0; i < containers.size(); i++) + void RvSession::readGTOSessionContainer(PropertyContainer* pc) { - PropertyContainer* pc = containers[i]; - - if (protocol(pc) == "RVSession") continue; - string nm = TwkContainer::name(pc); + StringProperty* vnp = pc->property("session.viewNode"); + StringProperty* sp = pc->property("session.sources"); + IntProperty* mp = pc->property("session.marks"); + IntProperty* tp = pc->property("session.type"); + Vec2iProperty* rp = pc->property("session.range"); + Vec2iProperty* iop = pc->property("session.region"); + FloatProperty* fpsp = pc->property("session.fps"); + IntProperty* rtp = pc->property("session.realtime"); + IntProperty* incp = pc->property("session.inc"); + IntProperty* fp = pc->property("session.currentFrame"); + IntProperty* bg = pc->property("session.background"); - int gp = nm.find('_'); - if (gp != string::npos) + if (sp) { - string newName; + // + // Backwards compat + // - string groupName = nm.substr (0, gp); - if (newNameMap.count (groupName)) groupName = newNameMap[groupName]; + Options::SourceArgs sargs; + for (int i = 0; i < sp->size(); i++) + { + addSource((*sp)[i], sargs); + cout << "INFO: added " << (*sp)[i] << endl; + } + } - int ip = nm.rfind('_'); - string inputName = nm.substr (ip+1); - if (newNameMap.count (inputName)) inputName = newNameMap[inputName]; + for (int i = 0; mp && i < mp->size(); i++) + { + markFrame((*mp)[i]); + } - newName = groupName + nm.substr(gp, ip-gp+1) + inputName; + if (fpsp && !fpsp->empty()) + setFPS(fpsp->front()); + if (rtp && !rtp->empty()) + setRealtime(rtp->front() ? true : false); + if (incp && !incp->empty()) + setInc(incp->front()); + if (rp && !rp->empty()) + setRangeStart(rp->front().x); + if (rp && !rp->empty()) + setRangeEnd(rp->front().y); + if (iop && !iop->empty()) + setInPoint(iop->front().x); + if (iop && !iop->empty()) + setOutPoint(iop->front().y); + + if (vnp && !vnp->empty()) + { + setViewNode(vnp->front(), true); + } - newNameMap[nm] = newName; + if (bg && !bg->empty()) + { + m_renderer->setBGPattern((ImageRenderer::BGPattern)bg->front()); } } - // run through all containers, change conflicting container name to new - // name, and any string properites that contain conflicting container name - // to new name - // - - for (int i = 0; i < containers.size(); i++) + namespace { - PropertyContainer* pc = containers[i]; - string nm = TwkContainer::name(pc); + void makeTopLevelSet(PropertyContainer* connections, + GTOReader::Containers& containers, + set& topLevelSet) + { + StringProperty* lhs = + connections + ? connections->property("evaluation.lhs") + : 0; + StringProperty* rhs = + connections + ? connections->property("evaluation.rhs") + : 0; + StringPairProperty* cons = + connections ? connections->property( + "evaluation.connections") + : 0; + StringProperty* top = + connections ? connections->property("top.nodes") + : 0; + + if (top) + { + std::copy(top->valueContainer().begin(), + top->valueContainer().end(), + std::inserter(topLevelSet, topLevelSet.begin())); + } + + if (lhs && rhs) + { + std::copy(lhs->valueContainer().begin(), + lhs->valueContainer().end(), + std::inserter(topLevelSet, topLevelSet.begin())); + + std::copy(rhs->valueContainer().begin(), + rhs->valueContainer().end(), + std::inserter(topLevelSet, topLevelSet.begin())); + } + + if (cons) + { + const StringPairProperty::container_type& array = + cons->valueContainer(); + + for (size_t i = 0; i < array.size(); i++) + { + topLevelSet.insert(array[i].first); + topLevelSet.insert(array[i].second); + } + } + + for (size_t i = 0; i < containers.size(); i++) + { + PropertyContainer* pc = containers[i]; + string name = TwkContainer::name(pc); + + if (pc->property("ui.name")) + { + // + // If ui.name *and* has no _ in the name (meaning its one + // of ours?) + // - if (newNameMap.count (nm)) pc->setName (newNameMap[nm]); + if (name.find("_") == string::npos) + topLevelSet.insert(name); + } + } + } - PropertyContainer::Components& comps = pc->components(); - for (int j = 0; j < comps.size(); ++j) + void inputsForNode(PropertyContainer* connections, IPGraph& graph, + const string& name, IPGraph::IPNodes& inputs) { - if (comps[j]->name() == "object") continue; + if (!connections) + return; + + StringProperty* lhs = + connections->property("evaluation.lhs"); + StringProperty* rhs = + connections->property("evaluation.rhs"); + StringPairProperty* cons = + connections->property( + "evaluation.connections"); + + if (!cons) + { + if (!lhs || !rhs || lhs->size() != rhs->size()) + return; + } - Component::Container& props = comps[j]->properties(); - for (int k = 0; k < props.size(); ++k) + inputs.clear(); + + if (cons) { - if (StringProperty* sp = dynamic_cast (props[k])) + for (size_t i = 0; i < cons->size(); i++) { - for (StringProperty::iterator l = sp->begin(); l != sp->end(); ++l) + const pair& arrow = (*cons)[i]; + + if (arrow.second == name) { - if (newNameMap.count(*l)) + if (IPNode* n = graph.findNode(arrow.first)) + { + inputs.push_back(n); + } + else { - *l = newNameMap[*l]; + cout << "WARNING: could not find node " + << arrow.first + << " when trying to connect inputs for " + << name << endl; } } } - else - if (StringPairProperty* spp = dynamic_cast (props[k])) + } + else + { + for (size_t i = 0; i < rhs->size(); i++) { - for (StringPairProperty::iterator l = spp->begin(); l != spp->end(); ++l) + if ((*rhs)[i] == name) { - if (newNameMap.count(l->first)) + if (IPNode* n = graph.findNode((*lhs)[i])) { - l->first = newNameMap[l->first]; + inputs.push_back(n); } - if (newNameMap.count(l->second)) + else { - l->second = newNameMap[l->second]; + cout << "WARNING: could not find node " << (*lhs)[i] + << " when trying to connect inputs for " + << name << endl; } } } } } - } -} -template -inline T* nonEmptyProperty(PropertyContainer* pc, const char* comp, const char* prop) -{ - T* p = pc->property(comp, prop); - if (p && p->size() == 0) p = 0; - return p; -} + typedef set NameSet; + typedef map NameMap; -} // anon namespace +#ifdef PLATFORM_WINDOWS +#define PAD "%06d" +#else +#define PAD "%06zd" +#endif + string uniqueName(string name, NameSet& disallowedNames) + { + static char buf[16]; + static RegEx endRE("(.*[^0-9])([0-9]+)"); + static RegEx midRE( + "(.*[^0-9])([0-9][0-9][0-9][0-9][0-9][0-9])([^0-9].*)"); -static bool isProgressionProtocol(const std::string &protoName) -{ - return (protoName == "RVSource" || protoName == "RVFileSource" || protoName == "RVImageSource"); -} + if (disallowedNames.count(name) > 0) + { + // + // Find a 6-zero-padded number in the middle. + // + Match midMatch(midRE, name); -void -RvSession::readGTO(const string& infilename, bool merge, Options::SourceArgs& sargs) -{ - HOP_PROF_DYN_NAME( - std::string(std::string("RvSession::readGTO : ") + - infilename).c_str()); + if (midMatch) + { + string finalName; + istringstream istr(midMatch.subStr(1)); + int n; + istr >> n; + do + { + ++n; + sprintf(buf, PAD, size_t(n)); + ostringstream str; + str << midMatch.subStr(0) << buf << midMatch.subStr(2); + finalName = str.str(); + } while (disallowedNames.count(finalName) > 0); + + return finalName; + } - const VideoDevice* outputDevice = outputVideoDevice(); + // + // Find a possibly zero-padded number on the end. + // + Match endMatch(endRE, name); - typedef std::set PropertyContainerSet; + if (endMatch) + { + string finalName; + istringstream istr(endMatch.subStr(1)); + int n; + istr >> n; + do + { + ++n; + sprintf(buf, PAD, size_t(n)); + ostringstream str; + str << endMatch.subStr(0) << buf; + finalName = str.str(); + } while (disallowedNames.count(finalName) > 0); + + return finalName; + } - string filename = pathConform(infilename); + // + // Fallback: add a number to the end and recurse + // + ostringstream str; + str << name << "000002"; + return uniqueName(str.str(), disallowedNames); + } - userGenericEvent("before-session-read", filename); + return name; + } - GTOReader reader; - GTOReader::Containers containers; - { - HOP_PROF_DYN_NAME( - std::string(std::string("RvSession::readGTO - GTOReader.read : ") + - filename).c_str()); + void uniqifyContainerNames(GTOReader::Containers& containers, + NameSet& existingNames) + { + NameSet origNames; + NameSet conflictingNames; + NameMap newNameMap; - containers = reader.read(filename.c_str()); - } + // + // run through containers that correspond to top-level nodes, + // identify those that conflict with existingNames + // - merge = merge && (sources().size()); + for (size_t i = 0; i < containers.size(); i++) + { + PropertyContainer* pc = containers[i]; - if (merge) - { - NameSet existingNames; + if (protocol(pc) == "RVSession") + continue; - for (IPGraph::NodeMap::const_iterator i = graph().viewableNodes().begin(); - i != graph().viewableNodes().end(); - ++i) - { - string n = (*i).second->name(); - if (! graph().isDefaultView(n)) existingNames.insert (n); - } + string nm = TwkContainer::name(pc); - uniqifyContainerNames (containers, existingNames); - applyRvSessionSpecificOptions(); - } - else - { - clear(); - } + if (nm.find('_') == string::npos && existingNames.count(nm)) + { + conflictingNames.insert(nm); + } + origNames.insert(nm); + } + + // + // for every conflicting top-level name, choose a new name (same + // type!) that isn't in either the original list, or the new one. + // - PropertyContainer* session = 0; - PropertyContainer* connections = 0; + NameSet disallowedNames = existingNames; + disallowedNames.insert(origNames.begin(), origNames.end()); - vector v1InsVec; - vector v1OutsVec; - string v1CTypeStr; - float v1FPS = 0.0; + for (NameSet::iterator i = conflictingNames.begin(); + i != conflictingNames.end(); ++i) + { - m_inputFileVersion = 0; + string newName = uniqueName(*i, disallowedNames); - Property::Info* notPersistent = new Property::Info(); - notPersistent->setPersistent(false); + newNameMap[*i] = newName; + disallowedNames.insert(newName); + } - for (size_t i = 0; i < containers.size(); i++) - { - PropertyContainer* pc = containers[i]; - string p = protocol(pc); + // + // run through all containers, add mappings for non-top-level + // containers, based on the mapping for the corresponding top-level + // container(s). + // - if (p == "RVSession") - { - session = pc; - m_inputFileVersion = TwkContainer::protocolVersion(pc); + for (size_t i = 0; i < containers.size(); i++) + { + PropertyContainer* pc = containers[i]; + + if (protocol(pc) == "RVSession") + continue; + + string nm = TwkContainer::name(pc); + + int gp = nm.find('_'); + if (gp != string::npos) + { + string newName; + + string groupName = nm.substr(0, gp); + if (newNameMap.count(groupName)) + groupName = newNameMap[groupName]; + + int ip = nm.rfind('_'); + string inputName = nm.substr(ip + 1); + if (newNameMap.count(inputName)) + inputName = newNameMap[inputName]; + + newName = + groupName + nm.substr(gp, ip - gp + 1) + inputName; + + newNameMap[nm] = newName; + } + } + + // run through all containers, change conflicting container name to + // new name, and any string properites that contain conflicting + // container name to new name + // + + for (int i = 0; i < containers.size(); i++) + { + PropertyContainer* pc = containers[i]; + + string nm = TwkContainer::name(pc); + + if (newNameMap.count(nm)) + pc->setName(newNameMap[nm]); + + PropertyContainer::Components& comps = pc->components(); + for (int j = 0; j < comps.size(); ++j) + { + if (comps[j]->name() == "object") + continue; + + Component::Container& props = comps[j]->properties(); + for (int k = 0; k < props.size(); ++k) + { + if (StringProperty* sp = + dynamic_cast(props[k])) + { + for (StringProperty::iterator l = sp->begin(); + l != sp->end(); ++l) + { + if (newNameMap.count(*l)) + { + *l = newNameMap[*l]; + } + } + } + else if (StringPairProperty* spp = + dynamic_cast( + props[k])) + { + for (StringPairProperty::iterator l = spp->begin(); + l != spp->end(); ++l) + { + if (newNameMap.count(l->first)) + { + l->first = newNameMap[l->first]; + } + if (newNameMap.count(l->second)) + { + l->second = newNameMap[l->second]; + } + } + } + } + } + } } - if (p == "IPNodeDefinition") + template + inline T* nonEmptyProperty(PropertyContainer* pc, const char* comp, + const char* prop) { - pc->declareProperty("node.origin", infilename, notPersistent, true); - NodeDefinition* def = new NodeDefinition(pc); - IPCore::App()->nodeManager()->addDefinition(def); + T* p = pc->property(comp, prop); + if (p && p->size() == 0) + p = 0; + return p; } - } - - switch (m_inputFileVersion) - { - case 0: - cout << "WARNING: no file version: assuming version 1 or 2 file format" << endl; - m_inputFileVersion = 1; - break; - case 1: - case 2: - case 4: - cout << "INFO: reading version " - << m_inputFileVersion - << " session file format" << endl; - break; - case 3: - cout << "INFO: reading version " - << m_inputFileVersion - << " session file format (which never existed)" << endl; - m_inputFileVersion = 4; - break; - default: - cout << "WARNING: trying to read version " - << m_inputFileVersion - << " session file format"; - if (m_inputFileVersion > 4) cout << " created by a newer version of RV"; - else cout << " which corresponds to no RV version"; - cout << endl; + } // namespace - break; + static bool isProgressionProtocol(const std::string& protoName) + { + return (protoName == "RVSource" || protoName == "RVFileSource" + || protoName == "RVImageSource"); } - // - // NOTE: IF YOU ARE MAKING BACKWARDS COMPATIBLE FILE CHANGES IN - // THIS FUNCTION: - // - // The correct place to make changes which are localized to a - // node's layout differing between file versions is in the node's - // readCompleted() function NOT here. Only add backwards - // compatible changes here if its a file scope change. For - // example default nodes got renamed, or a node was split into - // two separate nodes. - // - // For an example of localized node versioning look in - // PaintIPNode. - // - - // - // Pass 1: get the sources and the session information. Set - // protocols to backwards compat names - // + void RvSession::readGTO(const string& infilename, bool merge, + Options::SourceArgs& sargs) + { + HOP_PROF_DYN_NAME( + std::string(std::string("RvSession::readGTO : ") + infilename) + .c_str()); - set topLevelSet; + const VideoDevice* outputDevice = outputVideoDevice(); - { - HOP_PROF( "Rv::RvSession::readGTO : PASS 1" ); + typedef std::set PropertyContainerSet; - RvGraph::FastAddSourceGuard fastAddSourceGuard(rvgraph()); + string filename = pathConform(infilename); - m_gtoSourceTotal = 0; + userGenericEvent("before-session-read", filename); - for (int i=0; i < containers.size(); i++) + GTOReader reader; + GTOReader::Containers containers; { - PropertyContainer* pc = containers[i]; - string p = protocol(pc); - if ( isProgressionProtocol(p) ) - ++m_gtoSourceTotal; + HOP_PROF_DYN_NAME( + std::string( + std::string("RvSession::readGTO - GTOReader.read : ") + + filename) + .c_str()); + + containers = reader.read(filename.c_str()); } - m_gtoSourceCount = 0; - m_readingGTO = true; + merge = merge && (sources().size()); - for (int i=0; i < containers.size(); i++) + if (merge) { - PropertyContainer* pc = containers[i]; - string p = protocol(pc); - size_t pver = protocolVersion(pc); - string pcname = TwkContainer::name(pc); - - // - // Backwards compat - // + NameSet existingNames; - if (m_inputFileVersion == 1) + for (IPGraph::NodeMap::const_iterator i = + graph().viewableNodes().begin(); + i != graph().viewableNodes().end(); ++i) { - if (p == "RVStereo") - { - setProtocol(*pc, "RVDisplayStereo"); - p = "RVDisplayStereo"; - } + string n = (*i).second->name(); + if (!graph().isDefaultView(n)) + existingNames.insert(n); + } - Match rem(oldContainerNameRE, pcname); + uniqifyContainerNames(containers, existingNames); + applyRvSessionSpecificOptions(); + } + else + { + clear(); + } - if (rem) - { - pcname = "sourceGroup000"; - pcname += rem.subStr(1); - pcname += "_"; - pcname += rem.subStr(0); - TwkContainer::setName(*pc, pcname); - } - else if (pcname == "sequence") - { - TwkContainer::setName(*pc, defaultSequenceSequenceIPNodeName); + PropertyContainer* session = 0; + PropertyContainer* connections = 0; - IntProperty* v1Ins = pc->property("edl", "in"); - if (v1Ins) v1InsVec = v1Ins->valueContainer(); + vector v1InsVec; + vector v1OutsVec; + string v1CTypeStr; + float v1FPS = 0.0; - IntProperty* v1Outs = pc->property("edl", "out"); - if (v1Outs) v1OutsVec = v1Outs->valueContainer(); - } - else if (pcname == "composite") - { - // - // NOTE: this is on purpose. There's nothing at this - // point preventing two containers from sharing a - // name and 3.10 removed the composite node in favor - // of doing everything in the stack - // + m_inputFileVersion = 0; - TwkContainer::setName(*pc, "defaultStack_stack"); - TwkContainer::setProtocol(*pc, "RVStack"); - pc->removeProperty("single", "index"); - pc->removeProperty("pip", "x"); - pc->removeProperty("pip", "y"); - pc->removeProperty("pip", "width"); + Property::Info* notPersistent = new Property::Info(); + notPersistent->setPersistent(false); - StringProperty* v1CType = pc->property("composite", "type"); - if (v1CType) - { - if (v1CType->front() == "pip") v1CType->front() = "replace"; - v1CTypeStr = v1CType->front(); - } - } - else if (pcname == "stack") - { - TwkContainer::setName(*pc, "defaultStack_stack"); - } - else if (pcname == "stereo") - { - TwkContainer::setName(*pc, "displayGroup0_stereo"); - } - else if (pcname == "display") - { - TwkContainer::setName(*pc, "displayGroup0_display"); - } - else if (pcname == "displayTransform") - { - TwkContainer::setName(*pc, "viewGroup_dxform"); - } - else if (pcname == "soundtrack") - { - TwkContainer::setName(*pc, "viewGroup_soundtrack"); - } + for (size_t i = 0; i < containers.size(); i++) + { + PropertyContainer* pc = containers[i]; + string p = protocol(pc); - if (p == "RVSource") - { - setProtocol(*pc, "RVFileSource"); - p = "RVFileSource"; - } + if (p == "RVSession") + { + session = pc; + m_inputFileVersion = TwkContainer::protocolVersion(pc); } - if (m_inputFileVersion == 1 || m_inputFileVersion == 2) + if (p == "IPNodeDefinition") { - if (p == "RVColor" && pver == 1) - { - // - // RVColor is split into RVColor in the source group's - // color pipeline and RVLinearize in the source group's - // linearize pipeline. - // + pc->declareProperty("node.origin", infilename, + notPersistent, true); + NodeDefinition* def = new NodeDefinition(pc); + IPCore::App()->nodeManager()->addDefinition(def); + } + } - string pcname = TwkContainer::name(pc); + switch (m_inputFileVersion) + { + case 0: + cout << "WARNING: no file version: assuming version 1 or 2 file " + "format" + << endl; + m_inputFileVersion = 1; + break; + case 1: + case 2: + case 4: + cout << "INFO: reading version " << m_inputFileVersion + << " session file format" << endl; + break; + case 3: + cout << "INFO: reading version " << m_inputFileVersion + << " session file format (which never existed)" << endl; + m_inputFileVersion = 4; + break; + default: + cout << "WARNING: trying to read version " << m_inputFileVersion + << " session file format"; + + if (m_inputFileVersion > 4) + cout << " created by a newer version of RV"; + else + cout << " which corresponds to no RV version"; + cout << endl; - if (pver != 1) - { - cout << "WARNING: RVColor node in version 2 session file has unknown version " - << pver << endl; - } + break; + } + + // + // NOTE: IF YOU ARE MAKING BACKWARDS COMPATIBLE FILE CHANGES IN + // THIS FUNCTION: + // + // The correct place to make changes which are localized to a + // node's layout differing between file versions is in the node's + // readCompleted() function NOT here. Only add backwards + // compatible changes here if its a file scope change. For + // example default nodes got renamed, or a node was split into + // two separate nodes. + // + // For an example of localized node versioning look in + // PaintIPNode. + // - PropertyContainer* nl = new PropertyContainer(); + // + // Pass 1: get the sources and the session information. Set + // protocols to backwards compat names + // - string groupName = pcname.substr(0, pcname.size() - 6); - string nlName = groupName + "_tolinPipeline_0"; - string cName = groupName + "_colorPipeline_0"; + set topLevelSet; - TwkContainer::setProtocol(*nl, "RVLinearize"); - TwkContainer::setName(*nl, nlName); + { + HOP_PROF("Rv::RvSession::readGTO : PASS 1"); - TwkContainer::setProtocolVersion(*pc, 2); - TwkContainer::setName(*pc, cName); + RvGraph::FastAddSourceGuard fastAddSourceGuard(rvgraph()); - Component* clut = pc->component("lut"); - Component* ccolor = pc->component("color"); - Component* ccineon = pc->component("cineon"); - Component* clumlut = pc->component("luminanceLUT"); - Component* nllut = (clut) ? clut->copy() : 0; - Component* nlcolor = (ccolor) ? ccolor->copy() : 0; - Component* nlcineon = (ccineon) ? ccineon->copy() : 0; + m_gtoSourceTotal = 0; - // - // Remove non-linear and LUT props from color node - // + for (int i = 0; i < containers.size(); i++) + { + PropertyContainer* pc = containers[i]; + string p = protocol(pc); + if (isProgressionProtocol(p)) + ++m_gtoSourceTotal; + } - if (clut) pc->remove(clut); delete clut; - if (ccineon) pc->remove(ccineon); delete ccineon; + m_gtoSourceCount = 0; + m_readingGTO = true; + + for (int i = 0; i < containers.size(); i++) + { + PropertyContainer* pc = containers[i]; + string p = protocol(pc); + size_t pver = protocolVersion(pc); + string pcname = TwkContainer::name(pc); - if (clumlut) clumlut->remove("type"); + // + // Backwards compat + // - if (ccolor) + if (m_inputFileVersion == 1) + { + if (p == "RVStereo") { - ccolor->remove("alphaType"); - ccolor->remove("logtype"); - ccolor->remove("YUV"); - ccolor->remove("YIQ"); - ccolor->remove("sRGB2linear"); - ccolor->remove("Rec709ToLinear"); - ccolor->remove("fileGamma"); - ccolor->remove("ignoreChromaticities"); + setProtocol(*pc, "RVDisplayStereo"); + p = "RVDisplayStereo"; } - // - // Remove the color props the linearize node will not - // use (to prevent file pollution if the session is - // written out again). - // + Match rem(oldContainerNameRE, pcname); - if (nlcolor) + if (rem) + { + pcname = "sourceGroup000"; + pcname += rem.subStr(1); + pcname += "_"; + pcname += rem.subStr(0); + TwkContainer::setName(*pc, pcname); + } + else if (pcname == "sequence") { - nlcolor->remove("lut"); - nlcolor->remove("invert"); - nlcolor->remove("gamma"); - nlcolor->remove("YIQ"); - nlcolor->remove("offset"); - nlcolor->remove("scale"); - nlcolor->remove("exposure"); - nlcolor->remove("contrast"); - nlcolor->remove("saturation"); - nlcolor->remove("hue"); - nlcolor->remove("normalize"); + TwkContainer::setName( + *pc, defaultSequenceSequenceIPNodeName); + + IntProperty* v1Ins = + pc->property("edl", "in"); + if (v1Ins) + v1InsVec = v1Ins->valueContainer(); + + IntProperty* v1Outs = + pc->property("edl", "out"); + if (v1Outs) + v1OutsVec = v1Outs->valueContainer(); } + else if (pcname == "composite") + { + // + // NOTE: this is on purpose. There's nothing at this + // point preventing two containers from sharing a + // name and 3.10 removed the composite node in favor + // of doing everything in the stack + // - if (nllut) nl->add(nllut); - if (nlcolor) nl->add(nlcolor); - if (nlcineon) nl->add(nlcineon); + TwkContainer::setName(*pc, "defaultStack_stack"); + TwkContainer::setProtocol(*pc, "RVStack"); + pc->removeProperty("single", "index"); + pc->removeProperty("pip", "x"); + pc->removeProperty("pip", "y"); + pc->removeProperty("pip", "width"); + + StringProperty* v1CType = + pc->property("composite", "type"); + if (v1CType) + { + if (v1CType->front() == "pip") + v1CType->front() = "replace"; + v1CTypeStr = v1CType->front(); + } + } + else if (pcname == "stack") + { + TwkContainer::setName(*pc, "defaultStack_stack"); + } + else if (pcname == "stereo") + { + TwkContainer::setName(*pc, "displayGroup0_stereo"); + } + else if (pcname == "display") + { + TwkContainer::setName(*pc, "displayGroup0_display"); + } + else if (pcname == "displayTransform") + { + TwkContainer::setName(*pc, "viewGroup_dxform"); + } + else if (pcname == "soundtrack") + { + TwkContainer::setName(*pc, "viewGroup_soundtrack"); + } - containers.push_back(nl); + if (p == "RVSource") + { + setProtocol(*pc, "RVFileSource"); + p = "RVFileSource"; + } } - else if (p == "RVTransform2D") + + if (m_inputFileVersion == 1 || m_inputFileVersion == 2) { - // - // The pixel aspect ratio is now handled by the RVLensWarp node - // so we need to move it over. - // + if (p == "RVColor" && pver == 1) + { + // + // RVColor is split into RVColor in the source group's + // color pipeline and RVLinearize in the source group's + // linearize pipeline. + // - string pcname = TwkContainer::name(pc); + string pcname = TwkContainer::name(pc); - PropertyContainer* nl = new PropertyContainer(); + if (pver != 1) + { + cout << "WARNING: RVColor node in version 2 " + "session file has unknown version " + << pver << endl; + } - // - // Note: using the second slot of the tolinPipeline this way is - // fragile and will need updating if the order of pipeline - // nodes ever changes. - // + PropertyContainer* nl = new PropertyContainer(); - string groupName = pcname.substr(0, pcname.size() - 12); // Minus "_transform2D" - string nlName = groupName + "_tolinPipeline_1"; + string groupName = pcname.substr(0, pcname.size() - 6); + string nlName = groupName + "_tolinPipeline_0"; + string cName = groupName + "_colorPipeline_0"; - TwkContainer::setProtocol(*nl, "RVLensWarp"); - TwkContainer::setName(*nl, nlName); + TwkContainer::setProtocol(*nl, "RVLinearize"); + TwkContainer::setName(*nl, nlName); - if (FloatProperty* oldP = pc->property("pixel", "aspectRatio")) - { - FloatProperty* newP = nl->createProperty("warp", "pixelAspectRatio"); - newP->resize(1); - newP->front() = oldP->front(); + TwkContainer::setProtocolVersion(*pc, 2); + TwkContainer::setName(*pc, cName); + + Component* clut = pc->component("lut"); + Component* ccolor = pc->component("color"); + Component* ccineon = pc->component("cineon"); + Component* clumlut = pc->component("luminanceLUT"); + Component* nllut = (clut) ? clut->copy() : 0; + Component* nlcolor = (ccolor) ? ccolor->copy() : 0; + Component* nlcineon = (ccineon) ? ccineon->copy() : 0; // - // "aspectRatio" is the only property of the old "pixel" - // component. Therefore after we copy out the value we must - // delete the component. + // Remove non-linear and LUT props from color node // - if (Component* pixelcomp = pc->component("pixel")) + if (clut) + pc->remove(clut); + delete clut; + if (ccineon) + pc->remove(ccineon); + delete ccineon; + + if (clumlut) + clumlut->remove("type"); + + if (ccolor) { - pc->remove(pixelcomp); - delete pixelcomp; + ccolor->remove("alphaType"); + ccolor->remove("logtype"); + ccolor->remove("YUV"); + ccolor->remove("YIQ"); + ccolor->remove("sRGB2linear"); + ccolor->remove("Rec709ToLinear"); + ccolor->remove("fileGamma"); + ccolor->remove("ignoreChromaticities"); } - } - containers.push_back(nl); - } - else if (p == "RVFileSource") - { - if (StringProperty* oldP = pc->property("request", "stereoViews")) - { - oldP->clearToDefaultValue(); - } + // + // Remove the color props the linearize node will not + // use (to prevent file pollution if the session is + // written out again). + // - if (StringProperty* sp = pc->property("request.imageLayerSelection")) - { - if (!sp->empty()) + if (nlcolor) { - StringVector v(3); - v[0] = "layer"; - v[1] = ""; - v[2] = sp->front(); - pc->declareProperty("request.imageComponent", v); + nlcolor->remove("lut"); + nlcolor->remove("invert"); + nlcolor->remove("gamma"); + nlcolor->remove("YIQ"); + nlcolor->remove("offset"); + nlcolor->remove("scale"); + nlcolor->remove("exposure"); + nlcolor->remove("contrast"); + nlcolor->remove("saturation"); + nlcolor->remove("hue"); + nlcolor->remove("normalize"); } - pc->removeProperty(sp); - } + if (nllut) + nl->add(nllut); + if (nlcolor) + nl->add(nlcolor); + if (nlcineon) + nl->add(nlcineon); - if (StringProperty* sp = pc->property("request.imageViewSelection")) + containers.push_back(nl); + } + else if (p == "RVTransform2D") { - if (!sp->empty()) + // + // The pixel aspect ratio is now handled by the + // RVLensWarp node so we need to move it over. + // + + string pcname = TwkContainer::name(pc); + + PropertyContainer* nl = new PropertyContainer(); + + // + // Note: using the second slot of the tolinPipeline this + // way is fragile and will need updating if the order of + // pipeline nodes ever changes. + // + + string groupName = pcname.substr( + 0, pcname.size() - 12); // Minus "_transform2D" + string nlName = groupName + "_tolinPipeline_1"; + + TwkContainer::setProtocol(*nl, "RVLensWarp"); + TwkContainer::setName(*nl, nlName); + + if (FloatProperty* oldP = pc->property( + "pixel", "aspectRatio")) { - StringVector v(2); - v[0] = "view"; - v[1] = sp->front(); - pc->declareProperty("request.imageComponent", v); + FloatProperty* newP = + nl->createProperty( + "warp", "pixelAspectRatio"); + newP->resize(1); + newP->front() = oldP->front(); + + // + // "aspectRatio" is the only property of the old + // "pixel" component. Therefore after we copy out + // the value we must delete the component. + // + + if (Component* pixelcomp = pc->component("pixel")) + { + pc->remove(pixelcomp); + delete pixelcomp; + } } - pc->removeProperty(sp); + containers.push_back(nl); } - - if (StringProperty* sp = pc->property("request.imageChannelSelection")) + else if (p == "RVFileSource") { - if (!sp->empty()) + if (StringProperty* oldP = pc->property( + "request", "stereoViews")) + { + oldP->clearToDefaultValue(); + } + + if (StringProperty* sp = pc->property( + "request.imageLayerSelection")) + { + if (!sp->empty()) + { + StringVector v(3); + v[0] = "layer"; + v[1] = ""; + v[2] = sp->front(); + pc->declareProperty( + "request.imageComponent", v); + } + + pc->removeProperty(sp); + } + + if (StringProperty* sp = pc->property( + "request.imageViewSelection")) { - StringVector v(4); - v[0] = "channel"; - v[1] = ""; - v[2] = ""; - v[3] = sp->front(); + if (!sp->empty()) + { + StringVector v(2); + v[0] = "view"; + v[1] = sp->front(); + pc->declareProperty( + "request.imageComponent", v); + } - pc->declareProperty("request.imageComponent", v); + pc->removeProperty(sp); } - pc->removeProperty(sp); + if (StringProperty* sp = pc->property( + "request.imageChannelSelection")) + { + if (!sp->empty()) + { + StringVector v(4); + v[0] = "channel"; + v[1] = ""; + v[2] = ""; + v[3] = sp->front(); + + pc->declareProperty( + "request.imageComponent", v); + } + + pc->removeProperty(sp); + } } - } - else if (p == "RVSoundTrack") - { - // - // Used to be part of DisplayGroupIPNode but is now part of - // ViewGroupIPNode - // + else if (p == "RVSoundTrack") + { + // + // Used to be part of DisplayGroupIPNode but is now + // part of ViewGroupIPNode + // - TwkContainer::setName(*pc, "viewGroup_soundtrack"); - } - else if (p == "RVDispTransform2D") - { - // - // Same as RVSoundTrack - // + TwkContainer::setName(*pc, "viewGroup_soundtrack"); + } + else if (p == "RVDispTransform2D") + { + // + // Same as RVSoundTrack + // - TwkContainer::setName(*pc, "viewGroup_dxform"); + TwkContainer::setName(*pc, "viewGroup_dxform"); + } } - } - // - // Add sources - // - // Generally, we'd like to get rid of the way sources are - // created. They should be created just like any other node - // and load files / hook up props once that process is - // complete. The current way this is done puts a lot of - // constraints on timing + initialization which are - // unnecessarily complex. - // + // + // Add sources + // + // Generally, we'd like to get rid of the way sources are + // created. They should be created just like any other node + // and load files / hook up props once that process is + // complete. The current way this is done puts a lot of + // constraints on timing + initialization which are + // unnecessarily complex. + // - if (p == "RVFileSource" || p == "RVImageSource") - { - if (SourceIPNode* n = rvgraph().addSource(p, pcname)) + if (p == "RVFileSource" || p == "RVImageSource") { - n->copy(pc); - addNodeCreationContext(n); - userGenericEvent("new-node", n->name()); - - n->mediaChangedSignal().connect(boost::bind(&RvSession::newMediaLoaded, this, n)); - StringProperty* movie = n->property("media.movie"); - if (FileSourceIPNode* fsipn = dynamic_cast(n)) + if (SourceIPNode* n = rvgraph().addSource(p, pcname)) { - fsipn->storeInputParameters(sargs.inparams); - StringVector movies, userMovies; - for (int i = 0; i < movie->size(); ++i) movies.push_back((*movie)[i]); - buildFileList(movies, "session", userMovies); - movie->resize(0); - for (int j = 0; j < userMovies.size(); ++j) movie->push_back(userMovies[j]); - } + n->copy(pc); + addNodeCreationContext(n); + userGenericEvent("new-node", n->name()); + + n->mediaChangedSignal().connect( + boost::bind(&RvSession::newMediaLoaded, this, n)); + StringProperty* movie = + n->property("media.movie"); + if (FileSourceIPNode* fsipn = + dynamic_cast(n)) + { + fsipn->storeInputParameters(sargs.inparams); + StringVector movies, userMovies; + for (int i = 0; i < movie->size(); ++i) + movies.push_back((*movie)[i]); + buildFileList(movies, "session", userMovies); + movie->resize(0); + for (int j = 0; j < userMovies.size(); ++j) + movie->push_back(userMovies[j]); + } - // - // Handle new-source event - // + // + // Handle new-source event + // - ostringstream nscontents; - string media = (movie->size() > 0) ? (*movie)[0] : ""; - nscontents << n->name() << ";;RVSource;;" << media; - cout << "INFO: loading " << media << endl; - userGenericEvent("new-source", nscontents.str()); + ostringstream nscontents; + string media = (movie->size() > 0) ? (*movie)[0] : ""; + nscontents << n->name() << ";;RVSource;;" << media; + cout << "INFO: loading " << media << endl; + userGenericEvent("new-source", nscontents.str()); + } + } + else if (p == "connection") + { + connections = pc; } } - else if (p == "connection") - { - connections = pc; - } - } - makeTopLevelSet(connections, containers, topLevelSet); - } // HOP_PROF_DYN for PASS 1 + makeTopLevelSet(connections, containers, topLevelSet); + } // HOP_PROF_DYN for PASS 1 - // - // Pass 2: build any user created top level nodes (if we know how) - // + // + // Pass 2: build any user created top level nodes (if we know how) + // - { - HOP_PROF( "Rv::RvSession::readGTO : PASS 2" ); - for (int i=0; i < containers.size(); i++) { - PropertyContainer* pc = containers[i]; - string fprotocol = protocol(pc); - unsigned int fprotocolVersion = protocolVersion(pc); - - if (fprotocol == "RVSession" || fprotocol == "connection") continue; + HOP_PROF("Rv::RvSession::readGTO : PASS 2"); + for (int i = 0; i < containers.size(); i++) + { + PropertyContainer* pc = containers[i]; + string fprotocol = protocol(pc); + unsigned int fprotocolVersion = protocolVersion(pc); - string nodeName = TwkContainer::name(pc); - IPGraph::IPNodes inputs; - ostringstream msg; + if (fprotocol == "RVSession" || fprotocol == "connection") + continue; - const NodeDefinition* def = graph().nodeDefinition(fprotocol); + string nodeName = TwkContainer::name(pc); + IPGraph::IPNodes inputs; + ostringstream msg; - if (def && topLevelSet.count(nodeName) > 0) - { - if (IPNode* n = graph().findNode(nodeName)) - { - // - // Its a automatically created node, copy the state over - // + const NodeDefinition* def = graph().nodeDefinition(fprotocol); - n->copy(pc); - addNodeCreationContext(n); - } - else + if (def && topLevelSet.count(nodeName) > 0) { - if (IPNode* n = graph().newNode(fprotocol, nodeName)) + if (IPNode* n = graph().findNode(nodeName)) { - addNodeCreationContext(n); - // - // need to copy the state here also because some of - // the state (group nodes) will affect the topology + // Its a automatically created node, copy the state + // over // - // if (n->protocol() == fprotocol) - // { - // n->copy(pc); - // } + n->copy(pc); + addNodeCreationContext(n); } else { - cout << "WARNING: cannot make a node of type " - << fprotocol - << " for node " - << nodeName - << " in .rv file: ignoring" - << endl; + if (IPNode* n = graph().newNode(fprotocol, nodeName)) + { + addNodeCreationContext(n); + + // + // need to copy the state here also because some of + // the state (group nodes) will affect the topology + // + + // if (n->protocol() == fprotocol) + // { + // n->copy(pc); + // } + } + else + { + cout << "WARNING: cannot make a node of type " + << fprotocol << " for node " << nodeName + << " in .rv file: ignoring" << endl; + } } } } - } - } // HOP_PROF_DYN for PASS 2 + } // HOP_PROF_DYN for PASS 2 - PropertyContainerSet unusedContainers; - PropertyContainerSet usedContainers; - vector > readCompletedNodes; - - // - // Pass 3: connect and copy state into top level nodes - // + PropertyContainerSet unusedContainers; + PropertyContainerSet usedContainers; + vector> readCompletedNodes; - { - HOP_PROF( "Rv::RvSession::readGTO : PASS 3" ); + // + // Pass 3: connect and copy state into top level nodes + // - for (int i=0; i < containers.size(); i++) { - PropertyContainer* pc = containers[i]; - string fprotocol = protocol(pc); - unsigned int fprotocolVersion = protocolVersion(pc); - string nodeName = TwkContainer::name(pc); + HOP_PROF("Rv::RvSession::readGTO : PASS 3"); - if (fprotocol == "RVSession" || fprotocol == "connection") + for (int i = 0; i < containers.size(); i++) { - usedContainers.insert(pc); - } - else if (IPNode* n = graph().findNode(nodeName)) - { - addNodeCreationContext(n); - - // - // Does this node have top level connections? If so - // connect it up. All connectable nodes should exist by - // this pass. - // + PropertyContainer* pc = containers[i]; + string fprotocol = protocol(pc); + unsigned int fprotocolVersion = protocolVersion(pc); + string nodeName = TwkContainer::name(pc); - if (topLevelSet.count(nodeName) > 0) + if (fprotocol == "RVSession" || fprotocol == "connection") + { + usedContainers.insert(pc); + } + else if (IPNode* n = graph().findNode(nodeName)) { - IPGraph::IPNodes inputs; - inputsForNode(connections, graph(), nodeName, inputs); + addNodeCreationContext(n); // - // If it's a default view, it has connected itself - // automatically. But this may not be what the user saved in - // the session file, since we allow editing of the default - // views. So in the usual case, set the inputs for the - // default nodes like other nodes, from whatever is specified - // in the connections list. + // Does this node have top level connections? If so + // connect it up. All connectable nodes should exist by + // this pass. // - // But two special cases: If we're merging there's not really - // anything sensible to be done and if there are no - // connections for the default view (IE it's a stub session - // file), so in those cases allow default views to build - // themselves. - // - - if (!graph().isDefaultView(n->name()) || (!merge && inputs.size())) n->setInputs(inputs); - try + if (topLevelSet.count(nodeName) > 0) { - if (n->protocol() == fprotocol) + IPGraph::IPNodes inputs; + inputsForNode(connections, graph(), nodeName, inputs); + + // + // If it's a default view, it has connected itself + // automatically. But this may not be what the user + // saved in the session file, since we allow editing of + // the default views. So in the usual case, set the + // inputs for the default nodes like other nodes, from + // whatever is specified in the connections list. + // + // But two special cases: If we're merging there's not + // really anything sensible to be done and if there are + // no connections for the default view (IE it's a stub + // session file), so in those cases allow default views + // to build themselves. + // + + if (!graph().isDefaultView(n->name()) + || (!merge && inputs.size())) + n->setInputs(inputs); + + try + { + if (n->protocol() == fprotocol) + { + n->copy(pc); + readCompletedNodes.push_back( + make_pair(n->name(), fprotocolVersion)); + } + } + catch (std::exception& e) { - n->copy(pc); - readCompletedNodes.push_back(make_pair(n->name(),fprotocolVersion)); + cerr << "ERROR: in file, node " + << TwkContainer::name(pc) << ": " << endl + << e.what(); } } - catch (std::exception& e) + else { - cerr << "ERROR: in file, node " << TwkContainer::name(pc) - << ": " << endl - << e.what(); + unusedContainers.insert(pc); } } else + // + // The node has not been created yet, but it may be later (EG + // pipeline group contents), so be sure to add to unused list + // so we have a chance to copy state in pass 4. + // { unusedContainers.insert(pc); } } - else - // - // The node has not been created yet, but it may be later (EG pipeline - // group contents), so be sure to add to unused list so we have a - // chance to copy state in pass 4. - // - { - unusedContainers.insert(pc); - } - } - } // HOP_PROF_DYN for PASS 3 + } // HOP_PROF_DYN for PASS 3 - // - // Pass 4: iterate on all unused property containers until either - // there are none left or we can't find nodes that correspond to the - // containers. - // + // + // Pass 4: iterate on all unused property containers until either + // there are none left or we can't find nodes that correspond to the + // containers. + // - { - HOP_PROF( "Rv::RvSession::readGTO : PASS 4" ); - while (!unusedContainers.empty()) { - // Pass 4a + HOP_PROF("Rv::RvSession::readGTO : PASS 4"); + while (!unusedContainers.empty()) { - HOP_PROF( "Rv::RvSession::readGTO : PASS 4.A" ); - usedContainers.clear(); - - for (PropertyContainerSet::const_iterator i = unusedContainers.begin(); - i != unusedContainers.end(); - ++i) + // Pass 4a { - PropertyContainer* pc = *i; - string fprotocol = protocol(pc); - unsigned int fprotocolVersion = protocolVersion(pc); - string nodeName = TwkContainer::name(pc); + HOP_PROF("Rv::RvSession::readGTO : PASS 4.A"); + usedContainers.clear(); - if (IPNode* n = graph().findNode(nodeName)) + for (PropertyContainerSet::const_iterator i = + unusedContainers.begin(); + i != unusedContainers.end(); ++i) { - // - // Restore the state from the file. This may overwrite - // any default state created when the connections where - // made. - // + PropertyContainer* pc = *i; + string fprotocol = protocol(pc); + unsigned int fprotocolVersion = protocolVersion(pc); + string nodeName = TwkContainer::name(pc); - try + if (IPNode* n = graph().findNode(nodeName)) { - if (n->protocol() == fprotocol) - { - // - // Don't recopy sources. They have already been copied - // above in pass 1 and possibly modified their properties. - // + // + // Restore the state from the file. This may + // overwrite any default state created when the + // connections where made. + // - if (n->protocol() != "RVFileSource" && - n->protocol() != "RVImageSource") + try + { + if (n->protocol() == fprotocol) { - n->copy(pc); + // + // Don't recopy sources. They have already + // been copied above in pass 1 and possibly + // modified their properties. + // + + if (n->protocol() != "RVFileSource" + && n->protocol() != "RVImageSource") + { + n->copy(pc); + } + + addNodeCreationContext(n); + readCompletedNodes.push_back( + make_pair(n->name(), fprotocolVersion)); + usedContainers.insert(pc); } - - addNodeCreationContext(n); - readCompletedNodes.push_back(make_pair(n->name(),fprotocolVersion)); - usedContainers.insert(pc); } - } - catch (std::exception& e) - { - cerr << "ERROR: in file, node " << TwkContainer::name(pc) - << ": " << endl - << e.what(); + catch (std::exception& e) + { + cerr << "ERROR: in file, node " + << TwkContainer::name(pc) << ": " << endl + << e.what(); + } } } - } - for (PropertyContainerSet::const_iterator i = usedContainers.begin(); - i != usedContainers.end(); - ++i) - { - unusedContainers.erase(*i); - } - } // HOP_PROF_DYN for PASS 4.A + for (PropertyContainerSet::const_iterator i = + usedContainers.begin(); + i != usedContainers.end(); ++i) + { + unusedContainers.erase(*i); + } + } // HOP_PROF_DYN for PASS 4.A - // - // Pass 4b: Now that the graph is assembled and all reads are completed - // it is safe to trigger readCompleted for each node. - // - // Note this for-loop has to be within the pass4 while() loop as - // there are unusedContainers nodes that arent found in graph until - // nodes from a previous while-loop iteration have been readCompleted(). + // + // Pass 4b: Now that the graph is assembled and all reads are + // completed it is safe to trigger readCompleted for each node. + // + // Note this for-loop has to be within the pass4 while() loop + // as there are unusedContainers nodes that arent found in + // graph until nodes from a previous while-loop iteration have + // been readCompleted(). - { - HOP_PROF_DYN_NAME( - std::string( - std::string( "Rv::RvSession::readGTO : PASS 4.B (readCompletedNodes size = " ) + - std::to_string( readCompletedNodes.size() ) ).c_str() ); - for (int i=0; i < readCompletedNodes.size(); i++) { - HOP_ZONE( (i % 2== 0) ? HOP_ZONE_COLOR_10 :HOP_ZONE_COLOR_11 ); - IPNode* n(nullptr); + HOP_PROF_DYN_NAME( + std::string( + std::string("Rv::RvSession::readGTO : PASS 4.B " + "(readCompletedNodes size = ") + + std::to_string(readCompletedNodes.size())) + .c_str()); + for (int i = 0; i < readCompletedNodes.size(); i++) { - HOP_PROF_DYN_NAME( - std::string( - std::string( "findNode : " ) + - readCompletedNodes[i].first ).c_str() ); - - n = graph().findNode(readCompletedNodes[i].first); - } - if (n) - { - HOP_PROF( "readCompleted" ); - n->readCompleted(n->protocol(), readCompletedNodes[i].second); - if (isProgressionProtocol(n->protocol())) + HOP_ZONE((i % 2 == 0) ? HOP_ZONE_COLOR_10 + : HOP_ZONE_COLOR_11); + IPNode* n(nullptr); { - send(updateLoadingMessage()); - ++m_gtoSourceCount; - } - } - } - readCompletedNodes.clear(); - - if (usedContainers.empty()) break; - } // HOP_PROF_DYN for PASS 4.B - } - } // HOP_PROF_DYN for PASS 4 + HOP_PROF_DYN_NAME( + std::string(std::string("findNode : ") + + readCompletedNodes[i].first) + .c_str()); - // - // Pass 5: Safe to trigger readCompleted for each node not already done in - // pass4b - // - - { - HOP_PROF( "Rv::RvSession::readGTO : PASS 5" ); + n = graph().findNode(readCompletedNodes[i].first); + } + if (n) + { + HOP_PROF("readCompleted"); + n->readCompleted(n->protocol(), + readCompletedNodes[i].second); + if (isProgressionProtocol(n->protocol())) + { + send(updateLoadingMessage()); + ++m_gtoSourceCount; + } + } + } + readCompletedNodes.clear(); - for (int i=0; i < readCompletedNodes.size(); i++) - { - if (IPNode* n = graph().findNode(readCompletedNodes[i].first)) - { - n->readCompleted(n->protocol(), readCompletedNodes[i].second); + if (usedContainers.empty()) + break; + } // HOP_PROF_DYN for PASS 4.B } - } - } // HOP_PROF_DYN for PASS 5 + } // HOP_PROF_DYN for PASS 4 - // - // Pass 6: set the session state - // + // + // Pass 5: Safe to trigger readCompleted for each node not already done + // in + // pass4b + // - { - HOP_PROF( "Rv::RvSession::readGTO : PASS 6" ); - for (int i=0; i < containers.size(); i++) { - PropertyContainer* pc = containers[i]; - string p = protocol(pc); + HOP_PROF("Rv::RvSession::readGTO : PASS 5"); - if (p == "RVSession") + for (int i = 0; i < readCompletedNodes.size(); i++) { - // - // If we're merging a session file in, assume that the - // previous reads set up the session correctly. - // - - if (!merge) + if (IPNode* n = graph().findNode(readCompletedNodes[i].first)) { - readGTOSessionContainer(pc); - - SessionIPNode* sessionNode = graph().sessionNode(); - sessionNode->copy(pc); - sessionNode->remove(sessionNode->component("session")); + n->readCompleted(n->protocol(), + readCompletedNodes[i].second); } } - } - } // HOP_PROF_DYN for PASS 6 + } // HOP_PROF_DYN for PASS 5 - { - HOP_PROF( "Rv::RvSession::readGTO : TEARDOWN" ); // - // Delete the containers we got from the file + // Pass 6: set the session state // - for (int i=0; i < containers.size(); i++) { - delete containers[i]; - } + HOP_PROF("Rv::RvSession::readGTO : PASS 6"); + for (int i = 0; i < containers.size(); i++) + { + PropertyContainer* pc = containers[i]; + string p = protocol(pc); + + if (p == "RVSession") + { + // + // If we're merging a session file in, assume that the + // previous reads set up the session correctly. + // + + if (!merge) + { + readGTOSessionContainer(pc); + + SessionIPNode* sessionNode = graph().sessionNode(); + sessionNode->copy(pc); + sessionNode->remove(sessionNode->component("session")); + } + } + } + } // HOP_PROF_DYN for PASS 6 - if (v1FPS != 0.0) { + HOP_PROF("Rv::RvSession::readGTO : TEARDOWN"); // - // we read a v1 session file, so update all session/outputFPSs + // Delete the containers we got from the file // - for (IPGraph::NodeMap::const_iterator i = graph().nodeMap().begin(); - i != graph().nodeMap().end(); - ++i) + for (int i = 0; i < containers.size(); i++) { - FloatProperty* ofpsp = (*i).second->property("timing.outputFPS"); - FloatProperty* sfpsp = (*i).second->property("session.fps"); - - if (ofpsp) ofpsp->front() = v1FPS; - if (sfpsp) sfpsp->front() = v1FPS; + delete containers[i]; } - } - m_readingGTO = false; - m_gtoSourceTotal = 0; - m_gtoSourceCount = 0; + if (v1FPS != 0.0) + { + // + // we read a v1 session file, so update all session/outputFPSs + // - setFileName(filename); + for (IPGraph::NodeMap::const_iterator i = + graph().nodeMap().begin(); + i != graph().nodeMap().end(); ++i) + { + FloatProperty* ofpsp = (*i).second->property( + "timing.outputFPS"); + FloatProperty* sfpsp = + (*i).second->property("session.fps"); + + if (ofpsp) + ofpsp->front() = v1FPS; + if (sfpsp) + sfpsp->front() = v1FPS; + } + } - // - // Restore presentation device, if any. - // - setOutputVideoDevice(outputDevice); + m_readingGTO = false; + m_gtoSourceTotal = 0; + m_gtoSourceCount = 0; - // - // Send the file read event - // + setFileName(filename); - userGenericEvent("after-session-read", filename); - } // HOP_PROF_DYN for TEARDOWN -} + // + // Restore presentation device, if any. + // + setOutputVideoDevice(outputDevice); -void -RvSession::readLUTOnAll(string name, const string& nodeType, bool activate) -{ - NodeVector nodes; - string filename = pathConform(IPCore::Application::mapFromVar(name)); - graph().findNodesByTypeName(nodes, nodeType); + // + // Send the file read event + // - if (!TwkUtil::fileExists(filename.c_str())) - { - if (const char *path = getenv("RV_LUT_PATH")) - { - StringVector names = TwkUtil::findInPath(filename, path); - if (names.size()) filename = names[0]; - } + userGenericEvent("after-session-read", filename); + } // HOP_PROF_DYN for TEARDOWN } - for (int i=0; i < nodes.size(); i++) + void RvSession::readLUTOnAll(string name, const string& nodeType, + bool activate) { - readLUT(filename, nodes[i]->name(), activate); - } -} + NodeVector nodes; + string filename = pathConform(IPCore::Application::mapFromVar(name)); + graph().findNodesByTypeName(nodes, nodeType); -void -RvSession::readCDL(string name, const string& nodeName, bool activate) -{ - string filename = pathConform(IPCore::Application::mapFromVar(name)); - PropertyVector props; - graph().findProperty(m_frame, props, nodeName + ".CDL.active"); + if (!TwkUtil::fileExists(filename.c_str())) + { + if (const char* path = getenv("RV_LUT_PATH")) + { + StringVector names = TwkUtil::findInPath(filename, path); + if (names.size()) + filename = names[0]; + } + } - if (props.empty()) - { - TWK_THROW_EXC_STREAM("Bad node: " << nodeName); + for (int i = 0; i < nodes.size(); i++) + { + readLUT(filename, nodes[i]->name(), activate); + } } - CDL::ColorCorrectionCollection ccc = CDL::readCDL(name); - if (ccc.size() > 1) + void RvSession::readCDL(string name, const string& nodeName, bool activate) { - cout << "WARNING: Found more than one cdl in " << name - << ". Using first one found." << endl; - } + string filename = pathConform(IPCore::Application::mapFromVar(name)); + PropertyVector props; + graph().findProperty(m_frame, props, nodeName + ".CDL.active"); - if (ccc.size() <= 0) return; - - NodeVector cdlNodes; - for (size_t i = 0; i < props.size(); i++) - { - if (FileSpaceLinearizeIPNode* node = dynamic_cast(props[i]->container())) + if (props.empty()) { - cdlNodes.push_back(node); - - Vec3fProperty* slope = node->property("CDL.slope"); - Vec3fProperty* offset = node->property("CDL.offset"); - Vec3fProperty* power = node->property("CDL.power"); - FloatProperty* saturation = node->property("CDL.saturation"); - IntProperty* active = node->property("CDL.active"); - - CDL::ColorCorrection cc = ccc.front(); - - slope->front() = cc.slope; - offset->front() = cc.offset; - power->front() = cc.power; - saturation->front() = cc.saturation; - active->front() = (active) ? 1 : 0; + TWK_THROW_EXC_STREAM("Bad node: " << nodeName); } - else if (ColorIPNode* node = dynamic_cast(props[i]->container())) + + CDL::ColorCorrectionCollection ccc = CDL::readCDL(name); + if (ccc.size() > 1) { - cdlNodes.push_back(node); + cout << "WARNING: Found more than one cdl in " << name + << ". Using first one found." << endl; + } - Vec3fProperty* slope = node->property("CDL.slope"); - Vec3fProperty* offset = node->property("CDL.offset"); - Vec3fProperty* power = node->property("CDL.power"); - FloatProperty* saturation = node->property("CDL.saturation"); - IntProperty* active = node->property("CDL.active"); + if (ccc.size() <= 0) + return; - CDL::ColorCorrection cc = ccc.front(); + NodeVector cdlNodes; + for (size_t i = 0; i < props.size(); i++) + { + if (FileSpaceLinearizeIPNode* node = + dynamic_cast( + props[i]->container())) + { + cdlNodes.push_back(node); + + Vec3fProperty* slope = + node->property("CDL.slope"); + Vec3fProperty* offset = + node->property("CDL.offset"); + Vec3fProperty* power = + node->property("CDL.power"); + FloatProperty* saturation = + node->property("CDL.saturation"); + IntProperty* active = node->property("CDL.active"); + + CDL::ColorCorrection cc = ccc.front(); + + slope->front() = cc.slope; + offset->front() = cc.offset; + power->front() = cc.power; + saturation->front() = cc.saturation; + active->front() = (active) ? 1 : 0; + } + else if (ColorIPNode* node = + dynamic_cast(props[i]->container())) + { + cdlNodes.push_back(node); + + Vec3fProperty* slope = + node->property("CDL.slope"); + Vec3fProperty* offset = + node->property("CDL.offset"); + Vec3fProperty* power = + node->property("CDL.power"); + FloatProperty* saturation = + node->property("CDL.saturation"); + IntProperty* active = node->property("CDL.active"); + + CDL::ColorCorrection cc = ccc.front(); + + slope->front() = cc.slope; + offset->front() = cc.offset; + power->front() = cc.power; + saturation->front() = cc.saturation; + active->front() = (active) ? 1 : 0; + } + } - slope->front() = cc.slope; - offset->front() = cc.offset; - power->front() = cc.power; - saturation->front() = cc.saturation; - active->front() = (active) ? 1 : 0; + for (int i = 0; i < cdlNodes.size(); ++i) + { + string contents = filename + ";;" + cdlNodes[i]->name(); + userGenericEvent("read-cdl-complete", contents); } } - for (int i = 0; i < cdlNodes.size(); ++i) + void RvSession::readLUT(string filename, const string& nodeName, + bool activate) { - string contents = filename + ";;" + cdlNodes[i]->name(); - userGenericEvent("read-cdl-complete", contents); - } -} + PropertyVector props; + graph().findProperty(m_frame, props, nodeName + ".lut.active"); -void -RvSession::readLUT(string filename, const string& nodeName, bool activate) -{ - PropertyVector props; - graph().findProperty(m_frame, props, nodeName + ".lut.active"); - - NodeVector lutNodes; - for (size_t i = 0; i < props.size(); i++) - { - if (LUTIPNode* node = dynamic_cast(props[i]->container())) + NodeVector lutNodes; + for (size_t i = 0; i < props.size(); i++) { - lutNodes.push_back(node); + if (LUTIPNode* node = + dynamic_cast(props[i]->container())) + { + lutNodes.push_back(node); - StringProperty* lutFile = node->property("lut.file"); - lutFile->front() = filename; + StringProperty* lutFile = + node->property("lut.file"); + lutFile->front() = filename; - if (activate) - { - if (IntProperty* p = node->property("lut.active")) + if (activate) { - p->resize(1); - p->front() = 1; + if (IntProperty* p = + node->property("lut.active")) + { + p->resize(1); + p->front() = 1; + } } + node->propertyChanged(lutFile); } - node->propertyChanged(lutFile); + } + + for (int i = 0; i < lutNodes.size(); ++i) + { + string contents = filename + ";;" + lutNodes[i]->name(); + userGenericEvent("read-lut-complete", contents); } } - for (int i = 0; i < lutNodes.size(); ++i) + void RvSession::readEDL(const char* filename) { - string contents = filename + ";;" + lutNodes[i]->name(); - userGenericEvent("read-lut-complete", contents); - + cerr << "ERROR: Unsupported file format" << endl; } -} -void -RvSession::readEDL(const char* filename) -{ - cerr << "ERROR: Unsupported file format" << endl; -} + void RvSession::setScaleOnAll(float scale) + { + Rv::setScaleOnAll(graph(), scale); + reload(currentFrame(), currentFrame()); + } -void -RvSession::setScaleOnAll(float scale) -{ - Rv::setScaleOnAll(graph(), scale); - reload(currentFrame(), currentFrame()); -} + static string swapV(const string& filename, const string& pat, + const string& v) + { + string vfilename = filename; + string::size_type p; -static string -swapV(const string& filename, const string& pat, const string& v) -{ - string vfilename = filename; - string::size_type p; + while ((p = vfilename.find(pat)) != string::npos) + { + vfilename.replace(p, 2, v); + } - while ((p = vfilename.find(pat)) != string::npos) - { - vfilename.replace(p, 2, v); + return vfilename; } - return vfilename; -} - -void -RvSession::checkForStereoPaths(const string& filename, StringVector& movies) -{ - if (isStereoSequence(filename)) + void RvSession::checkForStereoPaths(const string& filename, + StringVector& movies) { - for (size_t i = 0; i < m_vStrings.size(); i+=2) + if (isStereoSequence(filename)) { - string vfilename = swapV(filename, "%v", m_vStrings[i]); - - for (size_t j = 0; j < m_VStrings.size(); j+=2) + for (size_t i = 0; i < m_vStrings.size(); i += 2) { - string Vfilename = swapV(vfilename, "%V", m_VStrings[j]); - ExistingFileList Vfiles = existingFilesInSequence(Vfilename); - if (Vfiles.size() > 0 && TwkUtil::fileExists(Vfiles[0].name.c_str())) + string vfilename = swapV(filename, "%v", m_vStrings[i]); + + for (size_t j = 0; j < m_VStrings.size(); j += 2) { - movies.push_back(Vfilename); - string rfilename = swapV(swapV(filename, "%v", m_vStrings[i+1]), "%V", m_VStrings[j+1]); - ExistingFileList rfiles = existingFilesInSequence(rfilename); - if (rfiles.size() > 0 && TwkUtil::fileExists(rfiles[0].name.c_str())) + string Vfilename = swapV(vfilename, "%V", m_VStrings[j]); + ExistingFileList Vfiles = + existingFilesInSequence(Vfilename); + if (Vfiles.size() > 0 + && TwkUtil::fileExists(Vfiles[0].name.c_str())) { - movies.push_back(rfilename); - } - else - { - cerr << "ERROR: can't find right eye in " << filename << endl; - } + movies.push_back(Vfilename); + string rfilename = + swapV(swapV(filename, "%v", m_vStrings[i + 1]), + "%V", m_VStrings[j + 1]); + ExistingFileList rfiles = + existingFilesInSequence(rfilename); + if (rfiles.size() > 0 + && TwkUtil::fileExists(rfiles[0].name.c_str())) + { + movies.push_back(rfilename); + } + else + { + cerr << "ERROR: can't find right eye in " + << filename << endl; + } - return; + return; + } } } } + else + { + movies.push_back(filename); + } } - else - { - movies.push_back(filename); - } -} - -void -RvSession::findProperty(PropertyVector& props, const std::string& name) -{ - StringVector parts; - algorithm::split(parts, name, is_any_of(string("."))); - if (parts[0] == "#RVSource" && parts.size() == 3) + void RvSession::findProperty(PropertyVector& props, const std::string& name) { - ostringstream fname; - ostringstream iname; + StringVector parts; + algorithm::split(parts, name, is_any_of(string("."))); - fname << "#RVFileSource." << parts[1] << "." << parts[2]; - iname << "#RVImageSource." << parts[1] << "." << parts[2]; + if (parts[0] == "#RVSource" && parts.size() == 3) + { + ostringstream fname; + ostringstream iname; - graph().findProperty(m_frame, props, fname.str()); - graph().findProperty(m_frame, props, iname.str()); - } - else - { - graph().findProperty(m_frame, props, name); - } -} + fname << "#RVFileSource." << parts[1] << "." << parts[2]; + iname << "#RVImageSource." << parts[1] << "." << parts[2]; -void -RvSession::findCurrentNodesByTypeName(NodeVector& nodes, const string& typeName) -{ - if (typeName == "RVSource") - { - graph().findNodesByTypeName(m_frame, nodes, "RVFileSource"); - graph().findNodesByTypeName(m_frame, nodes, "RVImageSource"); - } - else - { - graph().findNodesByTypeName(m_frame, nodes, typeName); + graph().findProperty(m_frame, props, fname.str()); + graph().findProperty(m_frame, props, iname.str()); + } + else + { + graph().findProperty(m_frame, props, name); + } } -} -void -RvSession::findNodesByTypeName(NodeVector& nodes, const string& typeName) -{ - if (typeName == "RVSource") - { - graph().findNodesByTypeName(nodes, "RVFileSource"); - graph().findNodesByTypeName(nodes, "RVImageSource"); - } - else + void RvSession::findCurrentNodesByTypeName(NodeVector& nodes, + const string& typeName) { - graph().findNodesByTypeName(nodes, typeName); + if (typeName == "RVSource") + { + graph().findNodesByTypeName(m_frame, nodes, "RVFileSource"); + graph().findNodesByTypeName(m_frame, nodes, "RVImageSource"); + } + else + { + graph().findNodesByTypeName(m_frame, nodes, typeName); + } } -} - -IPNode* -RvSession::newNode(const std::string& typeName, const std::string& nodeName) -{ - IPNode* node = graph().newNode(typeName, nodeName); - - if (node) userGenericEvent("new-node", node->name()); - - return node; -} -void -RvSession::setRendererType(const std::string& type) -{ - Session::setRendererType(type); - - if (renderer()) + void RvSession::findNodesByTypeName(NodeVector& nodes, + const string& typeName) { - Rv::Options& opts = Rv::Options::sharedOptions(); - renderer()->setFiltering(opts.imageFilter); + if (typeName == "RVSource") + { + graph().findNodesByTypeName(nodes, "RVFileSource"); + graph().findNodesByTypeName(nodes, "RVImageSource"); + } + else + { + graph().findNodesByTypeName(nodes, typeName); + } } -} -void -RvSession::deleteNode(IPNode* node) -{ - bool isSource = dynamic_cast(node) || dynamic_cast(node); - string name = node->name(); - - if (isSource) userGenericEvent("before-source-delete", name); - - if (node == m_conductorSource) m_conductorSource = nullptr; - if (node == m_sequenceIPNode) setSequenceIPNode(nullptr); - - Session::deleteNode(node); - - if (isSource) userGenericEvent("after-source-delete", name); -} + IPNode* RvSession::newNode(const std::string& typeName, + const std::string& nodeName) + { + IPNode* node = graph().newNode(typeName, nodeName); -void -RvSession::readProfile(const string& infilename, - IPNode* node, - const ReadRequest& request) -{ - Session::readProfile(infilename, node, request); -} + if (node) + userGenericEvent("new-node", node->name()); -// onGraphFastAddSourceChanged is called after the graph changes the state of fastAddSourceEnabled -// -void -RvSession::onGraphFastAddSourceChanged(bool begin, int newFastAddSourceEnabled) -{ - if (begin && (newFastAddSourceEnabled == 1)) - unsetSequenceEvents(); - else if(!begin && (newFastAddSourceEnabled == 0)) - setSequenceEvents(); -} + return node; + } -void -RvSession::onGraphMediaSetEmpty() -{ - userGenericEvent("after-progressive-loading", ""); -} + void RvSession::setRendererType(const std::string& type) + { + Session::setRendererType(type); -// connects events from the sequence IP node -// -void -RvSession::setSequenceEvents() -{ - if ( ! evUseSequenceEventsTracking.getValue() ) return; + if (renderer()) + { + Rv::Options& opts = Rv::Options::sharedOptions(); + renderer()->setFiltering(opts.imageFilter); + } + } - auto sequenceIPNode = dynamic_cast(m_graph->findNode(defaultSequenceSequenceIPNodeName)); - setSequenceIPNode(sequenceIPNode); - m_firstSequenceChange = true; -} + void RvSession::deleteNode(IPNode* node) + { + bool isSource = dynamic_cast(node) + || dynamic_cast(node); + string name = node->name(); -// disconnects events from the sequence IP node -// -void -RvSession::unsetSequenceEvents() -{ - if ( ! evUseSequenceEventsTracking.getValue() ) return; + if (isSource) + userGenericEvent("before-source-delete", name); - setSequenceIPNode(nullptr); -} + if (node == m_conductorSource) + m_conductorSource = nullptr; + if (node == m_sequenceIPNode) + setSequenceIPNode(nullptr); -// connect or disconnect a new sequence IP node -// -void -RvSession::setSequenceIPNode(IPCore::SequenceIPNode* newSequenceIPNode) -{ - if ( m_sequenceIPNode == newSequenceIPNode) - return; + Session::deleteNode(node); - if ( m_sequenceIPNode) - { - m_sequenceIPNode->changingSignal().disconnect(boost::bind(&RvSession::onSequenceChanging, this)); - m_sequenceIPNode->changedSignal().disconnect(boost::bind(&RvSession::onSequenceChanged, this)); + if (isSource) + userGenericEvent("after-source-delete", name); } - m_sequenceIPNode = newSequenceIPNode; - - if ( m_sequenceIPNode) + void RvSession::readProfile(const string& infilename, IPNode* node, + const ReadRequest& request) { - m_sequenceIPNode->changingSignal().connect(boost::bind(&RvSession::onSequenceChanging, this)); - m_sequenceIPNode->changedSignal().connect(boost::bind(&RvSession::onSequenceChanged, this)); + Session::readProfile(infilename, node, request); } -} - -// onSequenceChanging is called before all state modification -// in the sequence IP node. -// -// It saves the state of the source where the playhead is located. -// -void -RvSession::onSequenceChanging() -{ - auto root = rootNode(); - if (!root || m_readingGTO || !m_sequenceIPNode) - return; - if (m_firstSequenceChange) + // onGraphFastAddSourceChanged is called after the graph changes the state + // of fastAddSourceEnabled + // + void RvSession::onGraphFastAddSourceChanged(bool begin, + int newFastAddSourceEnabled) { - m_firstSequenceChange = false; - return; + if (begin && (newFastAddSourceEnabled == 1)) + unsetSequenceEvents(); + else if (!begin && (newFastAddSourceEnabled == 0)) + setSequenceEvents(); } - int frameNum = currentFrame(); - m_currentSourceIndex = m_sequenceIPNode->indexAtFrame(frameNum); - if (m_currentSourceIndex >= 0) + void RvSession::onGraphMediaSetEmpty() { - m_sequenceIPNode->getSourceRange(m_currentSourceIndex, m_currentSourceRangeInfo, m_currentSourceOffset); + userGenericEvent("after-progressive-loading", ""); } -} -// onSequenceChanged is called after all state modification in the -// sequence IP node. -// -// It loads the new state of the source where the playhead was before the layout -// and replaces the playhead to the same absolute position if the source is -// discovered or the same relative position if not. -// -// It changes the playhead position to avoid that it dances in the timeline. -void -RvSession::onSequenceChanged() -{ - if (m_currentSourceIndex < 0) - return; - auto root = rootNode(); - if (! root) + // connects events from the sequence IP node + // + void RvSession::setSequenceEvents() { - m_currentSourceIndex = -1; - return; + if (!evUseSequenceEventsTracking.getValue()) + return; + + auto sequenceIPNode = dynamic_cast( + m_graph->findNode(defaultSequenceSequenceIPNodeName)); + setSequenceIPNode(sequenceIPNode); + m_firstSequenceChange = true; } - IPCore::IPNode::ImageRangeInfo newSourceRangeInfo; - int newSourceOffset; - if(!m_sequenceIPNode->getSourceRange(m_currentSourceIndex, newSourceRangeInfo, newSourceOffset)) + // disconnects events from the sequence IP node + // + void RvSession::unsetSequenceEvents() { - m_currentSourceIndex = -1; - return; + if (!evUseSequenceEventsTracking.getValue()) + return; + + setSequenceIPNode(nullptr); } - int currFrameNum = currentFrame(); - int newFrameNum = currFrameNum; - if (m_currentSourceRangeInfo.isUndiscovered) + // connect or disconnect a new sequence IP node + // + void RvSession::setSequenceIPNode(IPCore::SequenceIPNode* newSequenceIPNode) { - // we want that the playhead stays at the same relative position in the source - double ratio = static_cast(currFrameNum - m_currentSourceOffset) / (m_currentSourceRangeInfo.cutOut - m_currentSourceRangeInfo.cutIn + 1); - newFrameNum = newSourceOffset + static_cast(ratio * (newSourceRangeInfo.cutOut - newSourceRangeInfo.cutIn + 1)); + if (m_sequenceIPNode == newSequenceIPNode) + return; + + if (m_sequenceIPNode) + { + m_sequenceIPNode->changingSignal().disconnect( + boost::bind(&RvSession::onSequenceChanging, this)); + m_sequenceIPNode->changedSignal().disconnect( + boost::bind(&RvSession::onSequenceChanged, this)); + } + + m_sequenceIPNode = newSequenceIPNode; + + if (m_sequenceIPNode) + { + m_sequenceIPNode->changingSignal().connect( + boost::bind(&RvSession::onSequenceChanging, this)); + m_sequenceIPNode->changedSignal().connect( + boost::bind(&RvSession::onSequenceChanged, this)); + } } - else + + // onSequenceChanging is called before all state modification + // in the sequence IP node. + // + // It saves the state of the source where the playhead is located. + // + void RvSession::onSequenceChanging() { - // we want that the playhead stays at the same absolute position in the source - int frameOffset = currFrameNum - m_currentSourceOffset; - newFrameNum = newSourceOffset + frameOffset; + auto root = rootNode(); + if (!root || m_readingGTO || !m_sequenceIPNode) + return; + + if (m_firstSequenceChange) + { + m_firstSequenceChange = false; + return; + } + + int frameNum = currentFrame(); + m_currentSourceIndex = m_sequenceIPNode->indexAtFrame(frameNum); + if (m_currentSourceIndex >= 0) + { + m_sequenceIPNode->getSourceRange(m_currentSourceIndex, + m_currentSourceRangeInfo, + m_currentSourceOffset); + } } - if (newFrameNum != currFrameNum) + // onSequenceChanged is called after all state modification in the + // sequence IP node. + // + // It loads the new state of the source where the playhead was before the + // layout and replaces the playhead to the same absolute position if the + // source is discovered or the same relative position if not. + // + // It changes the playhead position to avoid that it dances in the timeline. + void RvSession::onSequenceChanged() { - setFrame(newFrameNum); - } + if (m_currentSourceIndex < 0) + return; + auto root = rootNode(); + if (!root) + { + m_currentSourceIndex = -1; + return; + } - m_currentSourceIndex = -1; -} + IPCore::IPNode::ImageRangeInfo newSourceRangeInfo; + int newSourceOffset; + if (!m_sequenceIPNode->getSourceRange( + m_currentSourceIndex, newSourceRangeInfo, newSourceOffset)) + { + m_currentSourceIndex = -1; + return; + } -// onGraphNodeWillRemove is called when a node will be remove in the graph. -// -void RvSession::onGraphNodeWillRemove(IPCore::IPNode * node) -{ - // unlink all rendered image linked to this node - auto imageRenderer = renderer(); - if (imageRenderer) - imageRenderer->unlinkNode(node); -} + int currFrameNum = currentFrame(); + int newFrameNum = currFrameNum; + if (m_currentSourceRangeInfo.isUndiscovered) + { + // we want that the playhead stays at the same relative position in + // the source + double ratio = + static_cast(currFrameNum - m_currentSourceOffset) + / (m_currentSourceRangeInfo.cutOut + - m_currentSourceRangeInfo.cutIn + 1); + newFrameNum = + newSourceOffset + + static_cast(ratio + * (newSourceRangeInfo.cutOut + - newSourceRangeInfo.cutIn + 1)); + } + else + { + // we want that the playhead stays at the same absolute position in + // the source + int frameOffset = currFrameNum - m_currentSourceOffset; + newFrameNum = newSourceOffset + frameOffset; + } + + if (newFrameNum != currFrameNum) + { + setFrame(newFrameNum); + } + + m_currentSourceIndex = -1; + } -} // Rv + // onGraphNodeWillRemove is called when a node will be remove in the graph. + // + void RvSession::onGraphNodeWillRemove(IPCore::IPNode* node) + { + // unlink all rendered image linked to this node + auto imageRenderer = renderer(); + if (imageRenderer) + imageRenderer->unlinkNode(node); + } +} // namespace Rv diff --git a/src/lib/app/RvApp/RvViewGroupIPNode.cpp b/src/lib/app/RvApp/RvViewGroupIPNode.cpp index 8931be331..abec363d8 100644 --- a/src/lib/app/RvApp/RvViewGroupIPNode.cpp +++ b/src/lib/app/RvApp/RvViewGroupIPNode.cpp @@ -1,9 +1,9 @@ // -// Copyright (c) 2010 Tweak Software. +// Copyright (c) 2010 Tweak Software. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// // #include @@ -11,25 +11,25 @@ // RV third party optional customization #if defined(RV_VIEW_GROUP_THIRD_PARTY_CUSTOMIZATION) - extern IPCore::IPImage* rvViewGroupThirdPartyCustomization(IPCore::IPNode* node, const IPCore::IPNode::Context& context); +extern IPCore::IPImage* +rvViewGroupThirdPartyCustomization(IPCore::IPNode* node, + const IPCore::IPNode::Context& context); #endif -namespace Rv { - - -IPImage* -RvViewGroupIPNode::evaluate(const Context& context) +namespace Rv { + + IPImage* RvViewGroupIPNode::evaluate(const Context& context) + { #if defined(RV_VIEW_GROUP_THIRD_PARTY_CUSTOMIZATION) - IPImage* img = rvViewGroupThirdPartyCustomization(this, context); - if (img) return img; + IPImage* img = rvViewGroupThirdPartyCustomization(this, context); + if (img) + return img; #endif - return ViewGroupIPNode::evaluate(context); -} + return ViewGroupIPNode::evaluate(context); + } -RvViewGroupIPNode::~RvViewGroupIPNode() -{ -} + RvViewGroupIPNode::~RvViewGroupIPNode() {} -} // Rv +} // namespace Rv diff --git a/src/lib/app/RvCommon/CGDesktopVideoDevice.cpp b/src/lib/app/RvCommon/CGDesktopVideoDevice.cpp index dd37e9711..ab7c3e93b 100644 --- a/src/lib/app/RvCommon/CGDesktopVideoDevice.cpp +++ b/src/lib/app/RvCommon/CGDesktopVideoDevice.cpp @@ -1,9 +1,9 @@ // -// Copyright (c) 2011 Tweak Software. +// Copyright (c) 2011 Tweak Software. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// // #include #include @@ -11,260 +11,297 @@ #include #include -namespace Rv { +namespace Rv +{ -using namespace std; -using namespace TwkGLF; -using namespace TwkApp; -using namespace boost; + using namespace std; + using namespace TwkGLF; + using namespace TwkApp; + using namespace boost; -namespace { + namespace + { -string -tostring(CFStringRef s) -{ - vector str(CFStringGetLength(s) * 4 + 1); - CFStringGetCString(s, &str.front(), str.size(), kCFStringEncodingUTF8); - return string(&str.front()); -} + string tostring(CFStringRef s) + { + vector str(CFStringGetLength(s) * 4 + 1); + CFStringGetCString(s, &str.front(), str.size(), + kCFStringEncodingUTF8); + return string(&str.front()); + } -int -depthFromPixelEncoding(CFStringRef pixEnc) -{ - int depth = 0; - - if (CFStringCompare(pixEnc, CFSTR(IO32BitDirectPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo) depth = 8; - else if(CFStringCompare(pixEnc, CFSTR(IO16BitDirectPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo) depth = 5; - else if(CFStringCompare(pixEnc, CFSTR(IO8BitIndexedPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo) depth = 2; - else if(CFStringCompare(pixEnc, CFSTR(kIO30BitDirectPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo) depth = 10; - - CFRelease(pixEnc); - return depth; -} - -double -modeHz(CGDisplayModeRef mode, CFMutableArrayRef ioModesArray, int ioModeCount, double defaultHz) -{ - // - // CGDisplayModeGetRefreshRate can return 0.0 which is not - // helpful. So we look up the same mode in IOKit's mode list to - // get the a better rate number if it exists. - // - - const int32_t modeID = CGDisplayModeGetIODisplayModeID(mode); - const size_t width = CGDisplayModeGetWidth(mode); - const size_t height = CGDisplayModeGetHeight(mode); - double hz = CGDisplayModeGetRefreshRate(mode); - - for (CFIndex i = 0; i < ioModeCount; ++i) - { - if (CFMutableDictionaryRef dict = - (CFMutableDictionaryRef) CFArrayGetValueAtIndex(ioModesArray, i)) + int depthFromPixelEncoding(CFStringRef pixEnc) { - CFNumberRef num = (CFNumberRef) CFDictionaryGetValue(dict, CFSTR(kIOFBModeIDKey)); - int32_t n = 0; - CFNumberGetValue(num, kCFNumberSInt32Type, &n); + int depth = 0; + + if (CFStringCompare(pixEnc, CFSTR(IO32BitDirectPixels), + kCFCompareCaseInsensitive) + == kCFCompareEqualTo) + depth = 8; + else if (CFStringCompare(pixEnc, CFSTR(IO16BitDirectPixels), + kCFCompareCaseInsensitive) + == kCFCompareEqualTo) + depth = 5; + else if (CFStringCompare(pixEnc, CFSTR(IO8BitIndexedPixels), + kCFCompareCaseInsensitive) + == kCFCompareEqualTo) + depth = 2; + else if (CFStringCompare(pixEnc, CFSTR(kIO30BitDirectPixels), + kCFCompareCaseInsensitive) + == kCFCompareEqualTo) + depth = 10; + + CFRelease(pixEnc); + return depth; + } - if (n == modeID) + double modeHz(CGDisplayModeRef mode, CFMutableArrayRef ioModesArray, + int ioModeCount, double defaultHz) + { + // + // CGDisplayModeGetRefreshRate can return 0.0 which is not + // helpful. So we look up the same mode in IOKit's mode list to + // get the a better rate number if it exists. + // + + const int32_t modeID = CGDisplayModeGetIODisplayModeID(mode); + const size_t width = CGDisplayModeGetWidth(mode); + const size_t height = CGDisplayModeGetHeight(mode); + double hz = CGDisplayModeGetRefreshRate(mode); + + for (CFIndex i = 0; i < ioModeCount; ++i) { - if (const CFDataRef data = - (CFDataRef) CFDictionaryGetValue(dict, CFSTR(kIOFBModeDMKey))) + if (CFMutableDictionaryRef dict = + (CFMutableDictionaryRef)CFArrayGetValueAtIndex( + ioModesArray, i)) { - IODisplayModeInformation* ioModeInfo = - (IODisplayModeInformation *) CFDataGetBytePtr(data); + CFNumberRef num = (CFNumberRef)CFDictionaryGetValue( + dict, CFSTR(kIOFBModeIDKey)); + int32_t n = 0; + CFNumberGetValue(num, kCFNumberSInt32Type, &n); - if (ioModeInfo && - ioModeInfo->nominalWidth == width && - ioModeInfo->nominalHeight == height) + if (n == modeID) { - hz = ioModeInfo->refreshRate / 65536.0; - break; + if (const CFDataRef data = + (CFDataRef)CFDictionaryGetValue( + dict, CFSTR(kIOFBModeDMKey))) + { + IODisplayModeInformation* ioModeInfo = + (IODisplayModeInformation*)CFDataGetBytePtr( + data); + + if (ioModeInfo && ioModeInfo->nominalWidth == width + && ioModeInfo->nominalHeight == height) + { + hz = ioModeInfo->refreshRate / 65536.0; + break; + } + } } } } - } - } - // - // If IOKit gives us crap for the mode Hz just assume the - // DisplayLink hz is applied to all modes. This seems to happen - // when dynamic gpu switching is on in a laptop. In that case it - // appears that all the laptop hz are the same anyway so just - // make that assumption. It will be correct at least for the - // current mode - // - - if (hz == 0.0) hz = defaultHz; - - return hz; -} - -CGDisplayModeRef -displayModeRefFromIOMode(int32_t ioMode, CGDirectDisplayID cgScreen) -{ - io_service_t ioFB = CGDisplayIOServicePort(cgScreen); - CFMutableDictionaryRef ioFBConfigDict = (CFMutableDictionaryRef) IORegistryEntryCreateCFProperty(ioFB, CFSTR(kIOFBConfigKey), kCFAllocatorDefault, kNilOptions); - CFArrayRef array = CGDisplayCopyAllDisplayModes(cgScreen, NULL); - - for (CFIndex i = 0, n = CFArrayGetCount(array); i < n; i++) - { - const CGDisplayModeRef mode = (CGDisplayModeRef)CFArrayGetValueAtIndex(array, i); - const int32_t id = CGDisplayModeGetIODisplayModeID(mode); + // + // If IOKit gives us crap for the mode Hz just assume the + // DisplayLink hz is applied to all modes. This seems to happen + // when dynamic gpu switching is on in a laptop. In that case it + // appears that all the laptop hz are the same anyway so just + // make that assumption. It will be correct at least for the + // current mode + // - if (id == ioMode) return mode; - } + if (hz == 0.0) + hz = defaultHz; - return CGDisplayModeRef(0); -} - -} - -CGDesktopVideoDevice::CGDesktopVideoDevice(VideoModule* m, - const std::string& name, - CGDirectDisplayID cgScreen, - int qtScreen, - const QTGLVideoDevice* share) - : DesktopVideoDevice(m, name, share), - m_cgScreen(cgScreen), - m_qtScreen(qtScreen), - m_context(0), - m_modes(0), - m_savedMode(0) -{ - createFormats(); -} - -void -CGDesktopVideoDevice::createFormats() -{ - m_videoFormats.clear(); - m_videoFormatIndex = -1; - m_ioModeMap.clear(); - - // - // Create a temporary CVDisplayLink and get the hz from - // there. This seems to always work even in the case of Dynamic - // Switching between GPUs. Usually in that case we just 0.0 for - // all the hz. Forcing the GPU to a specific one will result in - // correct results. - // - // NOTE: you'd think CVDisplayLinkGetActualOutputVideoRefreshPeriod - // wouldn't return 0 but that's what it does rendering it useless. - // - - CVDisplayLinkRef cvLinkRef = 0; - CVDisplayLinkCreateWithCGDisplay (m_cgScreen, &cvLinkRef); - CVTime cvRef = CVDisplayLinkGetNominalOutputVideoRefreshPeriod(cvLinkRef); - double cvRefHz = double(cvRef.timeScale)/double(cvRef.timeValue); - CFRelease(cvLinkRef); - - // - // 10.6 SDK or better - // - // NOTE: on machines with 2 GPUs (discreet and integrated) you - // can get in a funny situation where we find the modes for the - // wrong GPU. Basically the integrated GPU modes are different - // than the discreet GPU's. This happens because we haven't - // switched to the discreet GPU yet when this is made? - // - - io_service_t ioFB = CGDisplayIOServicePort(m_cgScreen); - CFMutableDictionaryRef ioFBConfigDict = (CFMutableDictionaryRef) IORegistryEntryCreateCFProperty(ioFB, CFSTR(kIOFBConfigKey), kCFAllocatorDefault, kNilOptions); - CFMutableArrayRef ioModesArray = (ioFBConfigDict) ? (CFMutableArrayRef) CFDictionaryGetValue(ioFBConfigDict, CFSTR(kIOFBModesKey)) : 0; - int ioModeCount = (ioModesArray) ? CFArrayGetCount(ioModesArray) : 0; - - CFArrayRef array = CGDisplayCopyAllDisplayModes(m_cgScreen, NULL); - CGDisplayModeRef currentMode = CGDisplayCopyDisplayMode(m_cgScreen); - int32_t currentModeID = CGDisplayModeGetIODisplayModeID(currentMode); - io_connect_t displayPort = CGDisplayIOServicePort(m_cgScreen); - int uniqueModes = 0; - - m_modes = array; - CFRetain(array); - - for (CFIndex i = 0, n = CFArrayGetCount(array); i < n; i++) - { - const CGDisplayModeRef mode = (CGDisplayModeRef)CFArrayGetValueAtIndex(array, i); - const int32_t id = CGDisplayModeGetIODisplayModeID(mode); - const size_t flags = CGDisplayModeGetIOFlags(mode); - const size_t depth = depthFromPixelEncoding(CGDisplayModeCopyPixelEncoding(mode)); + return hz; + } - if ((flags & kDisplayModeSafetyFlags) && depth >= 8) + CGDisplayModeRef displayModeRefFromIOMode(int32_t ioMode, + CGDirectDisplayID cgScreen) { - const size_t width = CGDisplayModeGetWidth(mode); - const size_t height = CGDisplayModeGetHeight(mode); - const int32_t ioID = CGDisplayModeGetIODisplayModeID(mode); - const double hz = modeHz(mode, ioModesArray, ioModeCount, cvRefHz); - - ostringstream str; - str << width << " x " << height; - str.precision(4); - if (hz != 0.0) str << " " << hz << "Hz "; - if (flags & kDisplayModeStretchedFlag) str << " (stretched)"; - if (depth > 8) str << " " << depth << " bits/channel"; + io_service_t ioFB = CGDisplayIOServicePort(cgScreen); + CFMutableDictionaryRef ioFBConfigDict = + (CFMutableDictionaryRef)IORegistryEntryCreateCFProperty( + ioFB, CFSTR(kIOFBConfigKey), kCFAllocatorDefault, + kNilOptions); + CFArrayRef array = CGDisplayCopyAllDisplayModes(cgScreen, NULL); + + for (CFIndex i = 0, n = CFArrayGetCount(array); i < n; i++) + { + const CGDisplayModeRef mode = + (CGDisplayModeRef)CFArrayGetValueAtIndex(array, i); + const int32_t id = CGDisplayModeGetIODisplayModeID(mode); - // cerr << m_name << ": adding mode " << m_videoFormats.size() - // << " " << str.str() - // << ", (" << id << ")" - // << endl; + if (id == ioMode) + return mode; + } - m_videoFormats.push_back(DesktopVideoFormat(width, height, 1.0, 1.0, hz, - str.str(), (void*)(size_t)ioID)); + return CGDisplayModeRef(0); } - } - - addDefaultDataFormats(); - sortVideoFormatsByWidth(); - - // - // Locate the current mode index and create the IOModeMap going - // from IOKit display mode to video format index - // - for (size_t i = 0; i < m_videoFormats.size(); i++) + } // namespace + + CGDesktopVideoDevice::CGDesktopVideoDevice(VideoModule* m, + const std::string& name, + CGDirectDisplayID cgScreen, + int qtScreen, + const QTGLVideoDevice* share) + : DesktopVideoDevice(m, name, share) + , m_cgScreen(cgScreen) + , m_qtScreen(qtScreen) + , m_context(0) + , m_modes(0) + , m_savedMode(0) { - int32_t mid = int32_t((size_t)m_videoFormats[i].data); - if (mid == currentModeID) m_videoFormatIndex = i; - m_ioModeMap[mid] = i; + createFormats(); } - if (m_videoFormatIndex == -1) + void CGDesktopVideoDevice::createFormats() { + m_videoFormats.clear(); + m_videoFormatIndex = -1; + m_ioModeMap.clear(); + // - // We got here because somehow we were unable to find the - // current mode. This doesn't seem to happen anymore but just - // in case the code is still active. + // Create a temporary CVDisplayLink and get the hz from + // there. This seems to always work even in the case of Dynamic + // Switching between GPUs. Usually in that case we just 0.0 for + // all the hz. Forcing the GPU to a specific one will result in + // correct results. + // + // NOTE: you'd think CVDisplayLinkGetActualOutputVideoRefreshPeriod + // wouldn't return 0 but that's what it does rendering it useless. // - if (IPCore::debugPlayback) cout << "INFO: found new video modes" << endl; - - int w = CGDisplayModeGetWidth(currentMode); - int h = CGDisplayModeGetHeight(currentMode); - ostringstream str; - str << w << " x " << h; - str.precision(4); - str << " " << cvRefHz << "Hz "; + CVDisplayLinkRef cvLinkRef = 0; + CVDisplayLinkCreateWithCGDisplay(m_cgScreen, &cvLinkRef); + CVTime cvRef = + CVDisplayLinkGetNominalOutputVideoRefreshPeriod(cvLinkRef); + double cvRefHz = double(cvRef.timeScale) / double(cvRef.timeValue); + CFRelease(cvLinkRef); - m_ioModeMap[currentModeID] = m_videoFormats.size(); + // + // 10.6 SDK or better + // + // NOTE: on machines with 2 GPUs (discreet and integrated) you + // can get in a funny situation where we find the modes for the + // wrong GPU. Basically the integrated GPU modes are different + // than the discreet GPU's. This happens because we haven't + // switched to the discreet GPU yet when this is made? + // - m_videoFormats.push_back(DesktopVideoFormat(w, h, 1.0, 1.0, cvRefHz, str.str(), - (void*)(size_t)currentModeID)); + io_service_t ioFB = CGDisplayIOServicePort(m_cgScreen); + CFMutableDictionaryRef ioFBConfigDict = + (CFMutableDictionaryRef)IORegistryEntryCreateCFProperty( + ioFB, CFSTR(kIOFBConfigKey), kCFAllocatorDefault, kNilOptions); + CFMutableArrayRef ioModesArray = + (ioFBConfigDict) ? (CFMutableArrayRef)CFDictionaryGetValue( + ioFBConfigDict, CFSTR(kIOFBModesKey)) + : 0; + int ioModeCount = (ioModesArray) ? CFArrayGetCount(ioModesArray) : 0; + + CFArrayRef array = CGDisplayCopyAllDisplayModes(m_cgScreen, NULL); + CGDisplayModeRef currentMode = CGDisplayCopyDisplayMode(m_cgScreen); + int32_t currentModeID = CGDisplayModeGetIODisplayModeID(currentMode); + io_connect_t displayPort = CGDisplayIOServicePort(m_cgScreen); + int uniqueModes = 0; + + m_modes = array; + CFRetain(array); + + for (CFIndex i = 0, n = CFArrayGetCount(array); i < n; i++) + { + const CGDisplayModeRef mode = + (CGDisplayModeRef)CFArrayGetValueAtIndex(array, i); + const int32_t id = CGDisplayModeGetIODisplayModeID(mode); + const size_t flags = CGDisplayModeGetIOFlags(mode); + const size_t depth = + depthFromPixelEncoding(CGDisplayModeCopyPixelEncoding(mode)); + + if ((flags & kDisplayModeSafetyFlags) && depth >= 8) + { + const size_t width = CGDisplayModeGetWidth(mode); + const size_t height = CGDisplayModeGetHeight(mode); + const int32_t ioID = CGDisplayModeGetIODisplayModeID(mode); + const double hz = + modeHz(mode, ioModesArray, ioModeCount, cvRefHz); + + ostringstream str; + str << width << " x " << height; + str.precision(4); + if (hz != 0.0) + str << " " << hz << "Hz "; + if (flags & kDisplayModeStretchedFlag) + str << " (stretched)"; + if (depth > 8) + str << " " << depth << " bits/channel"; + + // cerr << m_name << ": adding mode " << m_videoFormats.size() + // << " " << str.str() + // << ", (" << id << ")" + // << endl; + + m_videoFormats.push_back( + DesktopVideoFormat(width, height, 1.0, 1.0, hz, str.str(), + (void*)(size_t)ioID)); + } + } + addDefaultDataFormats(); + sortVideoFormatsByWidth(); // - // Then re-sort and re-determine index. + // Locate the current mode index and create the IOModeMap going + // from IOKit display mode to video format index // - sortVideoFormatsByWidth(); - for (size_t i = 0; i < m_videoFormats.size(); i++) { int32_t mid = int32_t((size_t)m_videoFormats[i].data); - if (mid == currentModeID) m_videoFormatIndex = i; + if (mid == currentModeID) + m_videoFormatIndex = i; + m_ioModeMap[mid] = i; } - } - CFRelease(currentMode); + if (m_videoFormatIndex == -1) + { + // + // We got here because somehow we were unable to find the + // current mode. This doesn't seem to happen anymore but just + // in case the code is still active. + // + + if (IPCore::debugPlayback) + cout << "INFO: found new video modes" << endl; + + int w = CGDisplayModeGetWidth(currentMode); + int h = CGDisplayModeGetHeight(currentMode); + ostringstream str; + str << w << " x " << h; + str.precision(4); + str << " " << cvRefHz << "Hz "; + + m_ioModeMap[currentModeID] = m_videoFormats.size(); + + m_videoFormats.push_back( + DesktopVideoFormat(w, h, 1.0, 1.0, cvRefHz, str.str(), + (void*)(size_t)currentModeID)); + + // + // Then re-sort and re-determine index. + // + + sortVideoFormatsByWidth(); + + for (size_t i = 0; i < m_videoFormats.size(); i++) + { + int32_t mid = int32_t((size_t)m_videoFormats[i].data); + if (mid == currentModeID) + m_videoFormatIndex = i; + } + } + + CFRelease(currentMode); #if 0 for (size_t i = 0; i < m_videoFormats.size(); i++) @@ -278,237 +315,227 @@ CGDesktopVideoDevice::createFormats() << endl; } #endif -} - -CGDesktopVideoDevice::~CGDesktopVideoDevice() -{ - close(); -} - -void -CGDesktopVideoDevice::makeCurrent() const -{ - m_viewDevice->makeCurrent(); -} + } -bool -CGDesktopVideoDevice::isSyncing() const -{ - ScopedLock lock(m_syncTestMutex); - return m_syncing; -} + CGDesktopVideoDevice::~CGDesktopVideoDevice() { close(); } -void -CGDesktopVideoDevice::syncBuffers() const -{ - ScopedLock lock(m_mutex); + void CGDesktopVideoDevice::makeCurrent() const + { + m_viewDevice->makeCurrent(); + } + bool CGDesktopVideoDevice::isSyncing() const { ScopedLock lock(m_syncTestMutex); - m_syncing = true; + return m_syncing; } - makeCurrent(); + void CGDesktopVideoDevice::syncBuffers() const + { + ScopedLock lock(m_mutex); - // - // Docs for CGFlushDrawable say it includes a glFlush and user should - // "should not call glFlush() prior", so don't call it here. - // - // ARG! This breaks presentation mode. putting it back in. - // + { + ScopedLock lock(m_syncTestMutex); + m_syncing = true; + } - glFlush(); + makeCurrent(); - CGLFlushDrawable(m_context); + // + // Docs for CGFlushDrawable say it includes a glFlush and user should + // "should not call glFlush() prior", so don't call it here. + // + // ARG! This breaks presentation mode. putting it back in. + // - { - ScopedLock lock(m_syncTestMutex); - m_syncing = false; - } -} + glFlush(); -void -CGDesktopVideoDevice::open(const StringVector& args) -{ - CGDisplayCapture(m_cgScreen); - const DesktopVideoFormat& format = m_videoFormats[m_videoFormatIndex]; - - // - // Get the mac CGLContextObj from the shared QTGLVideoDevice - // context NOTE: we're using "pre 10.6" method because we want to - // capture the display (this lets us change the refresh rate, - // etc). - // - - shareDevice()->makeCurrent(); - CGLContextObj shareContext = CGLGetCurrentContext(); - - vector attrs; - - attrs.push_back(kCGLPFAAccelerated); - attrs.push_back(kCGLPFADoubleBuffer); - attrs.push_back(kCGLPFAColorSize); attrs.push_back(3 * 8); - attrs.push_back(kCGLPFAStencilSize); attrs.push_back(8); - attrs.push_back(kCGLPFADisplayMask); attrs.push_back(CGDisplayIDToOpenGLDisplayMask(m_cgScreen)); - if (m_dataFormats[m_dataFormatIndex].stereoMode == QuadBufferStereo) - { - attrs.push_back(kCGLPFAStereo); - } - attrs.push_back(0); + CGLFlushDrawable(m_context); - if (CGLError err = - CGLChoosePixelFormat((CGLPixelFormatAttribute*)&attrs.front(), &m_pfo, &m_npfo)) - { - cout << "ERROR: choosing pixel format: " << CGLErrorString(err) << endl; - exit(-1); + { + ScopedLock lock(m_syncTestMutex); + m_syncing = false; + } } - if (CGLError err = CGLCreateContext(m_pfo, shareContext, &m_context)) + void CGDesktopVideoDevice::open(const StringVector& args) { - cout << "ERROR: create context: " << CGLErrorString(err) << endl; - exit(-1); - } + CGDisplayCapture(m_cgScreen); + const DesktopVideoFormat& format = m_videoFormats[m_videoFormatIndex]; - //CGDisplayHideCursor(m_cgScreen); - m_savedMode = CGDisplayCopyDisplayMode(m_cgScreen); + // + // Get the mac CGLContextObj from the shared QTGLVideoDevice + // context NOTE: we're using "pre 10.6" method because we want to + // capture the display (this lets us change the refresh rate, + // etc). + // - CGDisplayModeRef mode = displayModeRefFromIOMode(int32_t((size_t)format.data), m_cgScreen); - CGDisplaySetDisplayMode(m_cgScreen, mode, NULL); - CGDisplayCapture(m_cgScreen); + shareDevice()->makeCurrent(); + CGLContextObj shareContext = CGLGetCurrentContext(); - CGLSetFullScreenOnDisplay(m_context, CGDisplayIDToOpenGLDisplayMask(m_cgScreen)); - GLint one = 1; - GLint zero = 0; - CGLSetParameter(m_context, kCGLCPSwapInterval, m_vsync ? &one : &zero); - CGLSetParameter(m_context, kCGLCPSurfaceOrder, &one); + vector attrs; - m_viewDevice = new CGGLVideoDevice(0, format.width, format.height, false, m_context, false); - m_viewDevice->makeCurrent(); -} + attrs.push_back(kCGLPFAAccelerated); + attrs.push_back(kCGLPFADoubleBuffer); + attrs.push_back(kCGLPFAColorSize); + attrs.push_back(3 * 8); + attrs.push_back(kCGLPFAStencilSize); + attrs.push_back(8); + attrs.push_back(kCGLPFADisplayMask); + attrs.push_back(CGDisplayIDToOpenGLDisplayMask(m_cgScreen)); + if (m_dataFormats[m_dataFormatIndex].stereoMode == QuadBufferStereo) + { + attrs.push_back(kCGLPFAStereo); + } + attrs.push_back(0); -bool -CGDesktopVideoDevice::isOpen() const -{ - return m_context != 0; -} + if (CGLError err = CGLChoosePixelFormat( + (CGLPixelFormatAttribute*)&attrs.front(), &m_pfo, &m_npfo)) + { + cout << "ERROR: choosing pixel format: " << CGLErrorString(err) + << endl; + exit(-1); + } -void -CGDesktopVideoDevice::close() -{ - // unbind() should be called by the renderer::setOutputVideoDevice, but just in case, call here too. - // - unbind(); - - ScopedLock lock(m_mutex); - - if (m_savedMode) CGDisplaySetDisplayMode(m_cgScreen, m_savedMode, NULL); - if (m_context) CGLReleaseContext(m_context); - if (m_cgScreen) CGDisplayRelease(m_cgScreen); - if (m_savedMode) CFRelease(m_savedMode); - m_savedMode = 0; - delete m_viewDevice; - m_viewDevice = 0; - m_context = 0; -} - -VideoDevice::Resolution -CGDesktopVideoDevice::resolution() const -{ - return format(); -} + if (CGLError err = CGLCreateContext(m_pfo, shareContext, &m_context)) + { + cout << "ERROR: create context: " << CGLErrorString(err) << endl; + exit(-1); + } -size_t -CGDesktopVideoDevice::width() const -{ - return resolution().width; -} + // CGDisplayHideCursor(m_cgScreen); + m_savedMode = CGDisplayCopyDisplayMode(m_cgScreen); -size_t -CGDesktopVideoDevice::height() const -{ - return resolution().height; -} + CGDisplayModeRef mode = + displayModeRefFromIOMode(int32_t((size_t)format.data), m_cgScreen); + CGDisplaySetDisplayMode(m_cgScreen, mode, NULL); + CGDisplayCapture(m_cgScreen); -float -CGDesktopVideoDevice::pixelScale() const -{ - return resolution().pixelScale; -} + CGLSetFullScreenOnDisplay(m_context, + CGDisplayIDToOpenGLDisplayMask(m_cgScreen)); + GLint one = 1; + GLint zero = 0; + CGLSetParameter(m_context, kCGLCPSwapInterval, m_vsync ? &one : &zero); + CGLSetParameter(m_context, kCGLCPSurfaceOrder, &one); -VideoDevice::VideoFormat -CGDesktopVideoDevice::format() const -{ - CGDisplayModeRef mode = CGDisplayCopyDisplayMode(m_cgScreen); - int32_t id = CGDisplayModeGetIODisplayModeID(mode); - IOModeMap::const_iterator i = m_ioModeMap.find(id); + m_viewDevice = new CGGLVideoDevice(0, format.width, format.height, + false, m_context, false); + m_viewDevice->makeCurrent(); + } - if (i != m_ioModeMap.end()) + bool CGDesktopVideoDevice::isOpen() const { return m_context != 0; } + + void CGDesktopVideoDevice::close() { - return m_videoFormats[i->second]; + // unbind() should be called by the renderer::setOutputVideoDevice, but + // just in case, call here too. + // + unbind(); + + ScopedLock lock(m_mutex); + + if (m_savedMode) + CGDisplaySetDisplayMode(m_cgScreen, m_savedMode, NULL); + if (m_context) + CGLReleaseContext(m_context); + if (m_cgScreen) + CGDisplayRelease(m_cgScreen); + if (m_savedMode) + CFRelease(m_savedMode); + m_savedMode = 0; + delete m_viewDevice; + m_viewDevice = 0; + m_context = 0; } - else + + VideoDevice::Resolution CGDesktopVideoDevice::resolution() const { - const_cast(this)->createFormats(); - i = m_ioModeMap.find(id); + return format(); + } - if (i == m_ioModeMap.end()) + size_t CGDesktopVideoDevice::width() const { return resolution().width; } + + size_t CGDesktopVideoDevice::height() const { return resolution().height; } + + float CGDesktopVideoDevice::pixelScale() const + { + return resolution().pixelScale; + } + + VideoDevice::VideoFormat CGDesktopVideoDevice::format() const + { + CGDisplayModeRef mode = CGDisplayCopyDisplayMode(m_cgScreen); + int32_t id = CGDisplayModeGetIODisplayModeID(mode); + IOModeMap::const_iterator i = m_ioModeMap.find(id); + + if (i != m_ioModeMap.end()) { - cout << "ERROR: unexpected video mode" << endl; - return VideoFormat(); + return m_videoFormats[i->second]; } else { - if (IPCore::debugPlayback) + const_cast(this)->createFormats(); + i = m_ioModeMap.find(id); + + if (i == m_ioModeMap.end()) { - cout << "WARNING: recovered from unexpected video mode " << endl; + cout << "ERROR: unexpected video mode" << endl; + return VideoFormat(); + } + else + { + if (IPCore::debugPlayback) + { + cout << "WARNING: recovered from unexpected video mode " + << endl; + } + return m_videoFormats[i->second]; } - return m_videoFormats[i->second]; } } -} - -VideoDevice::Offset -CGDesktopVideoDevice::offset() const -{ - return Offset(0,0); -} -VideoDevice::Timing -CGDesktopVideoDevice::timing() const -{ - return format(); -} - -TwkApp::VideoDevice::ColorProfile -CGDesktopVideoDevice::colorProfile() const -{ - // - // Get the display's color sync profile - // + VideoDevice::Offset CGDesktopVideoDevice::offset() const + { + return Offset(0, 0); + } - if (ColorSyncProfileRef iccRef = ColorSyncProfileCreateWithDisplayID(m_cgScreen)) + VideoDevice::Timing CGDesktopVideoDevice::timing() const { - m_colorProfile.type = ICCProfile; + return format(); + } - CFStringRef desc = ColorSyncProfileCopyDescriptionString(iccRef); - CFIndex n = CFStringGetLength(desc); - vector buffer(n*4+1); - CFStringGetCString(desc, &buffer.front(), buffer.size(), kCFStringEncodingUTF8); - m_colorProfile.description = &buffer.front(); + TwkApp::VideoDevice::ColorProfile CGDesktopVideoDevice::colorProfile() const + { + // + // Get the display's color sync profile + // - CFURLRef url = ColorSyncProfileGetURL(iccRef, NULL); - CFStringRef urlstr = CFURLGetString(url); - buffer.resize(CFStringGetLength(urlstr) * 4 + 1); - CFStringGetCString(urlstr, &buffer.front(), buffer.size(), kCFStringEncodingUTF8); + if (ColorSyncProfileRef iccRef = + ColorSyncProfileCreateWithDisplayID(m_cgScreen)) + { + m_colorProfile.type = ICCProfile; + + CFStringRef desc = ColorSyncProfileCopyDescriptionString(iccRef); + CFIndex n = CFStringGetLength(desc); + vector buffer(n * 4 + 1); + CFStringGetCString(desc, &buffer.front(), buffer.size(), + kCFStringEncodingUTF8); + m_colorProfile.description = &buffer.front(); + + CFURLRef url = ColorSyncProfileGetURL(iccRef, NULL); + CFStringRef urlstr = CFURLGetString(url); + buffer.resize(CFStringGetLength(urlstr) * 4 + 1); + CFStringGetCString(urlstr, &buffer.front(), buffer.size(), + kCFStringEncodingUTF8); + + m_colorProfile.url = &buffer.front(); + } + else + { + m_colorProfile = ColorProfile(); + } - m_colorProfile.url = &buffer.front(); - } - else - { - m_colorProfile = ColorProfile(); + return m_colorProfile; } - return m_colorProfile; -} - -} // Rv +} // namespace Rv diff --git a/src/lib/app/RvCommon/DesktopVideoDevice.cpp b/src/lib/app/RvCommon/DesktopVideoDevice.cpp index b390c7b30..e765c54fa 100644 --- a/src/lib/app/RvCommon/DesktopVideoDevice.cpp +++ b/src/lib/app/RvCommon/DesktopVideoDevice.cpp @@ -1,9 +1,9 @@ // -// Copyright (c) 2011 Tweak Software. +// Copyright (c) 2011 Tweak Software. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// // #ifdef PLATFORM_WINDOWS #include @@ -21,211 +21,200 @@ #include #include -namespace Rv { - -using namespace std; -using namespace TwkGLF; -using namespace TwkApp; - -DesktopVideoDevice::DesktopVideoDevice(VideoModule* m, - const std::string& name, - const QTGLVideoDevice* share) - : GLBindableVideoDevice(m, name, ImageOutput | ProvidesSync | SubWindow ), - m_viewDevice(0), - m_share(share), - m_stereoMode(Mono), - m_vsync(true), - m_videoFormatIndex(0), - m_dataFormatIndex(0), - m_syncing(false) +namespace Rv { - m_glGlobalState = new GLState(); - m_glGlobalState->useGLProgram(textureRectGLProgram()); -} -DesktopVideoDevice::~DesktopVideoDevice() -{ - delete m_glGlobalState; -} + using namespace std; + using namespace TwkGLF; + using namespace TwkApp; -void -DesktopVideoDevice::redraw() const -{ - ScopedLock lock(m_mutex); -} + DesktopVideoDevice::DesktopVideoDevice(VideoModule* m, + const std::string& name, + const QTGLVideoDevice* share) + : GLBindableVideoDevice(m, name, ImageOutput | ProvidesSync | SubWindow) + , m_viewDevice(0) + , m_share(share) + , m_stereoMode(Mono) + , m_vsync(true) + , m_videoFormatIndex(0) + , m_dataFormatIndex(0) + , m_syncing(false) + { + m_glGlobalState = new GLState(); + m_glGlobalState->useGLProgram(textureRectGLProgram()); + } -void -DesktopVideoDevice::redrawImmediately() const -{ - ScopedLock lock(m_mutex); -} + DesktopVideoDevice::~DesktopVideoDevice() { delete m_glGlobalState; } -void -DesktopVideoDevice::blockUntilSyncComplete() const -{ - ScopedLock lock(m_mutex); -} + void DesktopVideoDevice::redraw() const { ScopedLock lock(m_mutex); } -void -DesktopVideoDevice::bind(const TwkGLF::GLVideoDevice *d) const -{ - ScopedLock lock(m_mutex); - if (d) d->makeCurrent(); -} + void DesktopVideoDevice::redrawImmediately() const + { + ScopedLock lock(m_mutex); + } -void -DesktopVideoDevice::bind2(const GLVideoDevice* d, const GLVideoDevice* d2) const -{ - ScopedLock lock(m_mutex); - if (d) d->makeCurrent(); -} + void DesktopVideoDevice::blockUntilSyncComplete() const + { + ScopedLock lock(m_mutex); + } -void -DesktopVideoDevice::transfer(const GLFBO* fbo) const -{ - ScopedLock lock(m_mutex); - m_viewDevice->makeCurrent(); + void DesktopVideoDevice::bind(const TwkGLF::GLVideoDevice* d) const + { + ScopedLock lock(m_mutex); + if (d) + d->makeCurrent(); + } - GLFBO* local_fbo = m_fboMap[fbo]; + void DesktopVideoDevice::bind2(const GLVideoDevice* d, + const GLVideoDevice* d2) const + { + ScopedLock lock(m_mutex); + if (d) + d->makeCurrent(); + } - if (!local_fbo) + void DesktopVideoDevice::transfer(const GLFBO* fbo) const { - local_fbo = new GLFBO (fbo->width(), fbo->height(), fbo->primaryColorFormat()); - local_fbo->attachColorTexture (fbo->colorTarget(0), fbo->colorID(0)); - m_fboMap[fbo] = local_fbo; + ScopedLock lock(m_mutex); + m_viewDevice->makeCurrent(); + + GLFBO* local_fbo = m_fboMap[fbo]; + + if (!local_fbo) + { + local_fbo = new GLFBO(fbo->width(), fbo->height(), + fbo->primaryColorFormat()); + local_fbo->attachColorTexture(fbo->colorTarget(0), fbo->colorID(0)); + m_fboMap[fbo] = local_fbo; + } + + local_fbo->copyTo(m_viewDevice->defaultFBO()); + local_fbo->unbind(); } - - local_fbo->copyTo(m_viewDevice->defaultFBO()); - local_fbo->unbind(); -} -void -DesktopVideoDevice::setupModelviewAndProjection(float w, float h, GLPipeline* glPipeline) const -{ - // viewport, modelview, proj - glPipeline->setViewport(0, 0, w, h); - - TwkMath::Mat44f identity(1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1); - glPipeline->setModelview(identity); - - TwkMath::Frustumf f; - f.window(0, w-1, 0, h-1, -1, 1, true); - TwkMath::Mat44f projMat = f.matrix(); - - glPipeline->setProjection(projMat); -} - -void -DesktopVideoDevice::fillWithTexture2(const GLFBO* fbo1, const GLFBO* fbo2, size_t n, float w, float h, GLPipeline* glPipeline) const -{ - // tex - GLint id = 0; - glPipeline->setUniformInt("texture0", 1, &id); - glActiveTexture(GL_TEXTURE0); - fbo1->bindColorTexture(n); - id = 1; - glPipeline->setUniformInt("texture1", 1, &id); - glActiveTexture(GL_TEXTURE1); - fbo2->bindColorTexture(n); - - //draw - float data[] = {0, 0, 0, 0, w, 0, w-1, 0, w, h, w-1, h-1, 0, h, 0, h-1}; - PrimitiveData buffer(data, NULL, GL_QUADS, 4, 1, 16 * sizeof(float)); - std::vector attributeInfo; - - attributeInfo.push_back(VertexAttribute(std::string("in_Position"), - GL_FLOAT, - 2, - 2*sizeof(float), - 4*sizeof(float))); - - attributeInfo.push_back(VertexAttribute(std::string("in_TexCoord0"), - GL_FLOAT, - 2, - 0, - 4*sizeof(float))); - - RenderPrimitives renderprimitives(m_glGlobalState->activeGLProgram(), - buffer, - attributeInfo, - m_glGlobalState->vboList()); - renderprimitives.setupAndRender(); - - fbo1->unbindColorTexture(); - fbo2->unbindColorTexture(); -} - -void -DesktopVideoDevice::fillWithTexture(const GLFBO* fbo, size_t n, float w, float h, GLPipeline* glPipeline) const -{ - // tex - GLint id = 0; - glPipeline->setUniformInt("texture0", 1, &id); - glActiveTexture(GL_TEXTURE0); - fbo->bindColorTexture(n); - - //draw - float data[] = {0, 0, 0, 0, w, 0, w-1, 0, w, h, w-1, h-1, 0, h, 0, h-1}; - PrimitiveData buffer(data, NULL, GL_QUADS, 4, 1, 16 * sizeof(float)); - std::vector attributeInfo; - - attributeInfo.push_back(VertexAttribute(std::string("in_Position"), - GL_FLOAT, - 2, - 2*sizeof(float), - 4*sizeof(float))); - - attributeInfo.push_back(VertexAttribute(std::string("in_TexCoord0"), - GL_FLOAT, - 2, - 0, - 4*sizeof(float))); - - RenderPrimitives renderprimitives(m_glGlobalState->activeGLProgram(), - buffer, - attributeInfo, - m_glGlobalState->vboList()); - renderprimitives.setupAndRender(); - - fbo->unbindColorTexture(); -} - -void -DesktopVideoDevice::transfer2(const GLFBO* fbo1, const GLFBO* fbo2) const -{ - // - // NOTE: fbo1 and fbo2 are in the controllers context. So we - // can't use them directly. FBOs are not shared between contexts - // (textures are) so we need to use our own local fbos which use - // the shared textures. - // + void DesktopVideoDevice::setupModelviewAndProjection( + float w, float h, GLPipeline* glPipeline) const + { + // viewport, modelview, proj + glPipeline->setViewport(0, 0, w, h); + + TwkMath::Mat44f identity(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, + 1); + glPipeline->setModelview(identity); - ScopedLock lock(m_mutex); - m_viewDevice->makeCurrent();TWK_GLDEBUG; - const float w = m_viewDevice->width(); - const float h = m_viewDevice->height(); + TwkMath::Frustumf f; + f.window(0, w - 1, 0, h - 1, -1, 1, true); + TwkMath::Mat44f projMat = f.matrix(); - GLFBO* local_fbo1 = m_fboMap[fbo1]; - GLFBO* local_fbo2 = m_fboMap[fbo2]; + glPipeline->setProjection(projMat); + } - if (!local_fbo1) + void DesktopVideoDevice::fillWithTexture2(const GLFBO* fbo1, + const GLFBO* fbo2, size_t n, + float w, float h, + GLPipeline* glPipeline) const { - local_fbo1 = new GLFBO (fbo1->width(), fbo1->height(), fbo1->primaryColorFormat()); - local_fbo1->attachColorTexture (fbo1->colorTarget(0), fbo1->colorID(0)); - m_fboMap[fbo1] = local_fbo1; + // tex + GLint id = 0; + glPipeline->setUniformInt("texture0", 1, &id); + glActiveTexture(GL_TEXTURE0); + fbo1->bindColorTexture(n); + id = 1; + glPipeline->setUniformInt("texture1", 1, &id); + glActiveTexture(GL_TEXTURE1); + fbo2->bindColorTexture(n); + + // draw + float data[] = {0, 0, 0, 0, w, 0, w - 1, 0, + w, h, w - 1, h - 1, 0, h, 0, h - 1}; + PrimitiveData buffer(data, NULL, GL_QUADS, 4, 1, 16 * sizeof(float)); + std::vector attributeInfo; + + attributeInfo.push_back(VertexAttribute(std::string("in_Position"), + GL_FLOAT, 2, 2 * sizeof(float), + 4 * sizeof(float))); + + attributeInfo.push_back(VertexAttribute( + std::string("in_TexCoord0"), GL_FLOAT, 2, 0, 4 * sizeof(float))); + + RenderPrimitives renderprimitives(m_glGlobalState->activeGLProgram(), + buffer, attributeInfo, + m_glGlobalState->vboList()); + renderprimitives.setupAndRender(); + + fbo1->unbindColorTexture(); + fbo2->unbindColorTexture(); } - if (!local_fbo2) + void DesktopVideoDevice::fillWithTexture(const GLFBO* fbo, size_t n, + float w, float h, + GLPipeline* glPipeline) const { - local_fbo2 = new GLFBO (fbo2->width(), fbo2->height(), fbo2->primaryColorFormat()); - local_fbo2->attachColorTexture (fbo2->colorTarget(0), fbo2->colorID(0)); - m_fboMap[fbo2] = local_fbo2; + // tex + GLint id = 0; + glPipeline->setUniformInt("texture0", 1, &id); + glActiveTexture(GL_TEXTURE0); + fbo->bindColorTexture(n); + + // draw + float data[] = {0, 0, 0, 0, w, 0, w - 1, 0, + w, h, w - 1, h - 1, 0, h, 0, h - 1}; + PrimitiveData buffer(data, NULL, GL_QUADS, 4, 1, 16 * sizeof(float)); + std::vector attributeInfo; + + attributeInfo.push_back(VertexAttribute(std::string("in_Position"), + GL_FLOAT, 2, 2 * sizeof(float), + 4 * sizeof(float))); + + attributeInfo.push_back(VertexAttribute( + std::string("in_TexCoord0"), GL_FLOAT, 2, 0, 4 * sizeof(float))); + + RenderPrimitives renderprimitives(m_glGlobalState->activeGLProgram(), + buffer, attributeInfo, + m_glGlobalState->vboList()); + renderprimitives.setupAndRender(); + + fbo->unbindColorTexture(); } - const GLFBO *leftFBO = local_fbo1, *rightFBO = local_fbo2; + void DesktopVideoDevice::transfer2(const GLFBO* fbo1, + const GLFBO* fbo2) const + { + // + // NOTE: fbo1 and fbo2 are in the controllers context. So we + // can't use them directly. FBOs are not shared between contexts + // (textures are) so we need to use our own local fbos which use + // the shared textures. + // + + ScopedLock lock(m_mutex); + m_viewDevice->makeCurrent(); + TWK_GLDEBUG; + const float w = m_viewDevice->width(); + const float h = m_viewDevice->height(); + + GLFBO* local_fbo1 = m_fboMap[fbo1]; + GLFBO* local_fbo2 = m_fboMap[fbo2]; + + if (!local_fbo1) + { + local_fbo1 = new GLFBO(fbo1->width(), fbo1->height(), + fbo1->primaryColorFormat()); + local_fbo1->attachColorTexture(fbo1->colorTarget(0), + fbo1->colorID(0)); + m_fboMap[fbo1] = local_fbo1; + } + + if (!local_fbo2) + { + local_fbo2 = new GLFBO(fbo2->width(), fbo2->height(), + fbo2->primaryColorFormat()); + local_fbo2->attachColorTexture(fbo2->colorTarget(0), + fbo2->colorID(0)); + m_fboMap[fbo2] = local_fbo2; + } + + const GLFBO *leftFBO = local_fbo1, *rightFBO = local_fbo2; #if 0 { @@ -273,458 +262,479 @@ DesktopVideoDevice::transfer2(const GLFBO* fbo1, const GLFBO* fbo2) const #endif - if (m_stereoMode == SideBySideStereo) - { - const GLFBO* outputFBO = m_viewDevice->defaultFBO(); - local_fbo1->copyRegionTo(outputFBO, 0, 0, 1, 1, 0, 0, .5, 1, GL_COLOR_BUFFER_BIT, GL_LINEAR); - local_fbo2->copyRegionTo(outputFBO, 0, 0, 1, 1, .5, 0, .5, 1, GL_COLOR_BUFFER_BIT, GL_LINEAR); - outputFBO->unbind(); - } - else if (m_stereoMode == TopBottomStereo) - { - const GLFBO* outputFBO = m_viewDevice->defaultFBO(); - local_fbo1->copyRegionTo(outputFBO, 0, 0, 1, 1, 0, .5, 1, .5, GL_COLOR_BUFFER_BIT, GL_LINEAR); - local_fbo2->copyRegionTo(outputFBO, 0, 0, 1, 1, 0, 0, 1, .5, GL_COLOR_BUFFER_BIT, GL_LINEAR); - outputFBO->unbind(); - } - else if (m_stereoMode == QuadBufferStereo) - { - local_fbo1->unbind(); // this is necessary, because a fbo could be bound (from the - // render) at this point, and it will not have stereo, or double buffering - // causing the following glDrawBuffer lines to crash. - GLPipeline* glPipeline = m_glGlobalState->useGLProgram(textureRectGLProgram()); - setupModelviewAndProjection(w, h, glPipeline); - glDrawBuffer(GL_BACK_LEFT); // CORE DUMPS!? on Mac - fillWithTexture(fbo1, 0, w, h, glPipeline); - glDrawBuffer(GL_BACK_RIGHT); // CORE DUMPS!? on Mac - fillWithTexture(fbo2, 0, w, h, glPipeline); - glDrawBuffer(GL_BACK); // CORE DUMPS!? on Mac (yes, this one too!) - } - else if (m_stereoMode == ScanlineStereo) - { - const GLFBO* outputFBO = m_viewDevice->defaultFBO(); - outputFBO->bind(); - GLPipeline* glPipeline = m_glGlobalState->useGLProgram(stereoScanlineGLProgram()); - setupModelviewAndProjection(w, h, glPipeline); - // send in uniforms - VideoDevice::Offset o = this->offset(); - int viewYOrigin = this->height() - o.y - 1 - this->margins().bottom; - float parity = viewYOrigin % 2 == 0 ? 0.0 : 1.0; - glPipeline->setUniformFloat("parityOffset", 1, &parity); // send GL the uniform values to the current active glProgram - fillWithTexture2(leftFBO, rightFBO, 0, w, h, glPipeline); - outputFBO->unbind(); - } - else if (m_stereoMode == CheckerStereo) - { - const GLFBO* outputFBO = m_viewDevice->defaultFBO(); - outputFBO->bind(); - GLPipeline* glPipeline = m_glGlobalState->useGLProgram(stereoCheckerGLProgram()); - setupModelviewAndProjection(w, h, glPipeline); - // send in uniforms - VideoDevice::Offset o = this->offset(); - int viewXOrigin = o.x; - int viewYOrigin = this->height() - o.y - 1 - this->margins().bottom; - float parity[2]; - parity[0] = viewXOrigin % 2 == 0 ? 0.0 : 1.0; - parity[1] = viewYOrigin % 2 == 0 ? 0.0 : 1.0; - glPipeline->setUniformFloat("parityOffset", 2, parity); // send GL the uniform values to the current active glProgram - fillWithTexture2(leftFBO, rightFBO, 0, w, h, glPipeline); - outputFBO->unbind(); - } - else if (m_stereoMode == FramePacked) - { - const GLFBO* outputFBO = m_viewDevice->defaultFBO(); - const float iw = internalWidth(); - const float ih = internalHeight(); - const float padding = h - ih * 2.0; - - const float p0 = ih / h; - const float p1 = (ih + padding) / h; - - outputFBO->bind(); - glClearColor (0.0f, 0.0f, 0.0f, 1.0f); - glClear (GL_COLOR_BUFFER_BIT); - - // - // XXX This block for testing -- BEGIN - // - - static bool userOverrideFirst = true; - static bool userOverride = false; - - static float userOverrideLSrcX, userOverrideLSrcY, userOverrideLSrcW, userOverrideLSrcH; - static float userOverrideLDstX, userOverrideLDstY, userOverrideLDstW, userOverrideLDstH; - static float userOverrideRSrcX, userOverrideRSrcY, userOverrideRSrcW, userOverrideRSrcH; - static float userOverrideRDstX, userOverrideRDstY, userOverrideRDstW, userOverrideRDstH; - - if (userOverrideFirst) + if (m_stereoMode == SideBySideStereo) { - userOverrideFirst = false; - - const char *leftCopyString = getenv("RV_FRAME_PACKED_LEFT_COPY"); - const char *rightCopyString = getenv("RV_FRAME_PACKED_RIGHT_COPY"); - - if (leftCopyString && rightCopyString) - { - sscanf (leftCopyString, "%f %f %f %f %f %f %f %f", - &userOverrideLSrcX, &userOverrideLSrcY, &userOverrideLSrcW, &userOverrideLSrcH, - &userOverrideLDstX, &userOverrideLDstY, &userOverrideLDstW, &userOverrideLDstH); - - sscanf (rightCopyString, "%f %f %f %f %f %f %f %f", - &userOverrideRSrcX, &userOverrideRSrcY, &userOverrideRSrcW, &userOverrideRSrcH, - &userOverrideRDstX, &userOverrideRDstY, &userOverrideRDstW, &userOverrideRDstH); - - userOverride = true; - - float lw = local_fbo1->width(); - float rw = local_fbo2->width(); - float lh = local_fbo1->height(); - float rh = local_fbo2->height(); - - float dw = outputFBO->width(); - float dh = outputFBO->height(); - - cerr << "ndc left copy " << - " x " << userOverrideLSrcX << - " y " << userOverrideLSrcY << - " w " << userOverrideLSrcW << - " h " << userOverrideLSrcH << " -> " << - " x " << userOverrideLDstX << - " y " << userOverrideLDstY << - " w " << userOverrideLDstW << - " h " << userOverrideLDstH << endl; - - cerr << "ndc right copy " << - " x " << userOverrideRSrcX << - " y " << userOverrideRSrcY << - " w " << userOverrideRSrcW << - " h " << userOverrideRSrcH << " -> " << - " x " << userOverrideRDstX << - " y " << userOverrideRDstY << - " w " << userOverrideRDstW << - " h " << userOverrideRDstH << endl; - - cerr << "pixel left copy " << - " x0 " << int(userOverrideLSrcX * lw) << - " y0 " << int(userOverrideLSrcY * lh) << - " x1 " << int((userOverrideLSrcX + userOverrideLSrcW) * lw) << - " y1 " << int((userOverrideLSrcY + userOverrideLSrcH) * lh) << " -> " << - " x0 " << int(userOverrideLDstX * dw) << - " y0 " << int(userOverrideLDstY * dh) << - " x1 " << int((userOverrideLDstX + userOverrideLDstW) * dw) << - " y1 " << int((userOverrideLDstY + userOverrideLDstH) * dh) << endl; - - cerr << "pixel right copy " << - " x0 " << int(userOverrideRSrcX * rw) << - " y0 " << int(userOverrideRSrcY * rh) << - " x1 " << int((userOverrideRSrcX + userOverrideRSrcW) * rw) << - " y1 " << int((userOverrideRSrcY + userOverrideRSrcH) * rh) << " -> " << - " x0 " << int(userOverrideRDstX * dw) << - " y0 " << int(userOverrideRDstY * dh) << - " x1 " << int((userOverrideRDstX + userOverrideRDstW) * dw) << - " y1 " << int((userOverrideRDstY + userOverrideRDstH) * dh) << endl; - } + const GLFBO* outputFBO = m_viewDevice->defaultFBO(); + local_fbo1->copyRegionTo(outputFBO, 0, 0, 1, 1, 0, 0, .5, 1, + GL_COLOR_BUFFER_BIT, GL_LINEAR); + local_fbo2->copyRegionTo(outputFBO, 0, 0, 1, 1, .5, 0, .5, 1, + GL_COLOR_BUFFER_BIT, GL_LINEAR); + outputFBO->unbind(); } - - if (userOverride) + else if (m_stereoMode == TopBottomStereo) { - leftFBO->copyRegionTo(outputFBO, - userOverrideLSrcX, userOverrideLSrcY, userOverrideLSrcW, userOverrideLSrcH, - userOverrideLDstX, userOverrideLDstY, userOverrideLDstW, userOverrideLDstH, - GL_COLOR_BUFFER_BIT, GL_LINEAR); - - rightFBO->copyRegionTo(outputFBO, - userOverrideRSrcX, userOverrideRSrcY, userOverrideRSrcW, userOverrideRSrcH, - userOverrideRDstX, userOverrideRDstY, userOverrideRDstW, userOverrideRDstH, - GL_COLOR_BUFFER_BIT, GL_LINEAR); + const GLFBO* outputFBO = m_viewDevice->defaultFBO(); + local_fbo1->copyRegionTo(outputFBO, 0, 0, 1, 1, 0, .5, 1, .5, + GL_COLOR_BUFFER_BIT, GL_LINEAR); + local_fbo2->copyRegionTo(outputFBO, 0, 0, 1, 1, 0, 0, 1, .5, + GL_COLOR_BUFFER_BIT, GL_LINEAR); + outputFBO->unbind(); } - // - // XXX This block for testing -- END - // - else + else if (m_stereoMode == QuadBufferStereo) { - local_fbo1->copyRegionTo(outputFBO, - 0, 0, 1, 1, // NDC src x, y, w, h - 0, p1, 1, p0, // NDC dst x, y, w, h - GL_COLOR_BUFFER_BIT, GL_LINEAR); - - local_fbo2->copyRegionTo(outputFBO, - 0, 0, 1, 1, - 0, 0, 1, p0, - GL_COLOR_BUFFER_BIT, GL_LINEAR); + local_fbo1 + ->unbind(); // this is necessary, because a fbo could be bound + // (from the render) at this point, and it will not + // have stereo, or double buffering causing the + // following glDrawBuffer lines to crash. + GLPipeline* glPipeline = + m_glGlobalState->useGLProgram(textureRectGLProgram()); + setupModelviewAndProjection(w, h, glPipeline); + glDrawBuffer(GL_BACK_LEFT); // CORE DUMPS!? on Mac + fillWithTexture(fbo1, 0, w, h, glPipeline); + glDrawBuffer(GL_BACK_RIGHT); // CORE DUMPS!? on Mac + fillWithTexture(fbo2, 0, w, h, glPipeline); + glDrawBuffer(GL_BACK); // CORE DUMPS!? on Mac (yes, this one too!) } - outputFBO->unbind(); - } -} + else if (m_stereoMode == ScanlineStereo) + { + const GLFBO* outputFBO = m_viewDevice->defaultFBO(); + outputFBO->bind(); + GLPipeline* glPipeline = + m_glGlobalState->useGLProgram(stereoScanlineGLProgram()); + setupModelviewAndProjection(w, h, glPipeline); + // send in uniforms + VideoDevice::Offset o = this->offset(); + int viewYOrigin = this->height() - o.y - 1 - this->margins().bottom; + float parity = viewYOrigin % 2 == 0 ? 0.0 : 1.0; + glPipeline->setUniformFloat( + "parityOffset", 1, &parity); // send GL the uniform values to + // the current active glProgram + fillWithTexture2(leftFBO, rightFBO, 0, w, h, glPipeline); + outputFBO->unbind(); + } + else if (m_stereoMode == CheckerStereo) + { + const GLFBO* outputFBO = m_viewDevice->defaultFBO(); + outputFBO->bind(); + GLPipeline* glPipeline = + m_glGlobalState->useGLProgram(stereoCheckerGLProgram()); + setupModelviewAndProjection(w, h, glPipeline); + // send in uniforms + VideoDevice::Offset o = this->offset(); + int viewXOrigin = o.x; + int viewYOrigin = this->height() - o.y - 1 - this->margins().bottom; + float parity[2]; + parity[0] = viewXOrigin % 2 == 0 ? 0.0 : 1.0; + parity[1] = viewYOrigin % 2 == 0 ? 0.0 : 1.0; + glPipeline->setUniformFloat( + "parityOffset", 2, parity); // send GL the uniform values to the + // current active glProgram + fillWithTexture2(leftFBO, rightFBO, 0, w, h, glPipeline); + outputFBO->unbind(); + } + else if (m_stereoMode == FramePacked) + { + const GLFBO* outputFBO = m_viewDevice->defaultFBO(); + const float iw = internalWidth(); + const float ih = internalHeight(); + const float padding = h - ih * 2.0; + + const float p0 = ih / h; + const float p1 = (ih + padding) / h; + + outputFBO->bind(); + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + + // + // XXX This block for testing -- BEGIN + // + + static bool userOverrideFirst = true; + static bool userOverride = false; + + static float userOverrideLSrcX, userOverrideLSrcY, + userOverrideLSrcW, userOverrideLSrcH; + static float userOverrideLDstX, userOverrideLDstY, + userOverrideLDstW, userOverrideLDstH; + static float userOverrideRSrcX, userOverrideRSrcY, + userOverrideRSrcW, userOverrideRSrcH; + static float userOverrideRDstX, userOverrideRDstY, + userOverrideRDstW, userOverrideRDstH; + + if (userOverrideFirst) + { + userOverrideFirst = false; + + const char* leftCopyString = + getenv("RV_FRAME_PACKED_LEFT_COPY"); + const char* rightCopyString = + getenv("RV_FRAME_PACKED_RIGHT_COPY"); + + if (leftCopyString && rightCopyString) + { + sscanf(leftCopyString, "%f %f %f %f %f %f %f %f", + &userOverrideLSrcX, &userOverrideLSrcY, + &userOverrideLSrcW, &userOverrideLSrcH, + &userOverrideLDstX, &userOverrideLDstY, + &userOverrideLDstW, &userOverrideLDstH); + + sscanf(rightCopyString, "%f %f %f %f %f %f %f %f", + &userOverrideRSrcX, &userOverrideRSrcY, + &userOverrideRSrcW, &userOverrideRSrcH, + &userOverrideRDstX, &userOverrideRDstY, + &userOverrideRDstW, &userOverrideRDstH); + + userOverride = true; + + float lw = local_fbo1->width(); + float rw = local_fbo2->width(); + float lh = local_fbo1->height(); + float rh = local_fbo2->height(); + + float dw = outputFBO->width(); + float dh = outputFBO->height(); + + cerr << "ndc left copy " << " x " << userOverrideLSrcX + << " y " << userOverrideLSrcY << " w " + << userOverrideLSrcW << " h " << userOverrideLSrcH + << " -> " << " x " << userOverrideLDstX << " y " + << userOverrideLDstY << " w " << userOverrideLDstW + << " h " << userOverrideLDstH << endl; + + cerr << "ndc right copy " << " x " << userOverrideRSrcX + << " y " << userOverrideRSrcY << " w " + << userOverrideRSrcW << " h " << userOverrideRSrcH + << " -> " << " x " << userOverrideRDstX << " y " + << userOverrideRDstY << " w " << userOverrideRDstW + << " h " << userOverrideRDstH << endl; + + cerr << "pixel left copy " << " x0 " + << int(userOverrideLSrcX * lw) << " y0 " + << int(userOverrideLSrcY * lh) << " x1 " + << int((userOverrideLSrcX + userOverrideLSrcW) * lw) + << " y1 " + << int((userOverrideLSrcY + userOverrideLSrcH) * lh) + << " -> " << " x0 " << int(userOverrideLDstX * dw) + << " y0 " << int(userOverrideLDstY * dh) << " x1 " + << int((userOverrideLDstX + userOverrideLDstW) * dw) + << " y1 " + << int((userOverrideLDstY + userOverrideLDstH) * dh) + << endl; + + cerr << "pixel right copy " << " x0 " + << int(userOverrideRSrcX * rw) << " y0 " + << int(userOverrideRSrcY * rh) << " x1 " + << int((userOverrideRSrcX + userOverrideRSrcW) * rw) + << " y1 " + << int((userOverrideRSrcY + userOverrideRSrcH) * rh) + << " -> " << " x0 " << int(userOverrideRDstX * dw) + << " y0 " << int(userOverrideRDstY * dh) << " x1 " + << int((userOverrideRDstX + userOverrideRDstW) * dw) + << " y1 " + << int((userOverrideRDstY + userOverrideRDstH) * dh) + << endl; + } + } -bool -DesktopVideoDevice::isStereo() const -{ - return m_stereoMode != Mono; -} + if (userOverride) + { + leftFBO->copyRegionTo( + outputFBO, userOverrideLSrcX, userOverrideLSrcY, + userOverrideLSrcW, userOverrideLSrcH, userOverrideLDstX, + userOverrideLDstY, userOverrideLDstW, userOverrideLDstH, + GL_COLOR_BUFFER_BIT, GL_LINEAR); + + rightFBO->copyRegionTo( + outputFBO, userOverrideRSrcX, userOverrideRSrcY, + userOverrideRSrcW, userOverrideRSrcH, userOverrideRDstX, + userOverrideRDstY, userOverrideRDstW, userOverrideRDstH, + GL_COLOR_BUFFER_BIT, GL_LINEAR); + } + // + // XXX This block for testing -- END + // + else + { + local_fbo1->copyRegionTo(outputFBO, 0, 0, 1, + 1, // NDC src x, y, w, h + 0, p1, 1, p0, // NDC dst x, y, w, h + GL_COLOR_BUFFER_BIT, GL_LINEAR); -bool -DesktopVideoDevice::isDualStereo() const -{ - return isStereo(); -} + local_fbo2->copyRegionTo(outputFBO, 0, 0, 1, 1, 0, 0, 1, p0, + GL_COLOR_BUFFER_BIT, GL_LINEAR); + } + outputFBO->unbind(); + } + } -void -DesktopVideoDevice::unbind() const -{ - ScopedLock lock(m_mutex); + bool DesktopVideoDevice::isStereo() const { return m_stereoMode != Mono; } + + bool DesktopVideoDevice::isDualStereo() const { return isStereo(); } - for (FBOMap::iterator i = m_fboMap.begin(); - i != m_fboMap.end(); - ++i) + void DesktopVideoDevice::unbind() const { - delete i->second; - } + ScopedLock lock(m_mutex); - m_fboMap.clear(); -} + for (FBOMap::iterator i = m_fboMap.begin(); i != m_fboMap.end(); ++i) + { + delete i->second; + } -size_t -DesktopVideoDevice::numVideoFormats() const -{ - return m_videoFormats.size(); -} + m_fboMap.clear(); + } -DesktopVideoDevice::VideoFormat -DesktopVideoDevice::videoFormatAtIndex(size_t i) const -{ - if (i >= m_videoFormats.size()) i = m_videoFormats.size() - 1; - return m_videoFormats[i]; -} + size_t DesktopVideoDevice::numVideoFormats() const + { + return m_videoFormats.size(); + } -DesktopVideoDevice::VideoFormat -DesktopVideoDevice::videoFormatFromData(void *data) const -{ - for (int i = 0; i < m_videoFormats.size(); ++i) - if (m_videoFormats[i].data == data) return m_videoFormats[i]; + DesktopVideoDevice::VideoFormat + DesktopVideoDevice::videoFormatAtIndex(size_t i) const + { + if (i >= m_videoFormats.size()) + i = m_videoFormats.size() - 1; + return m_videoFormats[i]; + } - return m_videoFormats[m_videoFormatIndex]; -} + DesktopVideoDevice::VideoFormat + DesktopVideoDevice::videoFormatFromData(void* data) const + { + for (int i = 0; i < m_videoFormats.size(); ++i) + if (m_videoFormats[i].data == data) + return m_videoFormats[i]; -void -DesktopVideoDevice::setVideoFormat(size_t i) -{ - if (i >= m_videoFormats.size()) i = m_videoFormats.size() - 1; - m_videoFormatIndex = i; - GLBindableVideoDevice::setVideoFormat(i); -} + return m_videoFormats[m_videoFormatIndex]; + } -size_t -DesktopVideoDevice::currentVideoFormat() const -{ - return m_videoFormatIndex; -} + void DesktopVideoDevice::setVideoFormat(size_t i) + { + if (i >= m_videoFormats.size()) + i = m_videoFormats.size() - 1; + m_videoFormatIndex = i; + GLBindableVideoDevice::setVideoFormat(i); + } -bool -DesktopVideoDevice::maybeFramePacked(const TwkApp::VideoDevice::VideoFormat& d) const -{ - return - //(d.width == 1920 && d.height >= 1080 * 2 && d.hz == 24) || - //(d.width == 1280 && d.height >= 720 * 2 && (d.hz == 50 || d.hz == 60)); - (d.width == 1920 && d.height >= 1080 * 2) || - (d.width == 1280 && d.height >= 720 * 2); -} - -TwkApp::VideoDevice::Resolution -DesktopVideoDevice::internalResolution() const -{ - const DesktopVideoDevice::DesktopVideoFormat& d = m_videoFormats[m_videoFormatIndex]; + size_t DesktopVideoDevice::currentVideoFormat() const + { + return m_videoFormatIndex; + } - if (maybeFramePacked(d)) + bool DesktopVideoDevice::maybeFramePacked( + const TwkApp::VideoDevice::VideoFormat& d) const { - if (d.width == 1920) return Resolution(1920, 1080, d.pixelAspect, d.pixelScale); - else if (d.width == 1280) return Resolution(1280, 720, d.pixelAspect, d.pixelScale); + return + //(d.width == 1920 && d.height >= 1080 * 2 && d.hz == 24) || + //(d.width == 1280 && d.height >= 720 * 2 && (d.hz == 50 || d.hz == + // 60)); + (d.width == 1920 && d.height >= 1080 * 2) + || (d.width == 1280 && d.height >= 720 * 2); } - return resolution(); -} + TwkApp::VideoDevice::Resolution + DesktopVideoDevice::internalResolution() const + { + const DesktopVideoDevice::DesktopVideoFormat& d = + m_videoFormats[m_videoFormatIndex]; -TwkApp::VideoDevice::VideoFormat -DesktopVideoDevice::internalFormat() const -{ - const DesktopVideoDevice::DesktopVideoFormat& d = m_videoFormats[m_videoFormatIndex]; + if (maybeFramePacked(d)) + { + if (d.width == 1920) + return Resolution(1920, 1080, d.pixelAspect, d.pixelScale); + else if (d.width == 1280) + return Resolution(1280, 720, d.pixelAspect, d.pixelScale); + } + + return resolution(); + } - if (maybeFramePacked(d)) + TwkApp::VideoDevice::VideoFormat DesktopVideoDevice::internalFormat() const { - if (d.width == 1920) return VideoFormat(1920, 1080, d.pixelAspect, d.pixelScale, d.hz, d.description); - else if (d.width == 1280) return VideoFormat(1280, 720, d.pixelAspect, d.pixelScale, d.hz, d.description); + const DesktopVideoDevice::DesktopVideoFormat& d = + m_videoFormats[m_videoFormatIndex]; + + if (maybeFramePacked(d)) + { + if (d.width == 1920) + return VideoFormat(1920, 1080, d.pixelAspect, d.pixelScale, + d.hz, d.description); + else if (d.width == 1280) + return VideoFormat(1280, 720, d.pixelAspect, d.pixelScale, d.hz, + d.description); + } + + return format(); } - return format(); -} + size_t DesktopVideoDevice::internalHeight() const + { + const DesktopVideoDevice::DesktopVideoFormat& d = + m_videoFormats[m_videoFormatIndex]; -size_t -DesktopVideoDevice::internalHeight() const -{ - const DesktopVideoDevice::DesktopVideoFormat& d = m_videoFormats[m_videoFormatIndex]; + if (maybeFramePacked(d)) + { + if (d.width == 1920) + return 1080; + else if (d.width == 1280) + return 720; + } + + return height(); + } - if (maybeFramePacked(d)) + size_t DesktopVideoDevice::numDataFormats() const { - if (d.width == 1920) return 1080; - else if (d.width == 1280) return 720; + const DesktopVideoDevice::DesktopVideoFormat& d = + m_videoFormats[m_videoFormatIndex]; + return m_dataFormats.size() + (maybeFramePacked(d) ? 1 : 0); } - return height(); -} + DesktopVideoDevice::DataFormat + DesktopVideoDevice::dataFormatAtIndex(size_t i) const + { + const DesktopVideoDevice::DesktopVideoFormat& d = + m_videoFormats[m_videoFormatIndex]; -size_t -DesktopVideoDevice::numDataFormats() const -{ - const DesktopVideoDevice::DesktopVideoFormat& d = m_videoFormats[m_videoFormatIndex]; - return m_dataFormats.size() + (maybeFramePacked(d) ? 1 : 0); -} + if (maybeFramePacked(d) && i == m_dataFormats.size()) + { + ostringstream str; + str << "RGB8"; + str << " HDMI 1.4a Frame Packed Stereo"; -DesktopVideoDevice::DataFormat -DesktopVideoDevice::dataFormatAtIndex(size_t i) const -{ - const DesktopVideoDevice::DesktopVideoFormat& d = m_videoFormats[m_videoFormatIndex]; + return DesktopDataFormat(str.str(), FramePacked); + } + else + { + if (i >= m_dataFormats.size()) + i = m_dataFormats.size() - 1; + return m_dataFormats[i]; + } + } - if (maybeFramePacked(d) && i == m_dataFormats.size()) + void DesktopVideoDevice::setDataFormat(size_t i) { - ostringstream str; - str << "RGB8"; - str << " HDMI 1.4a Frame Packed Stereo"; + const DesktopVideoDevice::DesktopVideoFormat& d = + m_videoFormats[m_videoFormatIndex]; - return DesktopDataFormat(str.str(), FramePacked); + if (maybeFramePacked(d) && i == m_dataFormats.size()) + { + // nothing + m_dataFormatIndex = i; + m_stereoMode = FramePacked; + } + else + { + if (i >= m_dataFormats.size()) + i = m_dataFormats.size() - 1; + m_dataFormatIndex = i; + m_stereoMode = m_dataFormats[m_dataFormatIndex].stereoMode; + } } - else + + size_t DesktopVideoDevice::currentDataFormat() const { - if (i >= m_dataFormats.size()) i = m_dataFormats.size() - 1; - return m_dataFormats[i]; + return m_dataFormatIndex; } -} -void -DesktopVideoDevice::setDataFormat(size_t i) -{ - const DesktopVideoDevice::DesktopVideoFormat& d = m_videoFormats[m_videoFormatIndex]; + size_t DesktopVideoDevice::numSyncModes() const { return 2; } - if (maybeFramePacked(d) && i == m_dataFormats.size()) - { - // nothing - m_dataFormatIndex = i; - m_stereoMode = FramePacked; - } - else + DesktopVideoDevice::SyncMode + DesktopVideoDevice::syncModeAtIndex(size_t i) const { - if (i >= m_dataFormats.size()) i = m_dataFormats.size() - 1; - m_dataFormatIndex = i; - m_stereoMode = m_dataFormats[m_dataFormatIndex].stereoMode; + if (i == 0) + return SyncMode("No Sync"); + else + return SyncMode("Vertical Sync"); } -} -size_t -DesktopVideoDevice::currentDataFormat() const -{ - return m_dataFormatIndex; -} + void DesktopVideoDevice::setSyncMode(size_t i) { m_vsync = i != 0; } -size_t -DesktopVideoDevice::numSyncModes() const -{ - return 2; -} - -DesktopVideoDevice::SyncMode -DesktopVideoDevice::syncModeAtIndex(size_t i) const -{ - if (i == 0) return SyncMode("No Sync"); - else return SyncMode("Vertical Sync"); -} + size_t DesktopVideoDevice::currentSyncMode() const + { + return m_vsync ? 1 : 0; + } -void -DesktopVideoDevice::setSyncMode(size_t i) -{ - m_vsync = i != 0; -} + size_t DesktopVideoDevice::numSyncSources() const { return 0; } -size_t -DesktopVideoDevice::currentSyncMode() const -{ - return m_vsync ? 1 : 0; -} + DesktopVideoDevice::SyncSource + DesktopVideoDevice::syncSourceAtIndex(size_t) const + { + return SyncSource(); + } -size_t -DesktopVideoDevice::numSyncSources() const -{ - return 0; -} + void DesktopVideoDevice::setSyncSource(size_t) {} -DesktopVideoDevice::SyncSource -DesktopVideoDevice::syncSourceAtIndex(size_t) const -{ - return SyncSource(); -} + size_t DesktopVideoDevice::currentSyncSource() const { return 0; } -void -DesktopVideoDevice::setSyncSource(size_t) -{ -} + void DesktopVideoDevice::addDataFormatAtDepth(size_t depth, + DesktopStereoMode m) + { + ostringstream str; + str << "RGB"; + if (depth) + str << depth; + const char* d = ""; -size_t -DesktopVideoDevice::currentSyncSource() const -{ - return 0; -} + switch (m) + { + case Mono: + d = ""; + break; + case QuadBufferStereo: + str << " Quad Buffer Stereo"; + break; + case SideBySideStereo: + str << " HDMI 1.4a Side-by-Side Stereo"; + break; + case TopBottomStereo: + str << " HDMI 1.4a Top-and-Bottom Stereo"; + break; + case ScanlineStereo: + str << " Scanline Stereo"; + break; + case CheckerStereo: + str << " Checker Board Stereo"; + break; + default: + str << " DEFAULT"; + break; + } -void -DesktopVideoDevice::addDataFormatAtDepth(size_t depth, DesktopStereoMode m) -{ - ostringstream str; - str << "RGB"; - if (depth) str << depth; - const char* d = ""; + m_dataFormats.push_back(DesktopDataFormat(str.str(), m)); + } - switch (m) + void DesktopVideoDevice::addDefaultDataFormats(size_t depth) { - case Mono: d = ""; break; - case QuadBufferStereo: str << " Quad Buffer Stereo"; break; - case SideBySideStereo: str << " HDMI 1.4a Side-by-Side Stereo"; break; - case TopBottomStereo: str << " HDMI 1.4a Top-and-Bottom Stereo"; break; - case ScanlineStereo: str << " Scanline Stereo"; break; - case CheckerStereo: str << " Checker Board Stereo"; break; - default: - str << " DEFAULT"; - break; + addDataFormatAtDepth(depth, Mono); + addDataFormatAtDepth(depth, QuadBufferStereo); + addDataFormatAtDepth(depth, SideBySideStereo); + addDataFormatAtDepth(depth, TopBottomStereo); + addDataFormatAtDepth(depth, ScanlineStereo); + addDataFormatAtDepth(depth, CheckerStereo); } - m_dataFormats.push_back(DesktopDataFormat(str.str(), m)); -} + namespace + { -void -DesktopVideoDevice::addDefaultDataFormats(size_t depth) -{ - addDataFormatAtDepth(depth, Mono); - addDataFormatAtDepth(depth, QuadBufferStereo); - addDataFormatAtDepth(depth, SideBySideStereo); - addDataFormatAtDepth(depth, TopBottomStereo); - addDataFormatAtDepth(depth, ScanlineStereo); - addDataFormatAtDepth(depth, CheckerStereo); -} - -namespace { - -bool -widthSort(const TwkApp::VideoDevice::VideoFormat& a, - const TwkApp::VideoDevice::VideoFormat& b) -{ - if (a.width != b.width) return a.width < b.width; - else if (a.height != b.height) return a.height < b.height; - else if (a.hz != b.hz) return a.hz < b.hz; - else return a.description.compare(b.description) < 0; -} + bool widthSort(const TwkApp::VideoDevice::VideoFormat& a, + const TwkApp::VideoDevice::VideoFormat& b) + { + if (a.width != b.width) + return a.width < b.width; + else if (a.height != b.height) + return a.height < b.height; + else if (a.hz != b.hz) + return a.hz < b.hz; + else + return a.description.compare(b.description) < 0; + } -} + } // namespace -void -DesktopVideoDevice::sortVideoFormatsByWidth() -{ - sort(m_videoFormats.begin(), m_videoFormats.end(), widthSort); -} + void DesktopVideoDevice::sortVideoFormatsByWidth() + { + sort(m_videoFormats.begin(), m_videoFormats.end(), widthSort); + } -} // Rv +} // namespace Rv diff --git a/src/lib/app/RvCommon/DesktopVideoModule.cpp b/src/lib/app/RvCommon/DesktopVideoModule.cpp index 27e5fd252..bbbf6ce47 100644 --- a/src/lib/app/RvCommon/DesktopVideoModule.cpp +++ b/src/lib/app/RvCommon/DesktopVideoModule.cpp @@ -1,9 +1,9 @@ // -// Copyright (c) 2011 Tweak Software. +// Copyright (c) 2011 Tweak Software. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// // #include #include @@ -25,202 +25,198 @@ #include #include -namespace Rv { -using namespace std; -using namespace boost; +namespace Rv +{ + using namespace std; + using namespace boost; -//---------------------------------------------------------------------- + //---------------------------------------------------------------------- #ifdef PLATFORM_DARWIN -static void KeyArrayCallback (const void* key, const void* value, void* context) -{ - CFMutableArrayRef langKeys = (CFMutableArrayRef)context; - CFArrayAppendValue(langKeys, key); -} + static void KeyArrayCallback(const void* key, const void* value, + void* context) + { + CFMutableArrayRef langKeys = (CFMutableArrayRef)context; + CFArrayAppendValue(langKeys, key); + } #endif -DesktopVideoModule::DesktopVideoModule(NativeDisplayPtr np, QTGLVideoDevice* shareDevice) : VideoModule() -{ - bool useQt = true; - QDesktopWidget* desktop = QApplication::desktop(); - int nscreens = desktop->screenCount(); + DesktopVideoModule::DesktopVideoModule(NativeDisplayPtr np, + QTGLVideoDevice* shareDevice) + : VideoModule() + { + bool useQt = true; + QDesktopWidget* desktop = QApplication::desktop(); + int nscreens = desktop->screenCount(); #ifdef PLATFORM_DARWIN - useQt = false; - - // - // Use the CoreGraphics devices - // + useQt = false; - CGDirectDisplayID idArray[20]; - uint32_t idNum; - CGGetOnlineDisplayList(20, idArray, &idNum); - //CGDirectDisplayID mainID = CGMainDisplayID(); - - for (size_t i = 0; i < idNum; i++) - { - CGDirectDisplayID aID = idArray[i]; + // + // Use the CoreGraphics devices + // - CFStringRef localName = NULL; - io_connect_t displayPort = CGDisplayIOServicePort(aID); - CFDictionaryRef dict = (CFDictionaryRef)IODisplayCreateInfoDictionary(displayPort, kIODisplayOnlyPreferredName); - CFDictionaryRef names = (CFDictionaryRef)CFDictionaryGetValue(dict, CFSTR(kDisplayProductName)); + CGDirectDisplayID idArray[20]; + uint32_t idNum; + CGGetOnlineDisplayList(20, idArray, &idNum); + // CGDirectDisplayID mainID = CGMainDisplayID(); - if (names) + for (size_t i = 0; i < idNum; i++) { - CFArrayRef langKeys = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks ); - CFDictionaryApplyFunction(names, KeyArrayCallback, (void*)langKeys); - CFArrayRef orderLangKeys = CFBundleCopyPreferredLocalizationsFromArray(langKeys); - CFRelease(langKeys); + CGDirectDisplayID aID = idArray[i]; - if (orderLangKeys && CFArrayGetCount(orderLangKeys)) + CFStringRef localName = NULL; + io_connect_t displayPort = CGDisplayIOServicePort(aID); + CFDictionaryRef dict = + (CFDictionaryRef)IODisplayCreateInfoDictionary( + displayPort, kIODisplayOnlyPreferredName); + CFDictionaryRef names = (CFDictionaryRef)CFDictionaryGetValue( + dict, CFSTR(kDisplayProductName)); + + if (names) { - CFStringRef langKey = (CFStringRef)CFArrayGetValueAtIndex(orderLangKeys, 0); - localName = (CFStringRef)CFDictionaryGetValue(names, langKey); - CFRetain(localName); + CFArrayRef langKeys = CFArrayCreateMutable( + kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); + CFDictionaryApplyFunction(names, KeyArrayCallback, + (void*)langKeys); + CFArrayRef orderLangKeys = + CFBundleCopyPreferredLocalizationsFromArray(langKeys); + CFRelease(langKeys); + + if (orderLangKeys && CFArrayGetCount(orderLangKeys)) + { + CFStringRef langKey = + (CFStringRef)CFArrayGetValueAtIndex(orderLangKeys, 0); + localName = + (CFStringRef)CFDictionaryGetValue(names, langKey); + CFRetain(localName); + } + + CFRelease(orderLangKeys); } - CFRelease(orderLangKeys); - } + // + // Above process seems to fail to find the display name on some mac + // minis, so invent a name if we didn't find one. + // - // - // Above process seems to fail to find the display name on some mac - // minis, so invent a name if we didn't find one. - // + ostringstream nameStr; + const char* nameP = 0; + vector localBuffer; - ostringstream nameStr; - const char *nameP = 0; - vector localBuffer; + if (localName == NULL) + { + nameStr << "CG Display " << (i + 1); + nameP = nameStr.str().c_str(); + } + else + { + localBuffer = + vector(CFStringGetLength(localName) * 4 + 1); - if (localName == NULL) - { - nameStr << "CG Display " << (i+1); - nameP = nameStr.str().c_str(); - } - else - { - localBuffer = vector(CFStringGetLength(localName) * 4 + 1); + CFStringGetCString(localName, &localBuffer.front(), + localBuffer.size(), kCFStringEncodingUTF8); - CFStringGetCString(localName, - &localBuffer.front(), - localBuffer.size(), - kCFStringEncodingUTF8); + nameP = &localBuffer.front(); + } - nameP = &localBuffer.front(); - } + // + // In use of 'i' below, we're relying on the order of the devices + // here being the same as in the objc [NSScreen screens] call, but + // that + // seems to be true. The [NSScreen screens] call is used in Qt + // core\ code to define Qt screens. + // + CGDesktopVideoDevice* sd = + new CGDesktopVideoDevice(this, nameP, aID, i, shareDevice); + m_devices.push_back(sd); - // - // In use of 'i' below, we're relying on the order of the devices here - // being the same as in the objc [NSScreen screens] call, but that - // seems to be true. The [NSScreen screens] call is used in Qt core\ - // code to define Qt screens. - // - CGDesktopVideoDevice* sd = new CGDesktopVideoDevice(this, - nameP, - aID, - i, - shareDevice); - m_devices.push_back(sd); - - CFRelease(dict); - } + CFRelease(dict); + } #endif - if (useQt) - { - for (int screen = 0; screen < desktop->screenCount(); screen++) + if (useQt) { - QWidget* w = desktop->screen(screen); - ostringstream name; - name << w->screen()->manufacturer().toUtf8().data(); - name << " " << w->screen()->model().toUtf8().data(); - name << " " << w->screen()->name().toUtf8().data(); - QTDesktopVideoDevice* sd = - new QTDesktopVideoDevice(this, name.str(), screen, shareDevice); - m_devices.push_back(sd); + for (int screen = 0; screen < desktop->screenCount(); screen++) + { + QWidget* w = desktop->screen(screen); + ostringstream name; + name << w->screen()->manufacturer().toUtf8().data(); + name << " " << w->screen()->model().toUtf8().data(); + name << " " << w->screen()->name().toUtf8().data(); + QTDesktopVideoDevice* sd = new QTDesktopVideoDevice( + this, name.str(), screen, shareDevice); + m_devices.push_back(sd); + } } } -} -DesktopVideoModule::~DesktopVideoModule() -{ -} + DesktopVideoModule::~DesktopVideoModule() {} -string -DesktopVideoModule::name() const -{ - return "Desktop"; -} + string DesktopVideoModule::name() const { return "Desktop"; } -void -DesktopVideoModule::open() -{ -} + void DesktopVideoModule::open() {} -void -DesktopVideoModule::close() -{ -} + void DesktopVideoModule::close() {} -bool -DesktopVideoModule::isOpen() const -{ - return true; -} + bool DesktopVideoModule::isOpen() const { return true; } -TwkApp::VideoDevice* -DesktopVideoModule::deviceFromPosition(int x, int y) const -{ - TwkApp::VideoDevice* device = 0; - - #if defined (PLATFORM_DARWIN) - - const int maxDisplays = 64; - CGDirectDisplayID displays[maxDisplays]; - CGDisplayCount displayCount; - const CGPoint cgPoint = CGPointMake(x, y); - const CGDisplayErr err = CGGetDisplaysWithPoint(cgPoint, maxDisplays, displays, &displayCount); - - if (err != kCGErrorSuccess) cerr << "ERROR: CGGetDisplaysWithPoint returns " << err << endl; - else if (displayCount > 0) - { - for (int i = 0; i < m_devices.size(); ++i) - { - CGDesktopVideoDevice* d = dynamic_cast (m_devices[i]); - - if (d && d->cgDisplay() == displays[0]) - { - device = d; - break; - } - } - } - - #else // PLATFORM_LINUX or PLATFORM_WINDOWS - - int screen = QApplication::desktop()->screenNumber(QPoint(x, y)); - - for (int i = 0; i < m_devices.size(); ++i) - { - // - // These devices may be NVDesktopVideoDevices or QTDeskTopVideoDevices. - // - TwkApp::VideoDevice* d = m_devices[i]; - - if (DesktopVideoDevice* dd = dynamic_cast(d)) - { - if (dd->qtScreen() == screen) + TwkApp::VideoDevice* DesktopVideoModule::deviceFromPosition(int x, + int y) const + { + TwkApp::VideoDevice* device = 0; + +#if defined(PLATFORM_DARWIN) + + const int maxDisplays = 64; + CGDirectDisplayID displays[maxDisplays]; + CGDisplayCount displayCount; + const CGPoint cgPoint = CGPointMake(x, y); + const CGDisplayErr err = CGGetDisplaysWithPoint( + cgPoint, maxDisplays, displays, &displayCount); + + if (err != kCGErrorSuccess) + cerr << "ERROR: CGGetDisplaysWithPoint returns " << err << endl; + else if (displayCount > 0) + { + for (int i = 0; i < m_devices.size(); ++i) + { + CGDesktopVideoDevice* d = + dynamic_cast(m_devices[i]); + + if (d && d->cgDisplay() == displays[0]) { device = d; break; } - } - } + } + } + +#else // PLATFORM_LINUX or PLATFORM_WINDOWS + + int screen = QApplication::desktop()->screenNumber(QPoint(x, y)); - #endif + for (int i = 0; i < m_devices.size(); ++i) + { + // + // These devices may be NVDesktopVideoDevices or + // QTDeskTopVideoDevices. + // + TwkApp::VideoDevice* d = m_devices[i]; + + if (DesktopVideoDevice* dd = dynamic_cast(d)) + { + if (dd->qtScreen() == screen) + { + device = d; + break; + } + } + } - return device; -} +#endif -} // Rv + return device; + } +} // namespace Rv diff --git a/src/lib/app/RvCommon/DisplayLink.cpp b/src/lib/app/RvCommon/DisplayLink.cpp index 844b0fd2a..827894a95 100644 --- a/src/lib/app/RvCommon/DisplayLink.cpp +++ b/src/lib/app/RvCommon/DisplayLink.cpp @@ -10,95 +10,97 @@ #include using namespace std; -namespace Rv { - -static CVReturn CVDisplayLinkCallback(CVDisplayLinkRef displayLink, - const CVTimeStamp *inNow, - const CVTimeStamp *inOutputTime, - CVOptionFlags flagsIn, - CVOptionFlags *flagsOut, - void *displayLinkContext) +namespace Rv { - DisplayLink *link = (DisplayLink *)displayLinkContext; - link->displayLinkEvent(inNow, inOutputTime); - return kCVReturnSuccess; -} -DisplayLink::DisplayLink(QObject *parent) - : QObject(parent) - , m_displayLink(0) - , m_isActive(false) - , m_session(0) - , m_serial(0) -{ - // create display link for the main display - CVDisplayLinkCreateWithCGDisplay(kCGDirectMainDisplay, &m_displayLink); - if (m_displayLink) { - // set the current display of a display link. - CVDisplayLinkSetCurrentCGDisplay(m_displayLink, kCGDirectMainDisplay); + static CVReturn CVDisplayLinkCallback(CVDisplayLinkRef displayLink, + const CVTimeStamp* inNow, + const CVTimeStamp* inOutputTime, + CVOptionFlags flagsIn, + CVOptionFlags* flagsOut, + void* displayLinkContext) + { + DisplayLink* link = (DisplayLink*)displayLinkContext; + link->displayLinkEvent(inNow, inOutputTime); + return kCVReturnSuccess; + } - // set the renderer output callback function - CVDisplayLinkSetOutputCallback(m_displayLink, &CVDisplayLinkCallback, this); + DisplayLink::DisplayLink(QObject* parent) + : QObject(parent) + , m_displayLink(0) + , m_isActive(false) + , m_session(0) + , m_serial(0) + { + // create display link for the main display + CVDisplayLinkCreateWithCGDisplay(kCGDirectMainDisplay, &m_displayLink); + if (m_displayLink) + { + // set the current display of a display link. + CVDisplayLinkSetCurrentCGDisplay(m_displayLink, + kCGDirectMainDisplay); + + // set the renderer output callback function + CVDisplayLinkSetOutputCallback(m_displayLink, + &CVDisplayLinkCallback, this); + } } -} -DisplayLink::~DisplayLink() -{ - if (m_displayLink) + DisplayLink::~DisplayLink() { - stop(); - CVDisplayLinkRelease(m_displayLink); - m_displayLink = NULL; + if (m_displayLink) + { + stop(); + CVDisplayLinkRelease(m_displayLink); + m_displayLink = NULL; + } } -} -bool DisplayLink::isValid() const -{ - return m_displayLink != 0; -} + bool DisplayLink::isValid() const { return m_displayLink != 0; } -bool DisplayLink::isActive() const -{ - return m_isActive; -} + bool DisplayLink::isActive() const { return m_isActive; } -void DisplayLink::start(IPCore::Session* s, const CGDesktopVideoDevice* cgdevice) -{ - if (m_displayLink && !m_isActive) + void DisplayLink::start(IPCore::Session* s, + const CGDesktopVideoDevice* cgdevice) { - CVDisplayLinkSetCurrentCGDisplay(m_displayLink, cgdevice->cgDisplay()); - CVDisplayLinkStart(m_displayLink); - m_isActive = true; - m_session = s; + if (m_displayLink && !m_isActive) + { + CVDisplayLinkSetCurrentCGDisplay(m_displayLink, + cgdevice->cgDisplay()); + CVDisplayLinkStart(m_displayLink); + m_isActive = true; + m_session = s; + } } -} -void DisplayLink::stop() -{ - if (m_displayLink && m_isActive) + void DisplayLink::stop() { - CVDisplayLinkStop(m_displayLink); - m_isActive = false; + if (m_displayLink && m_isActive) + { + CVDisplayLinkStop(m_displayLink); + m_isActive = false; - // - // Make sure that a waiting render is allowed to finish - // + // + // Make sure that a waiting render is allowed to finish + // - if (m_session->waitingOnSync()) - { - m_session->setNextVSyncOffset(0, m_serial); + if (m_session->waitingOnSync()) + { + m_session->setNextVSyncOffset(0, m_serial); + } } } -} -void DisplayLink::displayLinkEvent(const CVTimeStamp* now, const CVTimeStamp *ts) -{ - if (ts && now) + void DisplayLink::displayLinkEvent(const CVTimeStamp* now, + const CVTimeStamp* ts) { - const double secs = double(ts->videoTime - now->videoTime) / double(now->videoTimeScale); - m_serial++; - m_session->setNextVSyncOffset(secs, m_serial); + if (ts && now) + { + const double secs = double(ts->videoTime - now->videoTime) + / double(now->videoTimeScale); + m_serial++; + m_session->setNextVSyncOffset(secs, m_serial); + } } -} -} +} // namespace Rv diff --git a/src/lib/app/RvCommon/FileTypeTraits.cpp b/src/lib/app/RvCommon/FileTypeTraits.cpp index 85e50fc04..e1484bc30 100644 --- a/src/lib/app/RvCommon/FileTypeTraits.cpp +++ b/src/lib/app/RvCommon/FileTypeTraits.cpp @@ -1,141 +1,126 @@ // -// Copyright (c) 2008 Tweak Software. +// Copyright (c) 2008 Tweak Software. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// // #include -namespace Rv { -using namespace std; - - -FileTypeTraits::FileTypeTraits() : - m_iconMode(SystemIcons) -{ -} - -FileTypeTraits::~FileTypeTraits() -{ -} - -FileTypeTraits* -FileTypeTraits::copyTraits() const -{ - FileTypeTraits* t = new FileTypeTraits(); - t->setIconMode(m_iconMode); - return t; -} - -QStringList -FileTypeTraits::typeDescriptions() -{ - QStringList list; - list.append("Any File"); - return list; -} - -bool -FileTypeTraits::isKnown(size_t index, const QString&) const +namespace Rv { - return true; -} + using namespace std; -QStringList -FileTypeTraits::fileAttributes(const QString& file) const -{ - QStringList list; - QFileInfo info(file); - - list << "Created" << info.created().toString(Qt::DefaultLocaleShortDate); - list << "Modified" << info.lastModified().toString(Qt::DefaultLocaleShortDate); + FileTypeTraits::FileTypeTraits() + : m_iconMode(SystemIcons) + { + } - size_t s = info.size(); + FileTypeTraits::~FileTypeTraits() {} - if (s < 1024) + FileTypeTraits* FileTypeTraits::copyTraits() const { - list << "Size" << QString("%1 bytes").arg(info.size()); + FileTypeTraits* t = new FileTypeTraits(); + t->setIconMode(m_iconMode); + return t; } - else if (s < 1024 * 1024) + + QStringList FileTypeTraits::typeDescriptions() { - list << "Size" << QString("%1 Kb").arg(info.size() / 1024); + QStringList list; + list.append("Any File"); + return list; } - else if (s < 1024 * 1024 * 1024) + + bool FileTypeTraits::isKnown(size_t index, const QString&) const { - list << "Size" << QString("%1 Mb").arg(info.size() / 1024 / 1024); + return true; } - else if (s < size_t(1024) * size_t(1024) * size_t(1024) * size_t(1024)) + + QStringList FileTypeTraits::fileAttributes(const QString& file) const { - list << "Size" << QString("%1 Gb").arg(info.size() / 1024 / 1024 / 1024); - } + QStringList list; + QFileInfo info(file); - return list; -} + list << "Created" + << info.created().toString(Qt::DefaultLocaleShortDate); + list << "Modified" + << info.lastModified().toString(Qt::DefaultLocaleShortDate); -QIcon -FileTypeTraits::fileIcon(const QString& file, - QFileIconProvider::IconType knownType) const -{ - if (m_iconMode == NoIcons) return QIcon(); + size_t s = info.size(); - QFileInfo info(file); - return fileInfoIcon(info, knownType); -} + if (s < 1024) + { + list << "Size" << QString("%1 bytes").arg(info.size()); + } + else if (s < 1024 * 1024) + { + list << "Size" << QString("%1 Kb").arg(info.size() / 1024); + } + else if (s < 1024 * 1024 * 1024) + { + list << "Size" << QString("%1 Mb").arg(info.size() / 1024 / 1024); + } + else if (s < size_t(1024) * size_t(1024) * size_t(1024) * size_t(1024)) + { + list << "Size" + << QString("%1 Gb").arg(info.size() / 1024 / 1024 / 1024); + } -QIcon -FileTypeTraits::fileInfoIcon ( - const QFileInfo& info, - QFileIconProvider::IconType knownType) const -{ - static QFileIconProvider provider; + return list; + } - if (m_iconMode == NoIcons) return QIcon(); + QIcon FileTypeTraits::fileIcon(const QString& file, + QFileIconProvider::IconType knownType) const + { + if (m_iconMode == NoIcons) + return QIcon(); - if (QFileIconProvider::Trashcan != knownType) return provider.icon(knownType); + QFileInfo info(file); + return fileInfoIcon(info, knownType); + } - if (m_iconMode == GenericIcons) + QIcon + FileTypeTraits::fileInfoIcon(const QFileInfo& info, + QFileIconProvider::IconType knownType) const { - if (info.isDir()) + static QFileIconProvider provider; + + if (m_iconMode == NoIcons) + return QIcon(); + + if (QFileIconProvider::Trashcan != knownType) + return provider.icon(knownType); + + if (m_iconMode == GenericIcons) { - return provider.icon(QFileIconProvider::Folder); + if (info.isDir()) + { + return provider.icon(QFileIconProvider::Folder); + } + else + { + return provider.icon(QFileIconProvider::File); + } } - else + + if (!info.exists()) { - return provider.icon(QFileIconProvider::File); + return provider.icon(QFileIconProvider::Folder); } - } - if (!info.exists()) - { - return provider.icon(QFileIconProvider::Folder); + return provider.icon(info); } - return provider.icon(info); -} - -bool -FileTypeTraits::hasImage(const QString&) const -{ - return false; -} + bool FileTypeTraits::hasImage(const QString&) const { return false; } -QImage -FileTypeTraits::fileImage(const QString&) const -{ - return QImage(); -} + QImage FileTypeTraits::fileImage(const QString&) const { return QImage(); } -void -FileTypeTraits::setIconMode(IconMode mode) -{ - m_iconMode = mode; -} + void FileTypeTraits::setIconMode(IconMode mode) { m_iconMode = mode; } -FileTypeTraits::IconMode -FileTypeTraits::iconMode() const -{ - return m_iconMode; -} + FileTypeTraits::IconMode FileTypeTraits::iconMode() const + { + return m_iconMode; + } -} // Rv +} // namespace Rv diff --git a/src/lib/app/RvCommon/GLSLSyntaxHighlighter.cpp b/src/lib/app/RvCommon/GLSLSyntaxHighlighter.cpp index ff43d2fd6..a745a871b 100644 --- a/src/lib/app/RvCommon/GLSLSyntaxHighlighter.cpp +++ b/src/lib/app/RvCommon/GLSLSyntaxHighlighter.cpp @@ -1,230 +1,518 @@ // -// Copyright (c) 2013 Tweak Software. +// Copyright (c) 2013 Tweak Software. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// // #include -namespace { - -const char* glslTypes[] = { -"float", "double", "int", "void", "bool", "true", "false", "mat2", "mat3", "mat4", "dmat2", "dmat3", -"dmat4", "mat2x2", "mat2x3", "mat2x4", "dmat2x2", "dmat2x3", "dmat2x4", "mat3x2", "mat3x3", "mat3x4", -"dmat3x2", "dmat3x3", "dmat3x4", "mat4x2", "mat4x3", "mat4x4", "dmat4x2", "dmat4x3", "dmat4x4", -"vec2", "vec3", "vec4", "ivec2", "ivec3", "ivec4", "bvec2", "bvec3", "bvec4", "dvec2", "dvec3", "dvec4", -"uint", "uvec2", "uvec3", "uvec4", "sampler1D", "sampler2D", "sampler3D", "samplerCube", "sampler1DShadow", -"sampler2DShadow", "samplerCubeShadow", "sampler1DArray", "sampler2DArray", "sampler1DArrayShadow", -"sampler2DArrayShadow", "isampler1D", "isampler2D", "isampler3D", "isamplerCube", "isampler1DArray", -"isampler2DArray", "usampler1D", "usampler2D", "usampler3D", "usamplerCube", "usampler1DArray", -"usampler2DArray", "sampler2DRect", "sampler2DRectShadow", "isampler2DRect", "usampler2DRect", -"samplerBuffer", "isamplerBuffer", "usamplerBuffer", "sampler2DMS", "isampler2DMS", -"usampler2DMS", "sampler2DMSArray", "isampler2DMSArray", "usampler2DMSArray", "samplerCubeArray", -"samplerCubeArrayShadow", "isamplerCubeArray", "usamplerCubeArray", "image1D", "iimage1D", -"uimage1D", "image2D", "iimage2D", "uimage2D", "image3D", "iimage3D", "uimage3D", "image2DRect", -"iimage2DRect", "uimage2DRect", "imageCube", "iimageCube", "uimageCube", "imageBuffer", "iimageBuffer", -"uimageBuffer", "image1DArray", "iimage1DArray", "uimage1DArray", "image2DArray", "iimage2DArray", -"uimage2DArray", "imageCubeArray", "iimageCubeArray", "uimageCubeArray", "image2DMS", -"iimage2DMS", "uimage2DMS", "image2DMSArray", "iimage2DMSArray", "uimage2DMSArray", "long", -"short", "half", "fixed", "unsigned", "hvec2", "hvec3", "hvec4", "fvec2", -"fvec3", "fvec4", "sampler3DRect", 0 -}; - -const char* glslModifiers[] = { -"attribute", "const", "uniform", "varying", "buffer", "shared", "coherent", "volatile", "restrict", -"readonly", "writeonly", "atomic_uint", "layout", "centroid", "flat", "smooth", "noperspective", -"patch", "sample", "break", "continue", "do", "for", "while", "switch", "case", "default", "if", -"else", "subroutine", "in", "out", "inout", "invariant", "discard", "return", "lowp", "mediump", "highp", -"precision", "struct", "common", "partition", "active", "asm", "class", "union", "enum", "typedef", -"template", "this", "packed", "resource", "goto", "inline", "noinline", "public", "static", "extern", -"external", "interface", "superp", "input", "output", "filter", "sizeof", "cast", "namespace", -"using", "row_major", "early_fragment_tests", 0 -}; - -const char* glslBuiltIns[] = { -"abs", "acos", "acosh", "all", "any", "asin", "asinh", "atan", "atanh", "atomicCounter", -"atomicCounterDecrement", "atomicCounterIncrement", "barrier", "bitCount", "bitfieldExtract", -"bitfieldInsert", "bitfieldReverse", "ceil", "clamp", "cos", "cosh", "cross", "degrees", "determinant", -"dFdx", "dFdy", "distance", "dot", "EmitStreamVertex", "EmitVertex", "EndPrimitive", -"EndStreamPrimitive", "equal", "exp", "exp2", "faceforward", "findLSB", "findMSB", "floatBitsToInt", -"floatBitsToUint", "floor", "fma", "fract", "frexp", "fwidth", "greaterThan", "greaterThanEqual", -"imageAtomicAdd", "imageAtomicAnd", "imageAtomicCompSwap", "imageAtomicExchange", "imageAtomicMax", -"imageAtomicMin", "imageAtomicOr", "imageAtomicXor", "imageLoad", "imageSize", "imageStore", -"imulExtended", "intBitsToFloat", "interpolateAtCentroid", "interpolateAtOffset", "interpolateAtSample", -"inverse", "inversesqrt", "isinf", "isnan", "ldexp", "length", "lessThan", "lessThanEqual", -"log", "log2", "matrixCompMult", "max", "memoryBarrier", "min", "mix", "mod", "modf", -"noise", "normalize", "not", "notEqual", "outerProduct", "packDouble2x32", "packHalf2x16", -"packSnorm2x16", "packSnorm4x8", "packUnorm2x16", "packUnorm4x8", "pow", "radians", "reflect", -"refract", "round", "roundEven", "sign", "sin", "sinh", "smoothstep", "sqrt", "step", "tan", -"tanh", "texelFetch", "texelFetchOffset", "texture", "textureGather", "textureGatherOffset", -"textureGatherOffsets", "textureGrad", "textureGradOffset", "textureLod", "textureLodOffset", -"textureOffset", "textureProj", "textureProjGrad", "textureProjGradOffset", "textureProjLod", -"textureProjLodOffset", "textureProjOffset", "textureQueryLevels", "textureQueryLod", "textureSize", -"transpose", "trunc", "uaddCarry", "uintBitsToFloat", "umulExtended", "unpackDouble2x32", -"unpackHalf2x16", "unpackSnorm2x16", "unpackSnorm4x8", "unpackUnorm2x16", "unpackUnorm4x8", -"usubBorrow", 0 -}; - -const char* glslPreProcessor[] = { -"define", "undef", "if", "ifdef", "ifndef", "else", "elif", "endif", "error", "pragma", -"extension", "version", "line", 0 -}; - -const char* glslPreProcessorBuiltIns[] = { -"__LINE__", "__FILE__", "__VERSION__", 0 -}; - -} - -namespace Rv { -using namespace std; - -GLSLSyntaxHighlighter::GLSLSyntaxHighlighter(QTextDocument *parent) - : QSyntaxHighlighter(parent) +namespace { - HighlightingRule rule; - //m_functionFormat.setFontWeight(QFont::Bold); - m_functionFormat.setForeground(QColor(230,230,230)); + const char* glslTypes[] = {"float", + "double", + "int", + "void", + "bool", + "true", + "false", + "mat2", + "mat3", + "mat4", + "dmat2", + "dmat3", + "dmat4", + "mat2x2", + "mat2x3", + "mat2x4", + "dmat2x2", + "dmat2x3", + "dmat2x4", + "mat3x2", + "mat3x3", + "mat3x4", + "dmat3x2", + "dmat3x3", + "dmat3x4", + "mat4x2", + "mat4x3", + "mat4x4", + "dmat4x2", + "dmat4x3", + "dmat4x4", + "vec2", + "vec3", + "vec4", + "ivec2", + "ivec3", + "ivec4", + "bvec2", + "bvec3", + "bvec4", + "dvec2", + "dvec3", + "dvec4", + "uint", + "uvec2", + "uvec3", + "uvec4", + "sampler1D", + "sampler2D", + "sampler3D", + "samplerCube", + "sampler1DShadow", + "sampler2DShadow", + "samplerCubeShadow", + "sampler1DArray", + "sampler2DArray", + "sampler1DArrayShadow", + "sampler2DArrayShadow", + "isampler1D", + "isampler2D", + "isampler3D", + "isamplerCube", + "isampler1DArray", + "isampler2DArray", + "usampler1D", + "usampler2D", + "usampler3D", + "usamplerCube", + "usampler1DArray", + "usampler2DArray", + "sampler2DRect", + "sampler2DRectShadow", + "isampler2DRect", + "usampler2DRect", + "samplerBuffer", + "isamplerBuffer", + "usamplerBuffer", + "sampler2DMS", + "isampler2DMS", + "usampler2DMS", + "sampler2DMSArray", + "isampler2DMSArray", + "usampler2DMSArray", + "samplerCubeArray", + "samplerCubeArrayShadow", + "isamplerCubeArray", + "usamplerCubeArray", + "image1D", + "iimage1D", + "uimage1D", + "image2D", + "iimage2D", + "uimage2D", + "image3D", + "iimage3D", + "uimage3D", + "image2DRect", + "iimage2DRect", + "uimage2DRect", + "imageCube", + "iimageCube", + "uimageCube", + "imageBuffer", + "iimageBuffer", + "uimageBuffer", + "image1DArray", + "iimage1DArray", + "uimage1DArray", + "image2DArray", + "iimage2DArray", + "uimage2DArray", + "imageCubeArray", + "iimageCubeArray", + "uimageCubeArray", + "image2DMS", + "iimage2DMS", + "uimage2DMS", + "image2DMSArray", + "iimage2DMSArray", + "uimage2DMSArray", + "long", + "short", + "half", + "fixed", + "unsigned", + "hvec2", + "hvec3", + "hvec4", + "fvec2", + "fvec3", + "fvec4", + "sampler3DRect", + 0}; + + const char* glslModifiers[] = {"attribute", + "const", + "uniform", + "varying", + "buffer", + "shared", + "coherent", + "volatile", + "restrict", + "readonly", + "writeonly", + "atomic_uint", + "layout", + "centroid", + "flat", + "smooth", + "noperspective", + "patch", + "sample", + "break", + "continue", + "do", + "for", + "while", + "switch", + "case", + "default", + "if", + "else", + "subroutine", + "in", + "out", + "inout", + "invariant", + "discard", + "return", + "lowp", + "mediump", + "highp", + "precision", + "struct", + "common", + "partition", + "active", + "asm", + "class", + "union", + "enum", + "typedef", + "template", + "this", + "packed", + "resource", + "goto", + "inline", + "noinline", + "public", + "static", + "extern", + "external", + "interface", + "superp", + "input", + "output", + "filter", + "sizeof", + "cast", + "namespace", + "using", + "row_major", + "early_fragment_tests", + 0}; + + const char* glslBuiltIns[] = {"abs", + "acos", + "acosh", + "all", + "any", + "asin", + "asinh", + "atan", + "atanh", + "atomicCounter", + "atomicCounterDecrement", + "atomicCounterIncrement", + "barrier", + "bitCount", + "bitfieldExtract", + "bitfieldInsert", + "bitfieldReverse", + "ceil", + "clamp", + "cos", + "cosh", + "cross", + "degrees", + "determinant", + "dFdx", + "dFdy", + "distance", + "dot", + "EmitStreamVertex", + "EmitVertex", + "EndPrimitive", + "EndStreamPrimitive", + "equal", + "exp", + "exp2", + "faceforward", + "findLSB", + "findMSB", + "floatBitsToInt", + "floatBitsToUint", + "floor", + "fma", + "fract", + "frexp", + "fwidth", + "greaterThan", + "greaterThanEqual", + "imageAtomicAdd", + "imageAtomicAnd", + "imageAtomicCompSwap", + "imageAtomicExchange", + "imageAtomicMax", + "imageAtomicMin", + "imageAtomicOr", + "imageAtomicXor", + "imageLoad", + "imageSize", + "imageStore", + "imulExtended", + "intBitsToFloat", + "interpolateAtCentroid", + "interpolateAtOffset", + "interpolateAtSample", + "inverse", + "inversesqrt", + "isinf", + "isnan", + "ldexp", + "length", + "lessThan", + "lessThanEqual", + "log", + "log2", + "matrixCompMult", + "max", + "memoryBarrier", + "min", + "mix", + "mod", + "modf", + "noise", + "normalize", + "not", + "notEqual", + "outerProduct", + "packDouble2x32", + "packHalf2x16", + "packSnorm2x16", + "packSnorm4x8", + "packUnorm2x16", + "packUnorm4x8", + "pow", + "radians", + "reflect", + "refract", + "round", + "roundEven", + "sign", + "sin", + "sinh", + "smoothstep", + "sqrt", + "step", + "tan", + "tanh", + "texelFetch", + "texelFetchOffset", + "texture", + "textureGather", + "textureGatherOffset", + "textureGatherOffsets", + "textureGrad", + "textureGradOffset", + "textureLod", + "textureLodOffset", + "textureOffset", + "textureProj", + "textureProjGrad", + "textureProjGradOffset", + "textureProjLod", + "textureProjLodOffset", + "textureProjOffset", + "textureQueryLevels", + "textureQueryLod", + "textureSize", + "transpose", + "trunc", + "uaddCarry", + "uintBitsToFloat", + "umulExtended", + "unpackDouble2x32", + "unpackHalf2x16", + "unpackSnorm2x16", + "unpackSnorm4x8", + "unpackUnorm2x16", + "unpackUnorm4x8", + "usubBorrow", + 0}; + + const char* glslPreProcessor[] = { + "define", "undef", "if", "ifdef", "ifndef", "else", "elif", + "endif", "error", "pragma", "extension", "version", "line", 0}; + + const char* glslPreProcessorBuiltIns[] = {"__LINE__", "__FILE__", + "__VERSION__", 0}; + +} // namespace + +namespace Rv +{ + using namespace std; - m_preProcessorFormat.setForeground(QColor(205, 80, 205)); - m_preProcessorFormat.setBackground(QColor(35, 35, 35)); - - //m_typeFormat.setForeground(QColor(85, 26, 139)); - m_typeFormat.setForeground(QColor(155, 110, 208)); - //m_typeFormat.setFontWeight(QFont::Bold); + GLSLSyntaxHighlighter::GLSLSyntaxHighlighter(QTextDocument* parent) + : QSyntaxHighlighter(parent) + { + HighlightingRule rule; - //m_keywordFormat.setForeground(QColor(24, 116, 205)); - //m_keywordFormat.setForeground(QColor(90, 170, 215)); - m_keywordFormat.setForeground(QColor(120, 180, 215)); - //m_keywordFormat.setFontWeight(QFont::Bold); + // m_functionFormat.setFontWeight(QFont::Bold); + m_functionFormat.setForeground(QColor(230, 230, 230)); - m_builtInFormat.setForeground(QColor(200, 90, 90)); - //m_builtInFormat.setFontWeight(QFont::Bold); + m_preProcessorFormat.setForeground(QColor(205, 80, 205)); + m_preProcessorFormat.setBackground(QColor(35, 35, 35)); - m_imageFormat.setForeground(QColor(155, 110, 208)); - //m_imageFormat.setFontWeight(QFont::Bold); - //m_imageFormat.setBackground(QColor(50, 50, 100)); + // m_typeFormat.setForeground(QColor(85, 26, 139)); + m_typeFormat.setForeground(QColor(155, 110, 208)); + // m_typeFormat.setFontWeight(QFont::Bold); - m_commentFormat.setForeground(QColor(127,127,127)); - m_quotationFormat.setForeground(Qt::green); + // m_keywordFormat.setForeground(QColor(24, 116, 205)); + // m_keywordFormat.setForeground(QColor(90, 170, 215)); + m_keywordFormat.setForeground(QColor(120, 180, 215)); + // m_keywordFormat.setFontWeight(QFont::Bold); - rule.pattern = QRegExp("\\b[A-Za-z0-9_]+[ \t]*(?=\\()"); - rule.format = m_functionFormat; - m_highlightingRules.append(rule); + m_builtInFormat.setForeground(QColor(200, 90, 90)); + // m_builtInFormat.setFontWeight(QFont::Bold); - for (const char** p = glslTypes; *p; p++) - { - QString pattern = "\\b"; - pattern += *p; - pattern += "\\b"; - rule.pattern = QRegExp(pattern); - rule.format = m_typeFormat; - m_highlightingRules.append(rule); - } + m_imageFormat.setForeground(QColor(155, 110, 208)); + // m_imageFormat.setFontWeight(QFont::Bold); + // m_imageFormat.setBackground(QColor(50, 50, 100)); - for (const char** p = glslModifiers; *p; p++) - { - QString pattern = "\\b"; - pattern += *p; - pattern += "\\b"; - rule.pattern = QRegExp(pattern); - rule.format = m_keywordFormat; - m_highlightingRules.append(rule); - } + m_commentFormat.setForeground(QColor(127, 127, 127)); + m_quotationFormat.setForeground(Qt::green); - for (const char** p = glslBuiltIns; *p; p++) - { - QString pattern = "\\b"; - pattern += *p; - pattern += "\\b"; - rule.pattern = QRegExp(pattern); - rule.format = m_builtInFormat; + rule.pattern = QRegExp("\\b[A-Za-z0-9_]+[ \t]*(?=\\()"); + rule.format = m_functionFormat; m_highlightingRules.append(rule); - } - - for (const char** p = glslPreProcessorBuiltIns; *p; p++) - { - QString pattern = "\\b"; - pattern += *p; - pattern += "\\b"; - rule.pattern = QRegExp(pattern); - rule.format = m_builtInFormat; - m_highlightingRules.append(rule); - } - rule.pattern = QRegExp("\\b(?:inputImage|outputImage)\\b"); - rule.format = m_imageFormat; - m_highlightingRules.append(rule); + for (const char** p = glslTypes; *p; p++) + { + QString pattern = "\\b"; + pattern += *p; + pattern += "\\b"; + rule.pattern = QRegExp(pattern); + rule.format = m_typeFormat; + m_highlightingRules.append(rule); + } - for (const char** p = glslPreProcessor; *p; p++) - { - QString pattern = "#[ \t]*"; - pattern += *p; - pattern += "\\b"; - rule.pattern = QRegExp(pattern); - rule.format = m_preProcessorFormat; - m_highlightingRules.append(rule); - } + for (const char** p = glslModifiers; *p; p++) + { + QString pattern = "\\b"; + pattern += *p; + pattern += "\\b"; + rule.pattern = QRegExp(pattern); + rule.format = m_keywordFormat; + m_highlightingRules.append(rule); + } - rule.pattern = QRegExp("//[^\n]*"); - rule.format = m_commentFormat; - m_highlightingRules.append(rule); + for (const char** p = glslBuiltIns; *p; p++) + { + QString pattern = "\\b"; + pattern += *p; + pattern += "\\b"; + rule.pattern = QRegExp(pattern); + rule.format = m_builtInFormat; + m_highlightingRules.append(rule); + } - // GLSL doesn't have string literals - //rule.pattern = QRegExp("\".*\""); - //rule.format = m_quotationFormat; - //m_highlightingRules.append(rule); + for (const char** p = glslPreProcessorBuiltIns; *p; p++) + { + QString pattern = "\\b"; + pattern += *p; + pattern += "\\b"; + rule.pattern = QRegExp(pattern); + rule.format = m_builtInFormat; + m_highlightingRules.append(rule); + } - m_commentStartExpression = QRegExp("/\\*"); - m_commentEndExpression = QRegExp("\\*/"); -} + rule.pattern = QRegExp("\\b(?:inputImage|outputImage)\\b"); + rule.format = m_imageFormat; + m_highlightingRules.append(rule); -void -GLSLSyntaxHighlighter::highlightBlock(const QString &text) -{ - foreach (const HighlightingRule &rule, m_highlightingRules) - { - QRegExp expression(rule.pattern); - int index = expression.indexIn(text); - while (index >= 0) + for (const char** p = glslPreProcessor; *p; p++) { - int length = expression.matchedLength(); - setFormat(index, length, rule.format); - index = expression.indexIn(text, index + length); + QString pattern = "#[ \t]*"; + pattern += *p; + pattern += "\\b"; + rule.pattern = QRegExp(pattern); + rule.format = m_preProcessorFormat; + m_highlightingRules.append(rule); } - } - setCurrentBlockState(0); + rule.pattern = QRegExp("//[^\n]*"); + rule.format = m_commentFormat; + m_highlightingRules.append(rule); - int startIndex = 0; + // GLSL doesn't have string literals + // rule.pattern = QRegExp("\".*\""); + // rule.format = m_quotationFormat; + // m_highlightingRules.append(rule); - if (previousBlockState() != 1) - { - startIndex = m_commentStartExpression.indexIn(text); + m_commentStartExpression = QRegExp("/\\*"); + m_commentEndExpression = QRegExp("\\*/"); } - while (startIndex >= 0) + void GLSLSyntaxHighlighter::highlightBlock(const QString& text) { - int endIndex = m_commentEndExpression.indexIn(text, startIndex); - int commentLength; - - if (endIndex == -1) + foreach (const HighlightingRule& rule, m_highlightingRules) { - setCurrentBlockState(1); - commentLength = text.length() - startIndex; - } - else + QRegExp expression(rule.pattern); + int index = expression.indexIn(text); + while (index >= 0) + { + int length = expression.matchedLength(); + setFormat(index, length, rule.format); + index = expression.indexIn(text, index + length); + } + } + + setCurrentBlockState(0); + + int startIndex = 0; + + if (previousBlockState() != 1) { - commentLength = endIndex - startIndex - + m_commentEndExpression.matchedLength(); + startIndex = m_commentStartExpression.indexIn(text); } - setFormat(startIndex, commentLength, m_commentFormat); - startIndex = m_commentStartExpression.indexIn(text, startIndex + commentLength); + while (startIndex >= 0) + { + int endIndex = m_commentEndExpression.indexIn(text, startIndex); + int commentLength; + + if (endIndex == -1) + { + setCurrentBlockState(1); + commentLength = text.length() - startIndex; + } + else + { + commentLength = endIndex - startIndex + + m_commentEndExpression.matchedLength(); + } + + setFormat(startIndex, commentLength, m_commentFormat); + startIndex = m_commentStartExpression.indexIn( + text, startIndex + commentLength); + } } -} - -} // Rv +} // namespace Rv diff --git a/src/lib/app/RvCommon/GLView.cpp b/src/lib/app/RvCommon/GLView.cpp index a1a8efc16..aab4587e3 100644 --- a/src/lib/app/RvCommon/GLView.cpp +++ b/src/lib/app/RvCommon/GLView.cpp @@ -1,9 +1,9 @@ //****************************************************************************** -// Copyright (c) 2007 Tweak Inc. +// Copyright (c) 2007 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #ifdef PLATFORM_WINDOWS @@ -25,330 +25,312 @@ #include -namespace Rv { -using namespace boost; -using namespace std; -using namespace TwkApp; -using namespace IPCore; - -namespace { - -class SyncBufferThreadData +namespace Rv { - public: - explicit SyncBufferThreadData(const VideoDevice* device) - : m_device(device), - m_done(false), - m_doSync(false), - m_running(false), - m_mutex(), - m_cond() {} - - void run() + using namespace boost; + using namespace std; + using namespace TwkApp; + using namespace IPCore; + + namespace { - while (!m_done) + + class SyncBufferThreadData { - boost::mutex::scoped_lock lock(m_mutex); - m_running = true; - m_doSync = false; - - m_cond.wait(lock); + public: + explicit SyncBufferThreadData(const VideoDevice* device) + : m_device(device) + , m_done(false) + , m_doSync(false) + , m_running(false) + , m_mutex() + , m_cond() + { + } - if (m_device && m_doSync && !m_done) m_device->syncBuffers(); + void run() + { + while (!m_done) + { + boost::mutex::scoped_lock lock(m_mutex); + m_running = true; + m_doSync = false; - m_doSync = false; - } - } + m_cond.wait(lock); - void notify(bool finish=false) - { - { - boost::mutex::scoped_lock lock(m_mutex); - if (finish) m_done = true; - else m_doSync = true; - if (!m_running) return; - } + if (m_device && m_doSync && !m_done) + m_device->syncBuffers(); - m_cond.notify_one(); - } + m_doSync = false; + } + } - const VideoDevice* device() const { return m_device; } + void notify(bool finish = false) + { + { + boost::mutex::scoped_lock lock(m_mutex); + if (finish) + m_done = true; + else + m_doSync = true; + if (!m_running) + return; + } - void setDevice(const VideoDevice* d) - { - m_device = d; - } + m_cond.notify_one(); + } - private: - SyncBufferThreadData(SyncBufferThreadData&) {} - void operator=(SyncBufferThreadData&) {} + const VideoDevice* device() const { return m_device; } - private: - bool m_done; - bool m_doSync; - bool m_running; - boost::mutex m_mutex; - boost::condition_variable m_cond; - const VideoDevice* m_device; -}; + void setDevice(const VideoDevice* d) { m_device = d; } -class ThreadTrampoline -{ - public: - ThreadTrampoline(GLView* view) : m_view(view) {} + private: + SyncBufferThreadData(SyncBufferThreadData&) {} - void operator()() - { - SyncBufferThreadData* closure = - reinterpret_cast(m_view->syncClosure()); - closure->run(); - } + void operator=(SyncBufferThreadData&) {} - private: - GLView* m_view; -}; - -} - -GLView::GLView(QWidget* parent, - const QGLWidget* share, - RvDocument* doc, - bool strereo, - bool vsync, - bool doubleBuffer, - int red, - int green, - int blue, - int alpha, - bool noResize) - : QGLWidget(GLView::rvGLFormat(strereo, vsync, doubleBuffer, red, green, blue, alpha), - parent, - share), - m_doc(doc), - m_red(red), - m_green(green), - m_blue(blue), - m_alpha(alpha), - m_lastKey(0), - m_lastKeyType(QEvent::None), - m_userActive(true), - m_renderCount(0), - m_firstPaintCompleted(false), - m_csize(1024, 576), - m_msize(128, 128), - m_postFirstNonEmptyRender(noResize), - m_stopProcessingEvents(false), - m_syncThreadData(0) -{ - setObjectName((m_doc->session()) ? m_doc->session()->name().c_str() : "no session"); - //m_frameBuffer = new QTFrameBuffer( this ); - ostringstream str; - str << UI_APPLICATION_NAME " Main Window" << "/" << m_doc; - m_videoDevice = new QTGLVideoDevice(0, str.str(), this); - m_activityTimer.start(); - setMouseTracking(true); - setAcceptDrops(true); - setFocusPolicy(Qt::StrongFocus); - setAutoBufferSwap(false); - - m_eventProcessingTimer.setSingleShot(true); - connect(&m_eventProcessingTimer, SIGNAL(timeout()), this, SLOT(eventProcessingTimeout())); - - QGLFormat f = format(); -} - -GLView::~GLView() -{ - //delete m_frameBuffer; - delete m_videoDevice; + private: + bool m_done; + bool m_doSync; + bool m_running; + boost::mutex m_mutex; + boost::condition_variable m_cond; + const VideoDevice* m_device; + }; - if (m_syncThreadData) + class ThreadTrampoline + { + public: + ThreadTrampoline(GLView* view) + : m_view(view) + { + } + + void operator()() + { + SyncBufferThreadData* closure = + reinterpret_cast( + m_view->syncClosure()); + closure->run(); + } + + private: + GLView* m_view; + }; + + } // namespace + + GLView::GLView(QWidget* parent, const QGLWidget* share, RvDocument* doc, + bool strereo, bool vsync, bool doubleBuffer, int red, + int green, int blue, int alpha, bool noResize) + : QGLWidget(GLView::rvGLFormat(strereo, vsync, doubleBuffer, red, green, + blue, alpha), + parent, share) + , m_doc(doc) + , m_red(red) + , m_green(green) + , m_blue(blue) + , m_alpha(alpha) + , m_lastKey(0) + , m_lastKeyType(QEvent::None) + , m_userActive(true) + , m_renderCount(0) + , m_firstPaintCompleted(false) + , m_csize(1024, 576) + , m_msize(128, 128) + , m_postFirstNonEmptyRender(noResize) + , m_stopProcessingEvents(false) + , m_syncThreadData(0) { - SyncBufferThreadData* closure = - reinterpret_cast(m_syncThreadData); - closure->notify(true); - m_swapThread.join(); + setObjectName((m_doc->session()) ? m_doc->session()->name().c_str() + : "no session"); + // m_frameBuffer = new QTFrameBuffer( this ); + ostringstream str; + str << UI_APPLICATION_NAME " Main Window" << "/" << m_doc; + m_videoDevice = new QTGLVideoDevice(0, str.str(), this); + m_activityTimer.start(); + setMouseTracking(true); + setAcceptDrops(true); + setFocusPolicy(Qt::StrongFocus); + setAutoBufferSwap(false); - delete closure; + m_eventProcessingTimer.setSingleShot(true); + connect(&m_eventProcessingTimer, SIGNAL(timeout()), this, + SLOT(eventProcessingTimeout())); + + QGLFormat f = format(); } -} -void -GLView::stopProcessingEvents() -{ - m_stopProcessingEvents = true; -} + GLView::~GLView() + { + // delete m_frameBuffer; + delete m_videoDevice; -QSize -GLView::sizeHint() const -{ - return m_csize; -} + if (m_syncThreadData) + { + SyncBufferThreadData* closure = + reinterpret_cast(m_syncThreadData); + closure->notify(true); + m_swapThread.join(); -QSize -GLView::minimumSizeHint() const -{ - return m_msize; -} + delete closure; + } + } -void -GLView::absolutePosition(int& x, int& y) const -{ - x = 0; - y = 0; - - QPoint p(0,0); - QPoint gp = mapToGlobal(p); - - x = gp.x(); - y = gp.y(); -} - -QGLFormat -GLView::rvGLFormat(bool stereo, - bool vsync, - bool doubleBuffer, - int red, - int green, - int blue, - int alpha) -{ - const Rv::Options& opts = Rv::Options::sharedOptions(); + void GLView::stopProcessingEvents() { m_stopProcessingEvents = true; } - QGLFormat fmt; - fmt.setDepthBufferSize(0); - fmt.setDoubleBuffer(doubleBuffer); - fmt.setStencilBufferSize(8); - fmt.setStencil(true); - fmt.setDepth(false); - fmt.setStereo(stereo); + QSize GLView::sizeHint() const { return m_csize; } - // - // The default value for these buffer sizes is -1, but it is - // illegal to set to that value so test for positive red, not - // just non-zero red. If any of these values is < 0, we ignore it. - // - if (red > 0) fmt.setRedBufferSize(red); - if (green > 0) fmt.setGreenBufferSize(green); - if (blue > 0) fmt.setBlueBufferSize(blue); - if (alpha >= 0) - { - fmt.setAlpha(alpha != 0); - fmt.setAlphaBufferSize(alpha); - } + QSize GLView::minimumSizeHint() const { return m_msize; } - fmt.setSwapInterval(vsync ? 1 : 0); + void GLView::absolutePosition(int& x, int& y) const + { + x = 0; + y = 0; - return fmt; -} + QPoint p(0, 0); + QPoint gp = mapToGlobal(p); -void -GLView::initializeGL() -{ - // - // At this point the format is known. Can't do this in the constructor - // + x = gp.x(); + y = gp.y(); + } - if (isValid()) + QGLFormat GLView::rvGLFormat(bool stereo, bool vsync, bool doubleBuffer, + int red, int green, int blue, int alpha) { - QGLFormat f = context()->format(); + const Rv::Options& opts = Rv::Options::sharedOptions(); + + QGLFormat fmt; + fmt.setDepthBufferSize(0); + fmt.setDoubleBuffer(doubleBuffer); + fmt.setStencilBufferSize(8); + fmt.setStencil(true); + fmt.setDepth(false); + fmt.setStereo(stereo); -#ifndef PLATFORM_DARWIN // - // Doesn't work on OS X + // The default value for these buffer sizes is -1, but it is + // illegal to set to that value so test for positive red, not + // just non-zero red. If any of these values is < 0, we ignore it. // - if (f.redBufferSize() != m_red && m_red != 0) + if (red > 0) + fmt.setRedBufferSize(red); + if (green > 0) + fmt.setGreenBufferSize(green); + if (blue > 0) + fmt.setBlueBufferSize(blue); + if (alpha >= 0) { - // QMessageBox box(this); - // box.setWindowTitle(tr("Ouput Display Format")); - - ostringstream str; - - str << "WARNING: asked for" - << " " << m_red - << " " << m_green - << " " << m_blue - << " " << m_alpha - << " RGBA color but got" - << " " << f.redBufferSize() - << " " << f.greenBufferSize() - << " " << f.blueBufferSize() - << " " << (f.alphaBufferSize() <= 0 ? 0 : f.alphaBufferSize()) - << " RGBA instead"; - - cout << str.str() << endl; - - // box.setText(str.str().c_str()); - // box.setDetailedText("You can change the default display color depth and target " - // "from the preferences under Rendering->Display Output Format.\n" - // "Choosing \"OpenGL Default Format\" will tell RV to ask for the " - // "default prefered format for this display."); - // box.setWindowModality(Qt::WindowModal); - // QPushButton* b1 = box.addButton(tr("Continue"), QMessageBox::AcceptRole); - // box.setIcon(QMessageBox::Critical); - // box.exec(); + fmt.setAlpha(alpha != 0); + fmt.setAlphaBufferSize(alpha); } + + fmt.setSwapInterval(vsync ? 1 : 0); + + return fmt; + } + + void GLView::initializeGL() + { + // + // At this point the format is known. Can't do this in the constructor + // + + if (isValid()) + { + QGLFormat f = context()->format(); + +#ifndef PLATFORM_DARWIN + // + // Doesn't work on OS X + // + if (f.redBufferSize() != m_red && m_red != 0) + { + // QMessageBox box(this); + // box.setWindowTitle(tr("Ouput Display Format")); + + ostringstream str; + + str << "WARNING: asked for" + << " " << m_red << " " << m_green << " " << m_blue << " " + << m_alpha << " RGBA color but got" + << " " << f.redBufferSize() << " " << f.greenBufferSize() + << " " << f.blueBufferSize() << " " + << (f.alphaBufferSize() <= 0 ? 0 : f.alphaBufferSize()) + << " RGBA instead"; + + cout << str.str() << endl; + + // box.setText(str.str().c_str()); + // box.setDetailedText("You can change the default display color + // depth and target " + // "from the preferences under + // Rendering->Display Output Format.\n" + // "Choosing \"OpenGL Default Format\" will + // tell RV to ask for the " "default + // prefered format for this display."); + // box.setWindowModality(Qt::WindowModal); + // QPushButton* b1 = box.addButton(tr("Continue"), + // QMessageBox::AcceptRole); box.setIcon(QMessageBox::Critical); + // box.exec(); + } #endif - if (!f.stencil()) + if (!f.stencil()) + { + cout << "WARNING: no stencil buffer available" << endl; + } + } + else { - cout << "WARNING: no stencil buffer available" << endl; + cout << "WARNING: invalid GL context" << endl; } } - else + + void GLView::resizeGL(int w, int h) { - cout << "WARNING: invalid GL context" << endl; + if (m_doc) + m_doc->viewSizeChanged(w, h); +#ifdef PLATFORM_WINDOWS + SetWindowRgn(reinterpret_cast(this->winId()), 0, false); +#endif } -} - -void -GLView::resizeGL(int w, int h) -{ - if (m_doc) m_doc->viewSizeChanged(w, h); - #ifdef PLATFORM_WINDOWS - SetWindowRgn (reinterpret_cast(this->winId()), 0, false); - #endif -} - -void -GLView::swapBuffersNoSync() -{ - glFlush(); - glBindFramebuffer(GL_FRAMEBUFFER, 0); - glReadBuffer(GL_BACK); - glDrawBuffer(GL_FRONT); - glBlitFramebufferEXT(0, 0, width(), height(), - 0, 0, width(), height(), - GL_COLOR_BUFFER_BIT, - GL_NEAREST); - glDrawBuffer(GL_BACK); -} - -void -GLView::paintGL() -{ - IPCore::Session* session = m_doc->session(); - bool debug = IPCore::debugProfile && session; + void GLView::swapBuffersNoSync() + { + glFlush(); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glReadBuffer(GL_BACK); + glDrawBuffer(GL_FRONT); + glBlitFramebufferEXT(0, 0, width(), height(), 0, 0, width(), height(), + GL_COLOR_BUFFER_BIT, GL_NEAREST); + glDrawBuffer(GL_BACK); + } - if (!m_postFirstNonEmptyRender && session && session->postFirstNonEmptyRender()) + void GLView::paintGL() { - m_postFirstNonEmptyRender = true; + IPCore::Session* session = m_doc->session(); + bool debug = IPCore::debugProfile && session; - if (! session->isFullScreen()) + if (!m_postFirstNonEmptyRender && session + && session->postFirstNonEmptyRender()) { - m_doc->resizeToFit(false, false); - m_doc->center(); + m_postFirstNonEmptyRender = true; + + if (!session->isFullScreen()) + { + m_doc->resizeToFit(false, false); + m_doc->center(); + } } - } - if (debug) - { - Session::ProfilingRecord& trecord = session->beginProfilingSample(); - trecord.renderStart = session->profilingElapsedTime(); - } + if (debug) + { + Session::ProfilingRecord& trecord = session->beginProfilingSample(); + trecord.renderStart = session->profilingElapsedTime(); + } - // should be no longer necessary, moved it to resize() + // should be no longer necessary, moved it to resize() #if 0 // // This is necessary to stop the Windows Desktop Window Manager @@ -358,193 +340,206 @@ GLView::paintGL() // behind" and not updated even when rv plays. especially when // going to/from fullscreen. // - #ifdef PLATFORM_WINDOWS +#ifdef PLATFORM_WINDOWS SetWindowRgn (this->winId(), 0, false); - #endif +#endif #endif - - if (m_doc && session && m_videoDevice) - { - //m_frameBuffer->makeCurrent(); - m_videoDevice->makeCurrent(); - - if (m_userActive && m_activityTimer.elapsed() > 1.0) + if (m_doc && session && m_videoDevice) { - if (m_doc->mainPopup() && !m_doc->mainPopup()->isVisible() && hasFocus()) + // m_frameBuffer->makeCurrent(); + m_videoDevice->makeCurrent(); + + if (m_userActive && m_activityTimer.elapsed() > 1.0) { - TwkApp::ActivityChangeEvent aevent("user-inactive", m_videoDevice); - m_videoDevice->sendEvent(aevent); - m_userActive = false; + if (m_doc->mainPopup() && !m_doc->mainPopup()->isVisible() + && hasFocus()) + { + TwkApp::ActivityChangeEvent aevent("user-inactive", + m_videoDevice); + m_videoDevice->sendEvent(aevent); + m_userActive = false; + } } + + // + // Make sure the video device knows where it is on screen. + // + int x = 0, y = 0; + absolutePosition(x, y); + m_videoDevice->setAbsolutePosition(x, y); + + session->render(); + m_firstPaintCompleted = true; + + // Starting with Qt 5.12.1, the resulting texture is later + // composited over white which creates undesirable artifacts. As a + // work around, we set the resulting alpha channel to 1 to make sure + // that the resulting texture is fully opaque. + glPushAttrib(GL_COLOR_BUFFER_BIT); + TWK_GLDEBUG; + glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE); + TWK_GLDEBUG; + glClearColor(0.f, 0.f, 0.f, 1.0f); + TWK_GLDEBUG; + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + TWK_GLDEBUG; + glPopAttrib(); + TWK_GLDEBUG; + } + else + { + glClearColor(0.f, 0.f, 0.f, 1.0f); + TWK_GLDEBUG; + glClear(GL_COLOR_BUFFER_BIT); + TWK_GLDEBUG; } + if (m_stopProcessingEvents) + return; + // - // Make sure the video device knows where it is on screen. + // We're done with drawing and about to (possibly) wait for + // vsync before the buffer swaps, but if the driver is layzy, + // it may not performs some requested gl actions until after + // the wait on vsync, in which case we get tearing. + // + // A glFlush here should make these gl actions happen during + // the wait. + // + // This could be a problem if further drawing is done to this + // buffer by Qt, for example if it's doing it's graphics area + // widget drawing. Seems fine for now. + // + // Update: We want to actually wait until the gfx operations are + // complete. glFlush just flushes the command buffer to + // hardware, glFinish blocks until the hardware is finished + // processing the commands. // - int x = 0, y = 0; - absolutePosition(x, y); - m_videoDevice->setAbsolutePosition(x, y); - - session->render(); - m_firstPaintCompleted = true; - - // Starting with Qt 5.12.1, the resulting texture is later composited over - // white which creates undesirable artifacts. - // As a work around, we set the resulting alpha channel to 1 to make sure - // that the resulting texture is fully opaque. - glPushAttrib( GL_COLOR_BUFFER_BIT ); TWK_GLDEBUG; - glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE); TWK_GLDEBUG; - glClearColor(0.f, 0.f, 0.f, 1.0f); TWK_GLDEBUG; - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); TWK_GLDEBUG; - glPopAttrib(); TWK_GLDEBUG; - } - else - { - glClearColor(0.f, 0.f, 0.f, 1.0f); TWK_GLDEBUG; - glClear(GL_COLOR_BUFFER_BIT); TWK_GLDEBUG; - } - - if (m_stopProcessingEvents) return; - - // - // We're done with drawing and about to (possibly) wait for - // vsync before the buffer swaps, but if the driver is layzy, - // it may not performs some requested gl actions until after - // the wait on vsync, in which case we get tearing. - // - // A glFlush here should make these gl actions happen during - // the wait. - // - // This could be a problem if further drawing is done to this - // buffer by Qt, for example if it's doing it's graphics area - // widget drawing. Seems fine for now. - // - // Update: We want to actually wait until the gfx operations are - // complete. glFlush just flushes the command buffer to - // hardware, glFinish blocks until the hardware is finished - // processing the commands. - // - // DONT - //glFlush(); - //glFinish(); + // DONT + // glFlush(); + // glFinish(); - // - // Do the swap, the vsync code is in the swapBuffers() code in - // Qt. It should block here waiting for the refresh. The debug - // code here is accumulating profiling information in the session - // ProfilingRecord struct. This can be dumped on exit to figure out - // what's going on. - // - - if (debug) - { - Session::ProfilingRecord& trecord = session->currentProfilingSample(); - trecord.renderEnd = session->profilingElapsedTime(); - trecord.swapStart = trecord.renderEnd; + // + // Do the swap, the vsync code is in the swapBuffers() code in + // Qt. It should block here waiting for the refresh. The debug + // code here is accumulating profiling information in the session + // ProfilingRecord struct. This can be dumped on exit to figure out + // what's going on. + // - if (session->outputVideoDevice() != videoDevice()) + if (debug) { + Session::ProfilingRecord& trecord = + session->currentProfilingSample(); + trecord.renderEnd = session->profilingElapsedTime(); + trecord.swapStart = trecord.renderEnd; + + if (session->outputVideoDevice() != videoDevice()) + { #ifdef PLATFORM_DARWIN - session->outputVideoDevice()->syncBuffers(); - makeCurrent(); - swapBuffers(); + session->outputVideoDevice()->syncBuffers(); + makeCurrent(); + swapBuffers(); #else - session->outputVideoDevice()->syncBuffers(); - makeCurrent(); - swapBuffersNoSync(); + session->outputVideoDevice()->syncBuffers(); + makeCurrent(); + swapBuffersNoSync(); #endif + } + else + { + swapBuffers(); + } + + trecord.swapEnd = session->profilingElapsedTime(); + session->endProfilingSample(); } else { - swapBuffers(); - } - - trecord.swapEnd = session->profilingElapsedTime(); - session->endProfilingSample(); - } - else - { - if (session->outputVideoDevice() != videoDevice()) - { - -#ifdef PLATFORM_DARWIN - if (!m_syncThreadData) + if (session->outputVideoDevice() != videoDevice()) { - m_syncThreadData = new SyncBufferThreadData(session->outputVideoDevice()); - m_swapThread = boost::thread(ThreadTrampoline(this)); - } - else - { - SyncBufferThreadData* sb = reinterpret_cast(m_syncThreadData); - if (sb->device() != session->outputVideoDevice()) +#ifdef PLATFORM_DARWIN + if (!m_syncThreadData) { - // - // This is questionable without shutting down and - // restarting the sync thread, but the worst case - // seems to be an extra swap on the closed (not - // visible) device - // - - sb->setDevice(session->outputVideoDevice()); + m_syncThreadData = + new SyncBufferThreadData(session->outputVideoDevice()); + m_swapThread = boost::thread(ThreadTrampoline(this)); + } + else + { + SyncBufferThreadData* sb = + reinterpret_cast( + m_syncThreadData); + + if (sb->device() != session->outputVideoDevice()) + { + // + // This is questionable without shutting down and + // restarting the sync thread, but the worst case + // seems to be an extra swap on the closed (not + // visible) device + // + + sb->setDevice(session->outputVideoDevice()); + } } - } - reinterpret_cast(m_syncThreadData)->notify(); + reinterpret_cast(m_syncThreadData) + ->notify(); - //session->outputVideoDevice()->syncBuffers(); + // session->outputVideoDevice()->syncBuffers(); - makeCurrent(); - swapBuffers(); + makeCurrent(); + swapBuffers(); #else - session->outputVideoDevice()->syncBuffers(); - makeCurrent(); - swapBuffersNoSync(); + session->outputVideoDevice()->syncBuffers(); + makeCurrent(); + swapBuffersNoSync(); #endif + } + else + { + swapBuffers(); + } } - else - { - swapBuffers(); - } - } - - session->addSyncSample(); - session->postRender(); + session->addSyncSample(); - m_eventProcessingTimer.start(); -} + session->postRender(); -void -GLView::eventProcessingTimeout() -{ - m_doc->session()->userGenericEvent ("per-render-event-processing", ""); -} - -bool -GLView::event(QEvent* event) -{ - bool keyevent = false; - Rv::Session* session = m_doc->session(); + m_eventProcessingTimer.start(); + } - if (m_stopProcessingEvents) + void GLView::eventProcessingTimeout() { - event->accept(); - return true; + m_doc->session()->userGenericEvent("per-render-event-processing", ""); } - // - // We want to exclude the "click-through" clicks on - // click-to-focus systems (like osX). Turns out the event - // sequence in these cases is exactly the same as a - // tab-to-focus, then click sequence. So the only way we have - // to identify the "click-through" is by how quickly the click - // (button push) follows the windowActivate event. - // + bool GLView::event(QEvent* event) + { + bool keyevent = false; + Rv::Session* session = m_doc->session(); - if (event->type() == QEvent::WindowActivate) m_activationTimer.start(); + if (m_stopProcessingEvents) + { + event->accept(); + return true; + } + + // + // We want to exclude the "click-through" clicks on + // click-to-focus systems (like osX). Turns out the event + // sequence in these cases is exactly the same as a + // tab-to-focus, then click sequence. So the only way we have + // to identify the "click-through" is by how quickly the click + // (button push) follows the windowActivate event. + // + + if (event->type() == QEvent::WindowActivate) + m_activationTimer.start(); #if 0 // @@ -570,233 +565,240 @@ GLView::event(QEvent* event) } #endif - float activationTime = 0.0; - if (m_activationTimer.isRunning()) - { - if (event->type() == QEvent::MouseButtonPress) + float activationTime = 0.0; + if (m_activationTimer.isRunning()) { - // - // Pass this time through with the event, so that - // event handling code can decide witehr or not to ignore - // this 'click-through' event. - // - activationTime = m_activationTimer.elapsed(); - m_activationTimer.stop(); + if (event->type() == QEvent::MouseButtonPress) + { + // + // Pass this time through with the event, so that + // event handling code can decide witehr or not to ignore + // this 'click-through' event. + // + activationTime = m_activationTimer.elapsed(); + m_activationTimer.stop(); + } + if (event->type() == QEvent::MouseMove) + m_activationTimer.stop(); } - if (event->type() == QEvent::MouseMove) m_activationTimer.stop(); - } - if (event->type() != QEvent::Paint) - { - m_activityTimer.stop(); - m_activityTimer.start(); - - if (!m_userActive) + if (event->type() != QEvent::Paint) { - TwkApp::ActivityChangeEvent aevent("user-active", m_videoDevice); - - // - // m_userActive set first will prevent recursive nightmare. In - // Qt 4.4 an event may recursively produce more - // events. For example, changing the cursor in 4.4 will - // cause a Paint event immediately (not after the - // previous event returns). - // + m_activityTimer.stop(); + m_activityTimer.start(); - m_userActive = true; - m_videoDevice->sendEvent(aevent); + if (!m_userActive) + { + TwkApp::ActivityChangeEvent aevent("user-active", + m_videoDevice); + + // + // m_userActive set first will prevent recursive nightmare. In + // Qt 4.4 an event may recursively produce more + // events. For example, changing the cursor in 4.4 will + // cause a Paint event immediately (not after the + // previous event returns). + // + + m_userActive = true; + m_videoDevice->sendEvent(aevent); + } } - } - - if (QKeyEvent* kevent = dynamic_cast(event)) - { - keyevent = true; - // - // Get around really annoying event bugs on Qt/Mac - // - - if (m_lastKey == kevent->key() && - (m_lastKeyType == QEvent::ShortcutOverride && - (kevent->type() == QEvent::KeyPress) || - (m_lastKeyType == kevent->type()))) + if (QKeyEvent* kevent = dynamic_cast(event)) { + keyevent = true; + // - // Qt 4.3.3 (4.5 too) will give both override and press events even if - // key is not in menu. Filter that here. + // Get around really annoying event bugs on Qt/Mac // - // Remember the new key/type, otherwise we filter out - // any number of ShortcutOverride/Press pairs, and - // auto-repeat doesn't work. - // - m_lastKey = kevent->key(); - m_lastKeyType = kevent->type(); - event->accept(); - return true; - } + if (m_lastKey == kevent->key() + && (m_lastKeyType == QEvent::ShortcutOverride + && (kevent->type() == QEvent::KeyPress) + || (m_lastKeyType == kevent->type()))) + { + // + // Qt 4.3.3 (4.5 too) will give both override and press events + // even if key is not in menu. Filter that here. + // + // Remember the new key/type, otherwise we filter out + // any number of ShortcutOverride/Press pairs, and + // auto-repeat doesn't work. + // + m_lastKey = kevent->key(); + m_lastKeyType = kevent->type(); - m_lastKeyType = kevent->type(); - m_lastKey = kevent->key(); - } - - switch (event->type()) - { - case QEvent::FocusIn: - m_videoDevice->translator().resetModifiers(); - case QEvent::Enter: - setFocus(Qt::MouseFocusReason); - break; - default: - break; - } - if (event->type() == QEvent::Resize) - { - QResizeEvent* e = static_cast(event); + event->accept(); + return true; + } - // QT5 BUG -- results in invalid drawable - if (!isVisible()) return true; + m_lastKeyType = kevent->type(); + m_lastKey = kevent->key(); + } - if (e->oldSize().width() != -1 && e->oldSize().height() != -1) + switch (event->type()) + { + case QEvent::FocusIn: + m_videoDevice->translator().resetModifiers(); + case QEvent::Enter: + setFocus(Qt::MouseFocusReason); + break; + default: + break; + } + if (event->type() == QEvent::Resize) { - ostringstream contents; - contents << e->oldSize().width() << - " " << e->oldSize().height() << - "|" << e->size().width() << - " " << e->size().height(); + QResizeEvent* e = static_cast(event); + + // QT5 BUG -- results in invalid drawable + if (!isVisible()) + return true; - if (m_doc && session) + if (e->oldSize().width() != -1 && e->oldSize().height() != -1) { - session->userGenericEvent("view-resized", contents.str()); + ostringstream contents; + contents << e->oldSize().width() << " " << e->oldSize().height() + << "|" << e->size().width() << " " + << e->size().height(); + + if (m_doc && session) + { + session->userGenericEvent("view-resized", contents.str()); + } } + return QGLWidget::event(event); } - return QGLWidget::event(event); - } - if (session && session->outputVideoDevice() && - session->outputVideoDevice()->displayMode() == TwkApp::VideoDevice::MirrorDisplayMode) - { - if (const TwkApp::VideoDevice* cdv = session->controlVideoDevice()) + if (session && session->outputVideoDevice() + && session->outputVideoDevice()->displayMode() + == TwkApp::VideoDevice::MirrorDisplayMode) { - const TwkApp::VideoDevice* odv = session->outputVideoDevice(); - - if (odv && cdv != odv && cdv == videoDevice()) + if (const TwkApp::VideoDevice* cdv = session->controlVideoDevice()) { - const float w = width(); - const float h = height(); - const float ow = odv->width(); - const float oh = odv->height(); + const TwkApp::VideoDevice* odv = session->outputVideoDevice(); - const float aspect = w / h; - const float oaspect = ow / oh; - - m_videoDevice->translator().setRelativeDomain(ow, oh); - - if (aspect >= oaspect) + if (odv && cdv != odv && cdv == videoDevice()) { - const float yscale = oh / h; - const float yoffset = 0.0; - const float xscale = yscale; - const float xoffset = -(w * yscale - ow) / 2.0; - m_videoDevice->translator().setScaleAndOffset(xoffset, yoffset, xscale, yscale); + const float w = width(); + const float h = height(); + const float ow = odv->width(); + const float oh = odv->height(); + + const float aspect = w / h; + const float oaspect = ow / oh; + + m_videoDevice->translator().setRelativeDomain(ow, oh); + + if (aspect >= oaspect) + { + const float yscale = oh / h; + const float yoffset = 0.0; + const float xscale = yscale; + const float xoffset = -(w * yscale - ow) / 2.0; + m_videoDevice->translator().setScaleAndOffset( + xoffset, yoffset, xscale, yscale); + } + else + { + const float xscale = ow / w; + const float xoffset = 0.0; + const float yscale = xscale; + const float yoffset = -(xscale * h - oh) / 2.0; + m_videoDevice->translator().setScaleAndOffset( + xoffset, yoffset, xscale, yscale); + } } else { - const float xscale = ow / w; - const float xoffset = 0.0; - const float yscale = xscale; - const float yoffset = -(xscale * h - oh) / 2.0; - m_videoDevice->translator().setScaleAndOffset(xoffset, yoffset, xscale, yscale); + m_videoDevice->translator().setScaleAndOffset(0, 0, 1.0, + 1.0); + m_videoDevice->translator().setRelativeDomain(width(), + height()); } } else { m_videoDevice->translator().setScaleAndOffset(0, 0, 1.0, 1.0); - m_videoDevice->translator().setRelativeDomain(width(), height()); + m_videoDevice->translator().setRelativeDomain(width(), + height()); } } else { - m_videoDevice->translator().setScaleAndOffset(0, 0, 1.0, 1.0); - m_videoDevice->translator().setRelativeDomain(width(), height()); + m_videoDevice->translator().setScaleAndOffset(0, 0, 1.0, 1.0); + m_videoDevice->translator().setRelativeDomain(width(), height()); } - } - else - { - m_videoDevice->translator().setScaleAndOffset(0, 0, 1.0, 1.0); - m_videoDevice->translator().setRelativeDomain(width(), height()); - } - if (session) session->setEventVideoDevice(videoDevice()); + if (session) + session->setEventVideoDevice(videoDevice()); - if (m_videoDevice->translator().sendQTEvent(event, activationTime)) - { - event->accept(); - return true; - } - else - { - bool result = QGLWidget::event(event); + if (m_videoDevice->translator().sendQTEvent(event, activationTime)) + { + event->accept(); + return true; + } + else + { + bool result = QGLWidget::event(event); - return result; + return result; + } } -} -bool -GLView::eventFilter(QObject *object, QEvent *event) -{ - if (event->type() == QEvent::KeyPress || - event->type() == QEvent::KeyRelease || - event->type() == QEvent::Shortcut || - event->type() == QEvent::ShortcutOverride) + bool GLView::eventFilter(QObject* object, QEvent* event) { + if (event->type() == QEvent::KeyPress + || event->type() == QEvent::KeyRelease + || event->type() == QEvent::Shortcut + || event->type() == QEvent::ShortcutOverride) + { - // - // Get around really annoying event bugs on Qt/Mac - // (copied from GLView::event... same bug applies -lo) - // - // Qt 4.3.3 (4.5 too) will give both override and press events even if - // key is not in menu. Filter that here. - // - // Remember the new key/type, otherwise we filter out - // any number of ShortcutOverride/Press pairs, and - // auto-repeat doesn't work. - // + // + // Get around really annoying event bugs on Qt/Mac + // (copied from GLView::event... same bug applies -lo) + // + // Qt 4.3.3 (4.5 too) will give both override and press events even + // if key is not in menu. Filter that here. + // + // Remember the new key/type, otherwise we filter out + // any number of ShortcutOverride/Press pairs, and + // auto-repeat doesn't work. + // - if (QKeyEvent* kevent = dynamic_cast(event)) - { - if (m_lastKey == kevent->key() && - (m_lastKeyType == QEvent::ShortcutOverride && - (kevent->type() == QEvent::KeyPress) || - (m_lastKeyType == kevent->type()))) + if (QKeyEvent* kevent = dynamic_cast(event)) { - m_lastKey = kevent->key(); + if (m_lastKey == kevent->key() + && (m_lastKeyType == QEvent::ShortcutOverride + && (kevent->type() == QEvent::KeyPress) + || (m_lastKeyType == kevent->type()))) + { + m_lastKey = kevent->key(); + m_lastKeyType = kevent->type(); + + event->accept(); + return true; + } + m_lastKeyType = kevent->type(); + m_lastKey = kevent->key(); + } + + // if (m_frameBuffer->translator().sendQTEvent(event)) + Session* session = m_doc->session(); + session->setEventVideoDevice(videoDevice()); + if (m_videoDevice->translator().sendQTEvent(event)) + { event->accept(); return true; } - m_lastKeyType = kevent->type(); - m_lastKey = kevent->key(); - } - - //if (m_frameBuffer->translator().sendQTEvent(event)) - Session* session = m_doc->session(); - session->setEventVideoDevice(videoDevice()); - if (m_videoDevice->translator().sendQTEvent(event)) - { - event->accept(); return true; } - event->accept(); - return true; + return false; } - return false; -} - - -} // Rv +} // namespace Rv diff --git a/src/lib/app/RvCommon/InitGL.cpp b/src/lib/app/RvCommon/InitGL.cpp index d36d3077b..6413865d2 100644 --- a/src/lib/app/RvCommon/InitGL.cpp +++ b/src/lib/app/RvCommon/InitGL.cpp @@ -1,28 +1,27 @@ // -// Copyright (C) 2023 Autodesk, Inc. All Rights Reserved. -// -// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2023 Autodesk, Inc. All Rights Reserved. +// +// SPDX-License-Identifier: Apache-2.0 // #include #include -namespace Rv { -using namespace std; - -void -initializeGLExtensions() +namespace Rv { + using namespace std; + + void initializeGLExtensions() + { #ifdef TWK_USE_GLEW - GLenum err = glewInit(NULL); + GLenum err = glewInit(NULL); - if (GLEW_OK != err) - { - cout << "ERROR: glew init failed in RvCommon" << endl; - abort(); - } + if (GLEW_OK != err) + { + cout << "ERROR: glew init failed in RvCommon" << endl; + abort(); + } #endif -} - -} + } +} // namespace Rv diff --git a/src/lib/app/RvCommon/MediaDirModel.cpp b/src/lib/app/RvCommon/MediaDirModel.cpp index 0863cf013..1023c6120 100644 --- a/src/lib/app/RvCommon/MediaDirModel.cpp +++ b/src/lib/app/RvCommon/MediaDirModel.cpp @@ -1,9 +1,9 @@ // -// Copyright (c) 2008 Tweak Software. +// Copyright (c) 2008 Tweak Software. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// // #include #include @@ -17,689 +17,856 @@ #include #if 0 -#define DB_ICON 0x01 -#define DB_ALL 0xff +#define DB_ICON 0x01 +#define DB_ALL 0xff // #define DB_LEVEL (DB_ALL & (~ DB_ICON)) -#define DB_LEVEL DB_ALL +#define DB_LEVEL DB_ALL -#define DB(x) cerr << x << endl; -#define DBL(level, x) if (level & DB_LEVEL) cerr << x << endl; +#define DB(x) cerr << x << endl; +#define DBL(level, x) \ + if (level & DB_LEVEL) \ + cerr << x << endl; #else #define DB(x) #define DBL(level, x) #endif - -namespace Rv { -using namespace std; -using namespace TwkMovie; -using namespace TwkFB; -using namespace TwkUtil; -using namespace TwkQtCoreUtil; - -// -// On Windows, we may end up with a mix of cases, some from FS, some from -// user typing, etc. We should always compare without regard for case. -// -static bool qstringEQ(const QString &s1, const QString &s2) +namespace Rv { - #ifdef PLATFORM_WINDOWS - return 0 == QString::compare(s1, s2, Qt::CaseInsensitive); - #else - return 0 == QString::compare(s1, s2, Qt::CaseSensitive); - #endif -} - -struct MediaDirItem -{ - MediaDirItem(const QFileInfo& i, - unsigned int detail, - unsigned int hidden, - unsigned int sortFlags, - const FileTypeTraits* traits, - size_t m_fileTraitsIndex, - MediaDirItem* p); - ~MediaDirItem(); - - void populate(); - int rows(); - int row(); - bool hasChildren(); - - QFileInfo info; - QIcon icon; - QList children; - MediaDirItem* parent; - QList data; - bool populated : 1; - bool iconed : 1; - unsigned int hidden : 1; - unsigned int detail : 2; - unsigned int sortFlags : 8; - - const FileTypeTraits* m_fileTraits; - size_t m_fileTraitsIndex; -}; - -namespace { - -void -fillData (QList& data, QFileInfo* fi) -{ - if (fi) + using namespace std; + using namespace TwkMovie; + using namespace TwkFB; + using namespace TwkUtil; + using namespace TwkQtCoreUtil; + + // + // On Windows, we may end up with a mix of cases, some from FS, some from + // user typing, etc. We should always compare without regard for case. + // + static bool qstringEQ(const QString& s1, const QString& s2) { - const auto path = UTF8::qconvert(fi->absoluteFilePath()); - - data << fi->owner() - << fi->size() - << (QString(TwkUtil::isReadable(path.c_str()) ? "r" : "-") - + QString(TwkUtil::isWritable(path.c_str()) ? "w" : "-")) - << fi->lastModified(); +#ifdef PLATFORM_WINDOWS + return 0 == QString::compare(s1, s2, Qt::CaseInsensitive); +#else + return 0 == QString::compare(s1, s2, Qt::CaseSensitive); +#endif } - else data << QString() << QString() << QString() << QString(); -} - -}; - -MediaDirItem::MediaDirItem(const QFileInfo& i, - unsigned int d, - unsigned int h, - unsigned int s, - const FileTypeTraits* traits, - size_t fileTraitsIndex, - MediaDirItem* p) - : info(i), - parent(p), - populated(false), - iconed(false), - sortFlags(s), - detail(d), - m_fileTraits(traits), - m_fileTraitsIndex(fileTraitsIndex), - hidden(h) -{ - if (parent) + + struct MediaDirItem + { + MediaDirItem(const QFileInfo& i, unsigned int detail, + unsigned int hidden, unsigned int sortFlags, + const FileTypeTraits* traits, size_t m_fileTraitsIndex, + MediaDirItem* p); + ~MediaDirItem(); + + void populate(); + int rows(); + int row(); + bool hasChildren(); + + QFileInfo info; + QIcon icon; + QList children; + MediaDirItem* parent; + QList data; + bool populated : 1; + bool iconed : 1; + unsigned int hidden : 1; + unsigned int detail : 2; + unsigned int sortFlags : 8; + + const FileTypeTraits* m_fileTraits; + size_t m_fileTraitsIndex; + }; + + namespace { - QString file = info.absoluteFilePath(); - string sfile = UTF8::qconvert(file); - data << info.fileName(); - switch (detail) + void fillData(QList& data, QFileInfo* fi) + { + if (fi) + { + const auto path = UTF8::qconvert(fi->absoluteFilePath()); + + data << fi->owner() << fi->size() + << (QString(TwkUtil::isReadable(path.c_str()) ? "r" : "-") + + QString(TwkUtil::isWritable(path.c_str()) ? "w" + : "-")) + << fi->lastModified(); + } + else + data << QString() << QString() << QString() << QString(); + } + + }; // namespace + + MediaDirItem::MediaDirItem(const QFileInfo& i, unsigned int d, + unsigned int h, unsigned int s, + const FileTypeTraits* traits, + size_t fileTraitsIndex, MediaDirItem* p) + : info(i) + , parent(p) + , populated(false) + , iconed(false) + , sortFlags(s) + , detail(d) + , m_fileTraits(traits) + , m_fileTraitsIndex(fileTraitsIndex) + , hidden(h) + { + if (parent) { - case 0: - break; - case 1: - { - if (info.exists()) fillData(data, &info); - else - { - ExistingFileList files = existingFilesInSequence(UTF8::qconvert(info.absoluteFilePath())); - - if (files.size()) - { - QDir dir = parent->info.absoluteDir(); - QFileInfo fi = QFileInfo(dir.absoluteFilePath(UTF8::qconvert(files.back().name))); - fillData (data, &fi); - } - else fillData (data, 0); - } - } - break; - case 2: - if (!info.isDir()) - { - if (MovieReader* reader = TwkMovie::GenericIO::movieReader(sfile, false)) - { - try - { - reader->open(sfile); - MovieInfo minfo = reader->info(); - int nc = minfo.numChannels; - - QString t; - switch (minfo.dataType) - { - case TwkFB::FrameBuffer::UCHAR: t = "8i"; break; - case TwkFB::FrameBuffer::USHORT: t = "16i"; break; - case TwkFB::FrameBuffer::HALF: t = "16f"; break; - case TwkFB::FrameBuffer::FLOAT: t = "32f"; break; - case TwkFB::FrameBuffer::UINT: t = "32i"; break; - case TwkFB::FrameBuffer::DOUBLE: t = "64i"; break; - case TwkFB::FrameBuffer::PACKED_Cb8_Y8_Cr8_Y8: + QString file = info.absoluteFilePath(); + string sfile = UTF8::qconvert(file); + data << info.fileName(); + + switch (detail) + { + case 0: + break; + case 1: + { + if (info.exists()) + fillData(data, &info); + else + { + ExistingFileList files = existingFilesInSequence( + UTF8::qconvert(info.absoluteFilePath())); + + if (files.size()) + { + QDir dir = parent->info.absoluteDir(); + QFileInfo fi = QFileInfo(dir.absoluteFilePath( + UTF8::qconvert(files.back().name))); + fillData(data, &fi); + } + else + fillData(data, 0); + } + } + break; + case 2: + if (!info.isDir()) + { + if (MovieReader* reader = + TwkMovie::GenericIO::movieReader(sfile, false)) + { + try + { + reader->open(sfile); + MovieInfo minfo = reader->info(); + int nc = minfo.numChannels; + + QString t; + switch (minfo.dataType) + { + case TwkFB::FrameBuffer::UCHAR: + t = "8i"; + break; + case TwkFB::FrameBuffer::USHORT: + t = "16i"; + break; + case TwkFB::FrameBuffer::HALF: + t = "16f"; + break; + case TwkFB::FrameBuffer::FLOAT: + t = "32f"; + break; + case TwkFB::FrameBuffer::UINT: + t = "32i"; + break; + case TwkFB::FrameBuffer::DOUBLE: + t = "64i"; + break; + case TwkFB::FrameBuffer::PACKED_Cb8_Y8_Cr8_Y8: case TwkFB::FrameBuffer::PACKED_Y8_Cb8_Y8_Cr8: - t ="8i"; + t = "8i"; nc = 3; break; case TwkFB::FrameBuffer::PACKED_R10_G10_B10_X2: case TwkFB::FrameBuffer::PACKED_X2_B10_G10_R10: - t ="10i"; + t = "10i"; nc = 3; break; default: t = "?"; - } - - data << minfo.width << minfo.height << t << nc; - int nframes = minfo.end - minfo.start; - if (nframes > 0) data << minfo.fps << nframes; - } - catch (std::exception& exc) - { - DB ("MediaDirItem Exception!"); - data << "?" << "?" << "?" << "?" ; - } - } - } - break; + } + + data << minfo.width << minfo.height << t << nc; + int nframes = minfo.end - minfo.start; + if (nframes > 0) + data << minfo.fps << nframes; + } + catch (std::exception& exc) + { + DB("MediaDirItem Exception!"); + data << "?" << "?" << "?" << "?"; + } + } + } + break; + } } - } - else - { - switch (detail) + else { - case 0: - data << "Name"; - break; - case 1: - data << "Name" << "Owner" << "Size" << "Perm" << "Modified"; - break; - case 2: - data << "Name" << "Width" << "Height" << "Type" << "Ch" << "FPS" << "#Frms"; - break; + switch (detail) + { + case 0: + data << "Name"; + break; + case 1: + data << "Name" << "Owner" << "Size" << "Perm" << "Modified"; + break; + case 2: + data << "Name" << "Width" << "Height" << "Type" << "Ch" << "FPS" + << "#Frms"; + break; + } } } -} - -MediaDirItem::~MediaDirItem() -{ - for (int i=0; i < children.size(); i++) delete children[i]; -} - -void -MediaDirItem::populate() -{ - HOP_PROF_FUNC(); - if (populated) return; - DB ("MediaDirItem::populate info " << UTF8::qconvert(info.absoluteFilePath())); + MediaDirItem::~MediaDirItem() + { + for (int i = 0; i < children.size(); i++) + delete children[i]; + } - if (info.isDir()) + void MediaDirItem::populate() { - QDir dir(info.absoluteFilePath()); + HOP_PROF_FUNC(); - QDir::Filters filter = QDir::NoDotAndDotDot - | QDir::AllEntries - | QDir::System - | QDir::AllDirs - | (hidden ? QDir::Hidden : QDir::Filters(0)); + if (populated) + return; + DB("MediaDirItem::populate info " + << UTF8::qconvert(info.absoluteFilePath())); + if (info.isDir()) + { + QDir dir(info.absoluteFilePath()); + + QDir::Filters filter = QDir::NoDotAndDotDot | QDir::AllEntries + | QDir::System | QDir::AllDirs + | (hidden ? QDir::Hidden : QDir::Filters(0)); - QFileInfoList infos = dir.entryInfoList(filter, (QDir::SortFlags)sortFlags); - DB (" found files: " << infos.size()); + QFileInfoList infos = + dir.entryInfoList(filter, (QDir::SortFlags)sortFlags); + DB(" found files: " << infos.size()); #ifdef PLATFORM_DARWIN - if (!hidden && dir.isRoot()) - { - if (QFile::exists("/Volumes")) infos.push_back(QFileInfo("/Volumes")); - if (QFile::exists("/Network")) infos.push_back(QFileInfo("/Network")); - } + if (!hidden && dir.isRoot()) + { + if (QFile::exists("/Volumes")) + infos.push_back(QFileInfo("/Volumes")); + if (QFile::exists("/Network")) + infos.push_back(QFileInfo("/Network")); + } #endif - DB ("populate: " << dir.absolutePath().toUtf8().data()); - - FileNameList ifiles; + DB("populate: " << dir.absolutePath().toUtf8().data()); - for (int i=0; i < infos.size(); i++) - { - QString fname = infos[i].fileName(); - DB (" " << fname.toUtf8().data());; + FileNameList ifiles; - // - // There needs to be a more robust way to do this: in - // order to identify directories, add a / onto the end of - // the file name. the GlobalExtensionPredicate will force - // sequencesInFileList to ignore those when grouping - // names together. - // + for (int i = 0; i < infos.size(); i++) + { + QString fname = infos[i].fileName(); + DB(" " << fname.toUtf8().data()); + ; - if (infos[i].isDir()) fname += "/"; - DB (" pushing info #" << i << " " << fname.toUtf8().data());; - ifiles.push_back(fname.toUtf8().data()); - } + // + // There needs to be a more robust way to do this: in + // order to identify directories, add a / onto the end of + // the file name. the GlobalExtensionPredicate will force + // sequencesInFileList to ignore those when grouping + // names together. + // - SequenceNameList seqs = sequencesInFileList(ifiles, GlobalExtensionPredicate); - DB (" found sequences: " << seqs.size()); + if (infos[i].isDir()) + fname += "/"; + DB(" pushing info #" << i << " " << fname.toUtf8().data()); + ; + ifiles.push_back(fname.toUtf8().data()); + } - // - // _don't_ use canonicalPath here, since this will expand symlinks. - // - QString dirName = dir.absolutePath(); - - for (int i=0; i < seqs.size(); i++) - { - string seq = seqs[i]; + SequenceNameList seqs = + sequencesInFileList(ifiles, GlobalExtensionPredicate); + DB(" found sequences: " << seqs.size()); // - // Undo our dir hack from above + // _don't_ use canonicalPath here, since this will expand symlinks. // + QString dirName = dir.absolutePath(); - if (seq[seq.size()-1] == '/') seq.erase(seq.size()-1, 1); + for (int i = 0; i < seqs.size(); i++) + { + string seq = seqs[i]; - // - // Qt 4.8 introduced a bug in using QDir::absoluteFilePath(file). - // This is a work around and likely a speed up generating the path - // directly. - // + // + // Undo our dir hack from above + // - QFileInfo sinfo(dirName + "/" + UTF8::qconvert(seq.c_str())); + if (seq[seq.size() - 1] == '/') + seq.erase(seq.size() - 1, 1); - if (sinfo.isDir() || m_fileTraits->isKnown(m_fileTraitsIndex, sinfo.absoluteFilePath())) - { - DB (" pushing seq #" << i << " " << sinfo.absoluteFilePath().toUtf8().data());; - children.push_back(new MediaDirItem(sinfo, detail, hidden, sortFlags, - m_fileTraits, m_fileTraitsIndex, - this)); - } - else - { - DB (" excluding seq #" << i << sinfo.absoluteFilePath().toUtf8().data()); + // + // Qt 4.8 introduced a bug in using + // QDir::absoluteFilePath(file). This is a work around and + // likely a speed up generating the path directly. + // + + QFileInfo sinfo(dirName + "/" + UTF8::qconvert(seq.c_str())); + + if (sinfo.isDir() + || m_fileTraits->isKnown(m_fileTraitsIndex, + sinfo.absoluteFilePath())) + { + DB(" pushing seq #" + << i << " " << sinfo.absoluteFilePath().toUtf8().data()); + ; + children.push_back(new MediaDirItem( + sinfo, detail, hidden, sortFlags, m_fileTraits, + m_fileTraitsIndex, this)); + } + else + { + DB(" excluding seq #" + << i << sinfo.absoluteFilePath().toUtf8().data()); + } } } - } - else if (!info.exists()) - { - string name = info.absoluteFilePath().toUtf8().data(); - QDir dir = info.absoluteDir(); - ExistingFileList files = existingFilesInSequence(name); - - for (int i=0; i < files.size(); i++) + else if (!info.exists()) { - QString path = dir.absoluteFilePath(files[i].name.c_str()); - QFileInfo sinfo(path); - if (sinfo.isDir() || m_fileTraits->isKnown(m_fileTraitsIndex, sinfo.absoluteFilePath())) - { - DB (" pushing file #" << i << " " << sinfo.absoluteFilePath().toUtf8().data());; - children.push_back(new MediaDirItem(sinfo, detail, hidden, sortFlags, - m_fileTraits, m_fileTraitsIndex, - this)); - } - else + string name = info.absoluteFilePath().toUtf8().data(); + QDir dir = info.absoluteDir(); + ExistingFileList files = existingFilesInSequence(name); + + for (int i = 0; i < files.size(); i++) { - DB (" excluding seq #" << i << sinfo.absoluteFilePath().toUtf8().data()); + QString path = dir.absoluteFilePath(files[i].name.c_str()); + QFileInfo sinfo(path); + if (sinfo.isDir() + || m_fileTraits->isKnown(m_fileTraitsIndex, + sinfo.absoluteFilePath())) + { + DB(" pushing file #" + << i << " " << sinfo.absoluteFilePath().toUtf8().data()); + ; + children.push_back(new MediaDirItem( + sinfo, detail, hidden, sortFlags, m_fileTraits, + m_fileTraitsIndex, this)); + } + else + { + DB(" excluding seq #" + << i << sinfo.absoluteFilePath().toUtf8().data()); + } } } - } - - populated = true; - DB (" populate() finished"); -} - -int -MediaDirItem::rows() -{ - populate(); - return children.size(); -} - -bool -MediaDirItem::hasChildren() -{ - if (populated) return children.size() != 0; - if (info.isDir() || !info.exists()) return true; - return false; -} - -int -MediaDirItem::row() -{ - return parent ? parent->children.indexOf(this) : 0; -} - -//---------------------------------------------------------------------- - -MediaDirModel::MediaDirModel(const QDir& dir, - FileTypeTraits* traits, - Details d, QObject* parent) - : QAbstractItemModel(parent), - m_detail(d), - m_root(0), - m_fileTraits(traits), - m_sortFlags(QDir::Name), - m_fileTraitsIndex(0) -{ - setDirectory(dir.absolutePath(), d); -} - -MediaDirModel::MediaDirModel(FileTypeTraits* traits, QObject* parent) - : QAbstractItemModel(parent), - m_detail(NoDetails), - m_root(0), - m_fileTraits(traits), - m_hidden(false), - m_sortFlags(QDir::Name), - m_fileTraitsIndex(0) -{ -} -MediaDirModel::~MediaDirModel() -{ - delete m_root; - delete m_fileTraits; -} - -void -MediaDirModel::setFileTraitsIndex(size_t i) -{ - m_fileTraitsIndex = i; - reload(); - layoutChanged(); // this will force a redraw of the view -} + populated = true; + DB(" populate() finished"); + } -void -MediaDirModel::setFileTraits(FileTypeTraits* t) -{ - delete m_fileTraits; - m_fileTraits = t; - reload(); - layoutChanged(); // this will force a redraw of the view -} - -void -MediaDirModel::reload() -{ - if (!m_root) return; - //QString dir = m_root->info.absolutePath(); - QString dir = m_root->info.absoluteFilePath(); - delete m_root; - - //const char* c = dir.toUtf8().data(); - //const char* o = odir.toUtf8().data(); - //cout << "reload = " << c << endl; - m_root = new MediaDirItem(QFileInfo(dir), m_detail, m_hidden, m_sortFlags, - m_fileTraits, m_fileTraitsIndex, 0); - m_root->populate(); - beginResetModel(); - endResetModel(); -} - -void -MediaDirModel::setDirectory(const QDir& dir, Details d) -{ - DB ("MDM::setDirectory " << dir.absolutePath().toUtf8().data()); - delete m_root; - m_detail = d; - - // - // Make sure Qt treats this path as a directory by forcing the trailing / - // + int MediaDirItem::rows() + { + populate(); + return children.size(); + } - QString rootStr = dir.absolutePath(); - if (!rootStr.endsWith("/")) rootStr += "/"; - m_root = new MediaDirItem(QFileInfo(rootStr), - (unsigned int)d, - m_hidden, - m_sortFlags, - m_fileTraits, m_fileTraitsIndex, - 0); - DB (" new item fileName " << m_root->info.absoluteFilePath().toUtf8().data()); - DB (" calling populate()"); - m_root->populate(); - DB (" calling reset()"); - beginResetModel(); - endResetModel(); - DB ("MDM::setDirectory done"); -} - -int -MediaDirModel::columnCount(const QModelIndex& parent) const -{ - return m_root ? m_root->data.size() : 0; -} + bool MediaDirItem::hasChildren() + { + if (populated) + return children.size() != 0; + if (info.isDir() || !info.exists()) + return true; + return false; + } -QVariant -MediaDirModel::data(const QModelIndex& index, int role) const -{ - if (!m_root || !index.isValid()) return QVariant(); + int MediaDirItem::row() + { + return parent ? parent->children.indexOf(this) : 0; + } - MediaDirItem* item = !index.isValid() - ? m_root - : static_cast(index.internalPointer()); + //---------------------------------------------------------------------- - if (role == Qt::DisplayRole) + MediaDirModel::MediaDirModel(const QDir& dir, FileTypeTraits* traits, + Details d, QObject* parent) + : QAbstractItemModel(parent) + , m_detail(d) + , m_root(0) + , m_fileTraits(traits) + , m_sortFlags(QDir::Name) + , m_fileTraitsIndex(0) { - if (item->data.size() > index.column()) return item->data[index.column()]; - else return QVariant(); + setDirectory(dir.absolutePath(), d); } - else if (index.column() == 0 && role == Qt::DecorationRole) - { - if (!item->iconed) - { - item->iconed = true; - if (!item->info.exists()) - { - QString name = firstFileInPattern(item->info.absoluteFilePath().toUtf8().data()).c_str(); - QFileInfo ninfo(item->info.absoluteDir().absoluteFilePath(name)); - item->icon = m_fileTraits->fileInfoIcon(ninfo); - } - else - { - item->icon = m_fileTraits->fileInfoIcon(item->info); - } - } - - return item->icon; + MediaDirModel::MediaDirModel(FileTypeTraits* traits, QObject* parent) + : QAbstractItemModel(parent) + , m_detail(NoDetails) + , m_root(0) + , m_fileTraits(traits) + , m_hidden(false) + , m_sortFlags(QDir::Name) + , m_fileTraitsIndex(0) + { } - else if (index.column() == 0 && role == Qt::UserRole) + + MediaDirModel::~MediaDirModel() { - return QVariant(item->info.absoluteFilePath()); + delete m_root; + delete m_fileTraits; } - else if (index.column() == 0 && role == Qt::ForegroundRole) + + void MediaDirModel::setFileTraitsIndex(size_t i) { - // if (!item->info.isDir() && - // !m_fileTraits->isKnown(m_fileTraitsIndex, item->info.absoluteFilePath())) - // { - // return QVariant(QBrush(QColor(128, 128, 128, 255))); - // } + m_fileTraitsIndex = i; + reload(); + layoutChanged(); // this will force a redraw of the view + } - return QVariant(); + void MediaDirModel::setFileTraits(FileTypeTraits* t) + { + delete m_fileTraits; + m_fileTraits = t; + reload(); + layoutChanged(); // this will force a redraw of the view } - else + + void MediaDirModel::reload() { - return QVariant(); + if (!m_root) + return; + // QString dir = m_root->info.absolutePath(); + QString dir = m_root->info.absoluteFilePath(); + delete m_root; + + // const char* c = dir.toUtf8().data(); + // const char* o = odir.toUtf8().data(); + // cout << "reload = " << c << endl; + m_root = + new MediaDirItem(QFileInfo(dir), m_detail, m_hidden, m_sortFlags, + m_fileTraits, m_fileTraitsIndex, 0); + m_root->populate(); + beginResetModel(); + endResetModel(); } -} -QModelIndex -MediaDirModel::index(int row, - int column, - const QModelIndex& i) const -{ - if (!m_root || !hasIndex(row, column, i)) return QModelIndex(); + void MediaDirModel::setDirectory(const QDir& dir, Details d) + { + DB("MDM::setDirectory " << dir.absolutePath().toUtf8().data()); + delete m_root; + m_detail = d; - MediaDirItem* p = !i.isValid() - ? m_root - : static_cast(i.internalPointer()); + // + // Make sure Qt treats this path as a directory by forcing the trailing + // / + // - MediaDirItem* c = p->children[row]; - return c ? createIndex(row, column, c) : QModelIndex(); -} + QString rootStr = dir.absolutePath(); + if (!rootStr.endsWith("/")) + rootStr += "/"; + m_root = + new MediaDirItem(QFileInfo(rootStr), (unsigned int)d, m_hidden, + m_sortFlags, m_fileTraits, m_fileTraitsIndex, 0); + DB(" new item fileName " + << m_root->info.absoluteFilePath().toUtf8().data()); + DB(" calling populate()"); + m_root->populate(); + DB(" calling reset()"); + beginResetModel(); + endResetModel(); + DB("MDM::setDirectory done"); + } -QModelIndex -MediaDirModel::parent(const QModelIndex & index) const -{ - if (m_root && index.isValid()) + int MediaDirModel::columnCount(const QModelIndex& parent) const { - MediaDirItem* item = static_cast(index.internalPointer()); - if (item->parent == m_root || item->parent == 0) return QModelIndex(); - return createIndex(item->parent->row(), 0, item->parent); + return m_root ? m_root->data.size() : 0; } - else + + QVariant MediaDirModel::data(const QModelIndex& index, int role) const { - return QModelIndex(); - } -} + if (!m_root || !index.isValid()) + return QVariant(); -int -MediaDirModel::rowCount(const QModelIndex & index) const -{ - if (!m_root || index.column() > 0) return 0; + MediaDirItem* item = + !index.isValid() + ? m_root + : static_cast(index.internalPointer()); - MediaDirItem* item = !index.isValid() - ? m_root - : static_cast(index.internalPointer()); + if (role == Qt::DisplayRole) + { + if (item->data.size() > index.column()) + return item->data[index.column()]; + else + return QVariant(); + } + else if (index.column() == 0 && role == Qt::DecorationRole) + { + if (!item->iconed) + { + item->iconed = true; - return item->rows(); -} + if (!item->info.exists()) + { + QString name = + firstFileInPattern( + item->info.absoluteFilePath().toUtf8().data()) + .c_str(); + QFileInfo ninfo( + item->info.absoluteDir().absoluteFilePath(name)); + item->icon = m_fileTraits->fileInfoIcon(ninfo); + } + else + { + item->icon = m_fileTraits->fileInfoIcon(item->info); + } + } -QVariant -MediaDirModel::headerData(int section, - Qt::Orientation orientation, - int role) const -{ - if (m_root && orientation == Qt::Horizontal && role == Qt::DisplayRole) - { - return m_root->data[section]; + return item->icon; + } + else if (index.column() == 0 && role == Qt::UserRole) + { + return QVariant(item->info.absoluteFilePath()); + } + else if (index.column() == 0 && role == Qt::ForegroundRole) + { + // if (!item->info.isDir() && + // !m_fileTraits->isKnown(m_fileTraitsIndex, + // item->info.absoluteFilePath())) + // { + // return QVariant(QBrush(QColor(128, 128, 128, 255))); + // } + + return QVariant(); + } + else + { + return QVariant(); + } } - else + + QModelIndex MediaDirModel::index(int row, int column, + const QModelIndex& i) const { - return QVariant(); - } -} + if (!m_root || !hasIndex(row, column, i)) + return QModelIndex(); -bool -MediaDirModel::hasChildren(const QModelIndex& index) const -{ - if (!m_root || index.column() > 0) return 0; + MediaDirItem* p = !i.isValid() + ? m_root + : static_cast(i.internalPointer()); - MediaDirItem* item = !index.isValid() - ? m_root - : static_cast(index.internalPointer()); + MediaDirItem* c = p->children[row]; + return c ? createIndex(row, column, c) : QModelIndex(); + } - return item->hasChildren(); -} + QModelIndex MediaDirModel::parent(const QModelIndex& index) const + { + if (m_root && index.isValid()) + { + MediaDirItem* item = + static_cast(index.internalPointer()); + if (item->parent == m_root || item->parent == 0) + return QModelIndex(); + return createIndex(item->parent->row(), 0, item->parent); + } + else + { + return QModelIndex(); + } + } -QString -MediaDirModel::absoluteFilePath(const QModelIndex& index) const -{ - if (!m_root || index.column() > 0) return 0; + int MediaDirModel::rowCount(const QModelIndex& index) const + { + if (!m_root || index.column() > 0) + return 0; - MediaDirItem* item = !index.isValid() - ? m_root - : static_cast(index.internalPointer()); + MediaDirItem* item = + !index.isValid() + ? m_root + : static_cast(index.internalPointer()); - return item->info.absoluteFilePath(); -} + return item->rows(); + } -Qt::ItemFlags -MediaDirModel::flags(const QModelIndex &index) const -{ - Qt::ItemFlags defaultFlags = QAbstractItemModel::flags(index); - - if (m_root && index.column() == 0) + QVariant MediaDirModel::headerData(int section, Qt::Orientation orientation, + int role) const { - if (index.isValid()) + if (m_root && orientation == Qt::Horizontal && role == Qt::DisplayRole) { - MediaDirItem* item = static_cast(index.internalPointer()); - - if (!item->info.isDir() && - !m_fileTraits->isKnown(m_fileTraitsIndex, item->info.absoluteFilePath())) - { - return Qt::NoItemFlags; - } - - return Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | defaultFlags; + return m_root->data[section]; } else { - return Qt::ItemIsDropEnabled | defaultFlags; + return QVariant(); } } - else + + bool MediaDirModel::hasChildren(const QModelIndex& index) const { - return defaultFlags; + if (!m_root || index.column() > 0) + return 0; + + MediaDirItem* item = + !index.isValid() + ? m_root + : static_cast(index.internalPointer()); + + return item->hasChildren(); } -} -QModelIndex -MediaDirModel::indexOfPath(const QFileInfo& info) -{ - DB ("MDM::indexOfPath " << info.absoluteFilePath().toUtf8().data()); - if (!m_root || !info.exists()) + QString MediaDirModel::absoluteFilePath(const QModelIndex& index) const { - DB (" returning from indexOfPath() 1"); - return QModelIndex(); + if (!m_root || index.column() > 0) + return 0; + + MediaDirItem* item = + !index.isValid() + ? m_root + : static_cast(index.internalPointer()); + + return item->info.absoluteFilePath(); } - DB (" columnCount() " << columnCount()); - if (info.isRoot()) + Qt::ItemFlags MediaDirModel::flags(const QModelIndex& index) const { - if (! qstringEQ (info.absoluteFilePath(), m_root->info.absoluteFilePath())) + Qt::ItemFlags defaultFlags = QAbstractItemModel::flags(index); + + if (m_root && index.column() == 0) { - DB (" root differs -- setting dir"); - setDirectory(info.absoluteFilePath(), Details(m_root->detail)); - return createIndex(m_root->row(), 0, m_root); + if (index.isValid()) + { + MediaDirItem* item = + static_cast(index.internalPointer()); + + if (!item->info.isDir() + && !m_fileTraits->isKnown(m_fileTraitsIndex, + item->info.absoluteFilePath())) + { + return Qt::NoItemFlags; + } + + return Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled + | defaultFlags; + } + else + { + return Qt::ItemIsDropEnabled | defaultFlags; + } } else { - DB (" returning from indexOfPath() 2"); - return createIndex(m_root->row(), 0, m_root); + return defaultFlags; } } - MediaDirItem* item = m_root; - if (1 == columnCount()) - // - // Then we're attached to a columnView, and we want to reset - // m_root only if the actual root changes (IE we were in "c:/" - // and now were'e in "//" or something") - // + QModelIndex MediaDirModel::indexOfPath(const QFileInfo& info) { - QDir dir (info.absoluteFilePath()); - QStringList parts; - do + DB("MDM::indexOfPath " << info.absoluteFilePath().toUtf8().data()); + if (!m_root || !info.exists()) { - DB (" pushing " << dir.dirName().toUtf8().data()); - parts.push_front (dir.dirName()); - dir.cdUp(); + DB(" returning from indexOfPath() 1"); + return QModelIndex(); } - while (!dir.isRoot()); + DB(" columnCount() " << columnCount()); + if (info.isRoot()) + { + if (!qstringEQ(info.absoluteFilePath(), + m_root->info.absoluteFilePath())) + { + DB(" root differs -- setting dir"); + setDirectory(info.absoluteFilePath(), Details(m_root->detail)); + return createIndex(m_root->row(), 0, m_root); + } + else + { + DB(" returning from indexOfPath() 2"); + return createIndex(m_root->row(), 0, m_root); + } + } + + MediaDirItem* item = m_root; + if (1 == columnCount()) // - // Make sure this path is compared as a directory by forcing the - // trailing / + // Then we're attached to a columnView, and we want to reset + // m_root only if the actual root changes (IE we were in "c:/" + // and now were'e in "//" or something") // + { + QDir dir(info.absoluteFilePath()); + QStringList parts; + do + { + DB(" pushing " << dir.dirName().toUtf8().data()); + parts.push_front(dir.dirName()); + dir.cdUp(); + } while (!dir.isRoot()); + + // + // Make sure this path is compared as a directory by forcing the + // trailing / + // - QString dirPath(dir.absolutePath()); - if (!dirPath.endsWith("/")) dirPath += "/"; - DB (" dir is at " << dirPath.toUtf8().data()); + QString dirPath(dir.absolutePath()); + if (!dirPath.endsWith("/")) + dirPath += "/"; + DB(" dir is at " << dirPath.toUtf8().data()); - if (! qstringEQ (m_root->info.absoluteFilePath(), dirPath)) - { - DB (" not at correct root -- setting dir") - DB (" m_root is at " << UTF8::qconvert(m_root->info.absoluteFilePath())); - DB (" new root is " << UTF8::qconvert(dirPath)); - setDirectory (dirPath, Details(m_root->detail)); - return createIndex(m_root->row(), 0, m_root); - } + if (!qstringEQ(m_root->info.absoluteFilePath(), dirPath)) + { + DB(" not at correct root -- setting dir") + DB(" m_root is at " + << UTF8::qconvert(m_root->info.absoluteFilePath())); + DB(" new root is " << UTF8::qconvert(dirPath)); + setDirectory(dirPath, Details(m_root->detail)); + return createIndex(m_root->row(), 0, m_root); + } - for (int i=0; i < parts.size(); i++) + for (int i = 0; i < parts.size(); i++) + { + MediaDirItem* matchItem = 0; + item->populate(); + QString p1 = parts[i]; + DB(" part " << i << ": " << UTF8::qconvert(p1)); + DB(" item " + << UTF8::qconvert(item->info.absoluteFilePath())); + DB(" has children " << item->hasChildren()); + + for (int q = 0; !matchItem && q < item->children.size(); q++) + { + MediaDirItem* child = item->children[q]; + + if (qstringEQ(child->info.fileName(), p1)) + { + DB(" child matches"); + matchItem = child; + } + else if (!child->info.exists()) + { + // + // This is a sequence + // + DB(" child " + << UTF8::qconvert(child->info.absoluteFilePath()) + << " does not exist, assumint it is a sequence"); + for (int j = 0; + !matchItem && j < child->children.size(); j++) + { + MediaDirItem* gchild = child->children[j]; + + if (qstringEQ(gchild->info.fileName(), p1)) + { + DB(" gchild matches"); + matchItem = gchild; + } + } + } + } + + if (!matchItem) + { + // + // Check for a "hidden" (in the Qt sense) directory + // + + if (item->info.isDir()) + { + QDir idir(item->info.absoluteFilePath()); + + if (idir.exists(p1)) + { + // + // Add a child for the hidden item + // + + QFileInfo sinfo(idir.absoluteFilePath(p1)); + item->children.push_back(new MediaDirItem( + sinfo, item->detail, item->hidden, + item->sortFlags, m_fileTraits, + m_fileTraitsIndex, item)); + DB(" hidden match"); + matchItem = item->children.back(); + } + } + } + + if (!matchItem) + { + // + // Not necessarily an error to not find a match, since + // this may be a partial sequence spec, and there for + // not appearing in the lists. + // + // Note that all callers of this method should be + // checking isValid() on the returned index. + // + /* + cerr << "ERROR: MediaDirItem::" << __FUNCTION__ << endl; + cerr << "ERROR: dir = " << + dir.absolutePath().toUtf8().data() << endl; cerr << "ERROR: + info = " << info.absoluteFilePath().toUtf8().data() << endl; + cerr << "ERROR: parts.size() = " << parts.size() << + endl; cerr << "ERROR: i = " << i << endl; + */ + DB(" no match found, returning"); + return QModelIndex(); + } + + item = matchItem; + } + } + else + // + // We're attached to a non-columnView, so we want to rese + // m_root if the incoming dir is not equal to that of m_root. + // { + QString dirPath = + info.isDir() ? info.absoluteFilePath() : info.absolutePath(); + + // + // Make sure this path is compared as a directory by forcing the + // trailing / + // + + if (!dirPath.endsWith("/")) + dirPath += "/"; + + if (!qstringEQ(m_root->info.absoluteFilePath(), dirPath)) + { + DB(" not at correct root -- setting dir") + DB(" m_root is at " + << m_root->info.absoluteFilePath().toUtf8().data()); + DB(" new root is " << dirPath.toUtf8().data()); + setDirectory(dirPath, Details(m_root->detail)); + } + // + // At this point m_root should be set to the dir part of the + // incomming path, or to the path itself if it's a dir. + // So we just need to find the baseName in this dir. + // + // But if this is a dir, we won't find the baseName + // (because it's the dir) so just return the default index. + + if (info.isDir()) + return QModelIndex(); + + item = 0; MediaDirItem* matchItem = 0; - item->populate(); - QString p1 = parts[i]; - DB (" part " << i << ": " << UTF8::qconvert(p1)); - DB (" item " << UTF8::qconvert(item->info.absoluteFilePath())); - DB (" has children " << item->hasChildren()); - - for (int q=0; !matchItem && q < item->children.size(); q++) + QString baseName = info.fileName(); + DB(" baseName " << baseName.toUtf8().data()); + m_root->populate(); + + for (int q = 0; !matchItem && q < m_root->children.size(); q++) { - MediaDirItem* child = item->children[q]; + MediaDirItem* child = m_root->children[q]; + DB(" child[" << q << "] " + << child->info.fileName().toUtf8().data()); - if (qstringEQ (child->info.fileName(), p1)) + if (qstringEQ(child->info.fileName(), baseName)) { - DB (" child matches"); matchItem = child; } else if (!child->info.exists()) @@ -707,14 +874,14 @@ MediaDirModel::indexOfPath(const QFileInfo& info) // // This is a sequence // - DB (" child " << UTF8::qconvert(child->info.absoluteFilePath()) << " does not exist, assumint it is a sequence"); - for (int j=0; !matchItem && j < child->children.size(); j++) + + for (int j = 0; !matchItem && j < child->children.size(); + j++) { MediaDirItem* gchild = child->children[j]; - if (qstringEQ (gchild->info.fileName(), p1)) + if (qstringEQ(gchild->info.fileName(), baseName)) { - DB (" gchild matches"); matchItem = gchild; } } @@ -727,25 +894,22 @@ MediaDirModel::indexOfPath(const QFileInfo& info) // Check for a "hidden" (in the Qt sense) directory // - if (item->info.isDir()) + if (m_root->info.isDir()) { - QDir idir(item->info.absoluteFilePath()); + QDir idir(m_root->info.absoluteFilePath()); - if (idir.exists(p1)) + if (idir.exists(baseName)) { // // Add a child for the hidden item // - QFileInfo sinfo(idir.absoluteFilePath(p1)); - item->children.push_back(new MediaDirItem(sinfo, - item->detail, - item->hidden, - item->sortFlags, - m_fileTraits, m_fileTraitsIndex, - item)); - DB (" hidden match"); - matchItem = item->children.back(); + QFileInfo sinfo(idir.absoluteFilePath(baseName)); + m_root->children.push_back(new MediaDirItem( + sinfo, m_root->detail, m_root->hidden, + m_root->sortFlags, m_fileTraits, m_fileTraitsIndex, + m_root)); + matchItem = m_root->children.back(); } } } @@ -756,181 +920,64 @@ MediaDirModel::indexOfPath(const QFileInfo& info) // Not necessarily an error to not find a match, since // this may be a partial sequence spec, and there for // not appearing in the lists. - // + // // Note that all callers of this method should be // checking isValid() on the returned index. // /* cerr << "ERROR: MediaDirItem::" << __FUNCTION__ << endl; - cerr << "ERROR: dir = " << dir.absolutePath().toUtf8().data() << endl; - cerr << "ERROR: info = " << info.absoluteFilePath().toUtf8().data() << endl; - cerr << "ERROR: parts.size() = " << parts.size() << endl; - cerr << "ERROR: i = " << i << endl; + cerr << "ERROR: dir = " << + dir.absolutePath().toUtf8().data() << endl; cerr << "ERROR: info + = " << info.absoluteFilePath().toUtf8().data() << endl; cerr << + "ERROR: parts.size() = " << parts.size() << endl; cerr << + "ERROR: i = " << i << endl; */ - DB (" no match found, returning"); return QModelIndex(); } - item = matchItem; } - } - else - // - // We're attached to a non-columnView, so we want to rese - // m_root if the incoming dir is not equal to that of m_root. - // - { - QString dirPath = info.isDir() ? info.absoluteFilePath() : info.absolutePath(); - - // - // Make sure this path is compared as a directory by forcing the - // trailing / - // - - if (!dirPath.endsWith("/")) dirPath += "/"; - - if (! qstringEQ (m_root->info.absoluteFilePath(), dirPath)) - { - DB (" not at correct root -- setting dir") - DB (" m_root is at " << m_root->info.absoluteFilePath().toUtf8().data()); - DB (" new root is " << dirPath.toUtf8().data()); - setDirectory (dirPath, Details(m_root->detail)); - } - // - // At this point m_root should be set to the dir part of the - // incomming path, or to the path itself if it's a dir. - // So we just need to find the baseName in this dir. - // - // But if this is a dir, we won't find the baseName - // (because it's the dir) so just return the default index. - - if (info.isDir()) - return QModelIndex(); - - item = 0; - MediaDirItem* matchItem = 0; - QString baseName = info.fileName(); - DB (" baseName " << baseName.toUtf8().data()); - m_root->populate(); - - for (int q=0; !matchItem && q < m_root->children.size(); q++) - { - MediaDirItem* child = m_root->children[q]; - DB (" child[" << q << "] " << child->info.fileName().toUtf8().data()); - if (qstringEQ (child->info.fileName(), baseName)) - { - matchItem = child; - } - else if (!child->info.exists()) - { - // - // This is a sequence - // - - for (int j=0; !matchItem && j < child->children.size(); j++) - { - MediaDirItem* gchild = child->children[j]; + DB(" match found, row " + << item->row() << " info " + << UTF8::qconvert(item->info.absoluteFilePath())); + return createIndex(item->row(), 0, item); + } - if (qstringEQ (gchild->info.fileName(), baseName)) - { - matchItem = gchild; - } - } - } - } + QMap MediaDirModel::itemData(const QModelIndex& index) const + { + QMap roles; - if (!matchItem) + if (m_root && index.column() == 0) { - // - // Check for a "hidden" (in the Qt sense) directory - // - - if (m_root->info.isDir()) + for (int i = 0; i <= Qt::UserRole; ++i) { - QDir idir(m_root->info.absoluteFilePath()); - - if (idir.exists(baseName)) - { - // - // Add a child for the hidden item - // - - QFileInfo sinfo(idir.absoluteFilePath(baseName)); - m_root->children.push_back(new MediaDirItem(sinfo, - m_root->detail, - m_root->hidden, - m_root->sortFlags, - m_fileTraits, m_fileTraitsIndex, - m_root)); - matchItem = m_root->children.back(); - } + QVariant variantData = data(index, i); + if (variantData.type() != QVariant::Invalid) + roles.insert(i, variantData); } } - if (!matchItem) - { - // - // Not necessarily an error to not find a match, since - // this may be a partial sequence spec, and there for - // not appearing in the lists. - // - // Note that all callers of this method should be - // checking isValid() on the returned index. - // - /* - cerr << "ERROR: MediaDirItem::" << __FUNCTION__ << endl; - cerr << "ERROR: dir = " << dir.absolutePath().toUtf8().data() << endl; - cerr << "ERROR: info = " << info.absoluteFilePath().toUtf8().data() << endl; - cerr << "ERROR: parts.size() = " << parts.size() << endl; - cerr << "ERROR: i = " << i << endl; - */ - return QModelIndex(); - } - item = matchItem; + return roles; } - DB (" match found, row " << item->row() << " info " << UTF8::qconvert(item->info.absoluteFilePath())); - return createIndex(item->row(), 0, item); -} - -QMap -MediaDirModel::itemData(const QModelIndex &index) const -{ - QMap roles; - - if (m_root && index.column() == 0) + void MediaDirModel::setSortFlags(QDir::SortFlags f) { - for (int i = 0; i <= Qt::UserRole; ++i) + if (m_sortFlags != f) { - QVariant variantData = data(index, i); - if (variantData.type() != QVariant::Invalid) roles.insert(i, variantData); + m_sortFlags = f; + reload(); } } - return roles; -} - -void -MediaDirModel::setSortFlags(QDir::SortFlags f) -{ - if (m_sortFlags != f) - { - m_sortFlags = f; - reload(); - } -} - -void -MediaDirModel::setShowHiddenFiles(bool b) -{ - if (m_hidden != b) + void MediaDirModel::setShowHiddenFiles(bool b) { - m_hidden = b; - if (m_root) setDirectory(m_root->info.absolutePath(), Details(m_root->detail)); + if (m_hidden != b) + { + m_hidden = b; + if (m_root) + setDirectory(m_root->info.absolutePath(), + Details(m_root->detail)); + } } -} - - -} // Rv +} // namespace Rv diff --git a/src/lib/app/RvCommon/MediaFileTypes.cpp b/src/lib/app/RvCommon/MediaFileTypes.cpp index 718b68208..fef06eac4 100644 --- a/src/lib/app/RvCommon/MediaFileTypes.cpp +++ b/src/lib/app/RvCommon/MediaFileTypes.cpp @@ -1,9 +1,9 @@ // -// Copyright (c) 2008 Tweak Software. +// Copyright (c) 2008 Tweak Software. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// // #ifdef PLATFORM_WINDOWS #ifndef WIN32_LEAN_AND_MEAN @@ -24,352 +24,363 @@ #include #include -namespace { -void addEventExts(const char* event, - IPCore::Session* session, - QStringList& exts, - QStringList& formats, - QSet extSet) +namespace { - static constexpr auto EVENT_SEP = ':'; - static constexpr auto EXT_SEP = ';'; + void addEventExts(const char* event, IPCore::Session* session, + QStringList& exts, QStringList& formats, + QSet extSet) + { + static constexpr auto EVENT_SEP = ':'; + static constexpr auto EXT_SEP = ';'; - std::istringstream filters(session->userGenericEvent(event, "")); - std::string next; + std::istringstream filters(session->userGenericEvent(event, "")); + std::string next; - while( std::getline(filters, next, EVENT_SEP)) - { - auto pos = next.find(EXT_SEP); - if( pos != std::string::npos ) + while (std::getline(filters, next, EVENT_SEP)) { - const auto subLen = pos + 1, nextLen = next.length(); - if ( subLen < nextLen && next[subLen] != EXT_SEP && next[subLen] != EVENT_SEP ) + auto pos = next.find(EXT_SEP); + if (pos != std::string::npos) { - auto ext = next.substr(0, subLen - 1); - auto format= next.substr(subLen, nextLen - subLen); - - if( !ext.empty() && !format.empty() ) + const auto subLen = pos + 1, nextLen = next.length(); + if (subLen < nextLen && next[subLen] != EXT_SEP + && next[subLen] != EVENT_SEP) { - exts.push_back(ext.c_str()); - extSet.insert(ext.c_str()); - formats.push_back(format.c_str()); + auto ext = next.substr(0, subLen - 1); + auto format = next.substr(subLen, nextLen - subLen); + + if (!ext.empty() && !format.empty()) + { + exts.push_back(ext.c_str()); + extSet.insert(ext.c_str()); + formats.push_back(format.c_str()); + } } } - } + } } -} -} - - -namespace Rv { -using namespace TwkMovie; -using namespace TwkFB; -using namespace std; - -MediaFileTypes::MediaFileTypes(bool readable, - bool writeable, - const QString& defaultExt) - : FileTypeTraits(), - m_readable(readable), - m_writeable(writeable), - m_defaultExt(defaultExt) -{ - m_formats.push_back("Any Media File"); - m_exts.push_back("&"); - - m_formats.push_back("Any File"); - m_exts.push_back("*"); - - m_formats.push_back("RV Session file"); - m_exts.push_back("rv"); - m_extSet.insert("rv"); +} // namespace - if( auto session = IPCore::Session::currentSession() ) +namespace Rv +{ + using namespace TwkMovie; + using namespace TwkFB; + using namespace std; + + MediaFileTypes::MediaFileTypes(bool readable, bool writeable, + const QString& defaultExt) + : FileTypeTraits() + , m_readable(readable) + , m_writeable(writeable) + , m_defaultExt(defaultExt) { - addEventExts("open-file-dialog-filters", session, m_exts, m_formats, m_extSet); - } + m_formats.push_back("Any Media File"); + m_exts.push_back("&"); - const TwkMovie::GenericIO::Plugins& plugins = TwkMovie::GenericIO::allPlugins(); + m_formats.push_back("Any File"); + m_exts.push_back("*"); - for (TwkMovie::GenericIO::Plugins::const_iterator i = plugins.begin(); - i != plugins.end(); - ++i) - { - const TwkMovie::MovieIO* plugin = *i; - const MovieIO::MovieTypeInfos& exts = plugin->extensionsSupported(); + m_formats.push_back("RV Session file"); + m_exts.push_back("rv"); + m_extSet.insert("rv"); - for (int q=0; q < exts.size(); q++) + if (auto session = IPCore::Session::currentSession()) { - const MovieIO::MovieTypeInfo& info = exts[q]; + addEventExts("open-file-dialog-filters", session, m_exts, m_formats, + m_extSet); + } - bool readsaudio = info.capabilities & MovieIO::MovieReadAudio; - bool readsimages = info.capabilities & MovieIO::MovieRead; - bool writesaudio = info.capabilities & MovieIO::MovieWriteAudio; - bool writesimages = info.capabilities & MovieIO::MovieWrite; + const TwkMovie::GenericIO::Plugins& plugins = + TwkMovie::GenericIO::allPlugins(); - if ((readable && !(readsaudio || readsimages)) || - (writeable && !(writesaudio || writesimages))) - { - continue; - } - - if (info.description != "") + for (TwkMovie::GenericIO::Plugins::const_iterator i = plugins.begin(); + i != plugins.end(); ++i) + { + const TwkMovie::MovieIO* plugin = *i; + const MovieIO::MovieTypeInfos& exts = plugin->extensionsSupported(); + + for (int q = 0; q < exts.size(); q++) { - if (!m_extSet.contains(info.extension.c_str())) + const MovieIO::MovieTypeInfo& info = exts[q]; + + bool readsaudio = info.capabilities & MovieIO::MovieReadAudio; + bool readsimages = info.capabilities & MovieIO::MovieRead; + bool writesaudio = info.capabilities & MovieIO::MovieWriteAudio; + bool writesimages = info.capabilities & MovieIO::MovieWrite; + + if ((readable && !(readsaudio || readsimages)) + || (writeable && !(writesaudio || writesimages))) { - m_extSet.insert(info.extension.c_str()); - ostringstream str; - str << info.description << " (" << info.extension << ")"; - m_formats.push_back(str.str().c_str()); - m_exts.push_back(info.extension.c_str()); + continue; + } + + if (info.description != "") + { + if (!m_extSet.contains(info.extension.c_str())) + { + m_extSet.insert(info.extension.c_str()); + ostringstream str; + str << info.description << " (" << info.extension + << ")"; + m_formats.push_back(str.str().c_str()); + m_exts.push_back(info.extension.c_str()); + } } } } - } - for (TwkMovie::GenericIO::Plugins::const_iterator i = plugins.begin(); - i != plugins.end(); - ++i) - { - const TwkMovie::MovieIO* plugin = *i; - const MovieIO::MovieTypeInfos& exts = plugin->extensionsSupported(); - - for (int q=0; q < exts.size(); q++) + for (TwkMovie::GenericIO::Plugins::const_iterator i = plugins.begin(); + i != plugins.end(); ++i) { - const MovieIO::MovieTypeInfo& info = exts[q]; + const TwkMovie::MovieIO* plugin = *i; + const MovieIO::MovieTypeInfos& exts = plugin->extensionsSupported(); - if ((readable && !(info.capabilities & MovieIO::MovieRead)) || - (writeable && !(info.capabilities & MovieIO::MovieWrite))) + for (int q = 0; q < exts.size(); q++) { - continue; - } + const MovieIO::MovieTypeInfo& info = exts[q]; - if (info.description == "") - { - if (!m_extSet.contains(info.extension.c_str())) + if ((readable && !(info.capabilities & MovieIO::MovieRead)) + || (writeable + && !(info.capabilities & MovieIO::MovieWrite))) { - m_extSet.insert(info.extension.c_str()); - ostringstream str; - str << "Image Format Extension" << " (" << info.extension << ")"; - m_formats.push_back(str.str().c_str()); - m_exts.push_back(info.extension.c_str()); + continue; + } + + if (info.description == "") + { + if (!m_extSet.contains(info.extension.c_str())) + { + m_extSet.insert(info.extension.c_str()); + ostringstream str; + str << "Image Format Extension" << " (" + << info.extension << ")"; + m_formats.push_back(str.str().c_str()); + m_exts.push_back(info.extension.c_str()); + } } } } } -} - -MediaFileTypes::MediaFileTypes(bool readable, - bool writeable, - const QList >& files, - const QString& defaultExt) - : FileTypeTraits(), - m_readable(readable), - m_writeable(writeable), - m_defaultExt(defaultExt) -{ - m_formats.push_back("All Relevant File Types"); - m_exts.push_back("&"); - m_formats.push_back("Any File"); - m_exts.push_back("*"); - - if( auto session = IPCore::Session::currentSession() ) + MediaFileTypes::MediaFileTypes(bool readable, bool writeable, + const QList>& files, + const QString& defaultExt) + : FileTypeTraits() + , m_readable(readable) + , m_writeable(writeable) + , m_defaultExt(defaultExt) { - addEventExts("save-file-dialog-filters", session, m_exts, m_formats, m_extSet); + m_formats.push_back("All Relevant File Types"); + m_exts.push_back("&"); + + m_formats.push_back("Any File"); + m_exts.push_back("*"); + + if (auto session = IPCore::Session::currentSession()) + { + addEventExts("save-file-dialog-filters", session, m_exts, m_formats, + m_extSet); + } + + for (size_t i = 0; i < files.size(); i++) + { + const QPair& pair = files[i]; + + m_extSet.insert(pair.first); + m_exts.push_back(pair.first); + m_formats.push_back(pair.second); + } } - for (size_t i = 0; i < files.size(); i++) + MediaFileTypes::MediaFileTypes(const MediaFileTypes* other) { - const QPair& pair = files[i]; - - m_extSet.insert(pair.first); - m_exts.push_back(pair.first); - m_formats.push_back(pair.second); + m_extSet = other->m_extSet; + m_exts = other->m_exts; + m_formats = other->m_formats; + m_readable = other->m_readable; + m_writeable = other->m_writeable; + m_defaultExt = other->m_defaultExt; } -} -MediaFileTypes::MediaFileTypes(const MediaFileTypes* other) -{ - m_extSet = other->m_extSet; - m_exts = other->m_exts; - m_formats = other->m_formats; - m_readable = other->m_readable; - m_writeable = other->m_writeable; - m_defaultExt = other->m_defaultExt; -} - -MediaFileTypes::~MediaFileTypes() -{ -} + MediaFileTypes::~MediaFileTypes() {} -size_t -MediaFileTypes::defaultIndex() const -{ - for (size_t i = 0; i < m_exts.size(); i++) + size_t MediaFileTypes::defaultIndex() const { - if (m_exts[i] == m_defaultExt) return i; - } - - return 0; -} + for (size_t i = 0; i < m_exts.size(); i++) + { + if (m_exts[i] == m_defaultExt) + return i; + } -FileTypeTraits* -MediaFileTypes::copyTraits() const -{ - return new MediaFileTypes(this); -} + return 0; + } -QStringList -MediaFileTypes::typeDescriptions() -{ - return m_formats; -} + FileTypeTraits* MediaFileTypes::copyTraits() const + { + return new MediaFileTypes(this); + } -QString -MediaFileTypes::extension(int index) -{ - return m_exts[index]; -} + QStringList MediaFileTypes::typeDescriptions() { return m_formats; } -QString -MediaFileTypes::description(int index) -{ - return m_formats[index]; -} + QString MediaFileTypes::extension(int index) { return m_exts[index]; } -bool -MediaFileTypes::isKnown(size_t index, const QString& file) const -{ - if (index >= m_exts.size()) return true; - if (m_exts[index] == "*") return true; + QString MediaFileTypes::description(int index) { return m_formats[index]; } - QString ext = file.split('.').last(); - if (m_exts[index] == "&") - { - return m_extSet.contains(ext) || - m_extSet.contains(ext.toLower()) || - m_extSet.contains("*"); - } - else + bool MediaFileTypes::isKnown(size_t index, const QString& file) const { - return m_exts[index] == ext || m_exts[index] == ext.toLower(); - } -} + if (index >= m_exts.size()) + return true; + if (m_exts[index] == "*") + return true; -QStringList -MediaFileTypes::fileAttributes(const QString& file) const -{ - QStringList list = Parent::fileAttributes(file); - string filename = file.toUtf8().data(); + QString ext = file.split('.').last(); + if (m_exts[index] == "&") + { + return m_extSet.contains(ext) || m_extSet.contains(ext.toLower()) + || m_extSet.contains("*"); + } + else + { + return m_exts[index] == ext || m_exts[index] == ext.toLower(); + } + } - try + QStringList MediaFileTypes::fileAttributes(const QString& file) const { - if (MovieReader* reader = TwkMovie::GenericIO::movieReader(filename, false)) - { - reader->open(filename); - const MovieInfo& i = reader->info(); + QStringList list = Parent::fileAttributes(file); + string filename = file.toUtf8().data(); - if (i.video) + try + { + if (MovieReader* reader = + TwkMovie::GenericIO::movieReader(filename, false)) { - QString dtype; + reader->open(filename); + const MovieInfo& i = reader->info(); - switch (i.dataType) + if (i.video) { - case FrameBuffer::UCHAR: dtype = "8 bit"; break; - case FrameBuffer::USHORT: dtype = "16 bit"; break; - case FrameBuffer::HALF: dtype = "16 bit float"; break; - case FrameBuffer::FLOAT: dtype = "32 bit float"; break; - case FrameBuffer::DOUBLE: dtype = "64 bit float"; break; - case FrameBuffer::PACKED_R10_G10_B10_X2: dtype = "10 bit packed"; break; - case FrameBuffer::PACKED_X2_B10_G10_R10: dtype = "10 bit packed"; break; - case FrameBuffer::PACKED_Y8_Cb8_Y8_Cr8: dtype = "YCbCr packed"; break; - case FrameBuffer::PACKED_Cb8_Y8_Cr8_Y8: dtype = "YCbCr packed"; break; - default: dtype = "-"; - } + QString dtype; - list << "Geometry" << QString("%1 x %2, %3 ch %4") - .arg(i.width) - .arg(i.height) - .arg(i.numChannels) - .arg(dtype); + switch (i.dataType) + { + case FrameBuffer::UCHAR: + dtype = "8 bit"; + break; + case FrameBuffer::USHORT: + dtype = "16 bit"; + break; + case FrameBuffer::HALF: + dtype = "16 bit float"; + break; + case FrameBuffer::FLOAT: + dtype = "32 bit float"; + break; + case FrameBuffer::DOUBLE: + dtype = "64 bit float"; + break; + case FrameBuffer::PACKED_R10_G10_B10_X2: + dtype = "10 bit packed"; + break; + case FrameBuffer::PACKED_X2_B10_G10_R10: + dtype = "10 bit packed"; + break; + case FrameBuffer::PACKED_Y8_Cb8_Y8_Cr8: + dtype = "YCbCr packed"; + break; + case FrameBuffer::PACKED_Cb8_Y8_Cr8_Y8: + dtype = "YCbCr packed"; + break; + default: + dtype = "-"; + } - if (i.views.size() > 1) - { - list << "Views"; - - QString views; - for (int q =0; q < i.views.size(); q++) + list << "Geometry" + << QString("%1 x %2, %3 ch %4") + .arg(i.width) + .arg(i.height) + .arg(i.numChannels) + .arg(dtype); + + if (i.views.size() > 1) { - if (q) views += ", "; - views += i.views[q].c_str(); + list << "Views"; + + QString views; + for (int q = 0; q < i.views.size(); q++) + { + if (q) + views += ", "; + views += i.views[q].c_str(); + } + + list << views; } - - list << views; - } - - if (i.layers.size() > 1) - { - list << "Layers"; - - QString layers; - for (int q =0; q < i.layers.size(); q++) + + if (i.layers.size() > 1) { - if (q) layers += ", "; - layers += i.layers[q].c_str(); + list << "Layers"; + + QString layers; + for (int q = 0; q < i.layers.size(); q++) + { + if (q) + layers += ", "; + layers += i.layers[q].c_str(); + } + + list << layers; } - list << layers; + if (i.start != i.end) + { + list << "Frames" + << QString("%1 - %2").arg(i.start).arg(i.end); + list << "FPS" << QString("%1").arg(i.fps); + } } - if (i.start != i.end) + if (i.audio) { - list << "Frames" << QString("%1 - %2").arg(i.start).arg(i.end); - list << "FPS" << QString("%1").arg(i.fps); + list << "Audio Sample Rate" + << QString("%1").arg(i.audioSampleRate); + list << "Audio Channels" + << QString("%1").arg(i.audioChannels.size()); } - } - if (i.audio) - { - list << "Audio Sample Rate" << QString("%1").arg(i.audioSampleRate); - list << "Audio Channels" << QString("%1").arg(i.audioChannels.size()); - } - - if (!i.proxy.attributes().empty()) - { - const FrameBuffer::AttributeVector& attrs = i.proxy.attributes(); - - for (int q = 0; q < attrs.size(); q++) + if (!i.proxy.attributes().empty()) { - list << attrs[q]->name().c_str(); - list << attrs[q]->valueAsString().c_str(); + const FrameBuffer::AttributeVector& attrs = + i.proxy.attributes(); + + for (int q = 0; q < attrs.size(); q++) + { + list << attrs[q]->name().c_str(); + list << attrs[q]->valueAsString().c_str(); + } } - } - delete reader; + delete reader; + } + } + catch (...) + { + list << "NOTE:" + << "File attributes cannot be read: may be damaged"; } + + return list; } - catch (...) + + QIcon MediaFileTypes::fileIcon(const QString& file) const { - list << "NOTE:" - << "File attributes cannot be read: may be damaged"; + QFileInfo info(file); + return fileInfoIcon(info); } - return list; -} - -QIcon -MediaFileTypes::fileIcon(const QString& file) const -{ - QFileInfo info(file); - return fileInfoIcon(info); -} + QIcon MediaFileTypes::fileInfoIcon(const QFileInfo& info) const + { + static QFileIconProvider provider; -QIcon -MediaFileTypes::fileInfoIcon(const QFileInfo& info) const -{ - static QFileIconProvider provider; - #if 0 if (info.isDir()) { @@ -380,35 +391,22 @@ MediaFileTypes::fileInfoIcon(const QFileInfo& info) const return provider.icon(QFileIconProvider::File); } #endif - - return provider.icon(info); -} -bool -MediaFileTypes::hasImage(const QString&) const -{ - return false; -} + return provider.icon(info); + } -QImage -MediaFileTypes::fileImage(const QString&) const -{ - return QImage(); -} - -bool -MediaFileTypes::sameAs(const FileTypeTraits* traits) const -{ - const MediaFileTypes* t = dynamic_cast(traits); - return ( (t != nullptr) && - (iconMode() == t->iconMode() ) && - (m_readable == t->m_readable ) && - (m_writeable == t->m_writeable ) && - (m_extSet == t->m_extSet ) && - (m_exts == t->m_exts ) && - (m_formats == t->m_formats ) && - (m_defaultExt == t->m_defaultExt) ); -} - - -} // Rv + bool MediaFileTypes::hasImage(const QString&) const { return false; } + + QImage MediaFileTypes::fileImage(const QString&) const { return QImage(); } + + bool MediaFileTypes::sameAs(const FileTypeTraits* traits) const + { + const MediaFileTypes* t = dynamic_cast(traits); + return ((t != nullptr) && (iconMode() == t->iconMode()) + && (m_readable == t->m_readable) + && (m_writeable == t->m_writeable) && (m_extSet == t->m_extSet) + && (m_exts == t->m_exts) && (m_formats == t->m_formats) + && (m_defaultExt == t->m_defaultExt)); + } + +} // namespace Rv diff --git a/src/lib/app/RvCommon/MuUICommands.cpp b/src/lib/app/RvCommon/MuUICommands.cpp index f2ec081ad..523009f20 100644 --- a/src/lib/app/RvCommon/MuUICommands.cpp +++ b/src/lib/app/RvCommon/MuUICommands.cpp @@ -1,8 +1,8 @@ //****************************************************************************** // Copyright (c) 2001-2005 Tweak Inc. All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #ifdef PLATFORM_WINDOWS @@ -48,7 +48,6 @@ #include #include - #include #include #include @@ -59,15 +58,15 @@ #include #include #include // WINDOWS NEEDS THIS LAST -//#include +// #include #ifdef PLATFORM_WINDOWS #undef _NTDDK_ #ifndef _WIN32_WINNT #define _WIN32_WINNT 0x0501 #define WINVER 0x0501 // both combined stand for Windows XP #endif -//#include -//#include +// #include +// #include #include #endif @@ -84,1008 +83,782 @@ #include -//#ifdef PLATFORM_DARWIN -//#define USE_NATIVE_DIALOGS -//#endif - -namespace Rv { - -using namespace TwkApp; -using namespace Mu; -using namespace std; -using namespace TwkUtil; -using namespace IPCore; -using namespace TwkQtCoreUtil; - -static void throwBadArgumentException(const Mu::Node& node, - Mu::Thread& thread, - const Mu::String& msg) -{ - ostringstream str; - const Mu::MuLangContext* context = - static_cast(thread.context()); - ExceptionType::Exception *e = - new ExceptionType::Exception(context->exceptionType()); - str << "in " << node.symbol()->fullyQualifiedName() << ": " << msg; - e->string() += str.str().c_str(); - thread.setException(e); - throw BadArgumentException(thread, e); -} - -void initUICommands() -{ - USING_MU_FUNCTION_SYMBOLS; - MuLangContext* context = muContext(); - Context* c = context; - Symbol* root = context->globalScope(); - Name cname = c->internName("commands"); - Mu::Module* commands = root->findSymbolOfType(cname); - - root->addSymbol(new qtModule(c, "qt")); - - Context::TypeVector types; - types.push_back(context->stringType()); - types.push_back(context->stringType()); - context->listType(context->tupleType(types)); - - commands->addSymbols(new Function(c, "resizeFit", resizeFit, None, - Return, "void", - End), - - new Function(c, "setViewSize", setViewSize, None, - Return, "void", - Parameters, - new Param(c, "width", "int"), - new Param(c, "height", "int"), - End), - - new Function(c, "startupResize", startupResize, None, - Return, "bool", - End), - - new Function(c, "popupMenu", popupMenu, None, - Return, "void", - Parameters, - new Param(c, "event", "Event"), - new Param(c, "menu", "MenuItem[]", Value(Pointer(0))), - End), - - new Function(c, "popupMenuAtPoint", popupMenuAtPoint, None, - Return, "void", - Parameters, - new Param(c, "x", "int"), - new Param(c, "y", "int"), - new Param(c, "menu", "MenuItem[]", Value(Pointer(0))), - End), - - new Function(c, "setWindowTitle", setWindowTitle, None, - Return, "void", - Parameters, - new Param(c, "title", "string"), - End), - - new Function(c, "center", center, None, - Return, "void", - End), - - new Function(c, "close", close, None, - Return, "void", - End), - - new Function(c, "toggleMenuBar", toggleMenuBar, None, - Return, "void", - End), - - new Function(c, "isMenuBarVisible", isMenuBarVisible, None, - Return, "bool", - End), - - new SymbolicConstant(c, "OneExistingFile", "int", Value(int(RvFileDialog::OneExistingFile))), - new SymbolicConstant(c, "ManyExistingFiles", "int", Value(int(RvFileDialog::ManyExistingFiles))), - new SymbolicConstant(c, "ManyExistingFilesAndDirectories", "int", Value(int(RvFileDialog::ManyExistingFilesAndDirectories))), - new SymbolicConstant(c, "OneFileName", "int", Value(int(RvFileDialog::OneFileName))), - new SymbolicConstant(c, "OneDirectory", "int", Value(int(RvFileDialog::OneDirectory))), - - new Function(c, "openMediaFileDialog", openMediaFileDialog, - None, - Return, "string[]", - Parameters, - new Param(c, "associated", "bool"), - new Param(c, "selectType", "int"), - new Param(c, "filter", "string", Value(Pointer(0))), - new Param(c, "defaultPath", "string", Value(Pointer(0))), - new Param(c, "label", "string", Value(Pointer(0))), - End), - - new Function(c, "openFileDialog", openFileDialog, - None, - Return, "string[]", - Parameters, - new Param(c, "associated", "bool"), - new Param(c, "multiple", "bool", Value(false)), - new Param(c, "directory", "bool", Value(false)), - new Param(c, "filter", "string", Value(Pointer(0))), - new Param(c, "defaultPath", "string", Value(Pointer(0))), - End), - - new Function(c, "saveFileDialog", saveFileDialog, - None, - Return, "string", - Parameters, - new Param(c, "associated", "bool"), - new Param(c, "filter", "string", Value(Pointer(0))), - new Param(c, "defaultPath", "string", Value(Pointer(0))), - new Param(c, "directory", "bool", Value(false)), - End), - - new SymbolicConstant(c, "CursorNone", "int", Value(int(Qt::BlankCursor))), - new SymbolicConstant(c, "CursorArrow", "int", Value(int(Qt::ArrowCursor))), - new SymbolicConstant(c, "CursorDefault", "int", Value(int(Qt::ArrowCursor))), - - new Function(c, "setCursor", setCursor, None, - Return, "void", - Parameters, - new Param(c, "cursorType", "int"), - End), - - new SymbolicConstant(c, "InfoAlert", "int", Value(0)), - new SymbolicConstant(c, "WarningAlert", "int", Value(1)), - new SymbolicConstant(c, "ErrorAlert", "int", Value(2)), - - new Function(c, "stereoSupported", stereoSupported, None, - Return, "bool", - End), - - new Function(c, "alertPanel", alertPanel, None, - Return, "int", - Parameters, - new Param(c, "associated", "bool"), - new Param(c, "type", "int"), - new Param(c, "title", "string"), - new Param(c, "message", "string"), - new Param(c, "button0", "string"), - new Param(c, "button1", "string"), - new Param(c, "button2", "string"), - End), - - new Function(c, "watchFile", watchFile, None, - Return, "void", - Parameters, - new Param(c, "filename", "string"), - new Param(c, "watch", "bool"), - End), - - new Function(c, "showNetworkDialog", showNetworkDialog, None, - Return, "void", - End), - - new Function(c, "showConsole", showConsole, None, - Return, "void", - End), - - new Function(c, "isConsoleVisible", isConsoleVisible, None, - Return, "bool", - End), - // network - - new Function(c, "remoteSendMessage", remoteSendMessage, None, - Return, "void", - Parameters, - new Param(c, "message", "string"), - new Param(c, "recipients", "string[]", Value(Pointer(0))), - End), - - new Function(c, "remoteSendEvent", remoteSendEvent, None, - Return, "void", - Parameters, - new Param(c, "event", "string"), - new Param(c, "target", "string"), - new Param(c, "contents", "string"), - new Param(c, "recipients", "string[]", Value(Pointer(0))), - End), - - new Function(c, "remoteSendDataEvent", remoteSendDataEvent, None, - Return, "void", - Parameters, - new Param(c, "event", "string"), - new Param(c, "target", "string"), - new Param(c, "interp", "string"), - new Param(c, "data", "byte[]"), - new Param(c, "recipients", "string[]"), - End), - - new Function(c, "remoteConnections", remoteConnections, None, - Return, "string[]", - End), - - new Function(c, "remoteApplications", remoteApplications, None, - Return, "string[]", - End), - - new Function(c, "remoteContacts", remoteContacts, None, - Return, "string[]", - End), - - new Function(c, "remoteLocalContactName", remoteLocalContactName, None, - Return, "string", - End), - - new Function(c, "setRemoteLocalContactName", setRemoteLocalContactName, None, - Return, "string", - Parameters, - new Param(c, "name", "string"), - End), - - new Function(c, "remoteConnect", remoteConnect, None, - Return, "void", - Parameters, - new Param(c, "name", "string"), - new Param(c, "host", "string"), - new Param(c, "port", "int", Value(0)), - End), - - new Function(c, "remoteDisconnect", remoteDisconnect, None, - Return, "void", - Parameters, - new Param(c, "remoteContact", "string"), - End), - - new Function(c, "remoteNetwork", remoteNetwork, None, - Return, "void", - Parameters, - new Param(c, "on", "bool"), - End), - - new Function(c, "remoteConnectionIsIncoming", remoteConnectionIsIncoming, None, - Return, "bool", - Parameters, - new Param(c, "connection", "string"), - End), - - new Function(c, "spoofConnectionStream", spoofConnectionStream, None, - Return, "void", - Parameters, - new Param(c, "streamFile", "string"), - new Param(c, "timeScale", "float"), - new Param(c, "verbose", "bool", Value(false)), - End), - - new SymbolicConstant(c, "NetworkStatusOn", "int", Value(1)), - new SymbolicConstant(c, "NetworkStatusOff", "int", Value(0)), - - new Function(c, "remoteNetworkStatus", remoteNetworkStatus, None, - Return, "int", - End), - - new SymbolicConstant(c, "NetworkPermissionAsk", "int", Value(int(RvNetworkDialog::AskConnect))), - new SymbolicConstant(c, "NetworkPermissionAllow", "int", Value(int(RvNetworkDialog::AllowConnect))), - new SymbolicConstant(c, "NetworkPermissionDeny", "int", Value(int(RvNetworkDialog::DenyConnect))), - - new Function(c, "remoteDefaultPermission", remoteDefaultPermission, None, - Return, "int", - End), - - new Function(c, "setRemoteDefaultPermission", setRemoteDefaultPermission, None, - Return, "void", - Parameters, - new Param(c, "permission", "int"), - End), - - new Function(c, "writeSetting", writeSetting, None, - Return, "void", - Parameters, - new Param(c, "group", "string"), - new Param(c, "name", "string"), - new Param(c, "value", "SettingsValue"), - End), - - new Function(c, "readSetting", readSetting, None, - Return, "SettingsValue", - Parameters, - new Param(c, "group", "string"), - new Param(c, "name", "string"), - new Param(c, "defaultValue", "SettingsValue"), - End), - - new Function(c, "httpGet", httpGet, None, - Return, "void", - Parameters, - new Param(c, "url", "string"), - new Param(c, "headers", "[(string,string)]"), - new Param(c, "replyEvent", "string"), - new Param(c, "authenticationEvent", "string", Value(Pointer(0))), - new Param(c, "progressEvent", "string", Value(Pointer(0))), - new Param(c, "ignoreSslErrors", "bool", Value(false)), - new Param(c, "urlIsEncoded", "bool", Value(false)), - End), - - new Function(c, "httpPost", httpPostString, None, - Return, "void", - Parameters, - new Param(c, "url", "string"), - new Param(c, "headers", "[(string,string)]"), - new Param(c, "postString", "string"), - new Param(c, "replyEvent", "string"), - new Param(c, "authenticationEvent", "string", Value(Pointer(0))), - new Param(c, "progressEvent", "string", Value(Pointer(0))), - new Param(c, "ignoreSslErrors", "bool", Value(false)), - new Param(c, "urlIsEncoded", "bool", Value(false)), - End), - - new Function(c, "httpPost", httpPostData, None, - Return, "void", - Parameters, - new Param(c, "url", "string"), - new Param(c, "headers", "[(string,string)]"), - new Param(c, "postData", "byte[]"), - new Param(c, "replyEvent", "string"), - new Param(c, "authenticationEvent", "string", Value(Pointer(0))), - new Param(c, "progressEvent", "string", Value(Pointer(0))), - new Param(c, "ignoreSslErrors", "bool", Value(false)), - new Param(c, "urlIsEncoded", "bool", Value(false)), - End), - - new Function(c, "httpPut", httpPutString, None, - Return, "void", - Parameters, - new Param(c, "url", "string"), - new Param(c, "headers", "[(string,string)]"), - new Param(c, "putString", "string"), - new Param(c, "replyEvent", "string"), - new Param(c, "authenticationEvent", "string", Value(Pointer(0))), - new Param(c, "progressEvent", "string", Value(Pointer(0))), - new Param(c, "ignoreSslErrors", "bool", Value(false)), - new Param(c, "urlIsEncoded", "bool", Value(false)), - End), - - new Function(c, "httpPut", httpPutData, None, - Return, "void", - Parameters, - new Param(c, "url", "string"), - new Param(c, "headers", "[(string,string)]"), - new Param(c, "putData", "byte[]"), - new Param(c, "replyEvent", "string"), - new Param(c, "authenticationEvent", "string", Value(Pointer(0))), - new Param(c, "progressEvent", "string", Value(Pointer(0))), - new Param(c, "ignoreSslErrors", "bool", Value(false)), - new Param(c, "urlIsEncoded", "bool", Value(false)), - End), - - new Function(c, "mainWindowWidget", mainWindowWidget, None, - Return, "qt.QMainWindow", - End), - - new Function(c, "mainViewWidget", mainViewWidget, None, - Return, "qt.QWidget", - End), - - new Function(c, "prefTabWidget", prefTabWidget, None, - Return, "qt.QTabWidget", - End), - - new Function(c, "sessionBottomToolBar", sessionBottomToolBar, None, - Return, "qt.QToolBar", - End), - - new Function(c, "networkAccessManager", networkAccessManager, None, - Return, "qt.QNetworkAccessManager", - End), - - new Function(c, "javascriptMuExport", javascriptMuExport, None, - Return, "void", - Parameters, - new Param(c, "frame", "qt.QWebEnginePage"), - End), - - new Function(c, "sessionFromUrl", sessionFromUrl, None, - Return, "void", - Parameters, - new Param(c, "url", "string"), - End), - - new Function(c, "putUrlOnClipboard", putUrlOnClipboard, None, - Return, "void", - Parameters, - new Param(c, "url", "string"), - new Param(c, "title", "string"), - new Param(c, "doEncode", "bool", Value(true)), - End), - - new Function(c, "myNetworkPort", myNetworkPort, None, - Return, "int", - End), - - new Function(c, "myNetworkHost", myNetworkHost, None, - Return, "string", - End), - - new Function(c, "encodePassword", encodePassword, - None, - Return, "string", - Parameters, - new Param(c, "password", "string"), - End), - - new Function(c, "decodePassword", decodePassword, - None, - Return, "string", - Parameters, - new Param(c, "password", "string"), - End), - - new Function(c, "cacheDir", cacheDir, - None, - Return, "string", - End), - - new Function(c, "openUrl", openUrl, - None, - Return, "void", - Parameters, - new Param(c, "url", "string"), - End), - - new Function(c, "openUrlFromUrl", openUrlFromUrl, None, - Return, "void", - Parameters, - new Param(c, "url", "qt.QUrl"), - End), - - new Function(c, "queryDriverAttribute", queryDriverAttribute, - None, - Return, "string", - Parameters, - new Param(c, "attribute", "string"), - End), - - new Function(c, "setDriverAttribute", setDriverAttribute, - None, - Return, "void", - Parameters, - new Param(c, "attribute", "string"), - new Param(c, "value", "string"), - End), - - new Function(c, "setPresentationMode", setPresentationMode, - None, - Return, "void", - Parameters, - new Param(c, "value", "bool"), - End), - - new Function(c, "presentationMode", presentationMode, None, - Return, "bool", - End), - - new Function(c, "packageListFromSetting", packageListFromSetting, - None, - Return, "string[]", - Parameters, - new Param(c, "settingName", "string"), - End), - - new Function(c, "showTopViewToolbar", showTopViewToolbar, None, - Return, "void", - Parameters, - new Param(c, "show", "bool"), - End), - - new Function(c, "showBottomViewToolbar", showBottomViewToolbar, None, - Return, "void", - Parameters, - new Param(c, "show", "bool"), - End), - - new Function(c, "isTopViewToolbarVisible", isTopViewToolbarVisible, None, - Return, "bool", - End), - - new Function(c, "isBottomViewToolbarVisible", isBottomViewToolbarVisible, None, - Return, "bool", - End), - - new Function(c, "editNodeSource", editNodeSource, None, - Return, "void", - Parameters, - new Param(c, "nodeName", "string"), - End), - - new Function(c, "editProfiles", editProfiles, None, - Return, "void", - End), - - new Function(c, "validateShotgunToken", validateShotgunToken, None, - Return, "string", - Parameters, - new Param(c, "port", "int", Value(-1)), - new Param(c, "tag", "string", Value(Pointer(0))), - End), - - new Function(c, "launchTLI", launchTLI, None, - Return, "void", - End), - - new Function(c, "rvioSetup", rvioSetup, None, - Return, "void", - End), - - EndArguments); -} - -NODE_IMPLEMENTATION(queryDriverAttribute, Pointer) -{ - Process* p = NODE_THREAD.process(); - MuLangContext* context = static_cast(p->context()); - const StringType::String* attr = NODE_ARG_OBJECT(0, StringType::String); - const StringType* stype = context->stringType(); - - string v = RvApplication::queryDriverAttribute(attr->c_str()); - NODE_RETURN(stype->allocate(v)); -} - -NODE_IMPLEMENTATION(setDriverAttribute, void) -{ - const StringType::String* attr = NODE_ARG_OBJECT(0, StringType::String); - const StringType::String* val = NODE_ARG_OBJECT(1, StringType::String); - RvApplication::setDriverAttribute(attr->c_str(), val->c_str()); -} - -NODE_IMPLEMENTATION(resizeFit, void) -{ - RvSession *s = RvSession::currentRvSession(); - assert( s ); - - RvDocument *rvDoc = (RvDocument *)s->opaquePointer(); - assert( rvDoc ); - - rvDoc->resizeToFit(); - s->setUserHasSetViewSize (true); -} +// #ifdef PLATFORM_DARWIN +// #define USE_NATIVE_DIALOGS +// #endif -NODE_IMPLEMENTATION(setViewSize, void) +namespace Rv { - RvSession *s = RvSession::currentRvSession(); - RvDocument *rvDoc = (RvDocument *)s->opaquePointer(); - int w = NODE_ARG(0, int); - int h = NODE_ARG(1, int); - rvDoc->resizeView(w, h); - s->setUserHasSetViewSize (true); -} + using namespace TwkApp; + using namespace Mu; + using namespace std; + using namespace TwkUtil; + using namespace IPCore; + using namespace TwkQtCoreUtil; -NODE_IMPLEMENTATION(startupResize, bool) -{ - Session *s = Session::currentSession(); - RvDocument *rvDoc = (RvDocument *)s->opaquePointer(); - NODE_RETURN(rvDoc->startupResize()); -} - -static void -popupMenuInternal (DynamicArray* array, QPoint& location) -{ - Session *s = Session::currentSession(); - RvDocument *rvDoc = (RvDocument *)s->opaquePointer(); - - s->receivingEvents(false); - - QPoint p = rvDoc->view()->mapToGlobal(location); - - if (array) - { - if (TwkApp::Menu* m = createTwkAppMenu("temp", array)) - { - rvDoc->popupMenu(m, p); - } - } - else + static void throwBadArgumentException(const Mu::Node& node, + Mu::Thread& thread, + const Mu::String& msg) { - rvDoc->mainPopup()->popup(p); + ostringstream str; + const Mu::MuLangContext* context = + static_cast(thread.context()); + ExceptionType::Exception* e = + new ExceptionType::Exception(context->exceptionType()); + str << "in " << node.symbol()->fullyQualifiedName() << ": " << msg; + e->string() += str.str().c_str(); + thread.setException(e); + throw BadArgumentException(thread, e); } -} - -NODE_IMPLEMENTATION(popupMenu, void) -{ - Session *s = Session::currentSession(); - RvDocument *rvDoc = (RvDocument *)s->opaquePointer(); - - TwkApp::EventType::EventInstance* e = - NODE_ARG_OBJECT(0, TwkApp::EventType::EventInstance); - DynamicArray* array = NODE_ARG_OBJECT(1, DynamicArray); - QPoint lp; - - if (const TwkApp::PointerEvent* pevent = - dynamic_cast(e->event)) - { - lp = QPoint(pevent->x(), rvDoc->view()->height() - pevent->y() - 1); - } - else + void initUICommands() { - lp = QPoint(0, rvDoc->view()->height() - 1); - } + USING_MU_FUNCTION_SYMBOLS; + MuLangContext* context = muContext(); + Context* c = context; + Symbol* root = context->globalScope(); + Name cname = c->internName("commands"); + Mu::Module* commands = root->findSymbolOfType(cname); + + root->addSymbol(new qtModule(c, "qt")); + + Context::TypeVector types; + types.push_back(context->stringType()); + types.push_back(context->stringType()); + context->listType(context->tupleType(types)); + + commands->addSymbols( + new Function(c, "resizeFit", resizeFit, None, Return, "void", End), + + new Function(c, "setViewSize", setViewSize, None, Return, "void", + Parameters, new Param(c, "width", "int"), + new Param(c, "height", "int"), End), + + new Function(c, "startupResize", startupResize, None, Return, + "bool", End), + + new Function(c, "popupMenu", popupMenu, None, Return, "void", + Parameters, new Param(c, "event", "Event"), + new Param(c, "menu", "MenuItem[]", Value(Pointer(0))), + End), + + new Function( + c, "popupMenuAtPoint", popupMenuAtPoint, None, Return, "void", + Parameters, new Param(c, "x", "int"), new Param(c, "y", "int"), + new Param(c, "menu", "MenuItem[]", Value(Pointer(0))), End), + + new Function(c, "setWindowTitle", setWindowTitle, None, Return, + "void", Parameters, new Param(c, "title", "string"), + End), + + new Function(c, "center", center, None, Return, "void", End), + + new Function(c, "close", close, None, Return, "void", End), + + new Function(c, "toggleMenuBar", toggleMenuBar, None, Return, + "void", End), + + new Function(c, "isMenuBarVisible", isMenuBarVisible, None, Return, + "bool", End), + + new SymbolicConstant(c, "OneExistingFile", "int", + Value(int(RvFileDialog::OneExistingFile))), + new SymbolicConstant(c, "ManyExistingFiles", "int", + Value(int(RvFileDialog::ManyExistingFiles))), + new SymbolicConstant( + c, "ManyExistingFilesAndDirectories", "int", + Value(int(RvFileDialog::ManyExistingFilesAndDirectories))), + new SymbolicConstant(c, "OneFileName", "int", + Value(int(RvFileDialog::OneFileName))), + new SymbolicConstant(c, "OneDirectory", "int", + Value(int(RvFileDialog::OneDirectory))), + + new Function( + c, "openMediaFileDialog", openMediaFileDialog, None, Return, + "string[]", Parameters, new Param(c, "associated", "bool"), + new Param(c, "selectType", "int"), + new Param(c, "filter", "string", Value(Pointer(0))), + new Param(c, "defaultPath", "string", Value(Pointer(0))), + new Param(c, "label", "string", Value(Pointer(0))), End), + + new Function( + c, "openFileDialog", openFileDialog, None, Return, "string[]", + Parameters, new Param(c, "associated", "bool"), + new Param(c, "multiple", "bool", Value(false)), + new Param(c, "directory", "bool", Value(false)), + new Param(c, "filter", "string", Value(Pointer(0))), + new Param(c, "defaultPath", "string", Value(Pointer(0))), End), + + new Function( + c, "saveFileDialog", saveFileDialog, None, Return, "string", + Parameters, new Param(c, "associated", "bool"), + new Param(c, "filter", "string", Value(Pointer(0))), + new Param(c, "defaultPath", "string", Value(Pointer(0))), + new Param(c, "directory", "bool", Value(false)), End), + + new SymbolicConstant(c, "CursorNone", "int", + Value(int(Qt::BlankCursor))), + new SymbolicConstant(c, "CursorArrow", "int", + Value(int(Qt::ArrowCursor))), + new SymbolicConstant(c, "CursorDefault", "int", + Value(int(Qt::ArrowCursor))), + + new Function(c, "setCursor", setCursor, None, Return, "void", + Parameters, new Param(c, "cursorType", "int"), End), + + new SymbolicConstant(c, "InfoAlert", "int", Value(0)), + new SymbolicConstant(c, "WarningAlert", "int", Value(1)), + new SymbolicConstant(c, "ErrorAlert", "int", Value(2)), + + new Function(c, "stereoSupported", stereoSupported, None, Return, + "bool", End), + + new Function(c, "alertPanel", alertPanel, None, Return, "int", + Parameters, new Param(c, "associated", "bool"), + new Param(c, "type", "int"), + new Param(c, "title", "string"), + new Param(c, "message", "string"), + new Param(c, "button0", "string"), + new Param(c, "button1", "string"), + new Param(c, "button2", "string"), End), + + new Function(c, "watchFile", watchFile, None, Return, "void", + Parameters, new Param(c, "filename", "string"), + new Param(c, "watch", "bool"), End), + + new Function(c, "showNetworkDialog", showNetworkDialog, None, + Return, "void", End), + + new Function(c, "showConsole", showConsole, None, Return, "void", + End), + + new Function(c, "isConsoleVisible", isConsoleVisible, None, Return, + "bool", End), + // network + + new Function( + c, "remoteSendMessage", remoteSendMessage, None, Return, "void", + Parameters, new Param(c, "message", "string"), + new Param(c, "recipients", "string[]", Value(Pointer(0))), End), + + new Function( + c, "remoteSendEvent", remoteSendEvent, None, Return, "void", + Parameters, new Param(c, "event", "string"), + new Param(c, "target", "string"), + new Param(c, "contents", "string"), + new Param(c, "recipients", "string[]", Value(Pointer(0))), End), + + new Function(c, "remoteSendDataEvent", remoteSendDataEvent, None, + Return, "void", Parameters, + new Param(c, "event", "string"), + new Param(c, "target", "string"), + new Param(c, "interp", "string"), + new Param(c, "data", "byte[]"), + new Param(c, "recipients", "string[]"), End), + + new Function(c, "remoteConnections", remoteConnections, None, + Return, "string[]", End), + + new Function(c, "remoteApplications", remoteApplications, None, + Return, "string[]", End), + + new Function(c, "remoteContacts", remoteContacts, None, Return, + "string[]", End), + + new Function(c, "remoteLocalContactName", remoteLocalContactName, + None, Return, "string", End), + + new Function(c, "setRemoteLocalContactName", + setRemoteLocalContactName, None, Return, "string", + Parameters, new Param(c, "name", "string"), End), + + new Function(c, "remoteConnect", remoteConnect, None, Return, + "void", Parameters, new Param(c, "name", "string"), + new Param(c, "host", "string"), + new Param(c, "port", "int", Value(0)), End), + + new Function(c, "remoteDisconnect", remoteDisconnect, None, Return, + "void", Parameters, + new Param(c, "remoteContact", "string"), End), + + new Function(c, "remoteNetwork", remoteNetwork, None, Return, + "void", Parameters, new Param(c, "on", "bool"), End), + + new Function(c, "remoteConnectionIsIncoming", + remoteConnectionIsIncoming, None, Return, "bool", + Parameters, new Param(c, "connection", "string"), End), + + new Function(c, "spoofConnectionStream", spoofConnectionStream, + None, Return, "void", Parameters, + new Param(c, "streamFile", "string"), + new Param(c, "timeScale", "float"), + new Param(c, "verbose", "bool", Value(false)), End), + + new SymbolicConstant(c, "NetworkStatusOn", "int", Value(1)), + new SymbolicConstant(c, "NetworkStatusOff", "int", Value(0)), + + new Function(c, "remoteNetworkStatus", remoteNetworkStatus, None, + Return, "int", End), + + new SymbolicConstant(c, "NetworkPermissionAsk", "int", + Value(int(RvNetworkDialog::AskConnect))), + new SymbolicConstant(c, "NetworkPermissionAllow", "int", + Value(int(RvNetworkDialog::AllowConnect))), + new SymbolicConstant(c, "NetworkPermissionDeny", "int", + Value(int(RvNetworkDialog::DenyConnect))), + + new Function(c, "remoteDefaultPermission", remoteDefaultPermission, + None, Return, "int", End), + + new Function(c, "setRemoteDefaultPermission", + setRemoteDefaultPermission, None, Return, "void", + Parameters, new Param(c, "permission", "int"), End), + + new Function(c, "writeSetting", writeSetting, None, Return, "void", + Parameters, new Param(c, "group", "string"), + new Param(c, "name", "string"), + new Param(c, "value", "SettingsValue"), End), + + new Function(c, "readSetting", readSetting, None, Return, + "SettingsValue", Parameters, + new Param(c, "group", "string"), + new Param(c, "name", "string"), + new Param(c, "defaultValue", "SettingsValue"), End), + + new Function( + c, "httpGet", httpGet, None, Return, "void", Parameters, + new Param(c, "url", "string"), + new Param(c, "headers", "[(string,string)]"), + new Param(c, "replyEvent", "string"), + new Param(c, "authenticationEvent", "string", + Value(Pointer(0))), + new Param(c, "progressEvent", "string", Value(Pointer(0))), + new Param(c, "ignoreSslErrors", "bool", Value(false)), + new Param(c, "urlIsEncoded", "bool", Value(false)), End), + + new Function( + c, "httpPost", httpPostString, None, Return, "void", Parameters, + new Param(c, "url", "string"), + new Param(c, "headers", "[(string,string)]"), + new Param(c, "postString", "string"), + new Param(c, "replyEvent", "string"), + new Param(c, "authenticationEvent", "string", + Value(Pointer(0))), + new Param(c, "progressEvent", "string", Value(Pointer(0))), + new Param(c, "ignoreSslErrors", "bool", Value(false)), + new Param(c, "urlIsEncoded", "bool", Value(false)), End), + + new Function( + c, "httpPost", httpPostData, None, Return, "void", Parameters, + new Param(c, "url", "string"), + new Param(c, "headers", "[(string,string)]"), + new Param(c, "postData", "byte[]"), + new Param(c, "replyEvent", "string"), + new Param(c, "authenticationEvent", "string", + Value(Pointer(0))), + new Param(c, "progressEvent", "string", Value(Pointer(0))), + new Param(c, "ignoreSslErrors", "bool", Value(false)), + new Param(c, "urlIsEncoded", "bool", Value(false)), End), + + new Function( + c, "httpPut", httpPutString, None, Return, "void", Parameters, + new Param(c, "url", "string"), + new Param(c, "headers", "[(string,string)]"), + new Param(c, "putString", "string"), + new Param(c, "replyEvent", "string"), + new Param(c, "authenticationEvent", "string", + Value(Pointer(0))), + new Param(c, "progressEvent", "string", Value(Pointer(0))), + new Param(c, "ignoreSslErrors", "bool", Value(false)), + new Param(c, "urlIsEncoded", "bool", Value(false)), End), + + new Function( + c, "httpPut", httpPutData, None, Return, "void", Parameters, + new Param(c, "url", "string"), + new Param(c, "headers", "[(string,string)]"), + new Param(c, "putData", "byte[]"), + new Param(c, "replyEvent", "string"), + new Param(c, "authenticationEvent", "string", + Value(Pointer(0))), + new Param(c, "progressEvent", "string", Value(Pointer(0))), + new Param(c, "ignoreSslErrors", "bool", Value(false)), + new Param(c, "urlIsEncoded", "bool", Value(false)), End), + + new Function(c, "mainWindowWidget", mainWindowWidget, None, Return, + "qt.QMainWindow", End), + + new Function(c, "mainViewWidget", mainViewWidget, None, Return, + "qt.QWidget", End), + + new Function(c, "prefTabWidget", prefTabWidget, None, Return, + "qt.QTabWidget", End), + + new Function(c, "sessionBottomToolBar", sessionBottomToolBar, None, + Return, "qt.QToolBar", End), + + new Function(c, "networkAccessManager", networkAccessManager, None, + Return, "qt.QNetworkAccessManager", End), + + new Function(c, "javascriptMuExport", javascriptMuExport, None, + Return, "void", Parameters, + new Param(c, "frame", "qt.QWebEnginePage"), End), + + new Function(c, "sessionFromUrl", sessionFromUrl, None, Return, + "void", Parameters, new Param(c, "url", "string"), + End), + + new Function(c, "putUrlOnClipboard", putUrlOnClipboard, None, + Return, "void", Parameters, + new Param(c, "url", "string"), + new Param(c, "title", "string"), + new Param(c, "doEncode", "bool", Value(true)), End), + + new Function(c, "myNetworkPort", myNetworkPort, None, Return, "int", + End), + + new Function(c, "myNetworkHost", myNetworkHost, None, Return, + "string", End), + + new Function(c, "encodePassword", encodePassword, None, Return, + "string", Parameters, + new Param(c, "password", "string"), End), + + new Function(c, "decodePassword", decodePassword, None, Return, + "string", Parameters, + new Param(c, "password", "string"), End), + + new Function(c, "cacheDir", cacheDir, None, Return, "string", End), + + new Function(c, "openUrl", openUrl, None, Return, "void", + Parameters, new Param(c, "url", "string"), End), + + new Function(c, "openUrlFromUrl", openUrlFromUrl, None, Return, + "void", Parameters, new Param(c, "url", "qt.QUrl"), + End), + + new Function(c, "queryDriverAttribute", queryDriverAttribute, None, + Return, "string", Parameters, + new Param(c, "attribute", "string"), End), + + new Function(c, "setDriverAttribute", setDriverAttribute, None, + Return, "void", Parameters, + new Param(c, "attribute", "string"), + new Param(c, "value", "string"), End), + + new Function(c, "setPresentationMode", setPresentationMode, None, + Return, "void", Parameters, + new Param(c, "value", "bool"), End), + + new Function(c, "presentationMode", presentationMode, None, Return, + "bool", End), + + new Function(c, "packageListFromSetting", packageListFromSetting, + None, Return, "string[]", Parameters, + new Param(c, "settingName", "string"), End), + + new Function(c, "showTopViewToolbar", showTopViewToolbar, None, + Return, "void", Parameters, + new Param(c, "show", "bool"), End), - popupMenuInternal (array, lp); -} - -NODE_IMPLEMENTATION(popupMenuAtPoint, void) -{ - Session *s = Session::currentSession(); - RvDocument *rvDoc = (RvDocument *)s->opaquePointer(); - int x = NODE_ARG(0, int); - int y = NODE_ARG(1, int); - DynamicArray* array = NODE_ARG_OBJECT(2, DynamicArray); + new Function(c, "showBottomViewToolbar", showBottomViewToolbar, + None, Return, "void", Parameters, + new Param(c, "show", "bool"), End), - QPoint lp (x, rvDoc->view()->height() - y - 1); + new Function(c, "isTopViewToolbarVisible", isTopViewToolbarVisible, + None, Return, "bool", End), - popupMenuInternal (array, lp); -} + new Function(c, "isBottomViewToolbarVisible", + isBottomViewToolbarVisible, None, Return, "bool", End), -NODE_IMPLEMENTATION(setWindowTitle, void) -{ - const StringType::String *title = NODE_ARG_OBJECT(0, StringType::String); + new Function(c, "editNodeSource", editNodeSource, None, Return, + "void", Parameters, new Param(c, "nodeName", "string"), + End), - Session *s = Session::currentSession(); - assert( s ); + new Function(c, "editProfiles", editProfiles, None, Return, "void", + End), - RvDocument *rvDoc = (RvDocument *)s->opaquePointer(); - assert( rvDoc ); + new Function(c, "validateShotgunToken", validateShotgunToken, None, + Return, "string", Parameters, + new Param(c, "port", "int", Value(-1)), + new Param(c, "tag", "string", Value(Pointer(0))), End), - rvDoc->setWindowTitle(UTF8::qconvert(title->c_str())); -} + new Function(c, "launchTLI", launchTLI, None, Return, "void", End), -NODE_IMPLEMENTATION(center, void) -{ - Session *s = Session::currentSession(); - assert( s ); + new Function(c, "rvioSetup", rvioSetup, None, Return, "void", End), - RvDocument *rvDoc = (RvDocument *)s->opaquePointer(); - assert( rvDoc ); + EndArguments); + } - rvDoc->resizeToFit(true); - rvDoc->center(); -} + NODE_IMPLEMENTATION(queryDriverAttribute, Pointer) + { + Process* p = NODE_THREAD.process(); + MuLangContext* context = static_cast(p->context()); + const StringType::String* attr = NODE_ARG_OBJECT(0, StringType::String); + const StringType* stype = context->stringType(); -NODE_IMPLEMENTATION(close, void) -{ - Session *s = Session::currentSession(); - assert( s ); + string v = RvApplication::queryDriverAttribute(attr->c_str()); + NODE_RETURN(stype->allocate(v)); + } - RvDocument *rvDoc = (RvDocument *)s->opaquePointer(); - assert( rvDoc ); + NODE_IMPLEMENTATION(setDriverAttribute, void) + { + const StringType::String* attr = NODE_ARG_OBJECT(0, StringType::String); + const StringType::String* val = NODE_ARG_OBJECT(1, StringType::String); + RvApplication::setDriverAttribute(attr->c_str(), val->c_str()); + } - rvDoc->close(); -} + NODE_IMPLEMENTATION(resizeFit, void) + { + RvSession* s = RvSession::currentRvSession(); + assert(s); -NODE_IMPLEMENTATION(toggleMenuBar, void) -{ - Session *s = Session::currentSession(); - assert( s ); - RvDocument *rvDoc = (RvDocument *)s->opaquePointer(); - rvDoc->toggleMenuBar(); -} + RvDocument* rvDoc = (RvDocument*)s->opaquePointer(); + assert(rvDoc); -NODE_IMPLEMENTATION(isMenuBarVisible, bool) -{ - Session *s = Session::currentSession(); - assert( s ); - RvDocument *rvDoc = (RvDocument *)s->opaquePointer(); - NODE_RETURN(rvDoc->menuBarShown()); -} + rvDoc->resizeToFit(); + s->setUserHasSetViewSize(true); + } -static map sessionToMediaDialog; + NODE_IMPLEMENTATION(setViewSize, void) + { + RvSession* s = RvSession::currentRvSession(); + RvDocument* rvDoc = (RvDocument*)s->opaquePointer(); + int w = NODE_ARG(0, int); + int h = NODE_ARG(1, int); -NODE_IMPLEMENTATION(openMediaFileDialog, Pointer) -{ - HOP_PROF_FUNC(); + rvDoc->resizeView(w, h); + s->setUserHasSetViewSize(true); + } - Session* s = Session::currentSession(); - RvDocument* rvDoc = (RvDocument *)s->opaquePointer(); - Process* p = NODE_THREAD.process(); - bool sheet = NODE_ARG(0, bool); - int mode = NODE_ARG(1, int); - StringType::String* filter = NODE_ARG_OBJECT(2, StringType::String); - StringType::String* path = NODE_ARG_OBJECT(3, StringType::String); - StringType::String* label = NODE_ARG_OBJECT(4, StringType::String); + NODE_IMPLEMENTATION(startupResize, bool) + { + Session* s = Session::currentSession(); + RvDocument* rvDoc = (RvDocument*)s->opaquePointer(); + NODE_RETURN(rvDoc->startupResize()); + } - const DynamicArrayType* atype = static_cast(NODE_THIS.type()); - const StringType* stype = static_cast(atype->elementType()); + static void popupMenuInternal(DynamicArray* array, QPoint& location) + { + Session* s = Session::currentSession(); + RvDocument* rvDoc = (RvDocument*)s->opaquePointer(); - FileTypeTraits* traits = 0; - bool hasSinglePair = false; + s->receivingEvents(false); - if (filter) - { - QStringList parts; - QList > pairs; - parts = UTF8::qconvert(filter->c_str()).split("|"); + QPoint p = rvDoc->view()->mapToGlobal(location); - if (parts.size() == 1) + if (array) { - QString v = parts.front(); - - if (v != "*" && v != "") + if (TwkApp::Menu* m = createTwkAppMenu("temp", array)) { - pairs.push_back(qMakePair(v, v)); + rvDoc->popupMenu(m, p); } } else { - for (size_t i = 0; i < parts.size(); i+=2) - { - pairs.push_back(qMakePair(parts[i], parts[i+1])); - } + rvDoc->mainPopup()->popup(p); } + } + + NODE_IMPLEMENTATION(popupMenu, void) + { + Session* s = Session::currentSession(); + RvDocument* rvDoc = (RvDocument*)s->opaquePointer(); + + TwkApp::EventType::EventInstance* e = + NODE_ARG_OBJECT(0, TwkApp::EventType::EventInstance); - if (pairs.size() == 0) + DynamicArray* array = NODE_ARG_OBJECT(1, DynamicArray); + QPoint lp; + + if (const TwkApp::PointerEvent* pevent = + dynamic_cast(e->event)) { - traits = new MediaFileTypes(true, false); + lp = QPoint(pevent->x(), rvDoc->view()->height() - pevent->y() - 1); } else { - traits = new MediaFileTypes(true, false, pairs); + lp = QPoint(0, rvDoc->view()->height() - 1); } - hasSinglePair = (pairs.size() == 1); - } - else - { - traits = new MediaFileTypes(true, false); + popupMenuInternal(array, lp); } - if (sessionToMediaDialog.find(s) == sessionToMediaDialog.end()) + NODE_IMPLEMENTATION(popupMenuAtPoint, void) { - sessionToMediaDialog[s] = new RvFileDialog(rvDoc, - new MediaFileTypes(true, false), - RvFileDialog::OpenFileRole, - sheet ? Qt::Sheet : Qt::Dialog, - "MediaFileDialog"); - } - - RvFileDialog& dialog = *sessionToMediaDialog[s]; + Session* s = Session::currentSession(); + RvDocument* rvDoc = (RvDocument*)s->opaquePointer(); + int x = NODE_ARG(0, int); + int y = NODE_ARG(1, int); + DynamicArray* array = NODE_ARG_OBJECT(2, DynamicArray); - if (path) dialog.setDirectory(UTF8::qconvert(path->c_str())); - dialog.setTitleLabel(UTF8::qconvert(label->c_str())); - dialog.setFileMode((RvFileDialog::FileMode)mode); - dialog.setFileTypeTraits(traits); - if (hasSinglePair) dialog.setFileTypeIndex(2); + QPoint lp(x, rvDoc->view()->height() - y - 1); - rvDoc->setDocumentDisabled(false, true); - bool result = dialog.exec(); - rvDoc->view()->setFocus(Qt::OtherFocusReason); - rvDoc->setDocumentDisabled(false, false); + popupMenuInternal(array, lp); + } - if (result) + NODE_IMPLEMENTATION(setWindowTitle, void) { - QStringList files; - files = dialog.selectedFiles(); + const StringType::String* title = + NODE_ARG_OBJECT(0, StringType::String); - DynamicArray* array = new DynamicArray(atype, 1); - array->resize(files.size()); + Session* s = Session::currentSession(); + assert(s); - for (int i=0, size = files.size(); i < size; i++) - { - string v = pathConform(UTF8::qconvert(files.at(i))); - array->element(i) = stype->allocate(v); - } + RvDocument* rvDoc = (RvDocument*)s->opaquePointer(); + assert(rvDoc); - NODE_RETURN((Pointer)array); + rvDoc->setWindowTitle(UTF8::qconvert(title->c_str())); } - else + + NODE_IMPLEMENTATION(center, void) { - MuLangContext* context = static_cast(p->context()); - ExceptionType::Exception *e = - new ExceptionType::Exception(context->exceptionType()); - e->string() += "operation cancelled"; - NODE_THREAD.setException(e); - ProgramException exc(NODE_THREAD, e); - throw exc; + Session* s = Session::currentSession(); + assert(s); + + RvDocument* rvDoc = (RvDocument*)s->opaquePointer(); + assert(rvDoc); + + rvDoc->resizeToFit(true); + rvDoc->center(); } - NODE_RETURN((Pointer)0); -} + NODE_IMPLEMENTATION(close, void) + { + Session* s = Session::currentSession(); + assert(s); -/* - * XXX in progress (see below). - * -class MyIconProvider : public QFileIconProvider -{ - public: - virtual QString type (const QFileInfo& info) { return QFileIconProvider::File; }; -}; -*/ + RvDocument* rvDoc = (RvDocument*)s->opaquePointer(); + assert(rvDoc); -static map sessionToOpenDialog; + rvDoc->close(); + } -NODE_IMPLEMENTATION(openFileDialog, Pointer) -{ - Session* s = Session::currentSession(); - RvDocument* rvDoc = (RvDocument *)s->opaquePointer(); - Process* p = NODE_THREAD.process(); - bool sheet = NODE_ARG(0, bool); - bool multi = NODE_ARG(1, bool); - bool directory = NODE_ARG(2, bool); - StringType::String* filter = NODE_ARG_OBJECT(3, StringType::String); - StringType::String* path = NODE_ARG_OBJECT(4, StringType::String); + NODE_IMPLEMENTATION(toggleMenuBar, void) + { + Session* s = Session::currentSession(); + assert(s); + RvDocument* rvDoc = (RvDocument*)s->opaquePointer(); + rvDoc->toggleMenuBar(); + } - const DynamicArrayType* atype = static_cast(NODE_THIS.type()); - const StringType* stype = static_cast(atype->elementType()); + NODE_IMPLEMENTATION(isMenuBarVisible, bool) + { + Session* s = Session::currentSession(); + assert(s); + RvDocument* rvDoc = (RvDocument*)s->opaquePointer(); + NODE_RETURN(rvDoc->menuBarShown()); + } - FileTypeTraits* traits = 0; - bool hasSinglePair = false; + static map sessionToMediaDialog; - if (filter) + NODE_IMPLEMENTATION(openMediaFileDialog, Pointer) { - QStringList parts; - QList > pairs; - parts = UTF8::qconvert(filter->c_str()).split("|"); + HOP_PROF_FUNC(); - if (parts.size() == 1) + Session* s = Session::currentSession(); + RvDocument* rvDoc = (RvDocument*)s->opaquePointer(); + Process* p = NODE_THREAD.process(); + bool sheet = NODE_ARG(0, bool); + int mode = NODE_ARG(1, int); + StringType::String* filter = NODE_ARG_OBJECT(2, StringType::String); + StringType::String* path = NODE_ARG_OBJECT(3, StringType::String); + StringType::String* label = NODE_ARG_OBJECT(4, StringType::String); + + const DynamicArrayType* atype = + static_cast(NODE_THIS.type()); + const StringType* stype = + static_cast(atype->elementType()); + + FileTypeTraits* traits = 0; + bool hasSinglePair = false; + + if (filter) { - QString v = parts.front(); + QStringList parts; + QList> pairs; + parts = UTF8::qconvert(filter->c_str()).split("|"); - if (v != "*" && v != "") + if (parts.size() == 1) { - pairs.push_back(qMakePair(v, v)); + QString v = parts.front(); + + if (v != "*" && v != "") + { + pairs.push_back(qMakePair(v, v)); + } } - } - else - { - for (size_t i = 0; i < parts.size(); i+=2) + else { - pairs.push_back(qMakePair(parts[i], parts[i+1])); + for (size_t i = 0; i < parts.size(); i += 2) + { + pairs.push_back(qMakePair(parts[i], parts[i + 1])); + } } - } - - traits = new MediaFileTypes(true, false, pairs); - - hasSinglePair = (pairs.size() == 1); - } - else - { - traits = new MediaFileTypes(true, false); - } - RvFileDialog* d = 0; + if (pairs.size() == 0) + { + traits = new MediaFileTypes(true, false); + } + else + { + traits = new MediaFileTypes(true, false, pairs); + } - if (sessionToOpenDialog.find(s) == sessionToOpenDialog.end()) - { - sessionToOpenDialog[s] = new RvFileDialog(rvDoc, - traits, - RvFileDialog::OpenFileRole, - sheet ? Qt::Sheet : Qt::Dialog, - "OpenFileDialog"); - } - else - { - sessionToOpenDialog[s]->setFileTypeTraits(traits); - } + hasSinglePair = (pairs.size() == 1); + } + else + { + traits = new MediaFileTypes(true, false); + } - RvFileDialog& dialog = *sessionToOpenDialog[s]; + if (sessionToMediaDialog.find(s) == sessionToMediaDialog.end()) + { + sessionToMediaDialog[s] = new RvFileDialog( + rvDoc, new MediaFileTypes(true, false), + RvFileDialog::OpenFileRole, sheet ? Qt::Sheet : Qt::Dialog, + "MediaFileDialog"); + } - if (hasSinglePair) dialog.setFileTypeIndex(2); + RvFileDialog& dialog = *sessionToMediaDialog[s]; - dialog.setFileMode(multi ? RvFileDialog::ManyExistingFiles : - ((directory) ? RvFileDialog::OneDirectoryName : RvFileDialog::OneFileName)); + if (path) + dialog.setDirectory(UTF8::qconvert(path->c_str())); + dialog.setTitleLabel(UTF8::qconvert(label->c_str())); + dialog.setFileMode((RvFileDialog::FileMode)mode); + dialog.setFileTypeTraits(traits); + if (hasSinglePair) + dialog.setFileTypeIndex(2); - if (path) dialog.setDirectory(UTF8::qconvert(path->c_str())); - dialog.setRole(RvFileDialog::OpenFileRole); - dialog.setTitleLabel(multi ? QString("Open Files") : QString("Open File")); - dialog.setViewMode(RvFileDialog::DetailedFileView); - dialog.lockViewMode(true); + rvDoc->setDocumentDisabled(false, true); + bool result = dialog.exec(); + rvDoc->view()->setFocus(Qt::OtherFocusReason); + rvDoc->setDocumentDisabled(false, false); - rvDoc->setDocumentDisabled(false, true); - bool result = dialog.exec(); - rvDoc->view()->setFocus(Qt::OtherFocusReason); - rvDoc->setDocumentDisabled(false, false); + if (result) + { + QStringList files; + files = dialog.selectedFiles(); - if (result) - { - QStringList files; - files = dialog.selectedFiles(); + DynamicArray* array = new DynamicArray(atype, 1); + array->resize(files.size()); - DynamicArray* array = new DynamicArray(atype, 1); - array->resize(files.size()); + for (int i = 0, size = files.size(); i < size; i++) + { + string v = pathConform(UTF8::qconvert(files.at(i))); + array->element(i) = stype->allocate(v); + } - for (int i=0, size = files.size(); i < size; i++) + NODE_RETURN((Pointer)array); + } + else { - string v = pathConform(UTF8::qconvert(files.at(i))); - array->element(i) = stype->allocate(v); + MuLangContext* context = static_cast(p->context()); + ExceptionType::Exception* e = + new ExceptionType::Exception(context->exceptionType()); + e->string() += "operation cancelled"; + NODE_THREAD.setException(e); + ProgramException exc(NODE_THREAD, e); + throw exc; } - NODE_RETURN((Pointer)array); - } - else - { - MuLangContext* context = static_cast(p->context()); - ExceptionType::Exception *e = - new ExceptionType::Exception(context->exceptionType()); - e->string() += "operation cancelled"; - NODE_THREAD.setException(e); - ProgramException exc(NODE_THREAD, e); - throw exc; + NODE_RETURN((Pointer)0); } - NODE_RETURN((Pointer)0); -} - -static map sessionToSaveDialog; - -NODE_IMPLEMENTATION(saveFileDialog, Pointer) -{ - Session* s = Session::currentSession(); - RvDocument* rvDoc = (RvDocument *)s->opaquePointer(); - Process* p = NODE_THREAD.process(); - bool sheet = NODE_ARG(0, bool); - StringType::String* filter = NODE_ARG_OBJECT(1, StringType::String); - StringType::String* path = NODE_ARG_OBJECT(2, StringType::String); - bool directory = NODE_ARG(3, bool); - - const StringType* stype = - static_cast(NODE_THIS.type()); + /* + * XXX in progress (see below). + * + class MyIconProvider : public QFileIconProvider + { + public: + virtual QString type (const QFileInfo& info) { return + QFileIconProvider::File; }; + }; + */ - FileTypeTraits* traits = 0; - bool hasSinglePair = false; + static map sessionToOpenDialog; - if (filter) + NODE_IMPLEMENTATION(openFileDialog, Pointer) { - QStringList parts; - QList > pairs; - parts = UTF8::qconvert(filter->c_str()).split("|"); - - if (parts.size() == 1) + Session* s = Session::currentSession(); + RvDocument* rvDoc = (RvDocument*)s->opaquePointer(); + Process* p = NODE_THREAD.process(); + bool sheet = NODE_ARG(0, bool); + bool multi = NODE_ARG(1, bool); + bool directory = NODE_ARG(2, bool); + StringType::String* filter = NODE_ARG_OBJECT(3, StringType::String); + StringType::String* path = NODE_ARG_OBJECT(4, StringType::String); + + const DynamicArrayType* atype = + static_cast(NODE_THIS.type()); + const StringType* stype = + static_cast(atype->elementType()); + + FileTypeTraits* traits = 0; + bool hasSinglePair = false; + + if (filter) { - QString v = parts.front(); + QStringList parts; + QList> pairs; + parts = UTF8::qconvert(filter->c_str()).split("|"); + + if (parts.size() == 1) + { + QString v = parts.front(); - if (v != "*" && v != "") + if (v != "*" && v != "") + { + pairs.push_back(qMakePair(v, v)); + } + } + else { - pairs.push_back(qMakePair(v, v)); + for (size_t i = 0; i < parts.size(); i += 2) + { + pairs.push_back(qMakePair(parts[i], parts[i + 1])); + } } + + traits = new MediaFileTypes(true, false, pairs); + + hasSinglePair = (pairs.size() == 1); } else { - for (size_t i = 0; i < parts.size(); i+=2) - { - pairs.push_back(qMakePair(parts[i], parts[i+1])); - } + traits = new MediaFileTypes(true, false); } - traits = new MediaFileTypes(false, true, pairs); + RvFileDialog* d = 0; - hasSinglePair = (pairs.size() == 1); - } - else - { - traits = new MediaFileTypes(false, true); - } + if (sessionToOpenDialog.find(s) == sessionToOpenDialog.end()) + { + sessionToOpenDialog[s] = new RvFileDialog( + rvDoc, traits, RvFileDialog::OpenFileRole, + sheet ? Qt::Sheet : Qt::Dialog, "OpenFileDialog"); + } + else + { + sessionToOpenDialog[s]->setFileTypeTraits(traits); + } - if (sessionToSaveDialog.find(s) == sessionToSaveDialog.end()) - { - sessionToSaveDialog[s] = new RvFileDialog(rvDoc, - traits, - RvFileDialog::SaveFileRole, - sheet ? Qt::Sheet : Qt::Dialog, - "SaveFileDialog"); - } - else - { - sessionToSaveDialog[s]->setFileTypeTraits(traits); - } + RvFileDialog& dialog = *sessionToOpenDialog[s]; - RvFileDialog& dialog = *sessionToSaveDialog[s]; + if (hasSinglePair) + dialog.setFileTypeIndex(2); - dialog.setFileMode((directory) ? - RvFileDialog::OneDirectoryName : RvFileDialog::OneFileName); + dialog.setFileMode(multi ? RvFileDialog::ManyExistingFiles + : ((directory) ? RvFileDialog::OneDirectoryName + : RvFileDialog::OneFileName)); - if (hasSinglePair) dialog.setFileTypeIndex(2); - if (path) dialog.setDirectory(UTF8::qconvert(path->c_str())); - dialog.setRole(RvFileDialog::SaveFileRole); - dialog.setTitleLabel(QString("Save to File")); - dialog.setViewMode(RvFileDialog::DetailedFileView); - dialog.lockViewMode(true); + if (path) + dialog.setDirectory(UTF8::qconvert(path->c_str())); + dialog.setRole(RvFileDialog::OpenFileRole); + dialog.setTitleLabel(multi ? QString("Open Files") + : QString("Open File")); + dialog.setViewMode(RvFileDialog::DetailedFileView); + dialog.lockViewMode(true); - string v = ""; - do - { rvDoc->setDocumentDisabled(false, true); bool result = dialog.exec(); rvDoc->view()->setFocus(Qt::OtherFocusReason); @@ -1096,1243 +869,1439 @@ NODE_IMPLEMENTATION(saveFileDialog, Pointer) QStringList files; files = dialog.selectedFiles(); - v = pathConform(UTF8::qconvert(files.at(0))); - QFileInfo info(UTF8::qconvert(v.c_str())); + DynamicArray* array = new DynamicArray(atype, 1); + array->resize(files.size()); - // - // QFileInfo says a non-existant file is not writable, so have to check the directory - // in that case. - // - const bool isDirWritable = TwkUtil::isWritable(UTF8::qconvert(info.absolutePath()).c_str()); - const bool isFileWritable = TwkUtil::isWritable(v.c_str()); - if ((!info.exists() && !isDirWritable) || (info.exists() && !isFileWritable)) - { - QString message = QString("File '") + UTF8::qconvert(v.c_str()) + - "' is not writable; please check the permissions or choose another location."; - QMessageBox confirm(QMessageBox::Warning, - "Permissions", - message, - QMessageBox::NoButton, rvDoc, Qt::Sheet); - - QPushButton* q1 = confirm.addButton("OK", QMessageBox::AcceptRole); - confirm.setIcon(QMessageBox::Question); - confirm.exec(); - v = ""; - } - else - if (info.exists()) + for (int i = 0, size = files.size(); i < size; i++) { - QString message = QString("File '") + UTF8::qconvert(v.c_str()) + "' exists; overwrite ?"; - QMessageBox confirm(QMessageBox::Warning, - "Overwrite", - message, - QMessageBox::NoButton, rvDoc, Qt::Sheet); - - QPushButton* q1 = confirm.addButton("Overwrite", QMessageBox::AcceptRole); - QPushButton* q2 = confirm.addButton("Cancel", QMessageBox::RejectRole); - confirm.setIcon(QMessageBox::Question); - confirm.exec(); - if (confirm.clickedButton() != q1) v = ""; + string v = pathConform(UTF8::qconvert(files.at(i))); + array->element(i) = stype->allocate(v); } + + NODE_RETURN((Pointer)array); } else { MuLangContext* context = static_cast(p->context()); - ExceptionType::Exception *e = + ExceptionType::Exception* e = new ExceptionType::Exception(context->exceptionType()); e->string() += "operation cancelled"; NODE_THREAD.setException(e); ProgramException exc(NODE_THREAD, e); throw exc; } - } - while (v.empty()); - - NODE_RETURN(stype->allocate(v)); -} - - -NODE_IMPLEMENTATION(setCursor, void) -{ - Session* s = Session::currentSession(); - RvDocument *rvDoc = (RvDocument *)s->opaquePointer(); - rvDoc->view()->setCursor(QCursor(Qt::CursorShape(NODE_ARG(0,int)))); -} - -NODE_IMPLEMENTATION(alertPanel, int) -{ - Session* s = Session::currentSession(); - RvDocument* doc = (RvDocument*)s->opaquePointer(); - Process* p = NODE_THREAD.process(); - bool sheet = NODE_ARG(0, bool); - int type = NODE_ARG(1, int); - const StringType::String* title = NODE_ARG_OBJECT(2, StringType::String); - const StringType::String* msg = NODE_ARG_OBJECT(3, StringType::String); - const StringType::String* b1 = NODE_ARG_OBJECT(4, StringType::String); - const StringType::String* b2 = NODE_ARG_OBJECT(5, StringType::String); - const StringType::String* b3 = NODE_ARG_OBJECT(6, StringType::String); - - QMessageBox box(doc); - QString temp = UTF8::qconvert(title->c_str()); - - if (msg && *msg != *title) - { - temp += "\n\n"; - temp += UTF8::qconvert(msg->c_str()); - } - - box.setWindowTitle(UTF8::qconvert(title->c_str())); - box.setText(temp); - //box.setDetailedText(QString(msg->c_str())); - -#ifdef PLATFORM_DARWIN - if (sheet) box.setWindowModality(Qt::WindowModal); -#else - box.setWindowModality(Qt::WindowModal); -#endif - - QPushButton* q1 = box.addButton(UTF8::qconvert(b1->c_str()), QMessageBox::AcceptRole); - QPushButton* q2 = b2 ? box.addButton(UTF8::qconvert(b2->c_str()), QMessageBox::RejectRole) : 0; - QPushButton* q3 = b3 ? box.addButton(UTF8::qconvert(b3->c_str()), QMessageBox::ApplyRole) : 0; - - switch (type) - { - case 0: - // Info - box.setIcon(QMessageBox::Information); - break; - - case 1: - // Warning - box.setIcon(QMessageBox::Warning); - break; - case 2: - // Error - box.setIcon(QMessageBox::Critical); - break; + NODE_RETURN((Pointer)0); } - doc->setDocumentDisabled(true, true); - box.exec(); - doc->setDocumentDisabled(false); + static map sessionToSaveDialog; - int result = 0; - - if (box.clickedButton() == q1 && b1) result = 0; - else if (box.clickedButton() == q2 && b2) result = 1; - else if (box.clickedButton() == q3 && b3) result = 2; - - doc->view()->setFocus(Qt::OtherFocusReason); - NODE_RETURN(result); -} - -NODE_IMPLEMENTATION(stereoSupported, bool) -{ - Session* s = Session::currentSession(); - RvDocument* doc = (RvDocument*)s->opaquePointer(); - - NODE_RETURN(true); -} - -NODE_IMPLEMENTATION(watchFile, void) -{ - Session* s = Session::currentSession(); - RvDocument* doc = (RvDocument*)s->opaquePointer(); - StringType::String* file = NODE_ARG_OBJECT(0, StringType::String); - bool watch = NODE_ARG(1, bool); - - if (watch) + NODE_IMPLEMENTATION(saveFileDialog, Pointer) { - doc->addWatchFile(file->c_str()); - } - else - { - doc->removeWatchFile(file->c_str()); - } -} - -NODE_IMPLEMENTATION(showNetworkDialog, void) -{ - RvApp()->networkWindow()->show(); - RvApp()->networkWindow()->raise(); -} + Session* s = Session::currentSession(); + RvDocument* rvDoc = (RvDocument*)s->opaquePointer(); + Process* p = NODE_THREAD.process(); + bool sheet = NODE_ARG(0, bool); + StringType::String* filter = NODE_ARG_OBJECT(1, StringType::String); + StringType::String* path = NODE_ARG_OBJECT(2, StringType::String); + bool directory = NODE_ARG(3, bool); -NODE_IMPLEMENTATION(showConsole, void) -{ - RvApp()->console()->show(); - RvApp()->console()->raise(); -} + const StringType* stype = + static_cast(NODE_THIS.type()); -NODE_IMPLEMENTATION(isConsoleVisible, bool) -{ - NODE_RETURN(RvApp()->console()->isVisible()); -} + FileTypeTraits* traits = 0; + bool hasSinglePair = false; -NODE_IMPLEMENTATION(remoteSendMessage, void) -{ - StringType::String* msg = NODE_ARG_OBJECT(0, StringType::String); - DynamicArray* recipients = NODE_ARG_OBJECT(1, DynamicArray); + if (filter) + { + QStringList parts; + QList> pairs; + parts = UTF8::qconvert(filter->c_str()).split("|"); - if (!msg) throw NilArgumentException(NODE_THREAD); + if (parts.size() == 1) + { + QString v = parts.front(); - if (TwkQtChat::Client* client = RvApp()->networkWindow()->client()) - { - if (recipients) - { - for (int i=0; i < recipients->size(); i++) + if (v != "*" && v != "") + { + pairs.push_back(qMakePair(v, v)); + } + } + else { - if (StringType::String* s = recipients->element(i)) + for (size_t i = 0; i < parts.size(); i += 2) { - client->sendMessage(s->c_str(), msg->c_str()); + pairs.push_back(qMakePair(parts[i], parts[i + 1])); } } + + traits = new MediaFileTypes(false, true, pairs); + + hasSinglePair = (pairs.size() == 1); } else { - client->broadcastMessage(msg->c_str()); + traits = new MediaFileTypes(false, true); } - } -} - -NODE_IMPLEMENTATION(remoteSendEvent, void) -{ - StringType::String* event = NODE_ARG_OBJECT(0, StringType::String); - StringType::String* target = NODE_ARG_OBJECT(1, StringType::String); - StringType::String* msg = NODE_ARG_OBJECT(2, StringType::String); - DynamicArray* recipients = NODE_ARG_OBJECT(3, DynamicArray); - - if (!msg || !target || !event) throw NilArgumentException(NODE_THREAD); - if (TwkQtChat::Client* client = RvApp()->networkWindow()->client()) - { - if (recipients) + if (sessionToSaveDialog.find(s) == sessionToSaveDialog.end()) { - for (int i=0; i < recipients->size(); i++) - { - if (StringType::String* s = recipients->element(i)) - { - client->sendEvent(s->c_str(), - event->c_str(), - target->c_str(), - msg->c_str()); - } - } + sessionToSaveDialog[s] = new RvFileDialog( + rvDoc, traits, RvFileDialog::SaveFileRole, + sheet ? Qt::Sheet : Qt::Dialog, "SaveFileDialog"); } else { - client->broadcastEvent(event->c_str(), - target->c_str(), - msg->c_str()); + sessionToSaveDialog[s]->setFileTypeTraits(traits); } - } -} -NODE_IMPLEMENTATION(remoteSendDataEvent, void) -{ - StringType::String* event = NODE_ARG_OBJECT(0, StringType::String); - StringType::String* target = NODE_ARG_OBJECT(1, StringType::String); - StringType::String* interp = NODE_ARG_OBJECT(2, StringType::String); - DynamicArray* array = NODE_ARG_OBJECT(3, DynamicArray); - DynamicArray* recipients = NODE_ARG_OBJECT(4, DynamicArray); - - if (!array || !interp || !target || !event ) throw NilArgumentException(NODE_THREAD); + RvFileDialog& dialog = *sessionToSaveDialog[s]; - string newInterp = string("DATAEVENT(") + event->c_str() + "," + target->c_str() + "," + interp->c_str() + ")"; + dialog.setFileMode((directory) ? RvFileDialog::OneDirectoryName + : RvFileDialog::OneFileName); - const unsigned char* datap = array->data(); - QByteArray qarray((const char *) datap, array->size()); + if (hasSinglePair) + dialog.setFileTypeIndex(2); + if (path) + dialog.setDirectory(UTF8::qconvert(path->c_str())); + dialog.setRole(RvFileDialog::SaveFileRole); + dialog.setTitleLabel(QString("Save to File")); + dialog.setViewMode(RvFileDialog::DetailedFileView); + dialog.lockViewMode(true); - if (TwkQtChat::Client* client = RvApp()->networkWindow()->client()) - { - if (recipients) + string v = ""; + do { - for (int i=0; i < recipients->size(); i++) + rvDoc->setDocumentDisabled(false, true); + bool result = dialog.exec(); + rvDoc->view()->setFocus(Qt::OtherFocusReason); + rvDoc->setDocumentDisabled(false, false); + + if (result) { - if (StringType::String* s = recipients->element(i)) + QStringList files; + files = dialog.selectedFiles(); + + v = pathConform(UTF8::qconvert(files.at(0))); + QFileInfo info(UTF8::qconvert(v.c_str())); + + // + // QFileInfo says a non-existant file is not writable, so have + // to check the directory in that case. + // + const bool isDirWritable = TwkUtil::isWritable( + UTF8::qconvert(info.absolutePath()).c_str()); + const bool isFileWritable = TwkUtil::isWritable(v.c_str()); + if ((!info.exists() && !isDirWritable) + || (info.exists() && !isFileWritable)) { - client->sendData(s->c_str(), newInterp.c_str(), qarray); + QString message = + QString("File '") + UTF8::qconvert(v.c_str()) + + "' is not writable; please check the permissions or " + "choose another location."; + QMessageBox confirm(QMessageBox::Warning, "Permissions", + message, QMessageBox::NoButton, rvDoc, + Qt::Sheet); + + QPushButton* q1 = + confirm.addButton("OK", QMessageBox::AcceptRole); + confirm.setIcon(QMessageBox::Question); + confirm.exec(); + v = ""; + } + else if (info.exists()) + { + QString message = QString("File '") + + UTF8::qconvert(v.c_str()) + + "' exists; overwrite ?"; + QMessageBox confirm(QMessageBox::Warning, "Overwrite", + message, QMessageBox::NoButton, rvDoc, + Qt::Sheet); + + QPushButton* q1 = + confirm.addButton("Overwrite", QMessageBox::AcceptRole); + QPushButton* q2 = + confirm.addButton("Cancel", QMessageBox::RejectRole); + confirm.setIcon(QMessageBox::Question); + confirm.exec(); + if (confirm.clickedButton() != q1) + v = ""; } } - } - } -} + else + { + MuLangContext* context = + static_cast(p->context()); + ExceptionType::Exception* e = + new ExceptionType::Exception(context->exceptionType()); + e->string() += "operation cancelled"; + NODE_THREAD.setException(e); + ProgramException exc(NODE_THREAD, e); + throw exc; + } + } while (v.empty()); -NODE_IMPLEMENTATION(remoteConnections, Pointer) -{ - Session* s = Session::currentSession(); - Process* p = NODE_THREAD.process(); - const DynamicArrayType* atype = static_cast(NODE_THIS.type()); - const StringType* stype = static_cast(atype->elementType()); - DynamicArray* array = new DynamicArray(atype, 1); - RvNetworkDialog* d = RvApp()->networkWindow(); - vector connections = d->connections(); - vector sessions = d->sessions(); - vector myConnections; + NODE_RETURN(stype->allocate(v)); + } - for (int i=0; i < connections.size(); i++) + NODE_IMPLEMENTATION(setCursor, void) { - if (sessions[i] == s->name()) myConnections.push_back(connections[i]); + Session* s = Session::currentSession(); + RvDocument* rvDoc = (RvDocument*)s->opaquePointer(); + rvDoc->view()->setCursor(QCursor(Qt::CursorShape(NODE_ARG(0, int)))); } - array->resize(myConnections.size()); - for (int i=0; i < myConnections.size(); i++) + NODE_IMPLEMENTATION(alertPanel, int) { - array->element(i) = stype->allocate(myConnections[i]); - } + Session* s = Session::currentSession(); + RvDocument* doc = (RvDocument*)s->opaquePointer(); + Process* p = NODE_THREAD.process(); + bool sheet = NODE_ARG(0, bool); + int type = NODE_ARG(1, int); + const StringType::String* title = + NODE_ARG_OBJECT(2, StringType::String); + const StringType::String* msg = NODE_ARG_OBJECT(3, StringType::String); + const StringType::String* b1 = NODE_ARG_OBJECT(4, StringType::String); + const StringType::String* b2 = NODE_ARG_OBJECT(5, StringType::String); + const StringType::String* b3 = NODE_ARG_OBJECT(6, StringType::String); + + QMessageBox box(doc); + QString temp = UTF8::qconvert(title->c_str()); + + if (msg && *msg != *title) + { + temp += "\n\n"; + temp += UTF8::qconvert(msg->c_str()); + } - NODE_RETURN(array); -} + box.setWindowTitle(UTF8::qconvert(title->c_str())); + box.setText(temp); + // box.setDetailedText(QString(msg->c_str())); -NODE_IMPLEMENTATION(remoteApplications, Pointer) -{ - Session* s = Session::currentSession(); - Process* p = NODE_THREAD.process(); - const DynamicArrayType* atype = static_cast(NODE_THIS.type()); - const StringType* stype = static_cast(atype->elementType()); - DynamicArray* array = new DynamicArray(atype, 1); - RvNetworkDialog* d = RvApp()->networkWindow(); - vector apps = d->applications(); +#ifdef PLATFORM_DARWIN + if (sheet) + box.setWindowModality(Qt::WindowModal); +#else + box.setWindowModality(Qt::WindowModal); +#endif - array->resize(apps.size()); + QPushButton* q1 = + box.addButton(UTF8::qconvert(b1->c_str()), QMessageBox::AcceptRole); + QPushButton* q2 = b2 ? box.addButton(UTF8::qconvert(b2->c_str()), + QMessageBox::RejectRole) + : 0; + QPushButton* q3 = b3 ? box.addButton(UTF8::qconvert(b3->c_str()), + QMessageBox::ApplyRole) + : 0; - for (int i=0; i < apps.size(); i++) - { - array->element(i) = stype->allocate(apps[i]); - } + switch (type) + { + case 0: + // Info + box.setIcon(QMessageBox::Information); + break; + + case 1: + // Warning + box.setIcon(QMessageBox::Warning); + break; + + case 2: + // Error + box.setIcon(QMessageBox::Critical); + break; + } - NODE_RETURN(array); -} + doc->setDocumentDisabled(true, true); + box.exec(); + doc->setDocumentDisabled(false); -NODE_IMPLEMENTATION(remoteContacts, Pointer) -{ - Session* s = Session::currentSession(); - Process* p = NODE_THREAD.process(); - const DynamicArrayType* atype = static_cast(NODE_THIS.type()); - const StringType* stype = static_cast(atype->elementType()); - DynamicArray* array = new DynamicArray(atype, 1); - RvNetworkDialog* d = RvApp()->networkWindow(); - vector contacts = d->contacts(); + int result = 0; - array->resize(contacts.size()); + if (box.clickedButton() == q1 && b1) + result = 0; + else if (box.clickedButton() == q2 && b2) + result = 1; + else if (box.clickedButton() == q3 && b3) + result = 2; - for (int i=0; i < contacts.size(); i++) - { - array->element(i) = stype->allocate(contacts[i]); + doc->view()->setFocus(Qt::OtherFocusReason); + NODE_RETURN(result); } - NODE_RETURN(array); -} - -NODE_IMPLEMENTATION(remoteLocalContactName, Pointer) -{ - const StringType* stype = static_cast(NODE_THIS.type()); - - NODE_RETURN(stype->allocate(RvApp()->networkWindow()->localContactName().c_str())); -} - -NODE_IMPLEMENTATION(setRemoteLocalContactName, void) -{ - const StringType::String* name = NODE_ARG_OBJECT(0, StringType::String); - - if (!name) throw NilArgumentException(NODE_THREAD); - - RvApp()->networkWindow()->setLocalContactName(name->c_str()); -} + NODE_IMPLEMENTATION(stereoSupported, bool) + { + Session* s = Session::currentSession(); + RvDocument* doc = (RvDocument*)s->opaquePointer(); -NODE_IMPLEMENTATION(remoteConnect, void) -{ - const StringType::String* name = NODE_ARG_OBJECT(0, StringType::String); - const StringType::String* host = NODE_ARG_OBJECT(1, StringType::String); - int port = NODE_ARG(2, int); + NODE_RETURN(true); + } - if (TwkQtChat::Client* client = RvApp()->networkWindow()->client()) + NODE_IMPLEMENTATION(watchFile, void) { - if (port) + Session* s = Session::currentSession(); + RvDocument* doc = (RvDocument*)s->opaquePointer(); + StringType::String* file = NODE_ARG_OBJECT(0, StringType::String); + bool watch = NODE_ARG(1, bool); + + if (watch) { - client->connectTo(name->c_str(), host->c_str(), port); + doc->addWatchFile(file->c_str()); } else { - client->connectTo(name->c_str(), host->c_str()); + doc->removeWatchFile(file->c_str()); } } -} - -NODE_IMPLEMENTATION(remoteDisconnect, void) -{ - StringType::String* name = NODE_ARG_OBJECT(0, StringType::String); - if (TwkQtChat::Client* client = RvApp()->networkWindow()->client()) + NODE_IMPLEMENTATION(showNetworkDialog, void) { - client->disconnectFrom(name->c_str()); + RvApp()->networkWindow()->show(); + RvApp()->networkWindow()->raise(); } -} - -NODE_IMPLEMENTATION(remoteNetwork, void) -{ - bool on = NODE_ARG(0, bool); - RvNetworkDialog* d = RvApp()->networkWindow(); - if (on) + NODE_IMPLEMENTATION(showConsole, void) { - if (!d->client()) d->toggleServer(); + RvApp()->console()->show(); + RvApp()->console()->raise(); } - else + + NODE_IMPLEMENTATION(isConsoleVisible, bool) { - if (d->client()) d->toggleServer(); + NODE_RETURN(RvApp()->console()->isVisible()); } -} - -NODE_IMPLEMENTATION(remoteConnectionIsIncoming, bool) -{ - StringType::String* name = NODE_ARG_OBJECT(0, StringType::String); - if (auto client = RvApp()->networkWindow()->client()) + NODE_IMPLEMENTATION(remoteSendMessage, void) { - return client->isIncoming(name->c_str()); + StringType::String* msg = NODE_ARG_OBJECT(0, StringType::String); + DynamicArray* recipients = NODE_ARG_OBJECT(1, DynamicArray); + + if (!msg) + throw NilArgumentException(NODE_THREAD); + + if (TwkQtChat::Client* client = RvApp()->networkWindow()->client()) + { + if (recipients) + { + for (int i = 0; i < recipients->size(); i++) + { + if (StringType::String* s = + recipients->element(i)) + { + client->sendMessage(s->c_str(), msg->c_str()); + } + } + } + else + { + client->broadcastMessage(msg->c_str()); + } + } } - return false; // network is not started -} + NODE_IMPLEMENTATION(remoteSendEvent, void) + { + StringType::String* event = NODE_ARG_OBJECT(0, StringType::String); + StringType::String* target = NODE_ARG_OBJECT(1, StringType::String); + StringType::String* msg = NODE_ARG_OBJECT(2, StringType::String); + DynamicArray* recipients = NODE_ARG_OBJECT(3, DynamicArray); -NODE_IMPLEMENTATION(spoofConnectionStream, void) -{ - StringType::String* name = NODE_ARG_OBJECT(0, StringType::String); - float timeScale = NODE_ARG(1, float); - bool verbose = NODE_ARG(2, bool); + if (!msg || !target || !event) + throw NilArgumentException(NODE_THREAD); - RvNetworkDialog* d = RvApp()->networkWindow(); + if (TwkQtChat::Client* client = RvApp()->networkWindow()->client()) + { + if (recipients) + { + for (int i = 0; i < recipients->size(); i++) + { + if (StringType::String* s = + recipients->element(i)) + { + client->sendEvent(s->c_str(), event->c_str(), + target->c_str(), msg->c_str()); + } + } + } + else + { + client->broadcastEvent(event->c_str(), target->c_str(), + msg->c_str()); + } + } + } - d->spoofConnectionStream (UTF8::qconvert(name->c_str()), timeScale, verbose); -} + NODE_IMPLEMENTATION(remoteSendDataEvent, void) + { + StringType::String* event = NODE_ARG_OBJECT(0, StringType::String); + StringType::String* target = NODE_ARG_OBJECT(1, StringType::String); + StringType::String* interp = NODE_ARG_OBJECT(2, StringType::String); + DynamicArray* array = NODE_ARG_OBJECT(3, DynamicArray); + DynamicArray* recipients = NODE_ARG_OBJECT(4, DynamicArray); -NODE_IMPLEMENTATION(remoteNetworkStatus, int) -{ - RvNetworkDialog* d = RvApp()->networkWindow(); - NODE_RETURN(d->client() ? 1 : 0); -} + if (!array || !interp || !target || !event) + throw NilArgumentException(NODE_THREAD); -NODE_IMPLEMENTATION(remoteDefaultPermission, int) -{ - NODE_RETURN(RvApp()->networkWindow()->defaultPermission()); -} + string newInterp = string("DATAEVENT(") + event->c_str() + "," + + target->c_str() + "," + interp->c_str() + ")"; -NODE_IMPLEMENTATION(setRemoteDefaultPermission, void) -{ - int perm = NODE_ARG(0, int); + const unsigned char* datap = array->data(); + QByteArray qarray((const char*)datap, array->size()); - NODE_RETURN(RvApp()->networkWindow()->setDefaultPermission(perm)); -} + if (TwkQtChat::Client* client = RvApp()->networkWindow()->client()) + { + if (recipients) + { + for (int i = 0; i < recipients->size(); i++) + { + if (StringType::String* s = + recipients->element(i)) + { + client->sendData(s->c_str(), newInterp.c_str(), qarray); + } + } + } + } + } -NODE_IMPLEMENTATION(writeSetting, void) -{ - StringType::String* group = NODE_ARG_OBJECT(0, StringType::String); - StringType::String* name = NODE_ARG_OBJECT(1, StringType::String); - VariantInstance* vobj = NODE_ARG_OBJECT(2, VariantInstance); - const VariantTagType* tt = vobj->tagType(); - const SettingsValueType* vtype = static_cast(tt->variantType()); - - QVariant value; - - switch (vtype->valueType(vobj)) - { - case SettingsValueType::NoType: - break; - case SettingsValueType::FloatType: - value.setValue(double(*vobj->data())); - break; - case SettingsValueType::IntType: - value.setValue(*vobj->data()); - break; - case SettingsValueType::StringType: - value.setValue(UTF8::qconvert(vobj->data()->c_str())); - break; - case SettingsValueType::BoolType: - value.setValue(*vobj->data()); - break; - case SettingsValueType::StringArrayType: - { - DynamicArray* array = vobj->data(); - QStringList list; - - for (size_t i = 0; i < array->size(); i++) - { - StringType::String* s = array->element(i); - list.push_back(s->c_str()); - } - - value.setValue(list); - } - break; - case SettingsValueType::IntArrayType: - { - DynamicArray* array = vobj->data(); - QList list; - - for (size_t i = 0; i < array->size(); i++) - { - list.push_back(QVariant(array->element(i))); - } - - value.setValue(list); - } - break; - case SettingsValueType::FloatArrayType: - { - DynamicArray* array = vobj->data(); - QList list; - - for (size_t i = 0; i < array->size(); i++) - { - list.push_back(QVariant(double(array->element(i)))); - } - - value.setValue(list); - } - break; - } - - RV_QSETTINGS; - - settings.beginGroup(UTF8::qconvert(group->c_str())); - settings.setValue(UTF8::qconvert(name->c_str()), value); - settings.endGroup(); -} - -static QVariant::Type -settingsTypeToQVariantType(SettingsValueType::ValueType t) -{ - switch (t) + NODE_IMPLEMENTATION(remoteConnections, Pointer) { - case SettingsValueType::FloatType: return QVariant::Double; - case SettingsValueType::IntType: return QVariant::Int; - case SettingsValueType::StringType: return QVariant::String; - case SettingsValueType::BoolType: return QVariant::Bool; - case SettingsValueType::FloatArrayType: return QVariant::List;// same as in - case SettingsValueType::IntArrayType: return QVariant::List; // same as float - case SettingsValueType::StringArrayType: return QVariant::StringList; - default: - break; - } + Session* s = Session::currentSession(); + Process* p = NODE_THREAD.process(); + const DynamicArrayType* atype = + static_cast(NODE_THIS.type()); + const StringType* stype = + static_cast(atype->elementType()); + DynamicArray* array = new DynamicArray(atype, 1); + RvNetworkDialog* d = RvApp()->networkWindow(); + vector connections = d->connections(); + vector sessions = d->sessions(); + vector myConnections; - return QVariant::List; -} + for (int i = 0; i < connections.size(); i++) + { + if (sessions[i] == s->name()) + myConnections.push_back(connections[i]); + } -NODE_IMPLEMENTATION(readSetting, Pointer) -{ - Process* p = NODE_THREAD.process(); - MuLangContext* c = static_cast(p->context()); - StringType::String* group = NODE_ARG_OBJECT(0, StringType::String); - StringType::String* name = NODE_ARG_OBJECT(1, StringType::String); - VariantInstance* defaultObj = NODE_ARG_OBJECT(2, VariantInstance); - const StringType* stype = static_cast(name->type()); + array->resize(myConnections.size()); + for (int i = 0; i < myConnections.size(); i++) + { + array->element(i) = + stype->allocate(myConnections[i]); + } - RV_QSETTINGS; + NODE_RETURN(array); + } - settings.beginGroup(UTF8::qconvert(group->c_str())); - if (!settings.contains(UTF8::qconvert(name->c_str()))) + NODE_IMPLEMENTATION(remoteApplications, Pointer) { - settings.endGroup(); - NODE_RETURN(defaultObj); - } - QVariant value = settings.value(UTF8::qconvert(name->c_str())); - settings.endGroup(); - - const SettingsValueType* vtype = - static_cast(NODE_THIS.type()); - - VariantInstance* vobj = 0; - QVariant::Type type = defaultObj ? settingsTypeToQVariantType(vtype->valueType(defaultObj)) - : value.type(); - - switch (type) - { - case QVariant::Bool: - vobj = VariantInstance::allocate(vtype->boolType()); - *vobj->data() = value.toBool(); - break; - case QVariant::Int: - vobj = VariantInstance::allocate(vtype->intType()); - *vobj->data() = value.toInt(); - break; - case QVariant::Double: - vobj = VariantInstance::allocate(vtype->floatType()); - *vobj->data() = value.toDouble(); - break; - case QVariant::String: - { - vobj = VariantInstance::allocate(vtype->stringType()); - StringType::String* s = vobj->data(); - s->set(value.toString().toUtf8().constData()); - } - break; - case QVariant::StringList: - { - // - // Creating it will also create the tagged object it - // contains. So we don't make a new DynamicArray we just - // get the one that was created. - // - vobj = VariantInstance::allocate(vtype->stringArrayType()); - DynamicArray* array = vobj->data(); - - QStringList list = value.toStringList(); - array->resize(list.size()); - - for (size_t i=0; i < array->size(); i++) - { - array->element(i) = - stype->allocate(list[i].toUtf8().constData()); - } - } - break; - case QVariant::List: - { - QVariantList list = value.toList(); - - if (list.empty()) throwBadArgumentException(NODE_THIS, - NODE_THREAD, - "Bad value in settings file"); - - QVariant one = list.front(); - bool isfloat = vtype->valueType(defaultObj) == SettingsValueType::FloatArrayType; - - vobj = VariantInstance::allocate(isfloat - ? vtype->floatArrayType() - : vtype->intArrayType()); - - DynamicArray* array = vobj->data(); - array->resize(list.size()); - - for (size_t i=0; i < array->size(); i++) - { - if (isfloat) - { - array->element(i) = float(list[i].toDouble()); - } - else - { - array->element(i) = list[i].toInt(); - } - } - } - break; - default: - break; - } - - NODE_RETURN(vobj); -} - -struct StringPairTupleStruct -{ - Mu::StringType::String* s0; - Mu::StringType::String* s1; -}; + Session* s = Session::currentSession(); + Process* p = NODE_THREAD.process(); + const DynamicArrayType* atype = + static_cast(NODE_THIS.type()); + const StringType* stype = + static_cast(atype->elementType()); + DynamicArray* array = new DynamicArray(atype, 1); + RvNetworkDialog* d = RvApp()->networkWindow(); + vector apps = d->applications(); -NODE_IMPLEMENTATION(httpGet, void) -{ - Process* p = NODE_THREAD.process(); - MuLangContext* c = static_cast(p->context()); - Session* s = Session::currentSession(); - StringType::String* url = NODE_ARG_OBJECT(0, StringType::String); - ClassInstance* hlist = NODE_ARG_OBJECT(1, ClassInstance); - StringType::String* replyEvent = NODE_ARG_OBJECT(2, StringType::String); - StringType::String* authEvent = NODE_ARG_OBJECT(3, StringType::String); - StringType::String* progEvent = NODE_ARG_OBJECT(4, StringType::String); - bool ignore = NODE_ARG(5, bool); - bool urlIsEncoded = NODE_ARG(6, bool); + array->resize(apps.size()); - RvWebManager::HeaderList headers; + for (int i = 0; i < apps.size(); i++) + { + array->element(i) = stype->allocate(apps[i]); + } - for (List list(p, hlist); !list.isNil(); list++) + NODE_RETURN(array); + } + + NODE_IMPLEMENTATION(remoteContacts, Pointer) { - if (ClassInstance* spair = list.value()) - { - const StringPairTupleStruct* sp = spair->data(); - if (!sp->s0 || !sp->s1) throwBadArgumentException(NODE_THIS, NODE_THREAD, "Bad header argument"); + Session* s = Session::currentSession(); + Process* p = NODE_THREAD.process(); + const DynamicArrayType* atype = + static_cast(NODE_THIS.type()); + const StringType* stype = + static_cast(atype->elementType()); + DynamicArray* array = new DynamicArray(atype, 1); + RvNetworkDialog* d = RvApp()->networkWindow(); + vector contacts = d->contacts(); + + array->resize(contacts.size()); - headers.push_back(QPair(UTF8::qconvert(sp->s0->c_str()), - UTF8::qconvert(sp->s1->c_str()))); + for (int i = 0; i < contacts.size(); i++) + { + array->element(i) = + stype->allocate(contacts[i]); } + + NODE_RETURN(array); } - if (RvWebManager* m = RvApp()->webManager()) + NODE_IMPLEMENTATION(remoteLocalContactName, Pointer) { - m->httpGet(UTF8::qconvert(url->c_str()), - headers, - s, - UTF8::qconvert(replyEvent ? replyEvent->c_str() : ""), - UTF8::qconvert(authEvent ? authEvent->c_str() : ""), - UTF8::qconvert(progEvent ? progEvent->c_str() : ""), - ignore, - urlIsEncoded); + const StringType* stype = + static_cast(NODE_THIS.type()); + + NODE_RETURN(stype->allocate( + RvApp()->networkWindow()->localContactName().c_str())); } -} -NODE_IMPLEMENTATION(httpPostString, void) -{ - Process* p = NODE_THREAD.process(); - MuLangContext* c = static_cast(p->context()); - Session* s = Session::currentSession(); - StringType::String* url = NODE_ARG_OBJECT(0, StringType::String); - ClassInstance* hlist = NODE_ARG_OBJECT(1, ClassInstance); - StringType::String* postString = NODE_ARG_OBJECT(2, StringType::String); - StringType::String* replyEvent = NODE_ARG_OBJECT(3, StringType::String); - StringType::String* authEvent = NODE_ARG_OBJECT(4, StringType::String); - StringType::String* progEvent = NODE_ARG_OBJECT(5, StringType::String); - bool ignore = NODE_ARG(6, bool); - bool urlIsEncoded = NODE_ARG(7, bool); + NODE_IMPLEMENTATION(setRemoteLocalContactName, void) + { + const StringType::String* name = NODE_ARG_OBJECT(0, StringType::String); + + if (!name) + throw NilArgumentException(NODE_THREAD); - RvWebManager::HeaderList headers; + RvApp()->networkWindow()->setLocalContactName(name->c_str()); + } - for (List list(p, hlist); !list.isNil(); list++) + NODE_IMPLEMENTATION(remoteConnect, void) { - if (ClassInstance* spair = list.value()) - { - const StringPairTupleStruct* sp = spair->data(); - if (!sp->s0 || !sp->s1) throwBadArgumentException(NODE_THIS, NODE_THREAD, "Bad header argument"); + const StringType::String* name = NODE_ARG_OBJECT(0, StringType::String); + const StringType::String* host = NODE_ARG_OBJECT(1, StringType::String); + int port = NODE_ARG(2, int); - headers.push_back(QPair(UTF8::qconvert(sp->s0->c_str()), - UTF8::qconvert(sp->s1->c_str()))); + if (TwkQtChat::Client* client = RvApp()->networkWindow()->client()) + { + if (port) + { + client->connectTo(name->c_str(), host->c_str(), port); + } + else + { + client->connectTo(name->c_str(), host->c_str()); + } } } - if (RvWebManager* m = RvApp()->webManager()) + NODE_IMPLEMENTATION(remoteDisconnect, void) { - m->httpPost(url->c_str(), - headers, - postString ? QByteArray(postString->c_str()) : QByteArray(), - s, - UTF8::qconvert(replyEvent ? replyEvent->c_str() : ""), - UTF8::qconvert(authEvent ? authEvent->c_str() : ""), - UTF8::qconvert(progEvent ? progEvent->c_str() : ""), - ignore, - urlIsEncoded); + StringType::String* name = NODE_ARG_OBJECT(0, StringType::String); + + if (TwkQtChat::Client* client = RvApp()->networkWindow()->client()) + { + client->disconnectFrom(name->c_str()); + } } -} -NODE_IMPLEMENTATION(httpPostData, void) -{ - Process* p = NODE_THREAD.process(); - MuLangContext* c = static_cast(p->context()); - Session* s = Session::currentSession(); - StringType::String* url = NODE_ARG_OBJECT(0, StringType::String); - ClassInstance* hlist = NODE_ARG_OBJECT(1, ClassInstance); - DynamicArray* postData = NODE_ARG_OBJECT(2, DynamicArray); - StringType::String* replyEvent = NODE_ARG_OBJECT(3, StringType::String); - StringType::String* authEvent = NODE_ARG_OBJECT(4, StringType::String); - StringType::String* progEvent = NODE_ARG_OBJECT(5, StringType::String); - bool ignore = NODE_ARG(6, bool); - bool urlIsEncoded = NODE_ARG(7, bool); + NODE_IMPLEMENTATION(remoteNetwork, void) + { + bool on = NODE_ARG(0, bool); + RvNetworkDialog* d = RvApp()->networkWindow(); - RvWebManager::HeaderList headers; + if (on) + { + if (!d->client()) + d->toggleServer(); + } + else + { + if (d->client()) + d->toggleServer(); + } + } - for (List list(p, hlist); !list.isNil(); list++) + NODE_IMPLEMENTATION(remoteConnectionIsIncoming, bool) { - if (ClassInstance* spair = list.value()) - { - const StringPairTupleStruct* sp = spair->data(); - if (!sp->s0 || !sp->s1) throwBadArgumentException(NODE_THIS, NODE_THREAD, "Bad header argument"); + StringType::String* name = NODE_ARG_OBJECT(0, StringType::String); - headers.push_back(QPair(UTF8::qconvert(sp->s0->c_str()), - UTF8::qconvert(sp->s1->c_str()))); + if (auto client = RvApp()->networkWindow()->client()) + { + return client->isIncoming(name->c_str()); } + + return false; // network is not started } - if (RvWebManager* m = RvApp()->webManager()) + NODE_IMPLEMENTATION(spoofConnectionStream, void) { - const unsigned char* datap = (postData) ? postData->data() : 0; + StringType::String* name = NODE_ARG_OBJECT(0, StringType::String); + float timeScale = NODE_ARG(1, float); + bool verbose = NODE_ARG(2, bool); + + RvNetworkDialog* d = RvApp()->networkWindow(); - m->httpPost(url->c_str(), - headers, - postData ? QByteArray((const char *) datap, postData->size()) : QByteArray(), - s, - UTF8::qconvert(replyEvent ? replyEvent->c_str() : ""), - UTF8::qconvert(authEvent ? authEvent->c_str() : ""), - UTF8::qconvert(progEvent ? progEvent->c_str() : ""), - ignore, - urlIsEncoded); + d->spoofConnectionStream(UTF8::qconvert(name->c_str()), timeScale, + verbose); } -} -NODE_IMPLEMENTATION(httpPutString, void) -{ - Process* p = NODE_THREAD.process(); - MuLangContext* c = static_cast(p->context()); - Session* s = Session::currentSession(); - StringType::String* url = NODE_ARG_OBJECT(0, StringType::String); - ClassInstance* hlist = NODE_ARG_OBJECT(1, ClassInstance); - StringType::String* putString = NODE_ARG_OBJECT(2, StringType::String); - StringType::String* replyEvent = NODE_ARG_OBJECT(3, StringType::String); - StringType::String* authEvent = NODE_ARG_OBJECT(4, StringType::String); - StringType::String* progEvent = NODE_ARG_OBJECT(5, StringType::String); - bool ignore = NODE_ARG(6, bool); - bool urlIsEncoded = NODE_ARG(7, bool); + NODE_IMPLEMENTATION(remoteNetworkStatus, int) + { + RvNetworkDialog* d = RvApp()->networkWindow(); + NODE_RETURN(d->client() ? 1 : 0); + } - RvWebManager::HeaderList headers; + NODE_IMPLEMENTATION(remoteDefaultPermission, int) + { + NODE_RETURN(RvApp()->networkWindow()->defaultPermission()); + } - for (List list(p, hlist); !list.isNil(); list++) + NODE_IMPLEMENTATION(setRemoteDefaultPermission, void) { - if (ClassInstance* spair = list.value()) - { - const StringPairTupleStruct* sp = spair->data(); - if (!sp->s0 || !sp->s1) throwBadArgumentException(NODE_THIS, NODE_THREAD, "Bad header argument"); + int perm = NODE_ARG(0, int); - headers.push_back(QPair(UTF8::qconvert(sp->s0->c_str()), - UTF8::qconvert(sp->s1->c_str()))); - } + NODE_RETURN(RvApp()->networkWindow()->setDefaultPermission(perm)); } - if (RvWebManager* m = RvApp()->webManager()) + NODE_IMPLEMENTATION(writeSetting, void) { - m->httpPut( UTF8::qconvert(url->c_str()), - headers, - putString ? QByteArray(putString->c_str()) : QByteArray(), - s, - UTF8::qconvert(replyEvent ? replyEvent->c_str() : ""), - UTF8::qconvert(authEvent ? authEvent->c_str() : ""), - UTF8::qconvert(progEvent ? progEvent->c_str() : ""), - ignore, - urlIsEncoded); - } -} + StringType::String* group = NODE_ARG_OBJECT(0, StringType::String); + StringType::String* name = NODE_ARG_OBJECT(1, StringType::String); + VariantInstance* vobj = NODE_ARG_OBJECT(2, VariantInstance); + const VariantTagType* tt = vobj->tagType(); + const SettingsValueType* vtype = + static_cast(tt->variantType()); -NODE_IMPLEMENTATION(httpPutData, void) -{ - Process* p = NODE_THREAD.process(); - MuLangContext* c = static_cast(p->context()); - Session* s = Session::currentSession(); - StringType::String* url = NODE_ARG_OBJECT(0, StringType::String); - ClassInstance* hlist = NODE_ARG_OBJECT(1, ClassInstance); - DynamicArray* putData = NODE_ARG_OBJECT(2, DynamicArray); - StringType::String* replyEvent = NODE_ARG_OBJECT(3, StringType::String); - StringType::String* authEvent = NODE_ARG_OBJECT(4, StringType::String); - StringType::String* progEvent = NODE_ARG_OBJECT(5, StringType::String); - bool ignore = NODE_ARG(6, bool); - bool urlIsEncoded = NODE_ARG(7, bool); + QVariant value; - RvWebManager::HeaderList headers; + switch (vtype->valueType(vobj)) + { + case SettingsValueType::NoType: + break; + case SettingsValueType::FloatType: + value.setValue(double(*vobj->data())); + break; + case SettingsValueType::IntType: + value.setValue(*vobj->data()); + break; + case SettingsValueType::StringType: + value.setValue( + UTF8::qconvert(vobj->data()->c_str())); + break; + case SettingsValueType::BoolType: + value.setValue(*vobj->data()); + break; + case SettingsValueType::StringArrayType: + { + DynamicArray* array = vobj->data(); + QStringList list; - for (List list(p, hlist); !list.isNil(); list++) - { - if (ClassInstance* spair = list.value()) + for (size_t i = 0; i < array->size(); i++) + { + StringType::String* s = array->element(i); + list.push_back(s->c_str()); + } + + value.setValue(list); + } + break; + case SettingsValueType::IntArrayType: { - const StringPairTupleStruct* sp = spair->data(); - if (!sp->s0 || !sp->s1) throwBadArgumentException(NODE_THIS, NODE_THREAD, "Bad header argument"); + DynamicArray* array = vobj->data(); + QList list; - headers.push_back(QPair(UTF8::qconvert(sp->s0->c_str()), - UTF8::qconvert(sp->s1->c_str()))); + for (size_t i = 0; i < array->size(); i++) + { + list.push_back(QVariant(array->element(i))); + } + + value.setValue(list); + } + break; + case SettingsValueType::FloatArrayType: + { + DynamicArray* array = vobj->data(); + QList list; + + for (size_t i = 0; i < array->size(); i++) + { + list.push_back(QVariant(double(array->element(i)))); + } + + value.setValue(list); + } + break; } + + RV_QSETTINGS; + + settings.beginGroup(UTF8::qconvert(group->c_str())); + settings.setValue(UTF8::qconvert(name->c_str()), value); + settings.endGroup(); } - if (RvWebManager* m = RvApp()->webManager()) + static QVariant::Type + settingsTypeToQVariantType(SettingsValueType::ValueType t) { - const unsigned char* datap = (putData) ? putData->data() : 0; + switch (t) + { + case SettingsValueType::FloatType: + return QVariant::Double; + case SettingsValueType::IntType: + return QVariant::Int; + case SettingsValueType::StringType: + return QVariant::String; + case SettingsValueType::BoolType: + return QVariant::Bool; + case SettingsValueType::FloatArrayType: + return QVariant::List; // same as in + case SettingsValueType::IntArrayType: + return QVariant::List; // same as float + case SettingsValueType::StringArrayType: + return QVariant::StringList; + default: + break; + } - m->httpPut( UTF8::qconvert(url->c_str()), - headers, - putData ? QByteArray((const char *) datap, putData->size()) : QByteArray(), - s, - UTF8::qconvert(replyEvent ? replyEvent->c_str() : ""), - UTF8::qconvert(authEvent ? authEvent->c_str() : ""), - UTF8::qconvert(progEvent ? progEvent->c_str() : ""), - ignore, - urlIsEncoded); + return QVariant::List; } -} - -NODE_IMPLEMENTATION(mainWindowWidget, Pointer) -{ - Process* p = NODE_THREAD.process(); - MuLangContext* c = static_cast(p->context()); - Session* s = Session::currentSession(); - RvDocument* doc = reinterpret_cast(s->opaquePointer()); - const QMainWindowType* type = - c->findSymbolOfTypeByQualifiedName - (c->internName("qt.QMainWindow"), false); + NODE_IMPLEMENTATION(readSetting, Pointer) + { + Process* p = NODE_THREAD.process(); + MuLangContext* c = static_cast(p->context()); + StringType::String* group = NODE_ARG_OBJECT(0, StringType::String); + StringType::String* name = NODE_ARG_OBJECT(1, StringType::String); + VariantInstance* defaultObj = NODE_ARG_OBJECT(2, VariantInstance); + const StringType* stype = static_cast(name->type()); - NODE_RETURN(makeinstance(type, static_cast(doc))); -} + RV_QSETTINGS; -NODE_IMPLEMENTATION(mainViewWidget, Pointer) -{ - Process* p = NODE_THREAD.process(); - MuLangContext* c = static_cast(p->context()); - Session* s = Session::currentSession(); - RvDocument* doc = reinterpret_cast(s->opaquePointer()); - QWidget* w = doc->view(); + settings.beginGroup(UTF8::qconvert(group->c_str())); + if (!settings.contains(UTF8::qconvert(name->c_str()))) + { + settings.endGroup(); + NODE_RETURN(defaultObj); + } + QVariant value = settings.value(UTF8::qconvert(name->c_str())); + settings.endGroup(); - const QWidgetType* type = - c->findSymbolOfTypeByQualifiedName - (c->internName("qt.QWidget"), false); + const SettingsValueType* vtype = + static_cast(NODE_THIS.type()); - NODE_RETURN(makeinstance(type, static_cast(w))); -} + VariantInstance* vobj = 0; + QVariant::Type type = + defaultObj + ? settingsTypeToQVariantType(vtype->valueType(defaultObj)) + : value.type(); -NODE_IMPLEMENTATION(prefTabWidget, Pointer) -{ - Process* p = NODE_THREAD.process(); - MuLangContext* c = static_cast(p->context()); - Session* s = Session::currentSession(); + switch (type) + { + case QVariant::Bool: + vobj = VariantInstance::allocate(vtype->boolType()); + *vobj->data() = value.toBool(); + break; + case QVariant::Int: + vobj = VariantInstance::allocate(vtype->intType()); + *vobj->data() = value.toInt(); + break; + case QVariant::Double: + vobj = VariantInstance::allocate(vtype->floatType()); + *vobj->data() = value.toDouble(); + break; + case QVariant::String: + { + vobj = VariantInstance::allocate(vtype->stringType()); + StringType::String* s = vobj->data(); + s->set(value.toString().toUtf8().constData()); + } + break; + case QVariant::StringList: + { + // + // Creating it will also create the tagged object it + // contains. So we don't make a new DynamicArray we just + // get the one that was created. + // + vobj = VariantInstance::allocate(vtype->stringArrayType()); + DynamicArray* array = vobj->data(); - QTabWidget* w = RvApp()->prefDialog()->tabWidget(); + QStringList list = value.toStringList(); + array->resize(list.size()); - const QTabWidgetType* type = - c->findSymbolOfTypeByQualifiedName - (c->internName("qt.QTabWidget"), false); + for (size_t i = 0; i < array->size(); i++) + { + array->element(i) = + stype->allocate(list[i].toUtf8().constData()); + } + } + break; + case QVariant::List: + { + QVariantList list = value.toList(); - NODE_RETURN(makeinstance(type, w)); -} + if (list.empty()) + throwBadArgumentException(NODE_THIS, NODE_THREAD, + "Bad value in settings file"); -NODE_IMPLEMENTATION(sessionBottomToolBar, Pointer) -{ - Process* p = NODE_THREAD.process(); - MuLangContext* c = static_cast(p->context()); - Session* s = Session::currentSession(); - RvDocument* doc = reinterpret_cast(s->opaquePointer()); + QVariant one = list.front(); + bool isfloat = vtype->valueType(defaultObj) + == SettingsValueType::FloatArrayType; - QToolBar* toolBar = doc->bottomViewToolBar(); + vobj = VariantInstance::allocate(isfloat ? vtype->floatArrayType() + : vtype->intArrayType()); - const QToolBarType* type = - c->findSymbolOfTypeByQualifiedName - (c->internName("qt.QToolBar"), false); + DynamicArray* array = vobj->data(); + array->resize(list.size()); - NODE_RETURN(makeinstance(type, toolBar)); -} + for (size_t i = 0; i < array->size(); i++) + { + if (isfloat) + { + array->element(i) = float(list[i].toDouble()); + } + else + { + array->element(i) = list[i].toInt(); + } + } + } + break; + default: + break; + } -NODE_IMPLEMENTATION(networkAccessManager, Pointer) -{ - Process* p = NODE_THREAD.process(); - MuLangContext* c = static_cast(p->context()); - Session* s = Session::currentSession(); - RvWebManager* m = RvApp()->webManager(); + NODE_RETURN(vobj); + } - const QNetworkAccessManagerType* type = - c->findSymbolOfTypeByQualifiedName - (c->internName("qt.QNetworkAccessManager"), false); + struct StringPairTupleStruct + { + Mu::StringType::String* s0; + Mu::StringType::String* s1; + }; - NODE_RETURN(makeinstance(type, static_cast(m->netManager()))); -} + NODE_IMPLEMENTATION(httpGet, void) + { + Process* p = NODE_THREAD.process(); + MuLangContext* c = static_cast(p->context()); + Session* s = Session::currentSession(); + StringType::String* url = NODE_ARG_OBJECT(0, StringType::String); + ClassInstance* hlist = NODE_ARG_OBJECT(1, ClassInstance); + StringType::String* replyEvent = NODE_ARG_OBJECT(2, StringType::String); + StringType::String* authEvent = NODE_ARG_OBJECT(3, StringType::String); + StringType::String* progEvent = NODE_ARG_OBJECT(4, StringType::String); + bool ignore = NODE_ARG(5, bool); + bool urlIsEncoded = NODE_ARG(6, bool); -NODE_IMPLEMENTATION(javascriptMuExport, void) -{ - Process* p = NODE_THREAD.process(); - MuLangContext* c = static_cast(p->context()); - Session* s = Session::currentSession(); - RvDocument* doc = reinterpret_cast(s->opaquePointer()); + RvWebManager::HeaderList headers; - QWebEnginePage* frame = Mu::object(NODE_ARG_OBJECT(0, ClassInstance)); + for (List list(p, hlist); !list.isNil(); list++) + { + if (ClassInstance* spair = list.value()) + { + const StringPairTupleStruct* sp = + spair->data(); + if (!sp->s0 || !sp->s1) + throwBadArgumentException(NODE_THIS, NODE_THREAD, + "Bad header argument"); + + headers.push_back( + QPair(UTF8::qconvert(sp->s0->c_str()), + UTF8::qconvert(sp->s1->c_str()))); + } + } - RvJavaScriptObject* obj = new RvJavaScriptObject(doc, frame); -} + if (RvWebManager* m = RvApp()->webManager()) + { + m->httpGet(UTF8::qconvert(url->c_str()), headers, s, + UTF8::qconvert(replyEvent ? replyEvent->c_str() : ""), + UTF8::qconvert(authEvent ? authEvent->c_str() : ""), + UTF8::qconvert(progEvent ? progEvent->c_str() : ""), + ignore, urlIsEncoded); + } + } -NODE_IMPLEMENTATION(sessionFromUrl, void) -{ - StringType::String* url = NODE_ARG_OBJECT(0, StringType::String); + NODE_IMPLEMENTATION(httpPostString, void) + { + Process* p = NODE_THREAD.process(); + MuLangContext* c = static_cast(p->context()); + Session* s = Session::currentSession(); + StringType::String* url = NODE_ARG_OBJECT(0, StringType::String); + ClassInstance* hlist = NODE_ARG_OBJECT(1, ClassInstance); + StringType::String* postString = NODE_ARG_OBJECT(2, StringType::String); + StringType::String* replyEvent = NODE_ARG_OBJECT(3, StringType::String); + StringType::String* authEvent = NODE_ARG_OBJECT(4, StringType::String); + StringType::String* progEvent = NODE_ARG_OBJECT(5, StringType::String); + bool ignore = NODE_ARG(6, bool); + bool urlIsEncoded = NODE_ARG(7, bool); + + RvWebManager::HeaderList headers; + + for (List list(p, hlist); !list.isNil(); list++) + { + if (ClassInstance* spair = list.value()) + { + const StringPairTupleStruct* sp = + spair->data(); + if (!sp->s0 || !sp->s1) + throwBadArgumentException(NODE_THIS, NODE_THREAD, + "Bad header argument"); + + headers.push_back( + QPair(UTF8::qconvert(sp->s0->c_str()), + UTF8::qconvert(sp->s1->c_str()))); + } + } - if (!url) throw NilArgumentException(NODE_THREAD); + if (RvWebManager* m = RvApp()->webManager()) + { + m->httpPost( + url->c_str(), headers, + postString ? QByteArray(postString->c_str()) : QByteArray(), s, + UTF8::qconvert(replyEvent ? replyEvent->c_str() : ""), + UTF8::qconvert(authEvent ? authEvent->c_str() : ""), + UTF8::qconvert(progEvent ? progEvent->c_str() : ""), ignore, + urlIsEncoded); + } + } - RvApp()->sessionFromUrl(url->c_str()); -} + NODE_IMPLEMENTATION(httpPostData, void) + { + Process* p = NODE_THREAD.process(); + MuLangContext* c = static_cast(p->context()); + Session* s = Session::currentSession(); + StringType::String* url = NODE_ARG_OBJECT(0, StringType::String); + ClassInstance* hlist = NODE_ARG_OBJECT(1, ClassInstance); + DynamicArray* postData = NODE_ARG_OBJECT(2, DynamicArray); + StringType::String* replyEvent = NODE_ARG_OBJECT(3, StringType::String); + StringType::String* authEvent = NODE_ARG_OBJECT(4, StringType::String); + StringType::String* progEvent = NODE_ARG_OBJECT(5, StringType::String); + bool ignore = NODE_ARG(6, bool); + bool urlIsEncoded = NODE_ARG(7, bool); + + RvWebManager::HeaderList headers; + + for (List list(p, hlist); !list.isNil(); list++) + { + if (ClassInstance* spair = list.value()) + { + const StringPairTupleStruct* sp = + spair->data(); + if (!sp->s0 || !sp->s1) + throwBadArgumentException(NODE_THIS, NODE_THREAD, + "Bad header argument"); + + headers.push_back( + QPair(UTF8::qconvert(sp->s0->c_str()), + UTF8::qconvert(sp->s1->c_str()))); + } + } + if (RvWebManager* m = RvApp()->webManager()) + { + const unsigned char* datap = + (postData) ? postData->data() : 0; + + m->httpPost( + url->c_str(), headers, + postData ? QByteArray((const char*)datap, postData->size()) + : QByteArray(), + s, UTF8::qconvert(replyEvent ? replyEvent->c_str() : ""), + UTF8::qconvert(authEvent ? authEvent->c_str() : ""), + UTF8::qconvert(progEvent ? progEvent->c_str() : ""), ignore, + urlIsEncoded); + } + } -NODE_IMPLEMENTATION(putUrlOnClipboard, void) -{ - StringType::String* url = NODE_ARG_OBJECT(0, StringType::String); - StringType::String* title = NODE_ARG_OBJECT(1, StringType::String); - bool doEncode = NODE_ARG(2, bool); + NODE_IMPLEMENTATION(httpPutString, void) + { + Process* p = NODE_THREAD.process(); + MuLangContext* c = static_cast(p->context()); + Session* s = Session::currentSession(); + StringType::String* url = NODE_ARG_OBJECT(0, StringType::String); + ClassInstance* hlist = NODE_ARG_OBJECT(1, ClassInstance); + StringType::String* putString = NODE_ARG_OBJECT(2, StringType::String); + StringType::String* replyEvent = NODE_ARG_OBJECT(3, StringType::String); + StringType::String* authEvent = NODE_ARG_OBJECT(4, StringType::String); + StringType::String* progEvent = NODE_ARG_OBJECT(5, StringType::String); + bool ignore = NODE_ARG(6, bool); + bool urlIsEncoded = NODE_ARG(7, bool); + + RvWebManager::HeaderList headers; + + for (List list(p, hlist); !list.isNil(); list++) + { + if (ClassInstance* spair = list.value()) + { + const StringPairTupleStruct* sp = + spair->data(); + if (!sp->s0 || !sp->s1) + throwBadArgumentException(NODE_THIS, NODE_THREAD, + "Bad header argument"); + + headers.push_back( + QPair(UTF8::qconvert(sp->s0->c_str()), + UTF8::qconvert(sp->s1->c_str()))); + } + } - if (!url) throw NilArgumentException(NODE_THREAD); + if (RvWebManager* m = RvApp()->webManager()) + { + m->httpPut(UTF8::qconvert(url->c_str()), headers, + putString ? QByteArray(putString->c_str()) + : QByteArray(), + s, UTF8::qconvert(replyEvent ? replyEvent->c_str() : ""), + UTF8::qconvert(authEvent ? authEvent->c_str() : ""), + UTF8::qconvert(progEvent ? progEvent->c_str() : ""), + ignore, urlIsEncoded); + } + } - RvApp()->putUrlOnClipboard(url->c_str(), - title->c_str(), - doEncode); + NODE_IMPLEMENTATION(httpPutData, void) + { + Process* p = NODE_THREAD.process(); + MuLangContext* c = static_cast(p->context()); + Session* s = Session::currentSession(); + StringType::String* url = NODE_ARG_OBJECT(0, StringType::String); + ClassInstance* hlist = NODE_ARG_OBJECT(1, ClassInstance); + DynamicArray* putData = NODE_ARG_OBJECT(2, DynamicArray); + StringType::String* replyEvent = NODE_ARG_OBJECT(3, StringType::String); + StringType::String* authEvent = NODE_ARG_OBJECT(4, StringType::String); + StringType::String* progEvent = NODE_ARG_OBJECT(5, StringType::String); + bool ignore = NODE_ARG(6, bool); + bool urlIsEncoded = NODE_ARG(7, bool); + + RvWebManager::HeaderList headers; + + for (List list(p, hlist); !list.isNil(); list++) + { + if (ClassInstance* spair = list.value()) + { + const StringPairTupleStruct* sp = + spair->data(); + if (!sp->s0 || !sp->s1) + throwBadArgumentException(NODE_THIS, NODE_THREAD, + "Bad header argument"); + + headers.push_back( + QPair(UTF8::qconvert(sp->s0->c_str()), + UTF8::qconvert(sp->s1->c_str()))); + } + } - /* - NO WORKY + if (RvWebManager* m = RvApp()->webManager()) + { + const unsigned char* datap = + (putData) ? putData->data() : 0; + + m->httpPut(UTF8::qconvert(url->c_str()), headers, + putData ? QByteArray((const char*)datap, putData->size()) + : QByteArray(), + s, UTF8::qconvert(replyEvent ? replyEvent->c_str() : ""), + UTF8::qconvert(authEvent ? authEvent->c_str() : ""), + UTF8::qconvert(progEvent ? progEvent->c_str() : ""), + ignore, urlIsEncoded); + } + } - QUrl qurl; - qurl.setScheme("rvlink"); - qurl.setUrl (url->c_str(), QUrl::TolerantMode); - cerr << "made QUrl from '" << url->c_str() << "', valid " << qurl.isValid() << endl; - QList qlist; - qlist.append (qurl); + NODE_IMPLEMENTATION(mainWindowWidget, Pointer) + { + Process* p = NODE_THREAD.process(); + MuLangContext* c = static_cast(p->context()); + Session* s = Session::currentSession(); + RvDocument* doc = reinterpret_cast(s->opaquePointer()); - // XXX memory leak, but a tiny one. - QMimeData *qmd = new QMimeData(); + const QMainWindowType* type = + c->findSymbolOfTypeByQualifiedName( + c->internName("qt.QMainWindow"), false); - qmd->setUrls(qlist); - qmd->setText(url->c_str()); + NODE_RETURN(makeinstance(type, static_cast(doc))); + } - QApplication::clipboard()->setMimeData(qmd); - */ -} + NODE_IMPLEMENTATION(mainViewWidget, Pointer) + { + Process* p = NODE_THREAD.process(); + MuLangContext* c = static_cast(p->context()); + Session* s = Session::currentSession(); + RvDocument* doc = reinterpret_cast(s->opaquePointer()); + QWidget* w = doc->view(); -NODE_IMPLEMENTATION(myNetworkPort, int) -{ - NODE_RETURN(RvApp()->networkWindow()->myPort()); -} + const QWidgetType* type = + c->findSymbolOfTypeByQualifiedName( + c->internName("qt.QWidget"), false); -NODE_IMPLEMENTATION(myNetworkHost, Pointer) -{ - const StringType* stype = static_cast(NODE_THIS.type()); - StringType::String* str = 0; + NODE_RETURN(makeinstance(type, static_cast(w))); + } - Options& opts = Options::sharedOptions(); - if (opts.networkHost) + NODE_IMPLEMENTATION(prefTabWidget, Pointer) { - str = stype->allocate(opts.networkHost); + Process* p = NODE_THREAD.process(); + MuLangContext* c = static_cast(p->context()); + Session* s = Session::currentSession(); + + QTabWidget* w = RvApp()->prefDialog()->tabWidget(); + + const QTabWidgetType* type = + c->findSymbolOfTypeByQualifiedName( + c->internName("qt.QTabWidget"), false); + + NODE_RETURN(makeinstance(type, w)); } - else + + NODE_IMPLEMENTATION(sessionBottomToolBar, Pointer) { - QString host = QHostInfo::localHostName(); - // - // On max os x 10.6, the returned "local" name is actually - // the fully-qualified domain name. So trim it. - // - QStringList parts = host.split("."); - host = parts[0]; + Process* p = NODE_THREAD.process(); + MuLangContext* c = static_cast(p->context()); + Session* s = Session::currentSession(); + RvDocument* doc = reinterpret_cast(s->opaquePointer()); - QString domain = QHostInfo::localDomainName(); - if (domain.size()) host = host + "." + domain; + QToolBar* toolBar = doc->bottomViewToolBar(); - str = stype->allocate(UTF8::qconvert(host)); + const QToolBarType* type = + c->findSymbolOfTypeByQualifiedName( + c->internName("qt.QToolBar"), false); + + NODE_RETURN(makeinstance(type, toolBar)); } - NODE_RETURN(str); -} -// -// Wing-dinging 32-bit encryption ! -// + NODE_IMPLEMENTATION(networkAccessManager, Pointer) + { + Process* p = NODE_THREAD.process(); + MuLangContext* c = static_cast(p->context()); + Session* s = Session::currentSession(); + RvWebManager* m = RvApp()->webManager(); -NODE_IMPLEMENTATION(encodePassword, Pointer) -{ - StringType::String* pass = NODE_ARG_OBJECT(0, StringType::String); - const StringType* stype = static_cast(NODE_THIS.type()); + const QNetworkAccessManagerType* type = + c->findSymbolOfTypeByQualifiedName( + c->internName("qt.QNetworkAccessManager"), false); - string enc = TwkQtBase::encode(pass->c_str()); + NODE_RETURN(makeinstance( + type, static_cast(m->netManager()))); + } - NODE_RETURN(stype->allocate(enc.c_str())); -} + NODE_IMPLEMENTATION(javascriptMuExport, void) + { + Process* p = NODE_THREAD.process(); + MuLangContext* c = static_cast(p->context()); + Session* s = Session::currentSession(); + RvDocument* doc = reinterpret_cast(s->opaquePointer()); -NODE_IMPLEMENTATION(decodePassword, Pointer) -{ - StringType::String* pass = NODE_ARG_OBJECT(0, StringType::String); - const StringType* stype = static_cast(NODE_THIS.type()); + QWebEnginePage* frame = + Mu::object(NODE_ARG_OBJECT(0, ClassInstance)); - if (!pass) + RvJavaScriptObject* obj = new RvJavaScriptObject(doc, frame); + } + + NODE_IMPLEMENTATION(sessionFromUrl, void) { - throwBadArgumentException(NODE_THIS, NODE_THREAD, "Null password could not be decoded."); + StringType::String* url = NODE_ARG_OBJECT(0, StringType::String); + + if (!url) + throw NilArgumentException(NODE_THREAD); + + RvApp()->sessionFromUrl(url->c_str()); } - string dec = TwkQtBase::decode(pass->c_str()); + NODE_IMPLEMENTATION(putUrlOnClipboard, void) + { + StringType::String* url = NODE_ARG_OBJECT(0, StringType::String); + StringType::String* title = NODE_ARG_OBJECT(1, StringType::String); + bool doEncode = NODE_ARG(2, bool); - NODE_RETURN(stype->allocate(dec.c_str())); -} + if (!url) + throw NilArgumentException(NODE_THREAD); -NODE_IMPLEMENTATION(cacheDir, Pointer) -{ - const StringType* stype = static_cast(NODE_THIS.type()); + RvApp()->putUrlOnClipboard(url->c_str(), title->c_str(), doEncode); - QStringList cacheLocations = QStandardPaths::standardLocations(QStandardPaths::CacheLocation); - QDir cacheDir(cacheLocations.front()); + /* + NO WORKY - if (!cacheDir.exists()) cacheDir.mkpath(cacheDir.absolutePath()); + QUrl qurl; + qurl.setScheme("rvlink"); + qurl.setUrl (url->c_str(), QUrl::TolerantMode); + cerr << "made QUrl from '" << url->c_str() << "', valid " << + qurl.isValid() << endl; QList qlist; qlist.append (qurl); - NODE_RETURN(stype->allocate(cacheDir.absolutePath().toUtf8().constData())); -} + // XXX memory leak, but a tiny one. + QMimeData *qmd = new QMimeData(); -namespace { + qmd->setUrls(qlist); + qmd->setText(url->c_str()); -void -openUrlWithDesktopServices (const Mu::Node& node, Mu::Thread& thread, QUrl& qurl) -{ - #ifdef PLATFORM_LINUX - string pathS; - const char* path = getenv("LD_LIBRARY_PATH"); - if (path) pathS = path; - unsetenv ("LD_LIBRARY_PATH"); - #endif + QApplication::clipboard()->setMimeData(qmd); + */ + } + + NODE_IMPLEMENTATION(myNetworkPort, int) + { + NODE_RETURN(RvApp()->networkWindow()->myPort()); + } - if (qurl.isValid()) QDesktopServices::openUrl(qurl); - else throwBadArgumentException(node, thread, "QUrl argument is not valid"); + NODE_IMPLEMENTATION(myNetworkHost, Pointer) + { + const StringType* stype = + static_cast(NODE_THIS.type()); + StringType::String* str = 0; - #ifdef PLATFORM_LINUX - if (path) setenv ("LD_LIBRARY_PATH", pathS.c_str(), 1); - #endif -} + Options& opts = Options::sharedOptions(); + if (opts.networkHost) + { + str = stype->allocate(opts.networkHost); + } + else + { + QString host = QHostInfo::localHostName(); + // + // On max os x 10.6, the returned "local" name is actually + // the fully-qualified domain name. So trim it. + // + QStringList parts = host.split("."); + host = parts[0]; -} + QString domain = QHostInfo::localDomainName(); + if (domain.size()) + host = host + "." + domain; -NODE_IMPLEMENTATION(openUrl, void) -{ - StringType::String* url = NODE_ARG_OBJECT(0, StringType::String); - QUrl qurl(url->c_str()); + str = stype->allocate(UTF8::qconvert(host)); + } + NODE_RETURN(str); + } - openUrlWithDesktopServices(NODE_THIS, NODE_THREAD, qurl); -} + // + // Wing-dinging 32-bit encryption ! + // -NODE_IMPLEMENTATION(openUrlFromUrl, void) -{ - Process* p = NODE_THREAD.process(); - MuLangContext* c = static_cast(p->context()); + NODE_IMPLEMENTATION(encodePassword, Pointer) + { + StringType::String* pass = NODE_ARG_OBJECT(0, StringType::String); + const StringType* stype = + static_cast(NODE_THIS.type()); - Pointer qp = NODE_ARG(0, Pointer); + string enc = TwkQtBase::encode(pass->c_str()); - if (!qp) throwBadArgumentException(NODE_THIS, NODE_THREAD, "Nil QUrl argument"); + NODE_RETURN(stype->allocate(enc.c_str())); + } - QUrl& qurl = getqtype(qp); + NODE_IMPLEMENTATION(decodePassword, Pointer) + { + StringType::String* pass = NODE_ARG_OBJECT(0, StringType::String); + const StringType* stype = + static_cast(NODE_THIS.type()); - openUrlWithDesktopServices(NODE_THIS, NODE_THREAD, qurl); -} + if (!pass) + { + throwBadArgumentException(NODE_THIS, NODE_THREAD, + "Null password could not be decoded."); + } -NODE_IMPLEMENTATION(setPresentationMode, void) -{ - bool value = NODE_ARG(0, bool); + string dec = TwkQtBase::decode(pass->c_str()); - // - // Turning presentation mode on/off may mean that - // we want to cache different frame buffers, so - // kick cache to be sure we recache if necessary. - // - Session* s = Session::currentSession(); - Session::CachingMode mode = s->cachingMode(); - s->setCaching(Session::NeverCache); + NODE_RETURN(stype->allocate(dec.c_str())); + } - if (RvApp()->documents().size() == 1) + NODE_IMPLEMENTATION(cacheDir, Pointer) { - RvApp()->setPresentationMode(value); + const StringType* stype = + static_cast(NODE_THIS.type()); + + QStringList cacheLocations = + QStandardPaths::standardLocations(QStandardPaths::CacheLocation); + QDir cacheDir(cacheLocations.front()); + + if (!cacheDir.exists()) + cacheDir.mkpath(cacheDir.absolutePath()); + + NODE_RETURN( + stype->allocate(cacheDir.absolutePath().toUtf8().constData())); } - else if (value) + + namespace { - Session* s = Session::currentSession(); - RvDocument *rvDoc = (RvDocument *)s->opaquePointer(); - QString message = "Cannot start presentation mode when multiple sessions are active"; - QMessageBox confirm(QMessageBox::Warning, - "Presentation Mode", - message, - QMessageBox::NoButton, rvDoc, Qt::Sheet); + void openUrlWithDesktopServices(const Mu::Node& node, + Mu::Thread& thread, QUrl& qurl) + { +#ifdef PLATFORM_LINUX + string pathS; + const char* path = getenv("LD_LIBRARY_PATH"); + if (path) + pathS = path; + unsetenv("LD_LIBRARY_PATH"); +#endif + + if (qurl.isValid()) + QDesktopServices::openUrl(qurl); + else + throwBadArgumentException(node, thread, + "QUrl argument is not valid"); + +#ifdef PLATFORM_LINUX + if (path) + setenv("LD_LIBRARY_PATH", pathS.c_str(), 1); +#endif + } + + } // namespace + + NODE_IMPLEMENTATION(openUrl, void) + { + StringType::String* url = NODE_ARG_OBJECT(0, StringType::String); + QUrl qurl(url->c_str()); - QPushButton* q1 = confirm.addButton("Ok", QMessageBox::AcceptRole); - confirm.setIcon(QMessageBox::Warning); - confirm.exec(); + openUrlWithDesktopServices(NODE_THIS, NODE_THREAD, qurl); } - s->setCaching(mode); -} + NODE_IMPLEMENTATION(openUrlFromUrl, void) + { + Process* p = NODE_THREAD.process(); + MuLangContext* c = static_cast(p->context()); -NODE_IMPLEMENTATION(presentationMode, bool) -{ - NODE_RETURN(RvApp()->isInPresentationMode()); -} + Pointer qp = NODE_ARG(0, Pointer); -NODE_IMPLEMENTATION(packageListFromSetting, Pointer) -{ - StringType::String* setting = NODE_ARG_OBJECT(0, StringType::String); - const DynamicArrayType* atype = static_cast(NODE_THIS.type()); - const StringType* stype = static_cast(atype->elementType()); - DynamicArray* array = new DynamicArray(atype, 1); + if (!qp) + throwBadArgumentException(NODE_THIS, NODE_THREAD, + "Nil QUrl argument"); - if (!setting) throwBadArgumentException(NODE_THIS, NODE_THREAD, "Nil setting name."); + QUrl& qurl = getqtype(qp); - RV_QSETTINGS; + openUrlWithDesktopServices(NODE_THIS, NODE_THREAD, qurl); + } - settings.beginGroup("ModeManager"); + NODE_IMPLEMENTATION(setPresentationMode, void) + { + bool value = NODE_ARG(0, bool); - QStringList l = Rv::PackageManager::swapAppDir(settings.value (setting->c_str(), QStringList()).toStringList(), false); + // + // Turning presentation mode on/off may mean that + // we want to cache different frame buffers, so + // kick cache to be sure we recache if necessary. + // + Session* s = Session::currentSession(); + Session::CachingMode mode = s->cachingMode(); + s->setCaching(Session::NeverCache); - settings.endGroup(); + if (RvApp()->documents().size() == 1) + { + RvApp()->setPresentationMode(value); + } + else if (value) + { + Session* s = Session::currentSession(); + RvDocument* rvDoc = (RvDocument*)s->opaquePointer(); + + QString message = "Cannot start presentation mode when multiple " + "sessions are active"; + QMessageBox confirm(QMessageBox::Warning, "Presentation Mode", + message, QMessageBox::NoButton, rvDoc, + Qt::Sheet); + + QPushButton* q1 = confirm.addButton("Ok", QMessageBox::AcceptRole); + confirm.setIcon(QMessageBox::Warning); + confirm.exec(); + } + + s->setCaching(mode); + } - array->resize (l.size()); - for (int i = 0; i < l.size(); i++) + NODE_IMPLEMENTATION(presentationMode, bool) { - array->element(i) = stype->allocate(UTF8::qconvert(l[i])); + NODE_RETURN(RvApp()->isInPresentationMode()); } - NODE_RETURN(array); -} + NODE_IMPLEMENTATION(packageListFromSetting, Pointer) + { + StringType::String* setting = NODE_ARG_OBJECT(0, StringType::String); + const DynamicArrayType* atype = + static_cast(NODE_THIS.type()); + const StringType* stype = + static_cast(atype->elementType()); + DynamicArray* array = new DynamicArray(atype, 1); -NODE_IMPLEMENTATION(showTopViewToolbar, void) -{ - Session* s = Session::currentSession(); - RvDocument* doc = reinterpret_cast(s->opaquePointer()); - bool value = NODE_ARG(0, bool); - doc->topViewToolBar()->makeActive(value); -} + if (!setting) + throwBadArgumentException(NODE_THIS, NODE_THREAD, + "Nil setting name."); -NODE_IMPLEMENTATION(isTopViewToolbarVisible, bool) -{ - Session* s = Session::currentSession(); - RvDocument* doc = reinterpret_cast(s->opaquePointer()); - NODE_RETURN(doc->topViewToolBar()->isVisible()); -} + RV_QSETTINGS; -NODE_IMPLEMENTATION(showBottomViewToolbar, void) -{ - Session* s = Session::currentSession(); - RvDocument* doc = reinterpret_cast(s->opaquePointer()); - bool value = NODE_ARG(0, bool); - doc->bottomViewToolBar()->makeActive(value); -} + settings.beginGroup("ModeManager"); -NODE_IMPLEMENTATION(isBottomViewToolbarVisible, bool) -{ - Session* s = Session::currentSession(); - RvDocument* doc = reinterpret_cast(s->opaquePointer()); - NODE_RETURN(doc->bottomViewToolBar()->isVisible()); -} + QStringList l = Rv::PackageManager::swapAppDir( + settings.value(setting->c_str(), QStringList()).toStringList(), + false); -NODE_IMPLEMENTATION(editNodeSource, void) -{ - Session* s = Session::currentSession(); - RvDocument* doc = reinterpret_cast(s->opaquePointer()); - StringType::String* node = NODE_ARG_OBJECT(0, StringType::String); + settings.endGroup(); - if (node) + array->resize(l.size()); + for (int i = 0; i < l.size(); i++) + { + array->element(i) = + stype->allocate(UTF8::qconvert(l[i])); + } + + NODE_RETURN(array); + } + + NODE_IMPLEMENTATION(showTopViewToolbar, void) { - doc->editSourceNode(node->c_str()); + Session* s = Session::currentSession(); + RvDocument* doc = reinterpret_cast(s->opaquePointer()); + bool value = NODE_ARG(0, bool); + doc->topViewToolBar()->makeActive(value); } - else + + NODE_IMPLEMENTATION(isTopViewToolbarVisible, bool) { - throwBadArgumentException(NODE_THIS, NODE_THREAD, "valid nodeName required"); + Session* s = Session::currentSession(); + RvDocument* doc = reinterpret_cast(s->opaquePointer()); + NODE_RETURN(doc->topViewToolBar()->isVisible()); } -} -NODE_IMPLEMENTATION(editProfiles, void) -{ - RvApp()->profileManager()->show(); -} + NODE_IMPLEMENTATION(showBottomViewToolbar, void) + { + Session* s = Session::currentSession(); + RvDocument* doc = reinterpret_cast(s->opaquePointer()); + bool value = NODE_ARG(0, bool); + doc->bottomViewToolBar()->makeActive(value); + } -NODE_IMPLEMENTATION(validateShotgunToken, Mu::Pointer) -{ - int index = NODE_ARG(0, int); - StringType::String* tag = NODE_ARG_OBJECT(1, StringType::String); + NODE_IMPLEMENTATION(isBottomViewToolbarVisible, bool) + { + Session* s = Session::currentSession(); + RvDocument* doc = reinterpret_cast(s->opaquePointer()); + NODE_RETURN(doc->bottomViewToolBar()->isVisible()); + } - Process* p = NODE_THREAD.process(); - MuLangContext* context = static_cast(p->context()); - const StringType* stype = context->stringType(); + NODE_IMPLEMENTATION(editNodeSource, void) + { + Session* s = Session::currentSession(); + RvDocument* doc = reinterpret_cast(s->opaquePointer()); + StringType::String* node = NODE_ARG_OBJECT(0, StringType::String); - // Note: This is no longer relevant in RV Open Source but kept to maintain - // backward compatibility. - string err = ""; + if (node) + { + doc->editSourceNode(node->c_str()); + } + else + { + throwBadArgumentException(NODE_THIS, NODE_THREAD, + "valid nodeName required"); + } + } - NODE_RETURN(stype->allocate(err)); -} + NODE_IMPLEMENTATION(editProfiles, void) + { + RvApp()->profileManager()->show(); + } -NODE_IMPLEMENTATION(launchTLI, void) -{ - // Note: This is no longer relevant in RV Open Source but kept to maintain - // backward compatibility. -} + NODE_IMPLEMENTATION(validateShotgunToken, Mu::Pointer) + { + int index = NODE_ARG(0, int); + StringType::String* tag = NODE_ARG_OBJECT(1, StringType::String); -NODE_IMPLEMENTATION(rvioSetup, void) -{ - // Note: This is no longer relevant in RV Open Source but kept to maintain - // backward compatibility. -} + Process* p = NODE_THREAD.process(); + MuLangContext* context = static_cast(p->context()); + const StringType* stype = context->stringType(); + + // Note: This is no longer relevant in RV Open Source but kept to + // maintain backward compatibility. + string err = ""; + + NODE_RETURN(stype->allocate(err)); + } + + NODE_IMPLEMENTATION(launchTLI, void) + { + // Note: This is no longer relevant in RV Open Source but kept to + // maintain backward compatibility. + } + + NODE_IMPLEMENTATION(rvioSetup, void) + { + // Note: This is no longer relevant in RV Open Source but kept to + // maintain backward compatibility. + } -} // Rv namespace +} // namespace Rv diff --git a/src/lib/app/RvCommon/PermDelegate.cpp b/src/lib/app/RvCommon/PermDelegate.cpp index d6e2efdf5..7a5758995 100644 --- a/src/lib/app/RvCommon/PermDelegate.cpp +++ b/src/lib/app/RvCommon/PermDelegate.cpp @@ -1,71 +1,72 @@ // -// Copyright (c) 2008 Tweak Software. +// Copyright (c) 2008 Tweak Software. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// // #include #include #include -namespace Rv { -using namespace std; - -PermDelegate::PermDelegate(QObject *parent) : QItemDelegate(parent) +namespace Rv { -} + using namespace std; -QWidget* -PermDelegate::createEditor(QWidget *parent, - const QStyleOptionViewItem &/* option */, - const QModelIndex &/* index */) const -{ - return new QComboBox(parent); -} + PermDelegate::PermDelegate(QObject* parent) + : QItemDelegate(parent) + { + } -void -PermDelegate::setEditorData(QWidget *editor, - const QModelIndex &index) const -{ - int value = index.model()->data(index, Qt::EditRole).toInt(); + QWidget* + PermDelegate::createEditor(QWidget* parent, + const QStyleOptionViewItem& /* option */, + const QModelIndex& /* index */) const + { + return new QComboBox(parent); + } - const QStandardItemModel* m = - static_cast(index.model()); + void PermDelegate::setEditorData(QWidget* editor, + const QModelIndex& index) const + { + int value = index.model()->data(index, Qt::EditRole).toInt(); - QComboBox *box = static_cast(editor); - box->addItem("Ask"); - box->addItem("Allow"); - box->addItem("Reject"); + const QStandardItemModel* m = + static_cast(index.model()); - QStandardItem* i = m->item(index.row(), index.column()); + QComboBox* box = static_cast(editor); + box->addItem("Ask"); + box->addItem("Allow"); + box->addItem("Reject"); - if (i->text() == "Ask") box->setCurrentIndex(0); - else if (i->text() == "Allow") box->setCurrentIndex(1); - else if (i->text() == "Reject") box->setCurrentIndex(2); -} + QStandardItem* i = m->item(index.row(), index.column()); -void -PermDelegate::setModelData(QWidget *editor, - QAbstractItemModel *model, - const QModelIndex &index) const -{ - QComboBox *cbox = static_cast(editor); - QStandardItemModel* m = static_cast(model); - QStandardItem* i = m->item(index.row(), index.column()); - i->setText(cbox->itemText(cbox->currentIndex())); + if (i->text() == "Ask") + box->setCurrentIndex(0); + else if (i->text() == "Allow") + box->setCurrentIndex(1); + else if (i->text() == "Reject") + box->setCurrentIndex(2); + } - // Just to make it signal - m->setData(index, i->text(), Qt::EditRole); -} + void PermDelegate::setModelData(QWidget* editor, QAbstractItemModel* model, + const QModelIndex& index) const + { + QComboBox* cbox = static_cast(editor); + QStandardItemModel* m = static_cast(model); + QStandardItem* i = m->item(index.row(), index.column()); + i->setText(cbox->itemText(cbox->currentIndex())); -void -PermDelegate::updateEditorGeometry(QWidget *editor, - const QStyleOptionViewItem &option, - const QModelIndex &/* index */) const -{ - editor->setGeometry(option.rect); -} + // Just to make it signal + m->setData(index, i->text(), Qt::EditRole); + } + void + PermDelegate::updateEditorGeometry(QWidget* editor, + const QStyleOptionViewItem& option, + const QModelIndex& /* index */) const + { + editor->setGeometry(option.rect); + } -} // Rv +} // namespace Rv diff --git a/src/lib/app/RvCommon/PyUICommands.cpp b/src/lib/app/RvCommon/PyUICommands.cpp index 9e82c0540..31de9dfdf 100644 --- a/src/lib/app/RvCommon/PyUICommands.cpp +++ b/src/lib/app/RvCommon/PyUICommands.cpp @@ -1,9 +1,9 @@ // // Copyright (c) 2011 Tweak Software. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// // #ifdef PLATFORM_WINDOWS @@ -41,441 +41,411 @@ #include #include // WINDOWS NEEDS THIS LAST -namespace Rv { -using namespace std; -using namespace TwkApp; -using namespace IPCore; - -static PyObject* -badArgument() -{ - PyErr_SetString(PyExc_Exception, "Bad argument"); - return NULL; -} - - -static QVariant::Type -pyTypeToQVariantType(PyObject* obj) +namespace Rv { - if (PyBool_Check(obj)) return QVariant::Bool; - else if (PyLong_Check(obj)) return QVariant::Int; - else if (PyFloat_Check(obj)) return QVariant::Double; - else if (PyBytes_Check(obj)) return QVariant::String; - else if (PyUnicode_Check(obj)) return QVariant::String; - else if (PyList_Check(obj)) return QVariant::List; - return QVariant::List; -} - -static PyObject* -qvariantToPyObject(QVariant::Type type, const QVariant& value) -{ - // - // As far as I can tell, all these functions "pass ownership" of a reference - // to the calling code, so we must INCREF the pyobject we return. - // - - PyObject* ret = Py_None; + using namespace std; + using namespace TwkApp; + using namespace IPCore; - switch (type) + static PyObject* badArgument() { - case QVariant::Bool: - ret = value.toBool() ? Py_True : Py_False; - break; - case QVariant::Int: - ret = PyLong_FromLong(value.toInt()); - break; - case QVariant::Double: - case QMetaType::Float: // does this happen? - ret = PyFloat_FromDouble(value.toDouble()); - break; - case QVariant::String: - { - // - // No you can't do this all in one step! if you go all the way - // from qvar to const char*, the const char* often points at - // '\0' or garbage. - // - QByteArray ba = value.toString().toUtf8(); - const char* s = ba.constData(); - ret = PyUnicode_DecodeUTF8(s, strlen(s), "ignore"); - } - break; - case QVariant::StringList: - { - QStringList list = value.toStringList(); - PyObject* pylist = PyList_New(list.size()); - - for (size_t i=0; i < list.size(); i++) - { - QByteArray ba = list[i].toUtf8(); - const char* s = ba.constData(); - PyList_SetItem(pylist, i, PyUnicode_DecodeUTF8(s, strlen(s), "ignore")); - } - - ret = pylist; - } - break; - case QVariant::List: - { - QVariantList list = value.toList(); - PyObject* pylist = PyList_New(list.size()); - - for (size_t i=0; i < list.size(); i++) - { - PyList_SetItem(pylist, i, qvariantToPyObject(list[i].type(), list[i])); - } - - ret = pylist; - } - default: - break; + PyErr_SetString(PyExc_Exception, "Bad argument"); + return NULL; } - Py_XINCREF(ret); - return ret; -} - -static QVariant -pyObjectToQVariant(PyObject* pyobj) -{ - if (PyBool_Check(pyobj)) return QVariant(pyobj == Py_True ? true : false); - else if (PyLong_Check(pyobj)) return QVariant(int(PyLong_AsLong(pyobj))); - else if (PyFloat_Check(pyobj)) return QVariant(PyFloat_AsDouble(pyobj)); - else if (PyBytes_Check(pyobj)) return QVariant(QString(PyBytes_AsString(pyobj))); - else if (PyUnicode_Check(pyobj)) + static QVariant::Type pyTypeToQVariantType(PyObject* obj) { - PyObject* utf8 = PyUnicode_AsUTF8String(pyobj); - QString qs = QString::fromUtf8(PyBytes_AsString(utf8)); - Py_XDECREF(utf8); - return QVariant(qs); + if (PyBool_Check(obj)) + return QVariant::Bool; + else if (PyLong_Check(obj)) + return QVariant::Int; + else if (PyFloat_Check(obj)) + return QVariant::Double; + else if (PyBytes_Check(obj)) + return QVariant::String; + else if (PyUnicode_Check(obj)) + return QVariant::String; + else if (PyList_Check(obj)) + return QVariant::List; + return QVariant::List; } - else if (PyList_Check(pyobj)) + + static PyObject* qvariantToPyObject(QVariant::Type type, + const QVariant& value) { - QVariantList list; - size_t n = PyList_Size(pyobj); + // + // As far as I can tell, all these functions "pass ownership" of a + // reference to the calling code, so we must INCREF the pyobject we + // return. + // - for (size_t i = 0; i < n; i++) + PyObject* ret = Py_None; + + switch (type) + { + case QVariant::Bool: + ret = value.toBool() ? Py_True : Py_False; + break; + case QVariant::Int: + ret = PyLong_FromLong(value.toInt()); + break; + case QVariant::Double: + case QMetaType::Float: // does this happen? + ret = PyFloat_FromDouble(value.toDouble()); + break; + case QVariant::String: { - list.append(pyObjectToQVariant(PyList_GetItem(pyobj, i))); + // + // No you can't do this all in one step! if you go all the way + // from qvar to const char*, the const char* often points at + // '\0' or garbage. + // + QByteArray ba = value.toString().toUtf8(); + const char* s = ba.constData(); + ret = PyUnicode_DecodeUTF8(s, strlen(s), "ignore"); } + break; + case QVariant::StringList: + { + QStringList list = value.toStringList(); + PyObject* pylist = PyList_New(list.size()); + + for (size_t i = 0; i < list.size(); i++) + { + QByteArray ba = list[i].toUtf8(); + const char* s = ba.constData(); + PyList_SetItem(pylist, i, + PyUnicode_DecodeUTF8(s, strlen(s), "ignore")); + } + + ret = pylist; + } + break; + case QVariant::List: + { + QVariantList list = value.toList(); + PyObject* pylist = PyList_New(list.size()); - return QVariant(list); - } - - return QVariant(); -} + for (size_t i = 0; i < list.size(); i++) + { + PyList_SetItem(pylist, i, + qvariantToPyObject(list[i].type(), list[i])); + } -static PyObject * -readSettings(PyObject *self, PyObject* args) -{ - PyLockObject locker; - const char* group; - const char* name; - PyObject* defaultObj; + ret = pylist; + } + default: + break; + } - if (!PyArg_ParseTuple(args, "ssO", &group, &name, &defaultObj)) - { - return NULL; + Py_XINCREF(ret); + return ret; } - if (!defaultObj || defaultObj == Py_None) + static QVariant pyObjectToQVariant(PyObject* pyobj) { - // THROW EXCEPTION - PyErr_SetString(PyExc_Exception, "readSettings: default return value is None or undefined, but must match setting type"); - return NULL; - } - PyObject* ret = defaultObj; - - RV_QSETTINGS; - settings.beginGroup(group); - - if (!settings.contains(name)) { - Py_XINCREF(ret); - } else { - QVariant value = settings.value(name); - QVariant::Type type = pyTypeToQVariantType(defaultObj); - ret = qvariantToPyObject(type, value); - } - settings.endGroup(); + if (PyBool_Check(pyobj)) + return QVariant(pyobj == Py_True ? true : false); + else if (PyLong_Check(pyobj)) + return QVariant(int(PyLong_AsLong(pyobj))); + else if (PyFloat_Check(pyobj)) + return QVariant(PyFloat_AsDouble(pyobj)); + else if (PyBytes_Check(pyobj)) + return QVariant(QString(PyBytes_AsString(pyobj))); + else if (PyUnicode_Check(pyobj)) + { + PyObject* utf8 = PyUnicode_AsUTF8String(pyobj); + QString qs = QString::fromUtf8(PyBytes_AsString(utf8)); + Py_XDECREF(utf8); + return QVariant(qs); + } + else if (PyList_Check(pyobj)) + { + QVariantList list; + size_t n = PyList_Size(pyobj); - return ret; -} + for (size_t i = 0; i < n; i++) + { + list.append(pyObjectToQVariant(PyList_GetItem(pyobj, i))); + } -static PyObject * -writeSettings(PyObject *self, PyObject* args) -{ - PyLockObject locker; - const char* group; - const char* name; - PyObject* value; + return QVariant(list); + } - if (!PyArg_ParseTuple(args, "ssO", &group, &name, &value)) - { - return NULL; + return QVariant(); } - if (!value) return NULL; - RV_QSETTINGS; + static PyObject* readSettings(PyObject* self, PyObject* args) + { + PyLockObject locker; + const char* group; + const char* name; + PyObject* defaultObj; - settings.beginGroup(group); - settings.setValue(name, pyObjectToQVariant(value)); - settings.endGroup(); + if (!PyArg_ParseTuple(args, "ssO", &group, &name, &defaultObj)) + { + return NULL; + } - Py_RETURN_NONE; -} + if (!defaultObj || defaultObj == Py_None) + { + // THROW EXCEPTION + PyErr_SetString(PyExc_Exception, + "readSettings: default return value is None or " + "undefined, but must match setting type"); + return NULL; + } + PyObject* ret = defaultObj; -static void -popupMenuInternal (PyObject* pylist, QPoint& location) -{ - Session *s = Session::currentSession(); - RvDocument *rvDoc = (RvDocument *)s->opaquePointer(); + RV_QSETTINGS; + settings.beginGroup(group); - s->receivingEvents(false); + if (!settings.contains(name)) + { + Py_XINCREF(ret); + } + else + { + QVariant value = settings.value(name); + QVariant::Type type = pyTypeToQVariantType(defaultObj); + ret = qvariantToPyObject(type, value); + } + settings.endGroup(); - QPoint p = rvDoc->view()->mapToGlobal(location); + return ret; + } - if (pylist) + static PyObject* writeSettings(PyObject* self, PyObject* args) { - if (TwkApp::Menu* m = pyListToMenu("temp", pylist)) + PyLockObject locker; + const char* group; + const char* name; + PyObject* value; + + if (!PyArg_ParseTuple(args, "ssO", &group, &name, &value)) { - rvDoc->popupMenu(m, p); + return NULL; } - } - else - { - rvDoc->mainPopup()->popup(p); - } -} + if (!value) + return NULL; -static PyObject * -popupMenu(PyObject *self, PyObject* args) -{ - PyLockObject locker; - Session *s = Session::currentSession(); - RvDocument *rvDoc = (RvDocument *)s->opaquePointer(); - PyEventObject* event; - PyObject* pylist; + RV_QSETTINGS; - if (!PyArg_ParseTuple(args, "O!O!", pyEventType(), &event, &PyList_Type, &pylist)) { - return NULL; - } + settings.beginGroup(group); + settings.setValue(name, pyObjectToQVariant(value)); + settings.endGroup(); - QPoint lp; + Py_RETURN_NONE; + } - if (const TwkApp::PointerEvent* pevent = - dynamic_cast(event->event)) + static void popupMenuInternal(PyObject* pylist, QPoint& location) { - lp = QPoint(pevent->x(), rvDoc->view()->height() - pevent->y() - 1); + Session* s = Session::currentSession(); + RvDocument* rvDoc = (RvDocument*)s->opaquePointer(); + + s->receivingEvents(false); + + QPoint p = rvDoc->view()->mapToGlobal(location); + + if (pylist) + { + if (TwkApp::Menu* m = pyListToMenu("temp", pylist)) + { + rvDoc->popupMenu(m, p); + } + } + else + { + rvDoc->mainPopup()->popup(p); + } } - else + + static PyObject* popupMenu(PyObject* self, PyObject* args) { - lp = QPoint(0, rvDoc->view()->height() - 1); - } + PyLockObject locker; + Session* s = Session::currentSession(); + RvDocument* rvDoc = (RvDocument*)s->opaquePointer(); + PyEventObject* event; + PyObject* pylist; + + if (!PyArg_ParseTuple(args, "O!O!", pyEventType(), &event, &PyList_Type, + &pylist)) + { + return NULL; + } - popupMenuInternal (pylist, lp); + QPoint lp; - Py_XINCREF(Py_None); - return Py_None; -} + if (const TwkApp::PointerEvent* pevent = + dynamic_cast(event->event)) + { + lp = QPoint(pevent->x(), rvDoc->view()->height() - pevent->y() - 1); + } + else + { + lp = QPoint(0, rvDoc->view()->height() - 1); + } -static PyObject * -popupMenuAtPoint(PyObject *self, PyObject* args) -{ - PyLockObject locker; - Session *s = Session::currentSession(); - RvDocument *rvDoc = (RvDocument *)s->opaquePointer(); - int x, y; - PyObject* pylist; + popupMenuInternal(pylist, lp); - if (!PyArg_ParseTuple(args, "iiO!", &x, &y, &PyList_Type, &pylist)) - { - return NULL; + Py_XINCREF(Py_None); + return Py_None; } - QPoint lp (x, rvDoc->view()->height() - y - 1); - - popupMenuInternal (pylist, lp); + static PyObject* popupMenuAtPoint(PyObject* self, PyObject* args) + { + PyLockObject locker; + Session* s = Session::currentSession(); + RvDocument* rvDoc = (RvDocument*)s->opaquePointer(); + int x, y; + PyObject* pylist; - Py_XINCREF(Py_None); - return Py_None; -} + if (!PyArg_ParseTuple(args, "iiO!", &x, &y, &PyList_Type, &pylist)) + { + return NULL; + } + QPoint lp(x, rvDoc->view()->height() - y - 1); -static PyObject * -sessionWindow(PyObject *self, PyObject* args) -{ - PyLockObject locker; - Session *s = Session::currentSession(); - void *rvDoc = (void *)s->opaquePointer(); + popupMenuInternal(pylist, lp); - PyObject* ret = Py_None; + Py_XINCREF(Py_None); + return Py_None; + } - if (void *rvDoc = (void *)s->opaquePointer()) + static PyObject* sessionWindow(PyObject* self, PyObject* args) { - ret = PyLong_FromVoidPtr(rvDoc); - } + PyLockObject locker; + Session* s = Session::currentSession(); + void* rvDoc = (void*)s->opaquePointer(); - Py_XINCREF(ret); - return ret; -} + PyObject* ret = Py_None; + if (void* rvDoc = (void*)s->opaquePointer()) + { + ret = PyLong_FromVoidPtr(rvDoc); + } + Py_XINCREF(ret); + return ret; + } -static PyObject * -sessionGLView(PyObject *self, PyObject* args) -{ - PyLockObject locker; - Session *s = Session::currentSession(); + static PyObject* sessionGLView(PyObject* self, PyObject* args) + { + PyLockObject locker; + Session* s = Session::currentSession(); - PyObject* ret = Py_None; + PyObject* ret = Py_None; - if (RvDocument *rvDoc = (RvDocument *)s->opaquePointer()) - { - if (void *glview = (void *) rvDoc->view()) + if (RvDocument* rvDoc = (RvDocument*)s->opaquePointer()) { - ret = PyLong_FromVoidPtr(glview); + if (void* glview = (void*)rvDoc->view()) + { + ret = PyLong_FromVoidPtr(glview); + } } + + Py_XINCREF(ret); + return ret; } - Py_XINCREF(ret); - return ret; -} + static PyObject* sessionTopToolBar(PyObject* self, PyObject* args) + { + PyLockObject locker; + Session* s = Session::currentSession(); + void* rvDoc = (void*)s->opaquePointer(); + PyObject* ret = Py_None; -static PyObject * -sessionTopToolBar(PyObject *self, PyObject* args) -{ - PyLockObject locker; - Session *s = Session::currentSession(); - void *rvDoc = (void *)s->opaquePointer(); + if (RvDocument* rvDoc = (RvDocument*)s->opaquePointer()) + { + if (void* topViewToolBar = (void*)rvDoc->topViewToolBar()) + { + ret = PyLong_FromVoidPtr(topViewToolBar); + } + } - PyObject* ret = Py_None; + Py_XINCREF(ret); + return ret; + } - if (RvDocument *rvDoc = (RvDocument *)s->opaquePointer()) + static PyObject* sessionBottomToolBar(PyObject* self, PyObject* args) { - if (void *topViewToolBar = (void *) rvDoc->topViewToolBar()) + PyLockObject locker; + Session* s = Session::currentSession(); + PyObject* ret = Py_None; + + if (RvDocument* rvDoc = (RvDocument*)s->opaquePointer()) { - ret = PyLong_FromVoidPtr(topViewToolBar); + if (void* bottomViewToolBar = (void*)rvDoc->bottomViewToolBar()) + { + ret = PyLong_FromVoidPtr(bottomViewToolBar); + } } + + Py_XINCREF(ret); + return ret; } - Py_XINCREF(ret); - return ret; -} +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) + static PyObject* javascriptExport(PyObject* self, PyObject* args) + { + Session* s = Session::currentSession(); + RvDocument* doc = reinterpret_cast(s->opaquePointer()); + uint64_t pointer; + if (!PyArg_ParseTuple(args, "K", &pointer)) + { + return NULL; + } -static PyObject * -sessionBottomToolBar(PyObject *self, PyObject* args) -{ - PyLockObject locker; - Session *s = Session::currentSession(); - PyObject* ret = Py_None; + QWebFrame* webFramePointer = (QWebFrame*)pointer; + RvJavaScriptObject* obj = new RvJavaScriptObject(doc, webFramePointer); - if (RvDocument *rvDoc = (RvDocument *)s->opaquePointer()) + Py_RETURN_NONE; + } +#else + static PyObject* javascriptExport(PyObject* self, PyObject* args) { - if (void *bottomViewToolBar = (void *) rvDoc->bottomViewToolBar()) + Session* s = Session::currentSession(); + RvDocument* doc = reinterpret_cast(s->opaquePointer()); + uint64_t pointer; + + if (!PyArg_ParseTuple(args, "K", &pointer)) { - ret = PyLong_FromVoidPtr(bottomViewToolBar); + return NULL; } + + QWebEnginePage* webPagePointer = (QWebEnginePage*)pointer; + RvJavaScriptObject* obj = new RvJavaScriptObject(doc, webPagePointer); + + Py_RETURN_NONE; } - Py_XINCREF(ret); - return ret; -} +#endif -#if QT_VERSION < QT_VERSION_CHECK(5,0,0) -static PyObject * -javascriptExport(PyObject *self, PyObject* args) -{ - Session* s = Session::currentSession(); - RvDocument* doc = reinterpret_cast(s->opaquePointer()); - uint64_t pointer; + static PyMethodDef localmethods[] = { - if (!PyArg_ParseTuple(args, "K", &pointer)) - { - return NULL; - } + {"readSettings", readSettings, METH_VARARGS, ""}, - QWebFrame* webFramePointer = (QWebFrame*) pointer; - RvJavaScriptObject* obj = new RvJavaScriptObject(doc, webFramePointer); + {"writeSettings", writeSettings, METH_VARARGS, ""}, - Py_RETURN_NONE; -} -#else -static PyObject * -javascriptExport(PyObject *self, PyObject* args) -{ - Session* s = Session::currentSession(); - RvDocument* doc = reinterpret_cast(s->opaquePointer()); - uint64_t pointer; + {"popupMenu", popupMenu, METH_VARARGS, ""}, - if (!PyArg_ParseTuple(args, "K", &pointer)) - { - return NULL; - } + {"popupMenuAtPoint", popupMenuAtPoint, METH_VARARGS, ""}, - QWebEnginePage* webPagePointer = (QWebEnginePage*) pointer; - RvJavaScriptObject* obj = new RvJavaScriptObject(doc, webPagePointer); + {"sessionWindow", sessionWindow, METH_NOARGS, ""}, - Py_RETURN_NONE; -} + {"sessionGLView", sessionGLView, METH_NOARGS, ""}, -#endif + {"sessionTopToolBar", sessionTopToolBar, METH_NOARGS, ""}, -static PyMethodDef localmethods[] = { - - {"readSettings", - readSettings, - METH_VARARGS, - ""}, - - {"writeSettings", - writeSettings, - METH_VARARGS, - ""}, - - {"popupMenu", - popupMenu, - METH_VARARGS, - ""}, - - {"popupMenuAtPoint", - popupMenuAtPoint, - METH_VARARGS, - ""}, - - {"sessionWindow", - sessionWindow, - METH_NOARGS, - ""}, - - {"sessionGLView", - sessionGLView, - METH_NOARGS, - ""}, - - {"sessionTopToolBar", - sessionTopToolBar, - METH_NOARGS, - ""}, - - {"sessionBottomToolBar", - sessionBottomToolBar, - METH_NOARGS, - ""}, - - {"javascriptExport", - javascriptExport, - METH_VARARGS, - ""}, - - {NULL} -}; - -void* -pyUICommands() -{ - return (void*)localmethods; -} + {"sessionBottomToolBar", sessionBottomToolBar, METH_NOARGS, ""}, + + {"javascriptExport", javascriptExport, METH_VARARGS, ""}, + + {NULL}}; + + void* pyUICommands() { return (void*)localmethods; } -} // Rv +} // namespace Rv diff --git a/src/lib/app/RvCommon/QTDesktopVideoDevice.cpp b/src/lib/app/RvCommon/QTDesktopVideoDevice.cpp index e2d901914..dc4aa417f 100644 --- a/src/lib/app/RvCommon/QTDesktopVideoDevice.cpp +++ b/src/lib/app/RvCommon/QTDesktopVideoDevice.cpp @@ -1,9 +1,9 @@ // -// Copyright (c) 2011 Tweak Software. +// Copyright (c) 2011 Tweak Software. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// // #ifdef PLATFORM_WINDOWS #include @@ -18,243 +18,223 @@ #include #include -namespace Rv { +namespace Rv +{ -using namespace std; -using namespace TwkGLF; -using namespace TwkApp; + using namespace std; + using namespace TwkGLF; + using namespace TwkApp; -//---------------------------------------------------------------------- + //---------------------------------------------------------------------- -class ScreenView : public QGLWidget -{ - public: - ScreenView(const QGLFormat& fmt, - QWidget* parent, - QGLWidget* share, - Qt::WindowFlags flags) - : QGLWidget(fmt, parent, share, flags) + class ScreenView : public QGLWidget + { + public: + ScreenView(const QGLFormat& fmt, QWidget* parent, QGLWidget* share, + Qt::WindowFlags flags) + : QGLWidget(fmt, parent, share, flags) { setAutoBufferSwap(false); } - ~ScreenView() {} -}; - -//---------------------------------------------------------------------- - - -QTDesktopVideoDevice::QTDesktopVideoDevice(VideoModule* m, - const std::string& name, - int screen, - const QTGLVideoDevice* share) - : DesktopVideoDevice(m, name, share), - m_screen(screen), - m_translator(0), - m_view(0), - m_x(0), - m_y(0) -{ - const QDesktopWidget* desktop = qApp->desktop(); - QRect rect = desktop->screenGeometry(screen); - ostringstream str; - str << rect.width() << " x " << rect.height(); - m_videoFormats.push_back(VideoFormat(rect.width(), rect.height(), 1.0, 1.0, 0.0, str.str())); - addDefaultDataFormats(); -} - -QTDesktopVideoDevice::~QTDesktopVideoDevice() -{ - close(); -} + ~ScreenView() {} + }; + + //---------------------------------------------------------------------- + + QTDesktopVideoDevice::QTDesktopVideoDevice(VideoModule* m, + const std::string& name, + int screen, + const QTGLVideoDevice* share) + : DesktopVideoDevice(m, name, share) + , m_screen(screen) + , m_translator(0) + , m_view(0) + , m_x(0) + , m_y(0) + { + const QDesktopWidget* desktop = qApp->desktop(); + QRect rect = desktop->screenGeometry(screen); + ostringstream str; + str << rect.width() << " x " << rect.height(); + m_videoFormats.push_back( + VideoFormat(rect.width(), rect.height(), 1.0, 1.0, 0.0, str.str())); + addDefaultDataFormats(); + } + QTDesktopVideoDevice::~QTDesktopVideoDevice() { close(); } -void -QTDesktopVideoDevice::setWidget(QGLWidget* widget) -{ - m_view = widget; - m_translator = new QTTranslator(this, m_view); -} - -void -QTDesktopVideoDevice::makeCurrent() const -{ - if (m_view) m_view->makeCurrent(); -} - -void -QTDesktopVideoDevice::redraw() const -{ - if (m_view) + void QTDesktopVideoDevice::setWidget(QGLWidget* widget) { - ScopedLock lock(m_mutex); - QSize s = m_view->size(); - m_view->update(); + m_view = widget; + m_translator = new QTTranslator(this, m_view); } -} -void -QTDesktopVideoDevice::redrawImmediately() const -{ - if (m_view && m_view->isVisible()) + void QTDesktopVideoDevice::makeCurrent() const { - ScopedLock lock(m_mutex); - m_view->updateGL(); + if (m_view) + m_view->makeCurrent(); } - else + + void QTDesktopVideoDevice::redraw() const { - redraw(); + if (m_view) + { + ScopedLock lock(m_mutex); + QSize s = m_view->size(); + m_view->update(); + } } -} -void -QTDesktopVideoDevice::syncBuffers() const -{ - if (m_view) + void QTDesktopVideoDevice::redrawImmediately() const { - ScopedLock lock(m_mutex); - makeCurrent(); - m_view->swapBuffers(); + if (m_view && m_view->isVisible()) + { + ScopedLock lock(m_mutex); + m_view->updateGL(); + } + else + { + redraw(); + } } -} - -void -QTDesktopVideoDevice::open(const StringVector& args) -{ - // - // always make the fullscreen device synced - // - QGLFormat fmt = shareDevice()->widget()->format(); - fmt.setSwapInterval(m_vsync ? 1 : 0); - ScreenView* s = new ScreenView(fmt, 0, shareDevice()->widget(), Qt::Window); - setWidget(s); - setViewDevice(new QTGLVideoDevice(0, "local view", s)); + void QTDesktopVideoDevice::syncBuffers() const + { + if (m_view) + { + ScopedLock lock(m_mutex); + makeCurrent(); + m_view->swapBuffers(); + } + } - QRect g = QApplication::desktop()->screenGeometry(m_screen); - widget()->move(g.x(), g.y()); - widget()->setWindowState(Qt::WindowFullScreen); - widget()->show(); + void QTDesktopVideoDevice::open(const StringVector& args) + { + // + // always make the fullscreen device synced + // + + QGLFormat fmt = shareDevice()->widget()->format(); + fmt.setSwapInterval(m_vsync ? 1 : 0); + ScreenView* s = + new ScreenView(fmt, 0, shareDevice()->widget(), Qt::Window); + setWidget(s); + setViewDevice(new QTGLVideoDevice(0, "local view", s)); + + QRect g = QApplication::desktop()->screenGeometry(m_screen); + widget()->move(g.x(), g.y()); + widget()->setWindowState(Qt::WindowFullScreen); + widget()->show(); #ifdef PLATFORM_WINDOWS - // Work around for QGLWidget::showFullScreen() windows specific issue - // introduced in Qt 5.15.3 - widget()->setGeometry(g); + // Work around for QGLWidget::showFullScreen() windows specific issue + // introduced in Qt 5.15.3 + widget()->setGeometry(g); #endif -} - -bool -QTDesktopVideoDevice::isOpen() const -{ - return m_view != 0; -} - -void -QTDesktopVideoDevice::close() -{ - delete m_view; - delete m_viewDevice; - delete m_translator; - m_view = 0; - m_viewDevice = 0; - m_translator = 0; -} - -VideoDevice::Resolution -QTDesktopVideoDevice::resolution() const -{ - QRect g = QApplication::desktop()->screenGeometry(m_screen); - return Resolution(g.width(), g.height(), 1.0, 1.0); -} + } -size_t -QTDesktopVideoDevice::width() const -{ - QRect g = QApplication::desktop()->screenGeometry(m_screen); - return g.width(); -} + bool QTDesktopVideoDevice::isOpen() const { return m_view != 0; } -size_t -QTDesktopVideoDevice::height() const -{ - QRect g = QApplication::desktop()->screenGeometry(m_screen); - return g.height(); -} - -VideoDevice::VideoFormat -QTDesktopVideoDevice::format() const -{ - QRect g = QApplication::desktop()->screenGeometry(m_screen); - ostringstream str; - str << g.width() << " x " << g.height(); - const float pa = 1.0; - const float ps = 1.0; - const float rate = 60.0; - return VideoFormat(g.width(), g.height(), pa, ps, rate, str.str()); -} - -VideoDevice::Offset -QTDesktopVideoDevice::offset() const -{ - return Offset(0,0); -} + void QTDesktopVideoDevice::close() + { + delete m_view; + delete m_viewDevice; + delete m_translator; + m_view = 0; + m_viewDevice = 0; + m_translator = 0; + } -VideoDevice::Timing -QTDesktopVideoDevice::timing() const -{ - return format(); -} + VideoDevice::Resolution QTDesktopVideoDevice::resolution() const + { + QRect g = QApplication::desktop()->screenGeometry(m_screen); + return Resolution(g.width(), g.height(), 1.0, 1.0); + } -#ifdef PLATFORM_WINDOWS -TwkApp::VideoDevice::ColorProfile -QTDesktopVideoDevice::colorProfile() const -{ - // - // XXX The following steps are not Unicode safe - // + size_t QTDesktopVideoDevice::width() const + { + QRect g = QApplication::desktop()->screenGeometry(m_screen); + return g.width(); + } - // Get the context for this screen - QDesktopWidget* desktop = QApplication::desktop(); - WId id = desktop->screen(m_screen)->effectiveWinId(); - HDC hdc = GetDC (reinterpret_cast(id)); + size_t QTDesktopVideoDevice::height() const + { + QRect g = QApplication::desktop()->screenGeometry(m_screen); + return g.height(); + } - if (hdc) + VideoDevice::VideoFormat QTDesktopVideoDevice::format() const { - // Look for the profile path - unsigned long pathLen; - GetICMProfile (hdc, &pathLen, NULL); - char* path = new char[pathLen]; + QRect g = QApplication::desktop()->screenGeometry(m_screen); + ostringstream str; + str << g.width() << " x " << g.height(); + const float pa = 1.0; + const float ps = 1.0; + const float rate = 60.0; + return VideoFormat(g.width(), g.height(), pa, ps, rate, str.str()); + } - if (GetICMProfile (hdc, &pathLen, path)) - { - // If we found a profile lets set the type, - // url, and description + VideoDevice::Offset QTDesktopVideoDevice::offset() const + { + return Offset(0, 0); + } - m_colorProfile.type = ICCProfile; + VideoDevice::Timing QTDesktopVideoDevice::timing() const + { + return format(); + } - unsigned long maxLen = 2084; - char* url = new char[maxLen]; - UrlCreateFromPath(path, url, &maxLen, NULL); - m_colorProfile.url = url; +#ifdef PLATFORM_WINDOWS + TwkApp::VideoDevice::ColorProfile QTDesktopVideoDevice::colorProfile() const + { + // + // XXX The following steps are not Unicode safe + // - char desc[256]; - cmsHPROFILE profile = cmsOpenProfileFromFile (path, "r"); - cmsGetProfileInfoASCII(profile, cmsInfoDescription, "en", "US", desc, 256); - m_colorProfile.description = desc; + // Get the context for this screen + QDesktopWidget* desktop = QApplication::desktop(); + WId id = desktop->screen(m_screen)->effectiveWinId(); + HDC hdc = GetDC(reinterpret_cast(id)); - delete url; + if (hdc) + { + // Look for the profile path + unsigned long pathLen; + GetICMProfile(hdc, &pathLen, NULL); + char* path = new char[pathLen]; + + if (GetICMProfile(hdc, &pathLen, path)) + { + // If we found a profile lets set the type, + // url, and description + + m_colorProfile.type = ICCProfile; + + unsigned long maxLen = 2084; + char* url = new char[maxLen]; + UrlCreateFromPath(path, url, &maxLen, NULL); + m_colorProfile.url = url; + + char desc[256]; + cmsHPROFILE profile = cmsOpenProfileFromFile(path, "r"); + cmsGetProfileInfoASCII(profile, cmsInfoDescription, "en", "US", + desc, 256); + m_colorProfile.description = desc; + + delete url; + } + + delete path; + ReleaseDC(reinterpret_cast(id), hdc); + } + else + { + m_colorProfile = ColorProfile(); } - delete path; - ReleaseDC (reinterpret_cast(id), hdc); - } - else - { - m_colorProfile = ColorProfile(); + return m_colorProfile; } - - return m_colorProfile; -} #endif -} // Rv +} // namespace Rv diff --git a/src/lib/app/RvCommon/QTFrameBuffer.cpp b/src/lib/app/RvCommon/QTFrameBuffer.cpp index 17324d479..804740572 100644 --- a/src/lib/app/RvCommon/QTFrameBuffer.cpp +++ b/src/lib/app/RvCommon/QTFrameBuffer.cpp @@ -1,74 +1,56 @@ //****************************************************************************** // Copyright (c) 2001-2003 Tweak Inc. All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #include #include #include #include -namespace Rv { -using namespace std; - -QTFrameBuffer::QTFrameBuffer(QGLWidget *view) : - FrameBuffer(view->objectName().toUtf8().data()), - m_view(view), - m_translator(this, view), - m_x(0), - m_y(0) +namespace Rv { - assert( view ); -} + using namespace std; + QTFrameBuffer::QTFrameBuffer(QGLWidget* view) + : FrameBuffer(view->objectName().toUtf8().data()) + , m_view(view) + , m_translator(this, view) + , m_x(0) + , m_y(0) + { + assert(view); + } -QTFrameBuffer::~QTFrameBuffer() -{ -} + QTFrameBuffer::~QTFrameBuffer() {} -void -QTFrameBuffer::makeCurrent() const -{ - FrameBuffer::makeCurrent(); -} + void QTFrameBuffer::makeCurrent() const { FrameBuffer::makeCurrent(); } -size_t QTFrameBuffer::width() const -{ - return m_view->size().width(); -} + size_t QTFrameBuffer::width() const { return m_view->size().width(); } -size_t QTFrameBuffer::height() const -{ - return m_view->size().height(); -} + size_t QTFrameBuffer::height() const { return m_view->size().height(); } -int QTFrameBuffer::x() const -{ - return m_x; -} - -int QTFrameBuffer::y() const -{ - return m_y; -} + int QTFrameBuffer::x() const { return m_x; } -void QTFrameBuffer::redraw() -{ - QSize s = m_view->size(); - return m_view->update(); -} + int QTFrameBuffer::y() const { return m_y; } -void QTFrameBuffer::redrawImmediately() -{ - if (m_view->isVisible()) + void QTFrameBuffer::redraw() { - m_view->updateGL(); + QSize s = m_view->size(); + return m_view->update(); } - else + + void QTFrameBuffer::redrawImmediately() { - redraw(); + if (m_view->isVisible()) + { + m_view->updateGL(); + } + else + { + redraw(); + } } -} -} // End namespace Rv +} // End namespace Rv diff --git a/src/lib/app/RvCommon/QTGLVideoDevice.cpp b/src/lib/app/RvCommon/QTGLVideoDevice.cpp index 6ed944736..02485f34e 100644 --- a/src/lib/app/RvCommon/QTGLVideoDevice.cpp +++ b/src/lib/app/RvCommon/QTGLVideoDevice.cpp @@ -1,12 +1,12 @@ // -// Copyright (c) 2011 Tweak Software. +// Copyright (c) 2011 Tweak Software. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// // -//#include -//#include +// +// #include +// #include #ifdef PLATFORM_WINDOWS #include #include @@ -18,228 +18,214 @@ #include #include -namespace Rv { -using namespace std; -using namespace TwkGLF; -using namespace TwkApp; - -QTGLVideoDevice::QTGLVideoDevice(VideoModule* m, const string& name, QGLWidget *view) - : GLVideoDevice(m, name, ImageOutput | ProvidesSync | SubWindow ), - m_view(view), - m_translator(new QTTranslator(this, view)), - m_x(0), - m_y(0), - m_refresh(-1.0) -{ - assert( view ); -} - -QTGLVideoDevice::QTGLVideoDevice(VideoModule* m, const string& name) - : GLVideoDevice(m, name, ImageOutput | ProvidesSync | SubWindow ), - m_view(0), - m_translator(0), - m_x(0), - m_y(0) +namespace Rv { -} - -QTGLVideoDevice::QTGLVideoDevice(const string& name, QGLWidget *view) - : GLVideoDevice(NULL, name, NoCapabilities ), - m_view(view), - m_translator(new QTTranslator(this, view)), - m_x(0), - m_y(0), - m_refresh(-1.0) -{ - assert( view ); -} + using namespace std; + using namespace TwkGLF; + using namespace TwkApp; -QTGLVideoDevice::~QTGLVideoDevice() -{ - delete m_translator; -} + QTGLVideoDevice::QTGLVideoDevice(VideoModule* m, const string& name, + QGLWidget* view) + : GLVideoDevice(m, name, ImageOutput | ProvidesSync | SubWindow) + , m_view(view) + , m_translator(new QTTranslator(this, view)) + , m_x(0) + , m_y(0) + , m_refresh(-1.0) + { + assert(view); + } -void -QTGLVideoDevice::setWidget(QGLWidget* widget) -{ - m_view = widget; - m_translator = new QTTranslator(this, m_view); -} + QTGLVideoDevice::QTGLVideoDevice(VideoModule* m, const string& name) + : GLVideoDevice(m, name, ImageOutput | ProvidesSync | SubWindow) + , m_view(0) + , m_translator(0) + , m_x(0) + , m_y(0) + { + } -GLVideoDevice* -QTGLVideoDevice::newSharedContextWorkerDevice() const -{ - QGLWidget* w = new QGLWidget(m_view->parentWidget(), m_view); - return new QTGLVideoDevice(name() + "-workerContextDevice", w); -} - -void -QTGLVideoDevice::makeCurrent() const -{ - if (m_view->context()->contextHandle() && m_view->context()->isValid()) m_view->makeCurrent(); - if (!isWorkerDevice()) GLVideoDevice::makeCurrent(); -} - -void -QTGLVideoDevice::redraw() const -{ - if (!isWorkerDevice()) + QTGLVideoDevice::QTGLVideoDevice(const string& name, QGLWidget* view) + : GLVideoDevice(NULL, name, NoCapabilities) + , m_view(view) + , m_translator(new QTTranslator(this, view)) + , m_x(0) + , m_y(0) + , m_refresh(-1.0) { - QSize s = m_view->size(); - m_view->update(); + assert(view); } -} -void -QTGLVideoDevice::redrawImmediately() const -{ - if (!isWorkerDevice()) + QTGLVideoDevice::~QTGLVideoDevice() { delete m_translator; } + + void QTGLVideoDevice::setWidget(QGLWidget* widget) { - if (m_view->isVisible()) + m_view = widget; + m_translator = new QTTranslator(this, m_view); + } + + GLVideoDevice* QTGLVideoDevice::newSharedContextWorkerDevice() const + { + QGLWidget* w = new QGLWidget(m_view->parentWidget(), m_view); + return new QTGLVideoDevice(name() + "-workerContextDevice", w); + } + + void QTGLVideoDevice::makeCurrent() const + { + if (m_view->context()->contextHandle() && m_view->context()->isValid()) + m_view->makeCurrent(); + if (!isWorkerDevice()) + GLVideoDevice::makeCurrent(); + } + + void QTGLVideoDevice::redraw() const + { + if (!isWorkerDevice()) + { + QSize s = m_view->size(); + m_view->update(); + } + } + + void QTGLVideoDevice::redrawImmediately() const + { + if (!isWorkerDevice()) { + if (m_view->isVisible()) + { #ifdef PLATFORM_DARWIN - // Make sure that the QGLWidget gets redrawn by updateGL() even - // when completely overlapped by another window. - // Note that on macOS, Qt correctly detects when the QGLWidget - // is completely overlapped by another window and in which case - // resets the Qt::WA_Mapped attribute. This will prevent the - // GLView::paintGL() operation from being called by - // m_view->updateGL(), which will result in automatically - // interrupting any video playback that might be in progress while - // the RV window is completely overlapped. - // This is an undesirable behaviour during a review session, - // especially if an external video output device is used. - m_view->setAttribute(Qt::WA_Mapped); + // Make sure that the QGLWidget gets redrawn by updateGL() even + // when completely overlapped by another window. + // Note that on macOS, Qt correctly detects when the QGLWidget + // is completely overlapped by another window and in which case + // resets the Qt::WA_Mapped attribute. This will prevent the + // GLView::paintGL() operation from being called by + // m_view->updateGL(), which will result in automatically + // interrupting any video playback that might be in progress + // while the RV window is completely overlapped. This is an + // undesirable behaviour during a review session, especially if + // an external video output device is used. + m_view->setAttribute(Qt::WA_Mapped); #endif - m_view->updateGL(); - } - else - { - redraw(); + m_view->updateGL(); + } + else + { + redraw(); + } } } -} -VideoDevice::Resolution -QTGLVideoDevice::resolution() const -{ - return Resolution(m_view->width(), m_view->height(), 1.0f, 1.0f); -} + VideoDevice::Resolution QTGLVideoDevice::resolution() const + { + return Resolution(m_view->width(), m_view->height(), 1.0f, 1.0f); + } -VideoDevice::Offset -QTGLVideoDevice::offset() const -{ - return Offset(m_x, m_y); -} + VideoDevice::Offset QTGLVideoDevice::offset() const + { + return Offset(m_x, m_y); + } -VideoDevice::Timing -QTGLVideoDevice::timing() const -{ - return Timing((m_refresh != -1.0) ? m_refresh : 0.0); -} + VideoDevice::Timing QTGLVideoDevice::timing() const + { + return Timing((m_refresh != -1.0) ? m_refresh : 0.0); + } -VideoDevice::VideoFormat -QTGLVideoDevice::format() const -{ - return VideoFormat(m_view->width(), - m_view->height(), - 1.0, - 1.0, - (m_refresh != -1.0) ? m_refresh : 0.0, - hardwareIdentification()); -} - -void -QTGLVideoDevice::open(const StringVector& args) -{ - if (!isWorkerDevice()) m_view->show(); -} + VideoDevice::VideoFormat QTGLVideoDevice::format() const + { + return VideoFormat(m_view->width(), m_view->height(), 1.0, 1.0, + (m_refresh != -1.0) ? m_refresh : 0.0, + hardwareIdentification()); + } -void -QTGLVideoDevice::close() -{ - if (!isWorkerDevice()) m_view->hide(); -} + void QTGLVideoDevice::open(const StringVector& args) + { + if (!isWorkerDevice()) + m_view->show(); + } -bool -QTGLVideoDevice::isOpen() const -{ - if (isWorkerDevice()) + void QTGLVideoDevice::close() { - return false; + if (!isWorkerDevice()) + m_view->hide(); } - else + + bool QTGLVideoDevice::isOpen() const { - return m_view->isVisible(); + if (isWorkerDevice()) + { + return false; + } + else + { + return m_view->isVisible(); + } } -} -size_t -QTGLVideoDevice::width() const -{ - return m_view->width(); -} + size_t QTGLVideoDevice::width() const { return m_view->width(); } -size_t -QTGLVideoDevice::height() const -{ - return m_view->height(); -} + size_t QTGLVideoDevice::height() const { return m_view->height(); } -void -QTGLVideoDevice::syncBuffers() const -{ - if (!isWorkerDevice()) + void QTGLVideoDevice::syncBuffers() const { - makeCurrent(); - m_view->swapBuffers(); + if (!isWorkerDevice()) + { + makeCurrent(); + m_view->swapBuffers(); + } } -} - -void -QTGLVideoDevice::setAbsolutePosition(int x, int y) -{ - if (isWorkerDevice()) return; - if (x != m_x || y != m_y || m_refresh == -1.0) + void QTGLVideoDevice::setAbsolutePosition(int x, int y) { - float refresh = -1.0; - - VideoDevice::Resolution res = resolution(); - int tx = x + res.width / 2; - int ty = y + res.height / 2; + if (isWorkerDevice()) + return; - if (const TwkApp::VideoModule* module = TwkApp::App()->primaryVideoModule()) + if (x != m_x || y != m_y || m_refresh == -1.0) { - if (TwkApp::VideoDevice* d = module->deviceFromPosition(tx, ty)) - { - setPhysicalDevice(d); - refresh = d->timing().hz; - - VideoDeviceContextChangeEvent event("video-device-changed", this, this, d); - sendEvent(event); - } - } + float refresh = -1.0; - if (refresh != m_refresh) - { - // Check to see refresh has a legal value before assigning it to m_refresh. - if (refresh > 0) + VideoDevice::Resolution res = resolution(); + int tx = x + res.width / 2; + int ty = y + res.height / 2; + + if (const TwkApp::VideoModule* module = + TwkApp::App()->primaryVideoModule()) { - m_refresh = refresh; + if (TwkApp::VideoDevice* d = module->deviceFromPosition(tx, ty)) + { + setPhysicalDevice(d); + refresh = d->timing().hz; + + VideoDeviceContextChangeEvent event("video-device-changed", + this, this, d); + sendEvent(event); + } } - else + + if (refresh != m_refresh) { - if (IPCore::debugPlayback) cout << "WARNING: ignoring intended desktop refresh rate = " << refresh << endl; + // Check to see refresh has a legal value before assigning it to + // m_refresh. + if (refresh > 0) + { + m_refresh = refresh; + } + else + { + if (IPCore::debugPlayback) + cout << "WARNING: ignoring intended desktop refresh " + "rate = " + << refresh << endl; + } + + if (IPCore::debugPlayback) + cout << "INFO: new desktop refresh rate " << m_refresh + << endl; } - - if (IPCore::debugPlayback) cout << "INFO: new desktop refresh rate " << m_refresh << endl; } + m_x = x; + m_y = y; } - m_x = x; - m_y = y; -} - -} // Rv +} // namespace Rv diff --git a/src/lib/app/RvCommon/QTTranslator.cpp b/src/lib/app/RvCommon/QTTranslator.cpp index d3024d905..a662b8876 100644 --- a/src/lib/app/RvCommon/QTTranslator.cpp +++ b/src/lib/app/RvCommon/QTTranslator.cpp @@ -1,9 +1,9 @@ //****************************************************************************** -// Copyright (c) 2004 Tweak Inc. +// Copyright (c) 2004 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #include @@ -17,397 +17,487 @@ #include #include -namespace { +namespace +{ -bool noAutoReleaseEvents = false; + bool noAutoReleaseEvents = false; }; -namespace Rv { -using namespace TwkApp; -using namespace std; -using namespace TwkUtil; - -QTTranslator::QTTranslator(EventNode* n, QWidget* w) - : m_node(n), - m_widget(w), - m_b1(false), - m_b2(false), - m_b3(false), - m_tabletPushed(false), - m_modifiers(0), - m_lastMods(Qt::NoModifier), - m_lastType(QEvent::None), - m_lastButtons(Qt::NoButton), - m_firstTime(true), - m_lastx(0), - m_lasty(0), - m_xscale(1.0), - m_yscale(1.0), - m_xoffset(0.0), - m_yoffset(0.0), - m_width(0), - m_height(0) -{ - noAutoReleaseEvents = (getenv("TWK_NO_AUTO_RELEASE_EVENTS") != 0); -} - -void -QTTranslator::sendEvent(const Event& event) const +namespace Rv { - //cout << "event: "; - //event.output(cout); - //cout << endl; - m_node->sendEvent(event); -} - -unsigned int -QTTranslator::modifiers(Qt::KeyboardModifiers s) const -{ - unsigned int m = 0; - - if (s & Qt::ShiftModifier) m |= ModifierEvent::Shift; - if (s & Qt::ControlModifier) m |= ModifierEvent::Control; - if (s & Qt::AltModifier) m |= ModifierEvent::Alt; - if (s & Qt::MetaModifier) m |= ModifierEvent::Meta; - if (s & Qt::KeypadModifier) m |= ModifierEvent::ScrollLock; + using namespace TwkApp; + using namespace std; + using namespace TwkUtil; + + QTTranslator::QTTranslator(EventNode* n, QWidget* w) + : m_node(n) + , m_widget(w) + , m_b1(false) + , m_b2(false) + , m_b3(false) + , m_tabletPushed(false) + , m_modifiers(0) + , m_lastMods(Qt::NoModifier) + , m_lastType(QEvent::None) + , m_lastButtons(Qt::NoButton) + , m_firstTime(true) + , m_lastx(0) + , m_lasty(0) + , m_xscale(1.0) + , m_yscale(1.0) + , m_xoffset(0.0) + , m_yoffset(0.0) + , m_width(0) + , m_height(0) + { + noAutoReleaseEvents = (getenv("TWK_NO_AUTO_RELEASE_EVENTS") != 0); + } - return m; -} + void QTTranslator::sendEvent(const Event& event) const + { + // cout << "event: "; + // event.output(cout); + // cout << endl; + m_node->sendEvent(event); + } -void -QTTranslator::resetModifiers() const -{ - m_modifiers = 0; -} + unsigned int QTTranslator::modifiers(Qt::KeyboardModifiers s) const + { + unsigned int m = 0; + + if (s & Qt::ShiftModifier) + m |= ModifierEvent::Shift; + if (s & Qt::ControlModifier) + m |= ModifierEvent::Control; + if (s & Qt::AltModifier) + m |= ModifierEvent::Alt; + if (s & Qt::MetaModifier) + m |= ModifierEvent::Meta; + if (s & Qt::KeypadModifier) + m |= ModifierEvent::ScrollLock; + + return m; + } -Qt::MouseButtons -QTTranslator::qbuttons(unsigned int b) const -{ - Qt::MouseButtons q = Qt::NoButton; + void QTTranslator::resetModifiers() const { m_modifiers = 0; } - if (b & 0x1 << 0) q |= Qt::LeftButton; - if (b & 0x1 << 1) q |= Qt::MidButton; - if (b & 0x1 << 2) q |= Qt::RightButton; - return q; -} + Qt::MouseButtons QTTranslator::qbuttons(unsigned int b) const + { + Qt::MouseButtons q = Qt::NoButton; + + if (b & 0x1 << 0) + q |= Qt::LeftButton; + if (b & 0x1 << 1) + q |= Qt::MidButton; + if (b & 0x1 << 2) + q |= Qt::RightButton; + return q; + } -bool -QTTranslator::sendQTEvent(QEvent* event, float activationTime) const -{ - // - // This is trying to correct for odd behavior with menu - // accelerators on the Mac. Qt will not necessarily send the up - // event on the modifer key so our internal state can get - // lost. For this reason, its a good idea not to use Alt combos - // in the menus. The Alt state is very strange in Qt. - // - - if (QInputEvent* inputEvent = dynamic_cast(event)) + bool QTTranslator::sendQTEvent(QEvent* event, float activationTime) const { - if ((inputEvent->modifiers() & 0xffff0000) != m_modifiers) + // + // This is trying to correct for odd behavior with menu + // accelerators on the Mac. Qt will not necessarily send the up + // event on the modifer key so our internal state can get + // lost. For this reason, its a good idea not to use Alt combos + // in the menus. The Alt state is very strange in Qt. + // + + if (QInputEvent* inputEvent = dynamic_cast(event)) { -// cout << "input event: modifier mismatch " -// << hex << inputEvent->modifiers() -// << " != " -// << hex << m_modifiers -// << " (event=" << event->type() << ")" -// << dec << endl; - - -// if (m_modifiers & Qt::ShiftModifier) cout << " Shift"; -// if (m_modifiers & Qt::AltModifier) cout << " Alt"; -// if (m_modifiers & Qt::ControlModifier) cout << " Control"; -// if (m_modifiers & Qt::MetaModifier) cout << " Meta"; -// if (m_modifiers & Qt::KeypadModifier) cout << " Keypad"; -// if (m_modifiers & Qt::GroupSwitchModifier) cout << " GroupSwitch"; -// if (m_modifiers != 0) cout << endl << endl; - - #ifndef PLATFORM_DARWIN + if ((inputEvent->modifiers() & 0xffff0000) != m_modifiers) + { + // cout << "input event: modifier mismatch " + // << hex << inputEvent->modifiers() + // << " != " + // << hex << m_modifiers + // << " (event=" << event->type() << ")" + // << dec << endl; + + // if (m_modifiers & Qt::ShiftModifier) cout << " + // Shift"; if (m_modifiers & Qt::AltModifier) cout + // << " Alt"; if (m_modifiers & Qt::ControlModifier) + // cout << " Control"; if (m_modifiers & + // Qt::MetaModifier) cout << " Meta"; if + // (m_modifiers & Qt::KeypadModifier) cout << " + // Keypad"; if (m_modifiers & + // Qt::GroupSwitchModifier) cout << " GroupSwitch"; + // if (m_modifiers != 0) cout << endl << endl; + +#ifndef PLATFORM_DARWIN // // This seems to be no longer necessary, in fact causes // problems on mac (qt 4.7), but not on win/lin. The problem // is that in many cases this code causes the control modifier // to be lost. // - if (m_modifiers & Qt::ControlModifier || - m_modifiers & Qt::MetaModifier) + if (m_modifiers & Qt::ControlModifier + || m_modifiers & Qt::MetaModifier) { m_modifiers = inputEvent->modifiers() & 0xffff0000; } - #endif +#endif + } + } + + switch (event->type()) + { + case QEvent::None: // invalid event + break; + case QEvent::Timer: // timer event + break; + case QEvent::Enter: // mouse enters widget + case QEvent::Leave: // mouse leaves widget + case QEvent::WindowActivate: // window becomes active + return sendEnterLeaveEvent(event); + case QEvent::MouseButtonPress: // mouse button pressed + case QEvent::MouseButtonRelease: // mouse button released + case QEvent::MouseButtonDblClick: // mouse button double click + case QEvent::MouseMove: // mouse move + if (!Options::sharedOptions().stylusAsMouse && m_tabletPushed) + { + // For some reason if the pen is in use ocassionally we + // get interfering mouse events. This is a workaround. + return true; + } + else + { + return sendMouseEvent(event, activationTime); + } + break; + case QEvent::Wheel: + return sendMouseWheelEvent(event); + + case QEvent::ShortcutOverride: // ignore this or not? + case QEvent::KeyPress: // key pressed + case QEvent::KeyRelease: // key released + case QEvent::Shortcut: + return sendKeyEvent(event); + + case QEvent::FocusIn: // keyboard focus received + case QEvent::FocusOut: // keyboard focus lost + case QEvent::Clipboard: // internal clipboard event + break; + case QEvent::DragEnter: // drag moves into widget + case QEvent::DragMove: // drag moves in widget + case QEvent::DragLeave: // drag leaves or is cancelled + case QEvent::Drop: // actual drop + case QEvent::DragResponse: // drag accepted/rejected + return sendDNDEvent(event); + case QEvent::ContextMenu: // context popup menu + break; + case QEvent::TabletMove: // Wacom tablet event + case QEvent::TabletPress: // tablet press + case QEvent::TabletRelease: // tablet release + if (!Options::sharedOptions().stylusAsMouse) + { + return sendTabletEvent(event); + } + break; + case QEvent::OkRequest: // CE (Ok) button pressed + case QEvent::HelpRequest: // CE (?) button pressed + break; + case QEvent::IconDrag: // proxy icon dragged + break; + case QEvent::TabletEnterProximity: + case QEvent::TabletLeaveProximity: + if (!Options::sharedOptions().stylusAsMouse) + { + return true; + } + break; + default: + break; } + + return false; } - switch (event->type()) + bool QTTranslator::sendKeyEvent(QEvent* qevent) const { - case QEvent::None: // invalid event - break; - case QEvent::Timer: // timer event - break; - case QEvent::Enter: // mouse enters widget - case QEvent::Leave: // mouse leaves widget - case QEvent::WindowActivate: // window becomes active - return sendEnterLeaveEvent(event); - case QEvent::MouseButtonPress: // mouse button pressed - case QEvent::MouseButtonRelease: // mouse button released - case QEvent::MouseButtonDblClick: // mouse button double click - case QEvent::MouseMove: // mouse move - if (!Options::sharedOptions().stylusAsMouse && m_tabletPushed) - { - // For some reason if the pen is in use ocassionally we - // get interfering mouse events. This is a workaround. - return true; - } - else - { - return sendMouseEvent(event, activationTime); - } - break; - case QEvent::Wheel: - return sendMouseWheelEvent(event); - - case QEvent::ShortcutOverride: // ignore this or not? - case QEvent::KeyPress: // key pressed - case QEvent::KeyRelease: // key released - case QEvent::Shortcut: - return sendKeyEvent(event); - - case QEvent::FocusIn: // keyboard focus received - case QEvent::FocusOut: // keyboard focus lost - case QEvent::Clipboard: // internal clipboard event - break; - case QEvent::DragEnter: // drag moves into widget - case QEvent::DragMove: // drag moves in widget - case QEvent::DragLeave: // drag leaves or is cancelled - case QEvent::Drop: // actual drop - case QEvent::DragResponse: // drag accepted/rejected - return sendDNDEvent(event); - case QEvent::ContextMenu: // context popup menu - break; - case QEvent::TabletMove: // Wacom tablet event - case QEvent::TabletPress: // tablet press - case QEvent::TabletRelease: // tablet release - if (!Options::sharedOptions().stylusAsMouse) - { - return sendTabletEvent(event); - } - break; - case QEvent::OkRequest: // CE (Ok) button pressed - case QEvent::HelpRequest: // CE (?) button pressed - break; - case QEvent::IconDrag: // proxy icon dragged - break; - case QEvent::TabletEnterProximity: - case QEvent::TabletLeaveProximity: - if (!Options::sharedOptions().stylusAsMouse) - { - return true; - } - break; - default: - break; - } + ostringstream str; + + QKeyEvent* event = static_cast(qevent); + bool showShift = true; + bool control = false; + bool nokeypad = false; + bool meta = false; + bool alt = false; + bool keydown = event->type() == QEvent::KeyPress + || event->type() == QEvent::ShortcutOverride + || event->type() == QEvent::Shortcut; + + // On the mac, there are no "releases" reported during auto-repeat, + // we do the below to make this consistant on other platforms. + // + if (noAutoReleaseEvents) + { + if (event->isAutoRepeat() && event->type() == QEvent::KeyRelease) + return true; + } - return false; -} + QVector ucs4string = event->text().toUcs4(); + string utf8string = event->text().toUtf8().data(); -bool -QTTranslator::sendKeyEvent(QEvent* qevent) const -{ - ostringstream str; - - QKeyEvent* event = static_cast(qevent); - bool showShift = true; - bool control = false; - bool nokeypad = false; - bool meta = false; - bool alt = false; - bool keydown = event->type() == QEvent::KeyPress || - event->type() == QEvent::ShortcutOverride || - event->type() == QEvent::Shortcut; - - // On the mac, there are no "releases" reported during auto-repeat, - // we do the below to make this consistant on other platforms. - // - if (noAutoReleaseEvents) - { - if (event->isAutoRepeat() && event->type() == QEvent::KeyRelease) return true; - } + // + // On the Mac the Alt/Option modifier key provides access to accents + // and additional symbols that we are not interested in dealing with. + // This platform specific code below will make sure things like "Alt + // + 4" send the "key-down--alt--4" event and not something about the + // United Kingdom's currency. The intended purpose is to make events + // match on all platforms. + // - QVector ucs4string = event->text().toUcs4(); - string utf8string = event->text().toUtf8().data(); - - // - // On the Mac the Alt/Option modifier key provides access to accents - // and additional symbols that we are not interested in dealing with. - // This platform specific code below will make sure things like "Alt - // + 4" send the "key-down--alt--4" event and not something about the - // United Kingdom's currency. The intended purpose is to make events - // match on all platforms. - // - - // XXX we _still_ have problems with release event modifiers not matching - // press event. This might fix it (for later): - // - // if (event->type() == QEvent::ShortcutOverride || event->type() == QEvent::KeyRelease) - // - - if (event->type() == QEvent::ShortcutOverride) - { + // XXX we _still_ have problems with release event modifiers not + // matching press event. This might fix it (for later): // - // Shortcuts with no mofifier are not have the text set in - // the event. The key is set, so if its ascii copy that to - // the event text. + // if (event->type() == QEvent::ShortcutOverride || event->type() == + // QEvent::KeyRelease) // - if (event->key() <= Qt::Key_AsciiTilde) + if (event->type() == QEvent::ShortcutOverride) { - if (event->key() >= Qt::Key_A && event->key() <= Qt::Key_Z) - { - unsigned int kd = event->key() - Qt::Key_A; - ucs4string.resize(1); - utf8string = " "; + // + // Shortcuts with no mofifier are not have the text set in + // the event. The key is set, so if its ascii copy that to + // the event text. + // - if (m_modifiers & Qt::ShiftModifier) + if (event->key() <= Qt::Key_AsciiTilde) + { + if (event->key() >= Qt::Key_A && event->key() <= Qt::Key_Z) { - utf8string[0] = kd + 'A'; + unsigned int kd = event->key() - Qt::Key_A; + ucs4string.resize(1); + utf8string = " "; + + if (m_modifiers & Qt::ShiftModifier) + { + utf8string[0] = kd + 'A'; + } + else + { + utf8string[0] = kd + 'a'; + } + + ucs4string[0] = utf8string[0]; } else { - utf8string[0] = kd + 'a'; - } - - ucs4string[0] = utf8string[0]; - } - else - { - #ifndef PLATFORM_WINDOWS +#ifndef PLATFORM_WINDOWS char temp[2]; temp[0] = char(event->key()); temp[1] = 0; utf8string = temp; ucs4string.resize(1); ucs4string[0] = event->key(); - #endif +#endif + } } } - } - // - // Qt has some really wacky platform-dependant behavior with even - // modifiers and keys. In some cases the modifiers are completely - // ignored. On the Mac they switch control and meta. Fortunately, the - // actual modifier keys themselves are consistantly tracked on all - // platforms. So we keep track of the modifier state ourselves and - // ignore the Qt state. This can be problematic when enter/leave - // occurs, but that should be dealt with as a special case. - // - - switch (event->key()) - { - case Qt::Key_Shift: - if (keydown) m_modifiers |= Qt::ShiftModifier; - else m_modifiers &= ~Qt::ShiftModifier; - break; - - case Qt::Key_Control: - if (keydown) m_modifiers |= Qt::ControlModifier; - else m_modifiers &= ~Qt::ControlModifier; - break; - - case Qt::Key_Meta: - case Qt::Key_Super_L: - case Qt::Key_Super_R: - meta = true; - if (keydown) m_modifiers |= Qt::MetaModifier; - else m_modifiers &= ~Qt::MetaModifier; - break; - - case Qt::Key_Alt: - alt = true; - if (keydown) m_modifiers |= Qt::AltModifier; - else m_modifiers &= ~Qt::AltModifier; - break; - - case Qt::Key_Left: - case Qt::Key_Right: - case Qt::Key_Up: - case Qt::Key_Down: - // - // On the mac the arrows come across with keypad mod set. Stop - // this from being passed on. - // - nokeypad = true; - break; - } + // + // Qt has some really wacky platform-dependant behavior with even + // modifiers and keys. In some cases the modifiers are completely + // ignored. On the Mac they switch control and meta. Fortunately, the + // actual modifier keys themselves are consistantly tracked on all + // platforms. So we keep track of the modifier state ourselves and + // ignore the Qt state. This can be problematic when enter/leave + // occurs, but that should be dealt with as a special case. + // - // - // If its an upper case key, make sure we show the shift modifier - // too. Also check for control keys. - // + switch (event->key()) + { + case Qt::Key_Shift: + if (keydown) + m_modifiers |= Qt::ShiftModifier; + else + m_modifiers &= ~Qt::ShiftModifier; + break; - if (utf8string.size() == 1) - { - char rkey = utf8string[0]; - if (isupper(rkey) || ispunct(rkey)) showShift = false; - control = event->key() <= 128 && iscntrl(rkey); - } - - // - // Add the key and modifers to the event string - // - - str << "key-" << (keydown ? "down-" : "up-"); + case Qt::Key_Control: + if (keydown) + m_modifiers |= Qt::ControlModifier; + else + m_modifiers &= ~Qt::ControlModifier; + break; - Qt::KeyboardModifiers mods = m_modifiers; - if (nokeypad) mods &= ~Qt::KeypadModifier; + case Qt::Key_Meta: + case Qt::Key_Super_L: + case Qt::Key_Super_R: + meta = true; + if (keydown) + m_modifiers |= Qt::MetaModifier; + else + m_modifiers &= ~Qt::MetaModifier; + break; - str << modifierString(mods, showShift); + case Qt::Key_Alt: + alt = true; + if (keydown) + m_modifiers |= Qt::AltModifier; + else + m_modifiers &= ~Qt::AltModifier; + break; - switch (event->key()) - { - case Qt::Key_Shift: str << "-shift"; break; - case Qt::Key_Control: str << "-control"; break; - case Qt::Key_Meta: str << "-meta"; break; - case Qt::Key_Alt: str << "-alt"; break; - case Qt::Key_Escape: str << "-escape"; break; - case Qt::Key_Tab: str << "-tab"; break; - case Qt::Key_Backtab: str << "-tab"; break; - case Qt::Key_Backspace: str << "-backspace"; break; - case Qt::Key_Return: str << "-enter"; break; - case Qt::Key_Enter: str << "-keypad-enter"; break; - case Qt::Key_Insert: str << "-insert"; break; - case Qt::Key_Delete: str << "-delete"; break; - case Qt::Key_Pause: str << "-pause"; break; - case Qt::Key_Print: str << "-print"; break; - case Qt::Key_SysReq: str << "-sysreq"; break; - case Qt::Key_Clear: str << "-clear"; break; - case Qt::Key_Home: str << "-home"; break; - case Qt::Key_End: str << "-end"; break; - case Qt::Key_Left: str << "-left"; break; - case Qt::Key_Up: str << "-up"; break; - case Qt::Key_Right: str << "-right"; break; - case Qt::Key_Down: str << "-down"; break; - case Qt::Key_PageUp: str << "-page-up"; break; - case Qt::Key_PageDown: str << "-page-down"; break; - case Qt::Key_AltGr: str << "-alt-gr"; alt = true; break; - case Qt::Key_CapsLock: str << "-caplock"; break; - case Qt::Key_NumLock: str << "-numlock"; break; - case Qt::Key_ScrollLock: str << "-scrolllock"; break; - case Qt::Key_Help: str << "-help"; break; - case Qt::Key_Space: str << "- "; break; - case Qt::Key_Super_L: str << "-super-left"; break; - case Qt::Key_Super_R: str << "-super-right"; break; - case Qt::Key_Hyper_L: str << "-hyper-left"; break; - case Qt::Key_Hyper_R: str << "-hyper-right"; break; - case Qt::Key_Direction_L: str << "-direction-left"; break; - case Qt::Key_Direction_R: str << "-direction-right"; break; - case Qt::Key_Menu: str << "-menu"; break; - case 0: - case Qt::Key_unknown: str << "-unknown"; break; - default: + case Qt::Key_Left: + case Qt::Key_Right: + case Qt::Key_Up: + case Qt::Key_Down: + // + // On the mac the arrows come across with keypad mod set. Stop + // this from being passed on. + // + nokeypad = true; + break; + } + + // + // If its an upper case key, make sure we show the shift modifier + // too. Also check for control keys. + // + + if (utf8string.size() == 1) + { + char rkey = utf8string[0]; + if (isupper(rkey) || ispunct(rkey)) + showShift = false; + control = event->key() <= 128 && iscntrl(rkey); + } + + // + // Add the key and modifers to the event string + // + + str << "key-" << (keydown ? "down-" : "up-"); + Qt::KeyboardModifiers mods = m_modifiers; + if (nokeypad) + mods &= ~Qt::KeypadModifier; + + str << modifierString(mods, showShift); + + switch (event->key()) + { + case Qt::Key_Shift: + str << "-shift"; + break; + case Qt::Key_Control: + str << "-control"; + break; + case Qt::Key_Meta: + str << "-meta"; + break; + case Qt::Key_Alt: + str << "-alt"; + break; + case Qt::Key_Escape: + str << "-escape"; + break; + case Qt::Key_Tab: + str << "-tab"; + break; + case Qt::Key_Backtab: + str << "-tab"; + break; + case Qt::Key_Backspace: + str << "-backspace"; + break; + case Qt::Key_Return: + str << "-enter"; + break; + case Qt::Key_Enter: + str << "-keypad-enter"; + break; + case Qt::Key_Insert: + str << "-insert"; + break; + case Qt::Key_Delete: + str << "-delete"; + break; + case Qt::Key_Pause: + str << "-pause"; + break; + case Qt::Key_Print: + str << "-print"; + break; + case Qt::Key_SysReq: + str << "-sysreq"; + break; + case Qt::Key_Clear: + str << "-clear"; + break; + case Qt::Key_Home: + str << "-home"; + break; + case Qt::Key_End: + str << "-end"; + break; + case Qt::Key_Left: + str << "-left"; + break; + case Qt::Key_Up: + str << "-up"; + break; + case Qt::Key_Right: + str << "-right"; + break; + case Qt::Key_Down: + str << "-down"; + break; + case Qt::Key_PageUp: + str << "-page-up"; + break; + case Qt::Key_PageDown: + str << "-page-down"; + break; + case Qt::Key_AltGr: + str << "-alt-gr"; + alt = true; + break; + case Qt::Key_CapsLock: + str << "-caplock"; + break; + case Qt::Key_NumLock: + str << "-numlock"; + break; + case Qt::Key_ScrollLock: + str << "-scrolllock"; + break; + case Qt::Key_Help: + str << "-help"; + break; + case Qt::Key_Space: + str << "- "; + break; + case Qt::Key_Super_L: + str << "-super-left"; + break; + case Qt::Key_Super_R: + str << "-super-right"; + break; + case Qt::Key_Hyper_L: + str << "-hyper-left"; + break; + case Qt::Key_Hyper_R: + str << "-hyper-right"; + break; + case Qt::Key_Direction_L: + str << "-direction-left"; + break; + case Qt::Key_Direction_R: + str << "-direction-right"; + break; + case Qt::Key_Menu: + str << "-menu"; + break; + case 0: + case Qt::Key_unknown: + str << "-unknown"; + break; + default: #if 0 if (event->modifiers() != m_modifiers) @@ -421,443 +511,429 @@ QTTranslator::sendKeyEvent(QEvent* qevent) const } #endif - // - // Function Keys - // - if (event->key() >= Qt::Key_F1 && event->key() <= Qt::Key_F35) - { - str << "-f" << ((event->key() - Qt::Key_F1) + 1); - } - else if (event->key() >= Qt::Key_A && event->key() <= Qt::Key_Z) - { - unsigned int kd = event->key() - Qt::Key_A; - - if (m_modifiers & Qt::ShiftModifier) - { - str << "-" << char(kd + 'A'); - } - else - { - str << "-" << char(kd + 'a'); - } - } - else - { - str << "-" << utf8string; - } + // + // Function Keys + // + if (event->key() >= Qt::Key_F1 && event->key() <= Qt::Key_F35) + { + str << "-f" << ((event->key() - Qt::Key_F1) + 1); + } + else if (event->key() >= Qt::Key_A && event->key() <= Qt::Key_Z) + { + unsigned int kd = event->key() - Qt::Key_A; - break; - } + if (m_modifiers & Qt::ShiftModifier) + { + str << "-" << char(kd + 'A'); + } + else + { + str << "-" << char(kd + 'a'); + } + } + else + { + str << "-" << utf8string; + } - // - // On windows, wchar_t == unsigned short, on all other platforms its - // unsigned int. Fortunately, Qt provides a UCS4 function which will - // work on all platforms. - // + break; + } - unsigned int key = (alt || ucs4string.empty()) - ? event->key() - : ucs4string.front(); + // + // On windows, wchar_t == unsigned short, on all other platforms its + // unsigned int. Fortunately, Qt provides a UCS4 function which will + // work on all platforms. + // - if (keydown) - { - KeyPressEvent e(str.str(), - m_node, - key, - modifiers(mods)); + unsigned int key = + (alt || ucs4string.empty()) ? event->key() : ucs4string.front(); - sendEvent(e); - return e.handled; - } - else - { - KeyReleaseEvent e(str.str(), - m_node, - key, - modifiers(mods)); + if (keydown) + { + KeyPressEvent e(str.str(), m_node, key, modifiers(mods)); - sendEvent(e); - return e.handled; - } -} - -string -QTTranslator::pointerString(bool b1, bool b2, bool b3, - QEvent::Type eventType, - Qt::KeyboardModifiers mods, - Qt::MouseButtons buttons, - bool tabletPushed = false) const -{ - string n; + sendEvent(e); + return e.handled; + } + else + { + KeyReleaseEvent e(str.str(), m_node, key, modifiers(mods)); - if (!Options::sharedOptions().stylusAsMouse && ( - eventType == QEvent::TabletPress || - eventType == QEvent::TabletRelease || - eventType == QEvent::TabletMove)) - { - n = ""; + sendEvent(e); + return e.handled; + } } - else + + string QTTranslator::pointerString(bool b1, bool b2, bool b3, + QEvent::Type eventType, + Qt::KeyboardModifiers mods, + Qt::MouseButtons buttons, + bool tabletPushed = false) const { - n = "pointer-"; - } + string n; + + if (!Options::sharedOptions().stylusAsMouse + && (eventType == QEvent::TabletPress + || eventType == QEvent::TabletRelease + || eventType == QEvent::TabletMove)) + { + n = ""; + } + else + { + n = "pointer-"; + } - if (b1) n += "1-"; - if (b2) n += "2-"; - if (b3) n += "3-"; + if (b1) + n += "1-"; + if (b2) + n += "2-"; + if (b3) + n += "3-"; - n += modifierString(mods, true); - n += "-"; + n += modifierString(mods, true); + n += "-"; - if (Options::sharedOptions().stylusAsMouse) - { - switch (eventType) + if (Options::sharedOptions().stylusAsMouse) { - case QEvent::MouseButtonPress: n += "push"; break; - case QEvent::MouseButtonRelease: n += "release"; break; - case QEvent::MouseButtonDblClick: n += "double"; break; - case QEvent::MouseMove: n += (buttons) ? "drag" : "move"; break; - case QEvent::Enter: n += "enter"; break; - case QEvent::Leave: n += "leave"; break; - case QEvent::WindowActivate: n += "activate"; break; - default: - break; + switch (eventType) + { + case QEvent::MouseButtonPress: + n += "push"; + break; + case QEvent::MouseButtonRelease: + n += "release"; + break; + case QEvent::MouseButtonDblClick: + n += "double"; + break; + case QEvent::MouseMove: + n += (buttons) ? "drag" : "move"; + break; + case QEvent::Enter: + n += "enter"; + break; + case QEvent::Leave: + n += "leave"; + break; + case QEvent::WindowActivate: + n += "activate"; + break; + default: + break; + } } - } - else - { - switch (eventType) + else { - case QEvent::MouseButtonPress: - case QEvent::TabletPress: - n += "push"; - break; - case QEvent::MouseButtonDblClick: - n += "double"; - break; - case QEvent::MouseButtonRelease: - case QEvent::TabletRelease: - n += "release"; - break; - case QEvent::MouseMove: - case QEvent::TabletMove: - n += (buttons || tabletPushed) ? "drag" : "move"; - break; - case QEvent::TabletEnterProximity: - case QEvent::Enter: - n += "enter"; - break; - case QEvent::WindowActivate: - n += "activate"; break; - break; - case QEvent::Leave: - case QEvent::TabletLeaveProximity: - n += "leave"; - break; - default: - break; + switch (eventType) + { + case QEvent::MouseButtonPress: + case QEvent::TabletPress: + n += "push"; + break; + case QEvent::MouseButtonDblClick: + n += "double"; + break; + case QEvent::MouseButtonRelease: + case QEvent::TabletRelease: + n += "release"; + break; + case QEvent::MouseMove: + case QEvent::TabletMove: + n += (buttons || tabletPushed) ? "drag" : "move"; + break; + case QEvent::TabletEnterProximity: + case QEvent::Enter: + n += "enter"; + break; + case QEvent::WindowActivate: + n += "activate"; + break; + break; + case QEvent::Leave: + case QEvent::TabletLeaveProximity: + n += "leave"; + break; + default: + break; + } } + return n; } - return n; -} -bool -QTTranslator::sendMouseWheelEvent(QEvent* qevent) const -{ - QWheelEvent* event = static_cast(qevent); - - string n = pointerString(m_b1, m_b2, m_b3, - event->type(), - m_modifiers, - event->buttons()); - - n += "wheel"; - if (event->delta() < 0) n += "down"; else n += "up"; - - PointerEvent e(n, m_node, modifiers(m_modifiers), - m_x, m_y, - m_width, m_height, - m_pushx, m_pushy, - buttons()); - - sendEvent(e); - return e.handled; -} - -bool -QTTranslator::sendEnterLeaveEvent(QEvent* event) const -{ - // - // Enter/Leave doesn't contain much information (er... any) about - // the pointer. So we'll assume that the app was able to track - // the state somehow while the pointer was out of the window. On - // some platforms this is true by default (mac/windows) on Linux, - // the window manager can completely make a mess out of this by - // shifting focus in unexpected ways. - // - - QEvent::Type type = event->type(); - Qt::KeyboardModifiers mods = m_modifiers; - - string n = pointerString(m_b1, m_b2, m_b3, type, mods, qbuttons(buttons())); - - PointerEvent e(n, m_node, modifiers(mods), - m_x, m_y, - m_width, m_height, - m_x, m_y, - buttons()); - - sendEvent(e); - return e.handled; -} - -bool -QTTranslator::sendMouseEvent(QEvent* qevent, float activationTime) const -{ - QMouseEvent* event = static_cast(qevent); - QEvent::Type type = event->type(); - Qt::KeyboardModifiers mods = m_modifiers; - Qt::MouseButtons ebuttons = event->buttons(); - bool handled = false; - string n; - - bool b1 = event->buttons() & Qt::LeftButton; - bool b2 = event->buttons() & Qt::MidButton; - bool b3 = event->buttons() & Qt::RightButton; + bool QTTranslator::sendMouseWheelEvent(QEvent* qevent) const + { + QWheelEvent* event = static_cast(qevent); - m_x = (m_xscale * event->x()) + m_xoffset; - m_y = (m_yscale * (m_widget->height() - event->y())) + m_yoffset; + string n = pointerString(m_b1, m_b2, m_b3, event->type(), m_modifiers, + event->buttons()); - if (type == QEvent::MouseMove && !buttons()) - { - n = pointerString(false, false, false, type, mods, ebuttons); + n += "wheel"; + if (event->delta() < 0) + n += "down"; + else + n += "up"; - PointerEvent event(n, m_node, modifiers(mods), - m_x, m_y, - m_width, m_height, - m_lastx, m_lasty, - buttons()); + PointerEvent e(n, m_node, modifiers(m_modifiers), m_x, m_y, m_width, + m_height, m_pushx, m_pushy, buttons()); - sendEvent(event); - handled = event.handled; + sendEvent(e); + return e.handled; } - else if (type == QEvent::MouseButtonPress || type == QEvent::MouseButtonDblClick) + + bool QTTranslator::sendEnterLeaveEvent(QEvent* event) const { // - // Release old push + // Enter/Leave doesn't contain much information (er... any) about + // the pointer. So we'll assume that the app was able to track + // the state somehow while the pointer was out of the window. On + // some platforms this is true by default (mac/windows) on Linux, + // the window manager can completely make a mess out of this by + // shifting focus in unexpected ways. // - if ((m_b1 || m_b2 || m_b3 || m_lastMods != m_modifiers) && - !m_firstTime) - { - n = pointerString(m_b1, m_b2, m_b3, - QEvent::MouseButtonRelease, - m_lastMods, qbuttons(m_lastButtons)); - - PointerButtonReleaseEvent event(n, m_node, modifiers(m_lastMods), - m_x, m_y, - m_width, m_height, - m_pushx, m_pushy, - m_lastButtons); - sendEvent(event); - } + QEvent::Type type = event->type(); + Qt::KeyboardModifiers mods = m_modifiers; - // - // Make new push - // + string n = + pointerString(m_b1, m_b2, m_b3, type, mods, qbuttons(buttons())); + + PointerEvent e(n, m_node, modifiers(mods), m_x, m_y, m_width, m_height, + m_x, m_y, buttons()); - n = pointerString(b1, b2, b3, type, mods, ebuttons); - - PointerButtonPressEvent event(n, m_node, mods, - m_x, m_y, - m_width, m_height, - m_x, m_y, - buttons(), 0, - activationTime); - sendEvent(event); - handled = event.handled; - m_pushx = m_x; - m_pushy = m_y; + sendEvent(e); + return e.handled; } - else if (type == QEvent::MouseButtonRelease) + + bool QTTranslator::sendMouseEvent(QEvent* qevent, + float activationTime) const { - // - // Release relative to old event - // + QMouseEvent* event = static_cast(qevent); + QEvent::Type type = event->type(); + Qt::KeyboardModifiers mods = m_modifiers; + Qt::MouseButtons ebuttons = event->buttons(); + bool handled = false; + string n; - n = pointerString(m_b1, m_b2, m_b3, - QEvent::MouseButtonRelease, mods, ebuttons); + bool b1 = event->buttons() & Qt::LeftButton; + bool b2 = event->buttons() & Qt::MidButton; + bool b3 = event->buttons() & Qt::RightButton; - PointerButtonReleaseEvent event(n, m_node, modifiers(mods), - m_x, m_y, - m_width, m_height, - m_pushx, m_pushy, - buttons()); - sendEvent(event); - handled = event.handled; + m_x = (m_xscale * event->x()) + m_xoffset; + m_y = (m_yscale * (m_widget->height() - event->y())) + m_yoffset; - if (b1 || b2 || b3) + if (type == QEvent::MouseMove && !buttons()) { - n = pointerString(b1, b2, b3, - QEvent::MouseButtonPress, mods, ebuttons); - - PointerButtonPressEvent event(n, m_node, modifiers(mods), - m_x, m_y, - m_width, m_height, - m_x, m_y, - buttons()); + n = pointerString(false, false, false, type, mods, ebuttons); + + PointerEvent event(n, m_node, modifiers(mods), m_x, m_y, m_width, + m_height, m_lastx, m_lasty, buttons()); + sendEvent(event); handled = event.handled; - m_pushx = m_x; - m_pushy = m_y; } - } - else - { - if ((b1 != m_b1 || b2 != m_b2 || b3 != m_b3 || m_lastMods != m_modifiers) - && !m_firstTime) + else if (type == QEvent::MouseButtonPress + || type == QEvent::MouseButtonDblClick) { - n = pointerString(m_b1, m_b2, m_b3, - QEvent::MouseButtonRelease, - m_lastMods, - qbuttons(m_lastButtons)); - - PointerButtonReleaseEvent eEnd(n, m_node, modifiers(m_modifiers), - m_x, m_y, - m_width, m_height, - m_pushx, m_pushy, - m_lastButtons); - - n = pointerString(b1, b2, b3, - QEvent::MouseButtonPress, - mods, ebuttons); + // + // Release old push + // + + if ((m_b1 || m_b2 || m_b3 || m_lastMods != m_modifiers) + && !m_firstTime) + { + n = pointerString(m_b1, m_b2, m_b3, QEvent::MouseButtonRelease, + m_lastMods, qbuttons(m_lastButtons)); + + PointerButtonReleaseEvent event( + n, m_node, modifiers(m_lastMods), m_x, m_y, m_width, + m_height, m_pushx, m_pushy, m_lastButtons); + sendEvent(event); + } + + // + // Make new push + // - PointerButtonPressEvent eBegin(n, m_node, modifiers(mods), - m_x, m_y, - m_width, m_height, - m_x, m_y, - buttons()); + n = pointerString(b1, b2, b3, type, mods, ebuttons); - sendEvent(eEnd); + PointerButtonPressEvent event(n, m_node, mods, m_x, m_y, m_width, + m_height, m_x, m_y, buttons(), 0, + activationTime); + sendEvent(event); + handled = event.handled; m_pushx = m_x; m_pushy = m_y; - sendEvent(eBegin); } + else if (type == QEvent::MouseButtonRelease) + { + // + // Release relative to old event + // - n = pointerString(b1, b2, b3, type, mods, ebuttons); + n = pointerString(m_b1, m_b2, m_b3, QEvent::MouseButtonRelease, + mods, ebuttons); - PointerEvent event(n, m_node, modifiers(mods), - m_x, m_y, - m_width, m_height, - m_pushx, m_pushy, - buttons()); + PointerButtonReleaseEvent event(n, m_node, modifiers(mods), m_x, + m_y, m_width, m_height, m_pushx, + m_pushy, buttons()); + sendEvent(event); + handled = event.handled; - sendEvent(event); - handled = event.handled; - } + if (b1 || b2 || b3) + { + n = pointerString(b1, b2, b3, QEvent::MouseButtonPress, mods, + ebuttons); + + PointerButtonPressEvent event(n, m_node, modifiers(mods), m_x, + m_y, m_width, m_height, m_x, m_y, + buttons()); + sendEvent(event); + handled = event.handled; + m_pushx = m_x; + m_pushy = m_y; + } + } + else + { + if ((b1 != m_b1 || b2 != m_b2 || b3 != m_b3 + || m_lastMods != m_modifiers) + && !m_firstTime) + { + n = pointerString(m_b1, m_b2, m_b3, QEvent::MouseButtonRelease, + m_lastMods, qbuttons(m_lastButtons)); + PointerButtonReleaseEvent eEnd( + n, m_node, modifiers(m_modifiers), m_x, m_y, m_width, + m_height, m_pushx, m_pushy, m_lastButtons); - m_lastButtons = buttons(); - m_lastType = type; - m_lastMods = m_modifiers; - m_b1 = b1; - m_b2 = b2; - m_b3 = b3; - m_firstTime = false; - m_lastx = m_x; - m_lasty = m_y; + n = pointerString(b1, b2, b3, QEvent::MouseButtonPress, mods, + ebuttons); - return handled ? true : false; -} + PointerButtonPressEvent eBegin(n, m_node, modifiers(mods), m_x, + m_y, m_width, m_height, m_x, m_y, + buttons()); -unsigned int -QTTranslator::buttons() const -{ - return int(m_b1) | (int(m_b2) << 1) | (int(m_b3) << 2); -} + sendEvent(eEnd); + m_pushx = m_x; + m_pushy = m_y; + sendEvent(eBegin); + } -string -QTTranslator::modifierString(Qt::KeyboardModifiers mods, bool showShift) const -{ - string s; - unsigned int m = modifiers(mods); - - if (m & ModifierEvent::Alt) s += "-alt"; - if (m & ModifierEvent::CapLock) s += "-caplock"; - if (m & ModifierEvent::Control) s += "-control"; - if (m & ModifierEvent::Meta) s += "-meta"; - if (m & ModifierEvent::NumLock) s += "-numlock"; - if (m & ModifierEvent::ScrollLock) s += "-scrolllock"; - - if (showShift && - m & ModifierEvent::Shift) s += "-shift"; - - if (s.size()) s += "-"; - - return s; -} - -bool -QTTranslator::sendDNDEvent(QEvent* event) const -{ - if (QDropEvent *de = dynamic_cast (event)) - { - // - // Ignore attempts by the dropper to delete the dropped file after RV accepts the drop. - // NOTE: on windows MoveAction means the explorere will delete the file after the drop. - // on mac, MoveAction seems to stand in for CopyAction sometimes, so just treat everything - // as a copy. - // - if (de->proposedAction() == Qt::MoveAction || de->proposedAction() == Qt::TargetMoveAction) - { - de->setDropAction (Qt::CopyAction); - } - } + n = pointerString(b1, b2, b3, type, mods, ebuttons); - bool handled = false; - DragDropEvent::Type type; - int w = m_width; - int h = m_height; + PointerEvent event(n, m_node, modifiers(mods), m_x, m_y, m_width, + m_height, m_pushx, m_pushy, buttons()); - bool leave = event->type() == QEvent::DragLeave; - string ename = "dragdrop--"; + sendEvent(event); + handled = event.handled; + } - switch (event->type()) - { - case QEvent::DragEnter: - type = DragDropEvent::Enter; - ename += "enter"; - break; - case QEvent::DragMove: - type = DragDropEvent::Move; - ename += "move"; - break; - case QEvent::DragLeave: - type = DragDropEvent::Leave; - ename += "leave"; - break; - case QEvent::Drop: - type = DragDropEvent::Release; - ename += "release"; - break; - default: - break; + m_lastButtons = buttons(); + m_lastType = type; + m_lastMods = m_modifiers; + m_b1 = b1; + m_b2 = b2; + m_b3 = b3; + m_firstTime = false; + m_lastx = m_x; + m_lasty = m_y; + + return handled ? true : false; } - if (leave) + unsigned int QTTranslator::buttons() const { - DragDropEvent e(ename, m_node, DragDropEvent::Leave, - DragDropEvent::File, - "", 0, - 0, 0, - w, h); + return int(m_b1) | (int(m_b2) << 1) | (int(m_b3) << 2); + } - sendEvent(e); - handled = e.handled; + string QTTranslator::modifierString(Qt::KeyboardModifiers mods, + bool showShift) const + { + string s; + unsigned int m = modifiers(mods); + + if (m & ModifierEvent::Alt) + s += "-alt"; + if (m & ModifierEvent::CapLock) + s += "-caplock"; + if (m & ModifierEvent::Control) + s += "-control"; + if (m & ModifierEvent::Meta) + s += "-meta"; + if (m & ModifierEvent::NumLock) + s += "-numlock"; + if (m & ModifierEvent::ScrollLock) + s += "-scrolllock"; + + if (showShift && m & ModifierEvent::Shift) + s += "-shift"; + + if (s.size()) + s += "-"; + + return s; } - else + + bool QTTranslator::sendDNDEvent(QEvent* event) const { - QDropEvent* devent = static_cast(event); + if (QDropEvent* de = dynamic_cast(event)) + { + // + // Ignore attempts by the dropper to delete the dropped file after + // RV accepts the drop. NOTE: on windows MoveAction means the + // explorere will delete the file after the drop. on mac, + // MoveAction seems to stand in for CopyAction sometimes, so just + // treat everything as a copy. + // + if (de->proposedAction() == Qt::MoveAction + || de->proposedAction() == Qt::TargetMoveAction) + { + de->setDropAction(Qt::CopyAction); + } + } + + bool handled = false; + DragDropEvent::Type type; + int w = m_width; + int h = m_height; + + bool leave = event->type() == QEvent::DragLeave; + string ename = "dragdrop--"; + + switch (event->type()) + { + case QEvent::DragEnter: + type = DragDropEvent::Enter; + ename += "enter"; + break; + case QEvent::DragMove: + type = DragDropEvent::Move; + ename += "move"; + break; + case QEvent::DragLeave: + type = DragDropEvent::Leave; + ename += "leave"; + break; + case QEvent::Drop: + type = DragDropEvent::Release; + ename += "release"; + break; + default: + break; + } + + if (leave) + { + DragDropEvent e(ename, m_node, DragDropEvent::Leave, + DragDropEvent::File, "", 0, 0, 0, w, h); + + sendEvent(e); + handled = e.handled; + } + else + { + QDropEvent* devent = static_cast(event); #if 0 QStringList formats = devent->mimeData()->formats(); @@ -868,237 +944,233 @@ QTTranslator::sendDNDEvent(QEvent* event) const } #endif - if (devent->mimeData()->hasUrls()) - { - QList urls = devent->mimeData()->urls(); - - FileNameList files; - FileNameList nonfiles; - - for (QList::iterator i=urls.begin(); i < urls.end(); ++i) + if (devent->mimeData()->hasUrls()) { - if (i->scheme() == "" || i->path() == "") continue; + QList urls = devent->mimeData()->urls(); + + FileNameList files; + FileNameList nonfiles; - if (i->scheme() == "file") + for (QList::iterator i = urls.begin(); i < urls.end(); + ++i) { - QString ppath = i->toLocalFile(); + if (i->scheme() == "" || i->path() == "") + continue; + + if (i->scheme() == "file") + { + QString ppath = i->toLocalFile(); #ifdef PLATFORM_WINDOWS - QFileInfo ppFI = QFileInfo(ppath); - if (ppFI.isDir()) + QFileInfo ppFI = QFileInfo(ppath); + if (ppFI.isDir()) + { + ppath += QString("/"); + } +#endif + // #ifdef WIN32 + // while (ppath[0] == '/') ppath.remove(0, 1); + // #endif + files.push_back( + pathConform(ppath.toUtf8().constData())); + } + else { - ppath += QString("/"); + nonfiles.push_back(i->toString().toUtf8().constData()); } -#endif -//#ifdef WIN32 - //while (ppath[0] == '/') ppath.remove(0, 1); -//#endif - files.push_back(pathConform(ppath.toUtf8().constData())); + } + + SequenceNameList seqs; + if (files.size() && QFileInfo(files[0].c_str()).isDir()) + // + // Don't try to form sequences out of list of directories + // + { + seqs = files; } else + seqs = sequencesInFileList(files, GlobalExtensionPredicate); + + for (int i = 0; i < seqs.size(); i++) { - nonfiles.push_back(i->toString().toUtf8().constData()); + DragDropEvent e(ename, m_node, type, DragDropEvent::File, + seqs[i], 0, devent->pos().x(), + h - devent->pos().y() - 1, w, h); + + sendEvent(e); + if (e.handled) + handled = true; } - } - SequenceNameList seqs; - if (files.size() && QFileInfo(files[0].c_str()).isDir()) - // - // Don't try to form sequences out of list of directories - // - { - seqs = files; - } - else seqs = sequencesInFileList(files, GlobalExtensionPredicate); + for (int i = 0; i < nonfiles.size(); i++) + { + DragDropEvent e(ename, m_node, type, DragDropEvent::URL, + nonfiles[i], 0, devent->pos().x(), + h - devent->pos().y() - 1, w, h); - for (int i=0; i < seqs.size(); i++) + sendEvent(e); + if (e.handled) + handled = true; + } + } + else if (devent->mimeData()->hasText()) { - DragDropEvent e(ename, m_node, type, DragDropEvent::File, - seqs[i], 0, - devent->pos().x(), - h - devent->pos().y() - 1, + DragDropEvent e(ename, m_node, type, DragDropEvent::Text, + devent->mimeData()->text().toUtf8().constData(), + 0, devent->pos().x(), h - devent->pos().y() - 1, w, h); sendEvent(e); - if (e.handled) handled = true; + if (e.handled) + handled = true; } + } - for (int i=0; i < nonfiles.size(); i++) - { - DragDropEvent e(ename, m_node, type, DragDropEvent::URL, - nonfiles[i], 0, - devent->pos().x(), - h - devent->pos().y() - 1, - w, h); + return handled; + } - sendEvent(e); - if (e.handled) handled = true; - } + bool QTTranslator::sendTabletEvent(QEvent* qevent) const + { + QTabletEvent* event = static_cast(qevent); + QEvent::Type type = event->type(); + Qt::KeyboardModifiers mods = m_modifiers; + Qt::MouseButtons ebuttons = qbuttons(m_lastButtons); + bool handled = false; + + QPoint p = m_widget->mapToGlobal(QPoint(0, 0)); + double xoff = p.x(); + double yoff = p.y(); + + const double gx = event->hiResGlobalX() - xoff; + const double gy = + double(m_widget->height()) - (event->hiResGlobalY() - yoff); + const double pressure = event->pressure(); + const double tpressure = event->tangentialPressure(); + const double rot = event->rotation(); + const int xtilt = event->xTilt(); + const int ytilt = event->yTilt(); + const int z = event->z(); + + TabletEvent::TabletKind kind; + TabletEvent::TabletDevice device; + + string n; + + switch (event->device()) + { + case QTabletEvent::NoDevice: + device = TabletEvent::NoTableDevice; + n = "generic-tablet-device-"; + break; + case QTabletEvent::Puck: + device = TabletEvent::PuckDevice; + n = "puck-"; + break; + case QTabletEvent::Stylus: + device = TabletEvent::StylusDevice; + n = "stylus-"; + break; + case QTabletEvent::Airbrush: + device = TabletEvent::AirBrushDevice; + n = "airbrush-"; + break; + case QTabletEvent::FourDMouse: + device = TabletEvent::FourDMouseDevice; + n = "mouse4D-"; + break; + case QTabletEvent::RotationStylus: + device = TabletEvent::RotationStylusDevice; + n = "rotating-stylus-"; + break; + default: + break; } - else if (devent->mimeData()->hasText()) + + switch (event->pointerType()) { - DragDropEvent e(ename, m_node, type, DragDropEvent::Text, - devent->mimeData()->text().toUtf8().constData(), 0, - devent->pos().x(), - h - devent->pos().y() - 1, - w, h); + case QTabletEvent::UnknownPointer: + kind = TabletEvent::UnknownTabletKind; + break; + case QTabletEvent::Pen: + kind = TabletEvent::PenKind; + n += "pen-"; + break; + case QTabletEvent::Cursor: + kind = TabletEvent::CursorKind; + n += "cursor-"; + break; + case QTabletEvent::Eraser: + kind = TabletEvent::EraserKind; + n += "eraser-"; + break; + } - sendEvent(e); - if (e.handled) handled = true; + bool b1 = m_b1; + bool b2 = m_b2; + bool b3 = m_b3; + + m_x = gx * m_xscale + m_xoffset; + m_y = gy * m_yscale + m_yoffset; + + if (type == QEvent::TabletPress) + { + m_pushx = m_x; + m_pushy = m_y; } - } - return handled; -} + n += pointerString(b1, b2, b3, type, mods, ebuttons, m_tabletPushed); -bool -QTTranslator::sendTabletEvent(QEvent* qevent) const -{ - QTabletEvent* event = static_cast(qevent); - QEvent::Type type = event->type(); - Qt::KeyboardModifiers mods = m_modifiers; - Qt::MouseButtons ebuttons = qbuttons(m_lastButtons); - bool handled = false; - - QPoint p = m_widget->mapToGlobal(QPoint(0,0)); - double xoff = p.x(); - double yoff = p.y(); - - const double gx = event->hiResGlobalX() - xoff; - const double gy = double(m_widget->height()) - (event->hiResGlobalY() - yoff); - const double pressure = event->pressure(); - const double tpressure = event->tangentialPressure(); - const double rot = event->rotation(); - const int xtilt = event->xTilt(); - const int ytilt = event->yTilt(); - const int z = event->z(); - - TabletEvent::TabletKind kind; - TabletEvent::TabletDevice device; - - string n; - - switch (event->device()) - { - case QTabletEvent::NoDevice: - device = TabletEvent::NoTableDevice; - n = "generic-tablet-device-"; - break; - case QTabletEvent::Puck: - device = TabletEvent::PuckDevice; - n = "puck-"; - break; - case QTabletEvent::Stylus: - device = TabletEvent::StylusDevice; - n = "stylus-"; - break; - case QTabletEvent::Airbrush: - device = TabletEvent::AirBrushDevice; - n = "airbrush-"; - break; - case QTabletEvent::FourDMouse: - device = TabletEvent::FourDMouseDevice; - n = "mouse4D-"; - break; - case QTabletEvent::RotationStylus: - device = TabletEvent::RotationStylusDevice; - n = "rotating-stylus-"; - break; - default: - break; - } + switch (type) + { + case QEvent::TabletPress: + // + // Note: Qt's autograb doesn't seem to work with tablets, + // so we grab/release manually here. + // + m_tabletPushed = true; + m_widget->grabMouse(); + break; + case QEvent::TabletRelease: + m_tabletPushed = false; + m_widget->releaseMouse(); + break; + default: + break; + } - switch (event->pointerType()) - { - case QTabletEvent::UnknownPointer: - kind = TabletEvent::UnknownTabletKind; - break; - case QTabletEvent::Pen: - kind = TabletEvent::PenKind; - n += "pen-"; - break; - case QTabletEvent::Cursor: - kind = TabletEvent::CursorKind; - n += "cursor-"; - break; - case QTabletEvent::Eraser: - kind = TabletEvent::EraserKind; - n += "eraser-"; - break; - } + TabletEvent e(n, m_node, modifiers(mods), m_x, m_y, m_width, m_height, + // m_lastx, m_lasty, + m_pushx, m_pushy, buttons(), kind, device, gx, gy, + pressure, tpressure, rot, xtilt, ytilt, z); - bool b1 = m_b1; - bool b2 = m_b2; - bool b3 = m_b3; + sendEvent(e); + handled = e.handled; - m_x = gx * m_xscale + m_xoffset; - m_y = gy * m_yscale + m_yoffset; + m_lastButtons = buttons(); + m_lastType = type; + m_lastMods = m_modifiers; + m_b1 = b1; + m_b2 = b2; + m_b3 = b3; + m_firstTime = false; + // m_lastx = m_x; + // m_lasty = m_y; + + return true; + } - if (type == QEvent::TabletPress) + void QTTranslator::setScaleAndOffset(float x, float y, float sx, + float sy) const { - m_pushx = m_x; - m_pushy = m_y; + m_xoffset = x; + m_yoffset = y; + m_xscale = sx; + m_yscale = sy; } - - n += pointerString(b1, b2, b3, type, mods, ebuttons, m_tabletPushed); - switch (type) + void QTTranslator::setRelativeDomain(float w, float h) const { - case QEvent::TabletPress: - // - // Note: Qt's autograb doesn't seem to work with tablets, - // so we grab/release manually here. - // - m_tabletPushed = true; - m_widget->grabMouse(); - break; - case QEvent::TabletRelease: - m_tabletPushed = false; - m_widget->releaseMouse(); - break; - default: - break; + m_width = w; + m_height = h; } - TabletEvent e(n, m_node, modifiers(mods), - m_x, m_y, - m_width, m_height, - //m_lastx, m_lasty, - m_pushx, m_pushy, - buttons(), - kind, device, - gx, gy, pressure, tpressure, rot, - xtilt, ytilt, z); - - sendEvent(e); - handled = e.handled; - - m_lastButtons = buttons(); - m_lastType = type; - m_lastMods = m_modifiers; - m_b1 = b1; - m_b2 = b2; - m_b3 = b3; - m_firstTime = false; - //m_lastx = m_x; - //m_lasty = m_y; - - return true; -} - -void -QTTranslator::setScaleAndOffset(float x, float y, float sx, float sy) const -{ - m_xoffset = x; - m_yoffset = y; - m_xscale = sx; - m_yscale = sy; -} - -void -QTTranslator::setRelativeDomain(float w, float h) const -{ - m_width = w; - m_height = h; -} - -} // Rv +} // namespace Rv diff --git a/src/lib/app/RvCommon/QTUtils.cpp b/src/lib/app/RvCommon/QTUtils.cpp index 420372717..06c0a6795 100644 --- a/src/lib/app/RvCommon/QTUtils.cpp +++ b/src/lib/app/RvCommon/QTUtils.cpp @@ -1,9 +1,9 @@ //****************************************************************************** -// Copyright (c) 2007 Tweak Inc. +// Copyright (c) 2007 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #include @@ -12,165 +12,172 @@ #include #include -namespace Rv { -using namespace std; -typedef map CMap; - -QPixmap -colorAdjustedPixmap(const QString& rpath, bool invertSense) +namespace Rv { - const char* darkval = getenv("RV_DARK"); - bool dark = darkval && !strcmp(darkval, "1"); - - QImage image(rpath); + using namespace std; + typedef map CMap; - if (dark != invertSense) + QPixmap colorAdjustedPixmap(const QString& rpath, bool invertSense) { - image.invertPixels(); - } + const char* darkval = getenv("RV_DARK"); + bool dark = darkval && !strcmp(darkval, "1"); - return QPixmap(QPixmap::fromImage(image)); -} + QImage image(rpath); -QIcon -colorAdjustedIcon(const QString& rpath, bool invertSense) -{ - const char* darkval = getenv("RV_DARK"); - bool dark = darkval && !strcmp(darkval, "1"); + if (dark != invertSense) + { + image.invertPixels(); + } - QImage image(rpath); + return QPixmap(QPixmap::fromImage(image)); + } - if (dark != invertSense) + QIcon colorAdjustedIcon(const QString& rpath, bool invertSense) { - image.invertPixels(); - } + const char* darkval = getenv("RV_DARK"); + bool dark = darkval && !strcmp(darkval, "1"); - return QIcon(QPixmap::fromImage(image)); -} + QImage image(rpath); -static QPalette defaultPalette; + if (dark != invertSense) + { + image.invertPixels(); + } -void -setDefaultPalette() -{ - qApp->setPalette(defaultPalette); -} + return QIcon(QPixmap::fromImage(image)); + } -void -initializeDefaultPalette() -{ - defaultPalette = qApp->palette(); -} + static QPalette defaultPalette; -void -installApplicationPalette() -{ - QPalette p = qApp->palette(); - p.setColor(QPalette::Active, QPalette::WindowText, QColor(217, 217, 197)); - p.setColor(QPalette::Active, QPalette::Button, QColor(99, 99, 99)); - p.setColor(QPalette::Active, QPalette::Window, QColor(68, 68, 66)); - p.setColor(QPalette::Active, QPalette::Shadow, QColor(0, 0, 0)); - p.setColor(QPalette::Active, QPalette::Highlight, QColor(117, 117, 112)); - p.setColor(QPalette::Active, QPalette::HighlightedText, QColor(248, 248, 227)); - p.setColor(QPalette::Active, QPalette::Link, QColor(0, 0, 238)); - p.setColor(QPalette::Active, QPalette::LinkVisited, QColor(82, 24, 139)); - p.setColor(QPalette::Active, QPalette::AlternateBase, QColor(65, 69, 65)); - p.setColor(QPalette::Active, QPalette::Light, QColor(106, 106, 106)); - p.setColor(QPalette::Active, QPalette::Midlight, QColor(124, 124, 124)); - p.setColor(QPalette::Active, QPalette::Dark, QColor(49, 49, 49)); - p.setColor(QPalette::Active, QPalette::Mid, QColor(66, 66, 66)); - p.setColor(QPalette::Active, QPalette::Text, QColor(180, 180, 163)); - p.setColor(QPalette::Active, QPalette::BrightText, QColor(255, 255, 255)); - p.setColor(QPalette::Active, QPalette::ButtonText, QColor(234, 234, 213)); - p.setColor(QPalette::Active, QPalette::Base, QColor(55, 59, 55)); - - p.setColor(QPalette::Disabled, QPalette::WindowText, QColor(128, 128, 128)); - p.setColor(QPalette::Disabled, QPalette::Button, QColor(99, 99, 99)); - p.setColor(QPalette::Disabled, QPalette::Window, QColor(68, 68, 66)); - p.setColor(QPalette::Disabled, QPalette::Shadow, QColor(0, 0, 0)); - //p.setColor(QPalette::Disabled, QPalette::Highlight, QColor(117, 117, 112)); - // Highlight and HighlightedText seem to be swapped in some cases - p.setColor(QPalette::Disabled, QPalette::Highlight, QColor(55, 59, 55)); - p.setColor(QPalette::Disabled, QPalette::HighlightedText, QColor(128, 128, 128)); - p.setColor(QPalette::Disabled, QPalette::Link, QColor(0, 0, 238)); - p.setColor(QPalette::Disabled, QPalette::LinkVisited, QColor(82, 24, 139)); - p.setColor(QPalette::Disabled, QPalette::AlternateBase, QColor(65, 69, 65)); - p.setColor(QPalette::Disabled, QPalette::Light, QColor(106, 106, 106)); - p.setColor(QPalette::Disabled, QPalette::Midlight, QColor(124, 124, 124)); - p.setColor(QPalette::Disabled, QPalette::Dark, QColor(49, 49, 49)); - p.setColor(QPalette::Disabled, QPalette::Mid, QColor(66, 66, 66)); - p.setColor(QPalette::Disabled, QPalette::Text, QColor(91, 90, 90)); - p.setColor(QPalette::Disabled, QPalette::BrightText, QColor(255, 255, 255)); - p.setColor(QPalette::Disabled, QPalette::ButtonText, QColor(128, 128, 128)); - p.setColor(QPalette::Disabled, QPalette::Base, QColor(55, 59, 55)); - - p.setColor(QPalette::Inactive, QPalette::WindowText, QColor(217, 217, 197)); - p.setColor(QPalette::Inactive, QPalette::Button, QColor(99, 99, 99)); - p.setColor(QPalette::Inactive, QPalette::Window, QColor(68, 68, 66)); - p.setColor(QPalette::Inactive, QPalette::Shadow, QColor(0, 0, 0)); - p.setColor(QPalette::Inactive, QPalette::Highlight, QColor(55, 59, 55)); - p.setColor(QPalette::Inactive, QPalette::HighlightedText, QColor(128, 128, 128)); - p.setColor(QPalette::Inactive, QPalette::Link, QColor(0, 0, 238)); - p.setColor(QPalette::Inactive, QPalette::LinkVisited, QColor(82, 24, 139)); - p.setColor(QPalette::Inactive, QPalette::AlternateBase, QColor(65, 69, 65)); - p.setColor(QPalette::Inactive, QPalette::Light, QColor(106, 106, 106)); - p.setColor(QPalette::Inactive, QPalette::Midlight, QColor(124, 124, 124)); - p.setColor(QPalette::Inactive, QPalette::Dark, QColor(49, 49, 49)); - p.setColor(QPalette::Inactive, QPalette::Mid, QColor(66, 66, 66)); - p.setColor(QPalette::Inactive, QPalette::Text, QColor(180, 180, 163)); - p.setColor(QPalette::Inactive, QPalette::BrightText, QColor(255, 255, 255)); - p.setColor(QPalette::Inactive, QPalette::ButtonText, QColor(234, 234, 213)); - p.setColor(QPalette::Inactive, QPalette::Base, QColor(55, 59, 55)); - qApp->setPalette(p); - //QFont font(QString("Kabel DM BT"), 12); - //QFont f = qApp->font(); - //f.setPointSize(10); - //qApp->setFont(f); -} - -void -dumpApplicationPalette() -{ - QPalette p = qApp->palette(); + void setDefaultPalette() { qApp->setPalette(defaultPalette); } - CMap active; - CMap inactive; - CMap disabled; + void initializeDefaultPalette() { defaultPalette = qApp->palette(); } - for (int i=0; i < 17; i++) + void installApplicationPalette() { - active[i] = p.color(QPalette::Active, (QPalette::ColorRole)i); - inactive[i] = p.color(QPalette::Inactive, (QPalette::ColorRole)i); - disabled[i] = p.color(QPalette::Disabled, (QPalette::ColorRole)i); - - QColor c = active[i]; - int r = c.red(); - int g = c.green(); - int b = c.blue(); - - cout << "p.setColor(QPalette::Active, (QPalette::ColorRole)" - << i << ", QColor(" - << r << ", " << g << ", " << b << "));" << endl; - - c = inactive[i]; - r = c.red(); - g = c.green(); - b = c.blue(); - - cout << "p.setColor(QPalette::Inactive, (QPalette::ColorRole)" - << i << ", QColor(" - << r << ", " << g << ", " << b << "));" << endl; - - c = disabled[i]; - r = c.red(); - g = c.green(); - b = c.blue(); - - cout << "p.setColor(QPalette::Disabled, (QPalette::ColorRole)" - << i << ", QColor(" - << r << ", " << g << ", " << b << "));" << endl; + QPalette p = qApp->palette(); + p.setColor(QPalette::Active, QPalette::WindowText, + QColor(217, 217, 197)); + p.setColor(QPalette::Active, QPalette::Button, QColor(99, 99, 99)); + p.setColor(QPalette::Active, QPalette::Window, QColor(68, 68, 66)); + p.setColor(QPalette::Active, QPalette::Shadow, QColor(0, 0, 0)); + p.setColor(QPalette::Active, QPalette::Highlight, + QColor(117, 117, 112)); + p.setColor(QPalette::Active, QPalette::HighlightedText, + QColor(248, 248, 227)); + p.setColor(QPalette::Active, QPalette::Link, QColor(0, 0, 238)); + p.setColor(QPalette::Active, QPalette::LinkVisited, + QColor(82, 24, 139)); + p.setColor(QPalette::Active, QPalette::AlternateBase, + QColor(65, 69, 65)); + p.setColor(QPalette::Active, QPalette::Light, QColor(106, 106, 106)); + p.setColor(QPalette::Active, QPalette::Midlight, QColor(124, 124, 124)); + p.setColor(QPalette::Active, QPalette::Dark, QColor(49, 49, 49)); + p.setColor(QPalette::Active, QPalette::Mid, QColor(66, 66, 66)); + p.setColor(QPalette::Active, QPalette::Text, QColor(180, 180, 163)); + p.setColor(QPalette::Active, QPalette::BrightText, + QColor(255, 255, 255)); + p.setColor(QPalette::Active, QPalette::ButtonText, + QColor(234, 234, 213)); + p.setColor(QPalette::Active, QPalette::Base, QColor(55, 59, 55)); + + p.setColor(QPalette::Disabled, QPalette::WindowText, + QColor(128, 128, 128)); + p.setColor(QPalette::Disabled, QPalette::Button, QColor(99, 99, 99)); + p.setColor(QPalette::Disabled, QPalette::Window, QColor(68, 68, 66)); + p.setColor(QPalette::Disabled, QPalette::Shadow, QColor(0, 0, 0)); + // p.setColor(QPalette::Disabled, QPalette::Highlight, QColor(117, + // 117, 112)); + // Highlight and HighlightedText seem to be swapped in some cases + p.setColor(QPalette::Disabled, QPalette::Highlight, QColor(55, 59, 55)); + p.setColor(QPalette::Disabled, QPalette::HighlightedText, + QColor(128, 128, 128)); + p.setColor(QPalette::Disabled, QPalette::Link, QColor(0, 0, 238)); + p.setColor(QPalette::Disabled, QPalette::LinkVisited, + QColor(82, 24, 139)); + p.setColor(QPalette::Disabled, QPalette::AlternateBase, + QColor(65, 69, 65)); + p.setColor(QPalette::Disabled, QPalette::Light, QColor(106, 106, 106)); + p.setColor(QPalette::Disabled, QPalette::Midlight, + QColor(124, 124, 124)); + p.setColor(QPalette::Disabled, QPalette::Dark, QColor(49, 49, 49)); + p.setColor(QPalette::Disabled, QPalette::Mid, QColor(66, 66, 66)); + p.setColor(QPalette::Disabled, QPalette::Text, QColor(91, 90, 90)); + p.setColor(QPalette::Disabled, QPalette::BrightText, + QColor(255, 255, 255)); + p.setColor(QPalette::Disabled, QPalette::ButtonText, + QColor(128, 128, 128)); + p.setColor(QPalette::Disabled, QPalette::Base, QColor(55, 59, 55)); + + p.setColor(QPalette::Inactive, QPalette::WindowText, + QColor(217, 217, 197)); + p.setColor(QPalette::Inactive, QPalette::Button, QColor(99, 99, 99)); + p.setColor(QPalette::Inactive, QPalette::Window, QColor(68, 68, 66)); + p.setColor(QPalette::Inactive, QPalette::Shadow, QColor(0, 0, 0)); + p.setColor(QPalette::Inactive, QPalette::Highlight, QColor(55, 59, 55)); + p.setColor(QPalette::Inactive, QPalette::HighlightedText, + QColor(128, 128, 128)); + p.setColor(QPalette::Inactive, QPalette::Link, QColor(0, 0, 238)); + p.setColor(QPalette::Inactive, QPalette::LinkVisited, + QColor(82, 24, 139)); + p.setColor(QPalette::Inactive, QPalette::AlternateBase, + QColor(65, 69, 65)); + p.setColor(QPalette::Inactive, QPalette::Light, QColor(106, 106, 106)); + p.setColor(QPalette::Inactive, QPalette::Midlight, + QColor(124, 124, 124)); + p.setColor(QPalette::Inactive, QPalette::Dark, QColor(49, 49, 49)); + p.setColor(QPalette::Inactive, QPalette::Mid, QColor(66, 66, 66)); + p.setColor(QPalette::Inactive, QPalette::Text, QColor(180, 180, 163)); + p.setColor(QPalette::Inactive, QPalette::BrightText, + QColor(255, 255, 255)); + p.setColor(QPalette::Inactive, QPalette::ButtonText, + QColor(234, 234, 213)); + p.setColor(QPalette::Inactive, QPalette::Base, QColor(55, 59, 55)); + qApp->setPalette(p); + // QFont font(QString("Kabel DM BT"), 12); + // QFont f = qApp->font(); + // f.setPointSize(10); + // qApp->setFont(f); + } + void dumpApplicationPalette() + { + QPalette p = qApp->palette(); + + CMap active; + CMap inactive; + CMap disabled; + + for (int i = 0; i < 17; i++) + { + active[i] = p.color(QPalette::Active, (QPalette::ColorRole)i); + inactive[i] = p.color(QPalette::Inactive, (QPalette::ColorRole)i); + disabled[i] = p.color(QPalette::Disabled, (QPalette::ColorRole)i); + + QColor c = active[i]; + int r = c.red(); + int g = c.green(); + int b = c.blue(); + + cout << "p.setColor(QPalette::Active, (QPalette::ColorRole)" << i + << ", QColor(" << r << ", " << g << ", " << b << "));" << endl; + + c = inactive[i]; + r = c.red(); + g = c.green(); + b = c.blue(); + + cout << "p.setColor(QPalette::Inactive, (QPalette::ColorRole)" << i + << ", QColor(" << r << ", " << g << ", " << b << "));" << endl; + + c = disabled[i]; + r = c.red(); + g = c.green(); + b = c.blue(); + + cout << "p.setColor(QPalette::Disabled, (QPalette::ColorRole)" << i + << ", QColor(" << r << ", " << g << ", " << b << "));" << endl; + } } -} -} // Rv +} // namespace Rv diff --git a/src/lib/app/RvCommon/RvApplication.cpp b/src/lib/app/RvCommon/RvApplication.cpp index 8bc523560..99966bb4e 100644 --- a/src/lib/app/RvCommon/RvApplication.cpp +++ b/src/lib/app/RvCommon/RvApplication.cpp @@ -15,7 +15,7 @@ #include #include #include -#include // WINDOWS: include AFTER other stuff +#include // WINDOWS: include AFTER other stuff #include #include #include @@ -53,7 +53,7 @@ #include #ifndef PLATFORM_WINDOWS -extern char **environ; +extern char** environ; #endif #ifdef PLATFORM_DARWIN @@ -73,14 +73,16 @@ static void init() } #if 0 -#define DB_ICON 0x01 -#define DB_ALL 0xff +#define DB_ICON 0x01 +#define DB_ALL 0xff // #define DB_LEVEL (DB_ALL & (~ DB_ICON)) -#define DB_LEVEL DB_ALL +#define DB_LEVEL DB_ALL -#define DB(x) cerr << x << endl -#define DBL(level, x) if (level & DB_LEVEL) cerr << x << endl +#define DB(x) cerr << x << endl +#define DBL(level, x) \ + if (level & DB_LEVEL) \ + cerr << x << endl #else #define DB(x) #define DBL(level, x) @@ -88,1435 +90,1485 @@ static void init() // RV lazy build third party optional customization #if defined(RV_LAZY_BUILD_THIRD_PARTY_CUSTOMIZATION) - extern void rvLazyBuildThirdPartyCustomization(); +extern void rvLazyBuildThirdPartyCustomization(); #endif -namespace Rv { -using namespace std; -using namespace TwkApp; -using namespace IPCore; -using namespace boost; -using namespace TwkQtCoreUtil; - -class RecursionLock +namespace Rv { - public: - RecursionLock() { _recursionLocked = true; }; - ~RecursionLock() { _recursionLocked = false; }; + using namespace std; + using namespace TwkApp; + using namespace IPCore; + using namespace boost; + using namespace TwkQtCoreUtil; - static bool _recursionLocked; - static bool locked() { return _recursionLocked; }; -}; + class RecursionLock + { + public: + RecursionLock() { _recursionLocked = true; }; -bool RecursionLock::_recursionLocked = false; + ~RecursionLock() { _recursionLocked = false; }; -void myMsgHandlerQT5(QtMsgType t, const QMessageLogContext& context, const QString& qmsg) -{ - // - // Since printing errors may generate errors, don't allow - // recursion. At worst we might lose some error messages. - // - if (RecursionLock::locked()) return; - RecursionLock l; + static bool _recursionLocked; - string msg = qmsg.toUtf8().constData(); + static bool locked() { return _recursionLocked; }; + }; - // Do not report Java script errors unless requested - static bool reportQWebEngineJavaScripErrors = - getenv( "RV_REPORT_QWEBENGINE_JAVA_SCRIPT_ERRORS" ) != nullptr; - if ( context.category && - ( strncmp( context.category, "js", 2 ) == 0 ) && - !reportQWebEngineJavaScripErrors ) - { - return; - } + bool RecursionLock::_recursionLocked = false; - switch (t) + void myMsgHandlerQT5(QtMsgType t, const QMessageLogContext& context, + const QString& qmsg) { - case QtDebugMsg: - { - // We always report Qt debug messages except for known issues. - // In which case the following environment variable can be used to check whether - // those known messages are still reported or not by Qt. - static const bool reportQtDebugMessages = getenv( "RV_REPORT_QT_DEBUG_MESSAGES" ) != nullptr; - - // "DEBUG: Release of profile requested but WebEnginePage still not deleted. Expect troubles !" - const bool knownMessage = (std::string(msg).find("Release of profile requested but WebEnginePage still not deleted") != std::string::npos); - - if ( !knownMessage || reportQtDebugMessages ) - { - cout << "DEBUG: " << msg << endl; - } - } - break; - case QtWarningMsg: - // - // We get these spurious errors from Qt with some tablets. They seem - // to indicate no real problem and slow down interaction. - // - if (std::string(msg).find("This tablet device is unknown") == std::string::npos) - { - cout << "WARNING: " << msg << endl; - } - break; - case QtCriticalMsg: - case QtFatalMsg: - { - //Qt warning about KVO observers. Qt have gotten rid of the check for this error in Qt 6.0. - //"ERROR: has active key-value observers (KVO)! - // These will stop working now that the window is recreated, and will result in exceptions - // when the observers are removed. Break in QCocoaWindow::recreateWindowIfNeeded to debug." - const bool ignoreError = std::string(msg).find("has active key-value observers (KVO)! These will stop working now that the window is recreated") != std::string::npos; - - if(!ignoreError) - { - cerr << "ERROR: " << msg << endl; - } - } + // + // Since printing errors may generate errors, don't allow + // recursion. At worst we might lose some error messages. + // + if (RecursionLock::locked()) + return; + RecursionLock l; + + string msg = qmsg.toUtf8().constData(); + + // Do not report Java script errors unless requested + static bool reportQWebEngineJavaScripErrors = + getenv("RV_REPORT_QWEBENGINE_JAVA_SCRIPT_ERRORS") != nullptr; + if (context.category && (strncmp(context.category, "js", 2) == 0) + && !reportQWebEngineJavaScripErrors) + { + return; + } + + switch (t) + { + case QtDebugMsg: + { + // We always report Qt debug messages except for known issues. + // In which case the following environment variable can be used to + // check whether those known messages are still reported or not by + // Qt. + static const bool reportQtDebugMessages = + getenv("RV_REPORT_QT_DEBUG_MESSAGES") != nullptr; + + // "DEBUG: Release of profile requested but WebEnginePage still not + // deleted. Expect troubles !" + const bool knownMessage = + (std::string(msg).find("Release of profile requested but " + "WebEnginePage still not deleted") + != std::string::npos); + + if (!knownMessage || reportQtDebugMessages) + { + cout << "DEBUG: " << msg << endl; + } + } break; - default: - cout << "INFO: " << msg << endl; break; - } + case QtWarningMsg: + // + // We get these spurious errors from Qt with some tablets. They + // seem to indicate no real problem and slow down interaction. + // + if (std::string(msg).find("This tablet device is unknown") + == std::string::npos) + { + cout << "WARNING: " << msg << endl; + } + break; + case QtCriticalMsg: + case QtFatalMsg: + { + // Qt warning about KVO observers. Qt have gotten rid of the check + // for this error in Qt 6.0. "ERROR: has active key-value observers + //(KVO)! + // These will stop working now that the window is recreated, + // and will result in exceptions when the observers are + // removed. Break in QCocoaWindow::recreateWindowIfNeeded to + // debug." + const bool ignoreError = + std::string(msg).find( + "has active key-value observers (KVO)! These will stop " + "working now that the window is recreated") + != std::string::npos; + + if (!ignoreError) + { + cerr << "ERROR: " << msg << endl; + } + } + break; + default: + cout << "INFO: " << msg << endl; + break; + } - assert(t != QtFatalMsg); -} + assert(t != QtFatalMsg); + } -class RvProxyFactory : public QNetworkProxyFactory -{ - public: - RvProxyFactory(); - virtual ~RvProxyFactory(); + class RvProxyFactory : public QNetworkProxyFactory + { + public: + RvProxyFactory(); + virtual ~RvProxyFactory(); - virtual QList queryProxy(const QNetworkProxyQuery& query); + virtual QList + queryProxy(const QNetworkProxyQuery& query); - bool hasProxy() { return m_hasProxy; } + bool hasProxy() { return m_hasProxy; } - private: - QNetworkProxy m_proxy; - bool m_hasProxy; -}; + private: + QNetworkProxy m_proxy; + bool m_hasProxy; + }; -RvProxyFactory::RvProxyFactory() : QNetworkProxyFactory(), m_hasProxy(false) -{ - if (getenv("RV_NETWORK_PROXY_HOST")) + RvProxyFactory::RvProxyFactory() + : QNetworkProxyFactory() + , m_hasProxy(false) { - m_proxy.setType(QNetworkProxy::HttpProxy); - m_proxy.setHostName(getenv("RV_NETWORK_PROXY_HOST")); + if (getenv("RV_NETWORK_PROXY_HOST")) + { + m_proxy.setType(QNetworkProxy::HttpProxy); + m_proxy.setHostName(getenv("RV_NETWORK_PROXY_HOST")); - if (getenv("RV_NETWORK_PROXY_PORT")) m_proxy.setPort(atoi(getenv("RV_NETWORK_PROXY_PORT"))); - if (getenv("RV_NETWORK_PROXY_USER")) m_proxy.setUser( getenv("RV_NETWORK_PROXY_USER")); - if (getenv("RV_NETWORK_PROXY_PASSWORD")) m_proxy.setPassword( getenv("RV_NETWORK_PROXY_PASSWORD")); + if (getenv("RV_NETWORK_PROXY_PORT")) + m_proxy.setPort(atoi(getenv("RV_NETWORK_PROXY_PORT"))); + if (getenv("RV_NETWORK_PROXY_USER")) + m_proxy.setUser(getenv("RV_NETWORK_PROXY_USER")); + if (getenv("RV_NETWORK_PROXY_PASSWORD")) + m_proxy.setPassword(getenv("RV_NETWORK_PROXY_PASSWORD")); - m_hasProxy = true; - } - else if (getenv("RV_NETWORK_PROXY_DISABLE")) - { - m_proxy.setType(QNetworkProxy::NoProxy); + m_hasProxy = true; + } + else if (getenv("RV_NETWORK_PROXY_DISABLE")) + { + m_proxy.setType(QNetworkProxy::NoProxy); + } + else + { + m_proxy.setType(QNetworkProxy::DefaultProxy); + } } - else + + QList + RvProxyFactory::queryProxy(const QNetworkProxyQuery& query) { - m_proxy.setType(QNetworkProxy::DefaultProxy); + QList l; + l.append(m_proxy); + return l; } -} -QList -RvProxyFactory::queryProxy(const QNetworkProxyQuery& query) -{ - QList l; - l.append(m_proxy); - return l; -} + RvProxyFactory::~RvProxyFactory() {} -RvProxyFactory::~RvProxyFactory() -{ -} - -static void setEnvVar(const string& var, const string& val) -{ + static void setEnvVar(const string& var, const string& val) + { #ifdef WIN32 - ostringstream str; - str << var << "=" << val; - putenv(str.str().c_str()); + ostringstream str; + str << var << "=" << val; + putenv(str.str().c_str()); #else - setenv(var.c_str(), val.c_str(), 1); + setenv(var.c_str(), val.c_str(), 1); #endif -} - -RvApplication::RvApplication(int argc, char** argv) - : QObject(), - RvConsoleApplication(), - m_newTimer(0), - m_lazyBuildTimer(0), - m_console(0), - m_prefDialog(0), - m_profileDialog(0), - m_aboutAct(0), - m_prefAct(0), - m_networkAct(0), - m_quitAct(0), - m_macMenuBar(0), - m_macRVMenu(0), - m_networkDialog(0), - m_webManager(0), - m_presentationMode(false), - m_presentationDevice(0), - m_executableNameCaps(UI_APPLICATION_NAME), - m_desktopModule(0), - m_dispatchAtomicInt(0) -{ - -#ifdef PLATFORM_DARWIN - sessionFromUrlPointer = sessionFromUrl; - #endif - - // Proxy support - // - RvProxyFactory* factory = new RvProxyFactory(); - if (factory->hasProxy()) - { - QNetworkProxyFactory::setApplicationProxyFactory(factory); } - IPCore::AudioRenderer::addModuleInitFunc(IPCore::QTAudioRenderer::addQTAudioModule, "Platform Audio"); - - qInstallMessageHandler(myMsgHandlerQT5); - init(); - - pthread_mutex_init(&m_deleteLock, 0); - m_timer = new QTimer(this); - m_timer->setObjectName("RvApplication::m_timer"); - connect(m_timer, SIGNAL(timeout()), this, SLOT(heartbeat())); - m_timer->start(int(1.0 / 120.0 * 1000.0)); - m_fireTimer.start(); - - m_lazyBuildTimer = new QTimer(); - connect(m_lazyBuildTimer, SIGNAL(timeout()), this, SLOT(lazyBuild())); - m_lazyBuildTimer->setSingleShot(true); - m_lazyBuildTimer->start(); - - m_aboutAct = new QAction(tr("About " UI_APPLICATION_NAME "..."), this); - m_aboutAct->setStatusTip(tr("Information about this version of " UI_APPLICATION_NAME)); - m_aboutAct->setMenuRole(QAction::AboutRole); - connect(m_aboutAct, SIGNAL(triggered()), this, SLOT(about())); - - m_prefAct = new QAction(tr("Preferences..."), this); - m_prefAct->setStatusTip(tr("Configure RV for this computer")); - m_prefAct->setMenuRole(QAction::PreferencesRole); - connect(m_prefAct, SIGNAL(triggered()), this, SLOT(prefs())); - - QAction* sep1 = new QAction(tr("sep1"), this); - sep1->setMenuRole(QAction::ApplicationSpecificRole); - sep1->setSeparator(true); + RvApplication::RvApplication(int argc, char** argv) + : QObject() + , RvConsoleApplication() + , m_newTimer(0) + , m_lazyBuildTimer(0) + , m_console(0) + , m_prefDialog(0) + , m_profileDialog(0) + , m_aboutAct(0) + , m_prefAct(0) + , m_networkAct(0) + , m_quitAct(0) + , m_macMenuBar(0) + , m_macRVMenu(0) + , m_networkDialog(0) + , m_webManager(0) + , m_presentationMode(false) + , m_presentationDevice(0) + , m_executableNameCaps(UI_APPLICATION_NAME) + , m_desktopModule(0) + , m_dispatchAtomicInt(0) + { - QAction* sep2 = new QAction(tr("sep2"), this); - sep2->setMenuRole(QAction::ApplicationSpecificRole); - sep2->setSeparator(true); +#ifdef PLATFORM_DARWIN + sessionFromUrlPointer = sessionFromUrl; +#endif - m_networkAct = new QAction(tr("Network..."), this); - m_networkAct->setStatusTip(tr("Allow remote communication with this " UI_APPLICATION_NAME)); - m_networkAct->setMenuRole(QAction::ApplicationSpecificRole); - connect(m_networkAct, SIGNAL(triggered()), this, SLOT(showNetworkDialog())); + // Proxy support + // + RvProxyFactory* factory = new RvProxyFactory(); + if (factory->hasProxy()) + { + QNetworkProxyFactory::setApplicationProxyFactory(factory); + } - m_quitAct = new QAction(tr("Quit " UI_APPLICATION_NAME), this); - #ifndef PLATFORM_DARWIN + IPCore::AudioRenderer::addModuleInitFunc( + IPCore::QTAudioRenderer::addQTAudioModule, + "Platform Audio"); + + qInstallMessageHandler(myMsgHandlerQT5); + init(); + + pthread_mutex_init(&m_deleteLock, 0); + m_timer = new QTimer(this); + m_timer->setObjectName("RvApplication::m_timer"); + connect(m_timer, SIGNAL(timeout()), this, SLOT(heartbeat())); + m_timer->start(int(1.0 / 120.0 * 1000.0)); + m_fireTimer.start(); + + m_lazyBuildTimer = new QTimer(); + connect(m_lazyBuildTimer, SIGNAL(timeout()), this, SLOT(lazyBuild())); + m_lazyBuildTimer->setSingleShot(true); + m_lazyBuildTimer->start(); + + m_aboutAct = new QAction(tr("About " UI_APPLICATION_NAME "..."), this); + m_aboutAct->setStatusTip( + tr("Information about this version of " UI_APPLICATION_NAME)); + m_aboutAct->setMenuRole(QAction::AboutRole); + connect(m_aboutAct, SIGNAL(triggered()), this, SLOT(about())); + + m_prefAct = new QAction(tr("Preferences..."), this); + m_prefAct->setStatusTip(tr("Configure RV for this computer")); + m_prefAct->setMenuRole(QAction::PreferencesRole); + connect(m_prefAct, SIGNAL(triggered()), this, SLOT(prefs())); + + QAction* sep1 = new QAction(tr("sep1"), this); + sep1->setMenuRole(QAction::ApplicationSpecificRole); + sep1->setSeparator(true); + + QAction* sep2 = new QAction(tr("sep2"), this); + sep2->setMenuRole(QAction::ApplicationSpecificRole); + sep2->setSeparator(true); + + m_networkAct = new QAction(tr("Network..."), this); + m_networkAct->setStatusTip( + tr("Allow remote communication with this " UI_APPLICATION_NAME)); + m_networkAct->setMenuRole(QAction::ApplicationSpecificRole); + connect(m_networkAct, SIGNAL(triggered()), this, + SLOT(showNetworkDialog())); + + m_quitAct = new QAction(tr("Quit " UI_APPLICATION_NAME), this); +#ifndef PLATFORM_DARWIN m_quitAct->setShortcut(QKeySequence("Ctrl+Q")); - #endif - m_quitAct->setStatusTip(tr("Exit all " UI_APPLICATION_NAME " Sessions")); - m_quitAct->setMenuRole(QAction::QuitRole); - connect(m_quitAct, SIGNAL(triggered()), this, SLOT(quitAll())); - +#endif + m_quitAct->setStatusTip( + tr("Exit all " UI_APPLICATION_NAME " Sessions")); + m_quitAct->setMenuRole(QAction::QuitRole); + connect(m_quitAct, SIGNAL(triggered()), this, SLOT(quitAll())); #if defined(PLATFORM_DARWIN) - m_macMenuBar = new QMenuBar(0); - // NOTE: the UI_APPLICATION_NAME string below isn't what's visible as main menu. - // The main menu visible string comes from the 'src/bin/nsapp/RV/Info.plist' file. - m_macRVMenu = m_macMenuBar->addMenu(UI_APPLICATION_NAME); - m_macRVMenu->addAction(m_aboutAct); - if (m_networkAct) m_macRVMenu->addAction(m_networkAct); - m_macRVMenu->addAction(m_prefAct); - m_macRVMenu->addAction(m_quitAct); + m_macMenuBar = new QMenuBar(0); + // NOTE: the UI_APPLICATION_NAME string below isn't what's visible as + // main menu. The main menu visible string comes from the + // 'src/bin/nsapp/RV/Info.plist' file. + m_macRVMenu = m_macMenuBar->addMenu(UI_APPLICATION_NAME); + m_macRVMenu->addAction(m_aboutAct); + if (m_networkAct) + m_macRVMenu->addAction(m_networkAct); + m_macRVMenu->addAction(m_prefAct); + m_macRVMenu->addAction(m_quitAct); - // - // As of Qt4.6 they conflate open url events with file open - // events, but the url they provide in that event is mangled - // so we re-register our url handler here to override their's. - // - // Of course, as of Qt4.7, they moved their registration deeper - // actually into the event loop, so there's no way to get 'behind' - // it with out own registration. - // - // if (registerEventHandlerPointer) (*registerEventHandlerPointer)(); + // + // As of Qt4.6 they conflate open url events with file open + // events, but the url they provide in that event is mangled + // so we re-register our url handler here to override their's. + // + // Of course, as of Qt4.7, they moved their registration deeper + // actually into the event loop, so there's no way to get 'behind' + // it with out own registration. + // + // if (registerEventHandlerPointer) (*registerEventHandlerPointer)(); #endif - // - // Font Awesome icon font - // - // See: http://fortawesome.github.io/Font-Awesome/icons/ - // - // NOTE: this is expensive and may be better done by FontLoader - // which supposedly can do this in a separate thread. The - // downside is that there can be a race condition between use of - // the font and its availability in that case - // - // The load time on debug build on tast machine was 0.012s - // + // + // Font Awesome icon font + // + // See: http://fortawesome.github.io/Font-Awesome/icons/ + // + // NOTE: this is expensive and may be better done by FontLoader + // which supposedly can do this in a separate thread. The + // downside is that there can be a race condition between use of + // the font and its availability in that case + // + // The load time on debug build on tast machine was 0.012s + // - QFile res(":/fonts/fontawesome-webfont.ttf"); - if (!res.open(QIODevice::ReadOnly)) - { - cerr << "ERROR: Font awesome font could not be loaded!"; - } - else - { - QByteArray fontData(res.readAll()); - res.close(); - int loaded = QFontDatabase::addApplicationFontFromData(fontData); - if (loaded == -1) + QFile res(":/fonts/fontawesome-webfont.ttf"); + if (!res.open(QIODevice::ReadOnly)) { cerr << "ERROR: Font awesome font could not be loaded!"; } + else + { + QByteArray fontData(res.readAll()); + res.close(); + int loaded = QFontDatabase::addApplicationFontFromData(fontData); + if (loaded == -1) + { + cerr << "ERROR: Font awesome font could not be loaded!"; + } + } + m_dispatchTimer = new QTimer(this); + m_dispatchTimer->setSingleShot(true); + connect(m_dispatchTimer, SIGNAL(timeout()), this, + SLOT(dispatchTimeout())); } - m_dispatchTimer = new QTimer(this); - m_dispatchTimer->setSingleShot(true); - connect(m_dispatchTimer, SIGNAL(timeout()), this, SLOT(dispatchTimeout())); -} -RvApplication::~RvApplication() -{ - delete m_timer; - delete m_newTimer; - delete m_console; - delete m_networkDialog; - delete m_lazyBuildTimer; - m_console = 0; - m_timer = 0; - m_lazyBuildTimer = 0; - pthread_mutex_destroy(&m_deleteLock); -} - -int -RvApplication::parseInFiles(int argc, char *argv[]) -{ - // cerr << "Application::parseInFiles " << argc << " files" << endl; - Rv::Options& opts = Rv::Options::sharedOptions(); + RvApplication::~RvApplication() + { + delete m_timer; + delete m_newTimer; + delete m_console; + delete m_networkDialog; + delete m_lazyBuildTimer; + m_console = 0; + m_timer = 0; + m_lazyBuildTimer = 0; + pthread_mutex_destroy(&m_deleteLock); + } - for (int i=0; ishow(); - networkWindow()->raise(); -} - -RvWebManager* -RvApplication::webManager() -{ - if (!m_webManager) - { - m_webManager = new RvWebManager(this); + rvLazyBuildThirdPartyCustomization(); +#endif } - return m_webManager; -} - -RvNetworkDialog* -RvApplication::networkWindow() -{ - if (!m_networkDialog) m_networkDialog = new RvNetworkDialog(0); - TwkApp::Document* doc = TwkApp::Document::activeDocument(); - - if (doc) + RvConsoleWindow* RvApplication::console() { - Rv::Session* session = static_cast(doc); - RvDocument *rvDoc = (RvDocument *)session->opaquePointer(); - - QSize ws = m_networkDialog->size(); - QSize s = rvDoc->size(); - QPoint p = rvDoc->pos(); - - m_networkDialog->move(p.x() + s.width() / 2 - ws.width() / 2, - p.y() + s.height() / 2 - ws.height() / 2); + if (!m_console) + m_console = new RvConsoleWindow(); + return m_console; } - return m_networkDialog; -} - -static void -callRunCreateSession(void* a) -{ - RvApplication* app = reinterpret_cast(a); - app->runCreateSession(); -} - -void -RvApplication::about() -{ - bool isReleaseBuild = strcmp(RELEASE_DESCRIPTION, "RELEASE") == 0; - - ostringstream headerComment; - - headerComment << "

"; - if (!isReleaseBuild) headerComment << ""; - headerComment << RELEASE_DESCRIPTION << " Version"; - if (!isReleaseBuild) headerComment << ""; - headerComment << "

"; - - ostringstream date; - TWK_DEPLOY_SHOW_PROGRAM_BANNER(date); - - vector temp; - temp.reserve(2048); - sprintf(temp.data(), - "

%s

%d.%d.%d (%s)

%s

%s %s

", - UI_APPLICATION_NAME, - TWK_DEPLOY_MAJOR_VERSION(), - TWK_DEPLOY_MINOR_VERSION(), - TWK_DEPLOY_PATCH_LEVEL(), - GIT_HEAD, - headerComment.str().c_str(), - UI_APPLICATION_NAME, - COPYRIGHT_TEXT); - - const TwkApp::Document* doc = TwkApp::Document::activeDocument(); - QWidget* parent = 0; - if (doc) parent = (RvDocument *)doc->opaquePointer(); - - QMessageBox *msgBox = - new QMessageBox("About " UI_APPLICATION_NAME, QString(temp.data()), QMessageBox::Information, 0, 0, 0, parent, - Qt::WindowTitleHint | Qt::WindowSystemMenuHint); - msgBox->setAttribute(Qt::WA_DeleteOnClose); - QIcon icon = msgBox->windowIcon(); - QSize size = icon.actualSize(QSize(64, 64)); - msgBox->setIconPixmap(icon.pixmap(size)); - msgBox->setStandardButtons(QMessageBox::Close); - - QGridLayout* grid = static_cast(msgBox->layout()); - - QDialogButtonBox *buttonBox = msgBox->findChild(); - grid->removeWidget(buttonBox); - buttonBox->setCenterButtons(true); - - grid->addItem(new QSpacerItem(1, 12, QSizePolicy::Fixed, QSizePolicy::Fixed), grid->rowCount(), 0); - grid->addWidget(buttonBox, grid->rowCount(), 0, 1, -1); - - msgBox->show(); - msgBox->exec(); -} - -void -RvApplication::quitAll() -{ - TwkApp::Application::Documents docs = documents(); - - for (size_t i = 0; i < docs.size(); i++) + void RvApplication::showNetworkDialog() { - Rv::Session* s = static_cast(docs[i]); - RvDocument *rvDoc = (RvDocument *)s->opaquePointer(); - rvDoc->close(); + networkWindow()->show(); + networkWindow()->raise(); } -} - -void -RvApplication::runCreateSession() -{ - if (m_newSessions.size()) + RvWebManager* RvApplication::webManager() { - // Make sure that the RV application has been initialized - // Otherwise wait for the next occurence of the newSession timer to - // prevent a crash. - if (!TwkApp::muProcess()) + if (!m_webManager) { - return; + m_webManager = new RvWebManager(this); } - Rv::Options& opts = Rv::Options::sharedOptions(); + return m_webManager; + } - StringVector all; + RvNetworkDialog* RvApplication::networkWindow() + { + if (!m_networkDialog) + m_networkDialog = new RvNetworkDialog(0); + TwkApp::Document* doc = TwkApp::Document::activeDocument(); - for (int i=0; i < m_newSessions.size(); i++) + if (doc) { - StringVector* sv = m_newSessions[i]; - copy(sv->begin(), sv->end(), back_inserter(all)); - delete sv; + Rv::Session* session = static_cast(doc); + RvDocument* rvDoc = (RvDocument*)session->opaquePointer(); + + QSize ws = m_networkDialog->size(); + QSize s = rvDoc->size(); + QPoint p = rvDoc->pos(); + + m_networkDialog->move(p.x() + s.width() / 2 - ws.width() / 2, + p.y() + s.height() / 2 - ws.height() / 2); } - m_newSessions.clear(); - if (m_newTimer) m_newTimer->stop(); + return m_networkDialog; + } - newSessionFromFiles(all); + static void callRunCreateSession(void* a) + { + RvApplication* app = reinterpret_cast(a); + app->runCreateSession(); } -} -RvDocument* -RvApplication::rebuildSessionFromFiles(Rv::RvSession *s, const StringVector& files) -{ - // - // If we have new files, clear the session. If we don't have - // new files, don't clear it, since we have have built a - // session "by hand" ie via mu. - // - // Code, like the shotgrid module, that want's to clear the - // session with each processed URL, should clear the session - // explicitly. - // - if (files.size() && s->sources().size()) s->clear(); + void RvApplication::about() + { + bool isReleaseBuild = strcmp(RELEASE_DESCRIPTION, "RELEASE") == 0; - Rv::Options& opts = Rv::Options::sharedOptions(); + ostringstream headerComment; - Rv::RvDocument *doc = (RvDocument *)s->opaquePointer(); + headerComment << "

"; + if (!isReleaseBuild) + headerComment << ""; + headerComment << RELEASE_DESCRIPTION << " Version"; + if (!isReleaseBuild) + headerComment << ""; + headerComment << "

"; - if (opts.nomb && doc->menuBarShown()) doc->toggleMenuBar(); + ostringstream date; + TWK_DEPLOY_SHOW_PROGRAM_BANNER(date); - try - { - s->readUnorganizedFileList(files, true); - } - catch (const std::exception& exc) - { - cerr << "ERROR: " << exc.what() << endl; + vector temp; + temp.reserve(2048); + sprintf( + temp.data(), "

%s

%d.%d.%d (%s)

%s

%s %s

", + UI_APPLICATION_NAME, TWK_DEPLOY_MAJOR_VERSION(), + TWK_DEPLOY_MINOR_VERSION(), TWK_DEPLOY_PATCH_LEVEL(), GIT_HEAD, + headerComment.str().c_str(), UI_APPLICATION_NAME, COPYRIGHT_TEXT); + + const TwkApp::Document* doc = TwkApp::Document::activeDocument(); + QWidget* parent = 0; + if (doc) + parent = (RvDocument*)doc->opaquePointer(); + + QMessageBox* msgBox = + new QMessageBox("About " UI_APPLICATION_NAME, QString(temp.data()), + QMessageBox::Information, 0, 0, 0, parent, + Qt::WindowTitleHint | Qt::WindowSystemMenuHint); + msgBox->setAttribute(Qt::WA_DeleteOnClose); + QIcon icon = msgBox->windowIcon(); + QSize size = icon.actualSize(QSize(64, 64)); + msgBox->setIconPixmap(icon.pixmap(size)); + msgBox->setStandardButtons(QMessageBox::Close); + + QGridLayout* grid = static_cast(msgBox->layout()); + + QDialogButtonBox* buttonBox = msgBox->findChild(); + grid->removeWidget(buttonBox); + buttonBox->setCenterButtons(true); + + grid->addItem( + new QSpacerItem(1, 12, QSizePolicy::Fixed, QSizePolicy::Fixed), + grid->rowCount(), 0); + grid->addWidget(buttonBox, grid->rowCount(), 0, 1, -1); + + msgBox->show(); + msgBox->exec(); } + void RvApplication::quitAll() + { + TwkApp::Application::Documents docs = documents(); - return doc; -} + for (size_t i = 0; i < docs.size(); i++) + { + Rv::Session* s = static_cast(docs[i]); + RvDocument* rvDoc = (RvDocument*)s->opaquePointer(); + rvDoc->close(); + } + } -RvDocument* -RvApplication::newSessionFromFiles(const StringVector& files) -{ - DB ("RvApplication::newSessionFromFiles()"); - Rv::RvDocument *doc = new Rv::RvDocument; - //doc->ensurePolished(); - Rv::RvSession* s = doc->session(); + void RvApplication::runCreateSession() + { + if (m_newSessions.size()) + { + // Make sure that the RV application has been initialized + // Otherwise wait for the next occurence of the newSession timer to + // prevent a crash. + if (!TwkApp::muProcess()) + { + return; + } - s->queryAndStoreGLInfo(); + Rv::Options& opts = Rv::Options::sharedOptions(); - Rv::Options& opts = Rv::Options::sharedOptions(); + StringVector all; - DB ("xl " << opts.xl); - doc->setAggressiveSizing (opts.xl); - if (opts.nomb && doc->menuBarShown()) doc->toggleMenuBar(); + for (int i = 0; i < m_newSessions.size(); i++) + { + StringVector* sv = m_newSessions[i]; + copy(sv->begin(), sv->end(), back_inserter(all)); + delete sv; + } - rebuildSessionFromFiles (s, files); + m_newSessions.clear(); + if (m_newTimer) + m_newTimer->stop(); - // - // Since we stopped giving Qt a style sheet, it doesn't seem to - // account for the menubar and it makes the window too small to - // hold both the menubar and the image. This "fixes" that. - // In general, the menubar does not seem to report the correct - // size until this point. - // + newSessionFromFiles(all); + } + } - if (s->userHasSetViewSize()) + RvDocument* + RvApplication::rebuildSessionFromFiles(Rv::RvSession* s, + const StringVector& files) { - doc->center(); - } + // + // If we have new files, clear the session. If we don't have + // new files, don't clear it, since we have have built a + // session "by hand" ie via mu. + // + // Code, like the shotgrid module, that want's to clear the + // session with each processed URL, should clear the session + // explicitly. + // + if (files.size() && s->sources().size()) + s->clear(); - // - // Allow command line placement - // + Rv::Options& opts = Rv::Options::sharedOptions(); - if (opts.x != -1 || opts.y != -1) - { - if (opts.screen != -1 && QApplication::desktop()->isVirtualDesktop()) - { - QRect r = QApplication::desktop()->screenGeometry(opts.screen); - opts.x += r.x(); - opts.y += r.y(); - } + Rv::RvDocument* doc = (RvDocument*)s->opaquePointer(); - if (opts.width != -1 && opts.height != -1) + if (opts.nomb && doc->menuBarShown()) + doc->toggleMenuBar(); + + try { - doc->setGeometry(opts.x, opts.y, opts.width, opts.height); + s->readUnorganizedFileList(files, true); } - else + catch (const std::exception& exc) { - doc->move(opts.x, opts.y); + cerr << "ERROR: " << exc.what() << endl; } + + return doc; } - int screen = QApplication::desktop()->screenNumber(QCursor::pos()); - if (opts.screen != -1) screen = opts.screen; + RvDocument* RvApplication::newSessionFromFiles(const StringVector& files) + { + DB("RvApplication::newSessionFromFiles()"); + Rv::RvDocument* doc = new Rv::RvDocument; + // doc->ensurePolished(); + Rv::RvSession* s = doc->session(); - int oldX = doc->pos().x(); - int oldY = doc->pos().y(); + s->queryAndStoreGLInfo(); - int oldScreen = QApplication::desktop()->screenNumber(QPoint(oldX,oldY)); + Rv::Options& opts = Rv::Options::sharedOptions(); - if (screen != -1 && QApplication::desktop()->isVirtualDesktop() && screen != oldScreen) - // - // The application is going to come up on the wrong screen, so figure out our - // our relative position on the current screen, and move to the same relative - // position on the correct screen. - // - { - QRect rnew = QApplication::desktop()->screenGeometry(screen); - QRect rold = QApplication::desktop()->screenGeometry(oldScreen); + DB("xl " << opts.xl); + doc->setAggressiveSizing(opts.xl); + if (opts.nomb && doc->menuBarShown()) + doc->toggleMenuBar(); - int xoff = oldX - rold.x(); - int yoff = oldY - rold.y(); + rebuildSessionFromFiles(s, files); - doc->move(rnew.x() + xoff, rnew.y() + yoff); - } + // + // Since we stopped giving Qt a style sheet, it doesn't seem to + // account for the menubar and it makes the window too small to + // hold both the menubar and the image. This "fixes" that. + // In general, the menubar does not seem to report the correct + // size until this point. + // - if (opts.fullscreen && !doc->isFullScreen()) - { - doc->toggleFullscreen(true); + if (s->userHasSetViewSize()) + { + doc->center(); + } - if (opts.width != -1 && opts.height != -1) + // + // Allow command line placement + // + + if (opts.x != -1 || opts.y != -1) { - doc->setGeometry(opts.x, opts.y, opts.width, opts.height); + if (opts.screen != -1 + && QApplication::desktop()->isVirtualDesktop()) + { + QRect r = QApplication::desktop()->screenGeometry(opts.screen); + opts.x += r.x(); + opts.y += r.y(); + } + + if (opts.width != -1 && opts.height != -1) + { + doc->setGeometry(opts.x, opts.y, opts.width, opts.height); + } + else + { + doc->move(opts.x, opts.y); + } } - } - doc->show(); + int screen = QApplication::desktop()->screenNumber(QCursor::pos()); + if (opts.screen != -1) + screen = opts.screen; -#ifndef PLATFORM_LINUX - doc->raise(); -#endif + int oldX = doc->pos().x(); + int oldY = doc->pos().y(); - if (videoModules().empty()) - { - doc->view()->makeCurrent(); + int oldScreen = + QApplication::desktop()->screenNumber(QPoint(oldX, oldY)); - try - { - addVideoModule(m_desktopModule = new DesktopVideoModule(0, doc->view()->videoDevice())); - } - catch (...) + if (screen != -1 && QApplication::desktop()->isVirtualDesktop() + && screen != oldScreen) + // + // The application is going to come up on the wrong screen, so figure + // out our our relative position on the current screen, and move to the + // same relative position on the correct screen. + // { - cerr << "ERROR: DesktopVideoModule failed" << endl; + QRect rnew = QApplication::desktop()->screenGeometry(screen); + QRect rold = QApplication::desktop()->screenGeometry(oldScreen); + + int xoff = oldX - rold.x(); + int yoff = oldY - rold.y(); + + doc->move(rnew.x() + xoff, rnew.y() + yoff); } - if (!getenv("RV_SKIP_LOADING_VIDEO_OUTPUT_PLUGINS")) { + if (opts.fullscreen && !doc->isFullScreen()) + { + doc->toggleFullscreen(true); - // Load audio/video output plugins - loadOutputPlugins("TWK_OUTPUT_PLUGIN_PATH"); - } else { - cout << "WARNING: Skipping loading of video output plugins" << endl; + if (opts.width != -1 && opts.height != -1) + { + doc->setGeometry(opts.x, opts.y, opts.width, opts.height); + } } - } - doc->session()->graph().setPhysicalDevices(videoModules()); + doc->show(); - // - // The above re-created the set of display groups, we know what screen - // we're on (video device) so make sure the primary display group is - // correct. - // - doc->session()->graph().setPrimaryDisplayGroup(doc->view()->videoDevice()); +#ifndef PLATFORM_LINUX + doc->raise(); +#endif - if (RvApp()->documents().size() == 1 && opts.present) - { - setPresentationMode(true); - } + if (videoModules().empty()) + { + doc->view()->makeCurrent(); - // - // All modes are toggled, command line processed, etc, so tell users: - // - s->userGenericEvent("session-initialized", ""); + try + { + addVideoModule(m_desktopModule = new DesktopVideoModule( + 0, doc->view()->videoDevice())); + } + catch (...) + { + cerr << "ERROR: DesktopVideoModule failed" << endl; + } - if (s->loadTotal() == 0) - // - // We will not be loading media at all, so send after-progressive-loading event. - // - { - s->userGenericEvent("after-progressive-loading", ""); - } + if (!getenv("RV_SKIP_LOADING_VIDEO_OUTPUT_PLUGINS")) + { - return doc; -} + // Load audio/video output plugins + loadOutputPlugins("TWK_OUTPUT_PLUGIN_PATH"); + } + else + { + cout << "WARNING: Skipping loading of video output plugins" + << endl; + } + } -VideoModule* -RvApplication::primaryVideoModule() const -{ - return m_desktopModule; -} + doc->session()->graph().setPhysicalDevices(videoModules()); -void -RvApplication::openVideoModule(VideoModule* m) const -{ - if (!m->isOpen()) - { - RvDocument* doc = - reinterpret_cast(documents().front()->opaquePointer()); - doc->view()->makeCurrent(); - m->open(); - // - // The open() may have added video devices, so make sure each device - // has a corresponding display group. - // - IPGraph& graph = doc->session()->graph(); - const VideoModule::VideoDevices& devs = m->devices(); - - for (size_t i = 0; i < devs.size(); i++) - { - TwkApp::VideoDevice* device = devs[i]; - - if (0 == graph.findDisplayGroupByDevice(device)) - { - ostringstream str; - str << "displayGroup" << graph.displayGroups().size(); - string name = str.str(); // windows - - graph.addDisplayGroup (graph.newDisplayGroup(name, device)); - } - } - } -} + // + // The above re-created the set of display groups, we know what screen + // we're on (video device) so make sure the primary display group is + // correct. + // + doc->session()->graph().setPrimaryDisplayGroup( + doc->view()->videoDevice()); -void -RvApplication::createNewSessionFromFiles(const StringVector& files) -{ - StringVector* sv = new StringVector(files.size()); - if (!files.empty()) copy(files.begin(), files.end(), sv->begin()); + if (RvApp()->documents().size() == 1 && opts.present) + { + setPresentationMode(true); + } - if (m_newSessions.empty()) - { - if (!m_newTimer) + // + // All modes are toggled, command line processed, etc, so tell users: + // + s->userGenericEvent("session-initialized", ""); + + if (s->loadTotal() == 0) + // + // We will not be loading media at all, so send + // after-progressive-loading event. + // { - m_newTimer = new QTimer(this); - m_newTimer->setObjectName("m_newTimer"); - connect(m_newTimer, SIGNAL(timeout()), this, SLOT(runCreateSession())); + s->userGenericEvent("after-progressive-loading", ""); } - m_newTimer->start(int(1.0 / 192.0 * 1000.0)); + return doc; } - m_newSessions.push_back(sv); -} + VideoModule* RvApplication::primaryVideoModule() const + { + return m_desktopModule; + } -RvApplication::DispatchID -RvApplication::dispatchToMainThread(DispatchCallback callback) -{ - std::lock_guard guard(m_dispatchMutex); + void RvApplication::openVideoModule(VideoModule* m) const + { + if (!m->isOpen()) + { + RvDocument* doc = reinterpret_cast( + documents().front()->opaquePointer()); + doc->view()->makeCurrent(); + m->open(); + // + // The open() may have added video devices, so make sure each + // device has a corresponding display group. + // + IPGraph& graph = doc->session()->graph(); + const VideoModule::VideoDevices& devs = m->devices(); - auto dispatchID = m_nextDispatchID++; - m_dispatchMap[dispatchID] = callback; + for (size_t i = 0; i < devs.size(); i++) + { + TwkApp::VideoDevice* device = devs[i]; - QMetaObject::invokeMethod(m_dispatchTimer, "start", Qt::QueuedConnection, Q_ARG(int, 0)); + if (0 == graph.findDisplayGroupByDevice(device)) + { + ostringstream str; + str << "displayGroup" << graph.displayGroups().size(); + string name = str.str(); // windows - return dispatchID; -} + graph.addDisplayGroup(graph.newDisplayGroup(name, device)); + } + } + } + } -void -RvApplication::undispatchToMainThread(DispatchID dispatchID, double maxDuration) -{ + void RvApplication::createNewSessionFromFiles(const StringVector& files) { - std::lock_guard guard(m_dispatchMutex); + StringVector* sv = new StringVector(files.size()); + if (!files.empty()) + copy(files.begin(), files.end(), sv->begin()); - auto iter = m_dispatchMap.find(dispatchID); - if (iter != m_dispatchMap.end()) - m_dispatchMap.erase(iter); - } - - TwkUtil::SystemClock clock; - auto t0 = clock.now(); + if (m_newSessions.empty()) + { + if (!m_newTimer) + { + m_newTimer = new QTimer(this); + m_newTimer->setObjectName("m_newTimer"); + connect(m_newTimer, SIGNAL(timeout()), this, + SLOT(runCreateSession())); + } - while ( (clock.now() - t0) < maxDuration ) - { - if( ! isDispatchExecuting(dispatchID) ) - return; + m_newTimer->start(int(1.0 / 192.0 * 1000.0)); + } - std::this_thread::sleep_for(std::chrono::milliseconds(10)); + m_newSessions.push_back(sv); } - std::cout << "ERROR: Max undispatch time reached." << std::endl; - return; -} + RvApplication::DispatchID + RvApplication::dispatchToMainThread(DispatchCallback callback) + { + std::lock_guard guard(m_dispatchMutex); -bool -RvApplication::isDispatchExecuting(DispatchID dispatchID) -{ - std::lock_guard guard(m_dispatchMutex); + auto dispatchID = m_nextDispatchID++; + m_dispatchMap[dispatchID] = callback; - return m_executingMap.find(dispatchID) != m_executingMap.end(); -} + QMetaObject::invokeMethod(m_dispatchTimer, "start", + Qt::QueuedConnection, Q_ARG(int, 0)); -void -RvApplication::dispatchTimeout() -{ - //Fix for error when loading multiple sources with the newly created API call AddsourcesVerbose() - //dispatchTimeout() was being called by another thread resulting in a crash. - int atomicInt = ++m_dispatchAtomicInt; - if(atomicInt == 1){ - HOP_PROF_FUNC(); + return dispatchID; + } + void RvApplication::undispatchToMainThread(DispatchID dispatchID, + double maxDuration) + { { std::lock_guard guard(m_dispatchMutex); - m_dispatchMap.swap(m_executingMap); - } - for (auto iter : m_executingMap) - { - HOP_PROF( "RvApplication::dispatchTimeout() : Execute 1" ); - iter.second(iter.first); + auto iter = m_dispatchMap.find(dispatchID); + if (iter != m_dispatchMap.end()) + m_dispatchMap.erase(iter); } + TwkUtil::SystemClock clock; + auto t0 = clock.now(); + + while ((clock.now() - t0) < maxDuration) { - std::lock_guard guard(m_dispatchMutex); - m_executingMap.clear(); + if (!isDispatchExecuting(dispatchID)) + return; + + std::this_thread::sleep_for(std::chrono::milliseconds(10)); } - } - m_dispatchAtomicInt--; -} -void -RvApplication::heartbeat() -{ - double secs = m_fireTimer.elapsed(); + std::cout << "ERROR: Max undispatch time reached." << std::endl; + return; + } - if (false) - if (secs > 1.0 / 30.0) + bool RvApplication::isDispatchExecuting(DispatchID dispatchID) { - cout << "WARNING: last timer fired " - << secs - << " seconds ago (" - << (1.0 / secs) - << " fps)" - << endl; - } + std::lock_guard guard(m_dispatchMutex); - m_fireTimer.stop(); - m_fireTimer.start(); + return m_executingMap.find(dispatchID) != m_executingMap.end(); + } - timerCB(); -} + void RvApplication::dispatchTimeout() + { + // Fix for error when loading multiple sources with the newly created + // API call AddsourcesVerbose() dispatchTimeout() was being called by + // another thread resulting in a crash. + int atomicInt = ++m_dispatchAtomicInt; + if (atomicInt == 1) + { + HOP_PROF_FUNC(); -void -RvApplication::stopTimer() -{ - //cout << "stop timer" << endl; - m_timer->stop(); -} + { + std::lock_guard guard(m_dispatchMutex); + m_dispatchMap.swap(m_executingMap); + } -void -RvApplication::startTimer() -{ - //cout << "start timer" << endl; - m_timer->start(int(1.0 / 192.0 * 1000.0)); -} + for (auto iter : m_executingMap) + { + HOP_PROF("RvApplication::dispatchTimeout() : Execute 1"); + iter.second(iter.first); + } -RvProfileManager* -RvApplication::profileManager() -{ - if (!m_profileDialog) - { - m_profileDialog = new RvProfileManager(this); + { + std::lock_guard guard(m_dispatchMutex); + m_executingMap.clear(); + } + } + m_dispatchAtomicInt--; } - return m_profileDialog; -} - -RvPreferences* -RvApplication::prefDialog() -{ - if (!m_prefDialog) + void RvApplication::heartbeat() { - Rv::Session* session = Rv::Session::currentSession(); - assert(session); - RvDocument *rvDoc = (RvDocument *)session->opaquePointer(); - m_prefDialog = new RvPreferences(rvDoc); - QRect docGeom = rvDoc->geometry(); - int docX = docGeom.left() + int(docGeom.width()/2); - int docY = docGeom.top() + int(docGeom.height()/2); - - int x = docX - int(m_prefDialog->width()/2); - int y = docY - int(m_prefDialog->height()/2); - m_prefDialog->move(x, y); - } + double secs = m_fireTimer.elapsed(); - return m_prefDialog; -} + if (false) + if (secs > 1.0 / 30.0) + { + cout << "WARNING: last timer fired " << secs << " seconds ago (" + << (1.0 / secs) << " fps)" << endl; + } -void -RvApplication::prefs() -{ - if (isInPresentationMode()) - { - const TwkApp::Document* doc = TwkApp::Document::activeDocument(); - QWidget* parent = 0; - if (doc) parent = (RvDocument *)doc->opaquePointer(); - QMessageBox box(parent); - box.setWindowTitle(tr(UI_APPLICATION_NAME ": Preferences")); - box.setText(tr("Presentation Mode is Enabled -- Preferences cannot be shown.\nDisable Presentation Mode?")); - // the detailed box mess up the buttons on OS X with CSS - // just getting rid of it fixes it - //box.setDetailedText(tr("Preferences cannot be shown until " - //"presentation mode is disabled.")); - box.setWindowModality(Qt::WindowModal); - QPushButton* b1 = box.addButton(tr("Cancel"), QMessageBox::RejectRole); - QPushButton* b2 = box.addButton(tr("Disable Presentation Mode"), QMessageBox::AcceptRole); -#ifdef PLATFORM_LINUX - box.setIconPixmap(QPixmap(qApp->applicationDirPath() + QString(RV_ICON_PATH_SUFFIX)).scaledToHeight(64)); -#else - box.setIcon(QMessageBox::Critical); -#endif - box.exec(); + m_fireTimer.stop(); + m_fireTimer.start(); - if (box.clickedButton() == b1) return; - setPresentationMode(false); + timerCB(); } - RvPreferences* prefs = prefDialog(); - prefs->update(); - - const TwkApp::Application::Documents& docs = documents(); - - for (size_t i = 0; i < docs.size(); i++) + void RvApplication::stopTimer() { - Rv::Session* s = static_cast(docs[i]); - s->userGenericEvent("preferences-show", ""); + // cout << "stop timer" << endl; + m_timer->stop(); } - prefs->raise(); - prefs->show(); -} + void RvApplication::startTimer() + { + // cout << "start timer" << endl; + m_timer->start(int(1.0 / 192.0 * 1000.0)); + } -bool -RvApplication::eventFilter(QObject* o, QEvent* event) -{ - if (event->type() == QEvent::FileOpen) + RvProfileManager* RvApplication::profileManager() { - QFileOpenEvent* fileEvent = static_cast(event); - StringVector files(1); - files.front() = fileEvent->file().toUtf8().data(); - if (!files.front().empty()) createNewSessionFromFiles(files); - else + if (!m_profileDialog) { - // - // As of Qt 4.6, the FileOpen event can contain a URL - // instead of a filename. - // - string url = fileEvent->url().toString().toUtf8().data(); - cout << "WARNING: URL from file open event '" << url << "'" << endl; - if (!url.empty()) sessionFromUrl(url); + m_profileDialog = new RvProfileManager(this); } + + return m_profileDialog; } - return false; -} + RvPreferences* RvApplication::prefDialog() + { + if (!m_prefDialog) + { + Rv::Session* session = Rv::Session::currentSession(); + assert(session); + RvDocument* rvDoc = (RvDocument*)session->opaquePointer(); + m_prefDialog = new RvPreferences(rvDoc); + QRect docGeom = rvDoc->geometry(); + int docX = docGeom.left() + int(docGeom.width() / 2); + int docY = docGeom.top() + int(docGeom.height() / 2); + + int x = docX - int(m_prefDialog->width() / 2); + int y = docY - int(m_prefDialog->height() / 2); + m_prefDialog->move(x, y); + } -void -RvApplication::sessionFromUrl (string url) -{ - // cerr << "RvApplication::sessionFromUrl '" << url << "'" << endl; + return m_prefDialog; + } - vector args; - args.push_back((char*)"rvlink"); - parseURL (url.c_str(), args); - char **newArgv = &(args[0]); - int newArgc = args.size(); + void RvApplication::prefs() + { + if (isInPresentationMode()) + { + const TwkApp::Document* doc = TwkApp::Document::activeDocument(); + QWidget* parent = 0; + if (doc) + parent = (RvDocument*)doc->opaquePointer(); + QMessageBox box(parent); + box.setWindowTitle(tr(UI_APPLICATION_NAME ": Preferences")); + box.setText(tr("Presentation Mode is Enabled -- Preferences cannot " + "be shown.\nDisable Presentation Mode?")); + // the detailed box mess up the buttons on OS X with CSS + // just getting rid of it fixes it + // box.setDetailedText(tr("Preferences cannot be shown until " + //"presentation mode is disabled.")); + box.setWindowModality(Qt::WindowModal); + QPushButton* b1 = + box.addButton(tr("Cancel"), QMessageBox::RejectRole); + QPushButton* b2 = box.addButton(tr("Disable Presentation Mode"), + QMessageBox::AcceptRole); +#ifdef PLATFORM_LINUX + box.setIconPixmap(QPixmap(qApp->applicationDirPath() + + QString(RV_ICON_PATH_SUFFIX)) + .scaledToHeight(64)); +#else + box.setIcon(QMessageBox::Critical); +#endif + box.exec(); - // for (int i = 0; i < newArgc; ++i) cerr << " " << newArgv[i] << endl; + if (box.clickedButton() == b1) + return; + setPresentationMode(false); + } - Rv::Options& opts = Rv::Options::sharedOptions(); - Rv::Options freshOpts, oldOpts = opts; - opts = freshOpts; + RvPreferences* prefs = prefDialog(); + prefs->update(); - Rv::RvPreferences::loadSettingsIntoOptions(opts); + const TwkApp::Application::Documents& docs = documents(); - // - // We want some settings to carry over ? - // + for (size_t i = 0; i < docs.size(); i++) + { + Rv::Session* s = static_cast(docs[i]); + s->userGenericEvent("preferences-show", ""); + } - freshOpts.urlsReuseSession = oldOpts.urlsReuseSession; - opts.delaySessionLoading = oldOpts.delaySessionLoading; - opts.progressiveSourceLoading = oldOpts.progressiveSourceLoading; - - Rv::Options::manglePerSourceArgs(newArgv, newArgc); - - opts.inputFiles.clear(); - - if (arg_parse - (newArgc, newArgv, - "", "", - RV_ARG_EXAMPLES, - "", "", - RV_ARG_SEQUENCE_HELP, - "", "", - RV_ARG_SOURCE_OPTIONS(opts), - "", "", - "", ARG_SUBR(parseInFiles), "Input sequence patterns, images, movies, or directories ", - RV_ARG_PARSE_OPTIONS(opts), - NULL) < 0) - { - cerr << "ERROR: could not parse options from URL: '" << url << "'" << endl; - return; + prefs->raise(); + prefs->show(); } - RvApplication* rvapp = RvApp(); - - if (!opts.initializeAfterParsing(&opts)) + bool RvApplication::eventFilter(QObject* o, QEvent* event) { - cerr << "ERROR: initializeAfterParsing failed" << endl; - rvapp->console()->processTextBuffer(); - return; - } + if (event->type() == QEvent::FileOpen) + { + QFileOpenEvent* fileEvent = static_cast(event); + StringVector files(1); + files.front() = fileEvent->file().toUtf8().data(); + if (!files.front().empty()) + createNewSessionFromFiles(files); + else + { + // + // As of Qt 4.6, the FileOpen event can contain a URL + // instead of a filename. + // + string url = fileEvent->url().toString().toUtf8().data(); + cout << "WARNING: URL from file open event '" << url << "'" + << endl; + if (!url.empty()) + sessionFromUrl(url); + } + } - TwkApp::Document* doc = TwkApp::Document::activeDocument(); - // cerr << "sessionFromUrl reuse " << opts.urlsReuseSession << endl; - if (!opts.urlsReuseSession || doc == 0) - { - rvapp->createNewSessionFromFiles(opts.inputFiles); + return false; } - else + + void RvApplication::sessionFromUrl(string url) { - Rv::RvSession* session = static_cast(doc); - RvDocument *rvDoc = (RvDocument *)session->opaquePointer(); + // cerr << "RvApplication::sessionFromUrl '" << url << "'" << endl; - rvapp->rebuildSessionFromFiles(session, opts.inputFiles); + vector args; + args.push_back((char*)"rvlink"); + parseURL(url.c_str(), args); + char** newArgv = &(args[0]); + int newArgc = args.size(); - //if (session->frameBuffer()) session->frameBuffer()->redraw(); - if (opts.fullscreen && !rvDoc->isFullScreen()) rvDoc->toggleFullscreen(true); - rvDoc->show(); + // for (int i = 0; i < newArgc; ++i) cerr << " " << newArgv[i] << + // endl; - #ifndef PLATFORM_LINUX - rvDoc->raise(); - #endif - } + Rv::Options& opts = Rv::Options::sharedOptions(); + Rv::Options freshOpts, oldOpts = opts; + opts = freshOpts; - rvapp->processNetworkOpts (false); -} + Rv::RvPreferences::loadSettingsIntoOptions(opts); + + // + // We want some settings to carry over ? + // + + freshOpts.urlsReuseSession = oldOpts.urlsReuseSession; + opts.delaySessionLoading = oldOpts.delaySessionLoading; + opts.progressiveSourceLoading = oldOpts.progressiveSourceLoading; + + Rv::Options::manglePerSourceArgs(newArgv, newArgc); + + opts.inputFiles.clear(); + + if (arg_parse( + newArgc, newArgv, "", "", RV_ARG_EXAMPLES, "", "", + RV_ARG_SEQUENCE_HELP, "", "", RV_ARG_SOURCE_OPTIONS(opts), "", + "", "", ARG_SUBR(parseInFiles), + "Input sequence patterns, images, movies, or directories ", + RV_ARG_PARSE_OPTIONS(opts), NULL) + < 0) + { + cerr << "ERROR: could not parse options from URL: '" << url << "'" + << endl; + return; + } -bool -decodeUrlString (string s, string &newUrl) -{ - bool didDecodeSomething = false; + RvApplication* rvapp = RvApp(); - newUrl = ""; + if (!opts.initializeAfterParsing(&opts)) + { + cerr << "ERROR: initializeAfterParsing failed" << endl; + rvapp->console()->processTextBuffer(); + return; + } - int len = s.size(); - for (int i = 0; i < len; ++i) - { - if ('%' == s[i] && i < len-2 && isxdigit(s[i+1]) && isxdigit(s[i+2])) - // - // This is an escaped char. - // + TwkApp::Document* doc = TwkApp::Document::activeDocument(); + // cerr << "sessionFromUrl reuse " << opts.urlsReuseSession << endl; + if (!opts.urlsReuseSession || doc == 0) { - int cInt; - sscanf (s.c_str()+i+1, "%02x", &cInt); - char c = cInt; - newUrl.push_back(c); - i += 2; - didDecodeSomething = true; + rvapp->createNewSessionFromFiles(opts.inputFiles); } - // - // XXX Hack! For some reason known only to bill gates, - // urls handled by windows (even ones that come from - // firefox) have a '/' tacked on the end. So we discard it - // here. - // - else if (i != len-1 || s[i] != '/') newUrl.push_back(s[i]); - } - // cerr << "decoded URL: '" << s << "' -> '" << newUrl << "'" << endl; + else + { + Rv::RvSession* session = static_cast(doc); + RvDocument* rvDoc = (RvDocument*)session->opaquePointer(); - return didDecodeSomething; -} + rvapp->rebuildSessionFromFiles(session, opts.inputFiles); -// -// Parse a string with embedded whitespace into an argument list. -// Any embedded whitespace or other special character is assumed to -// be represented as "%xx" where "xx" are the appropriate 2 hex -// digits. -// -// Supports on level of quoting, quote character is ' -// -// URL may be "baked" that is each byte of the contents transformed -// into a hex char pair. In that case "unbake" it first. -// + // if (session->frameBuffer()) session->frameBuffer()->redraw(); + if (opts.fullscreen && !rvDoc->isFullScreen()) + rvDoc->toggleFullscreen(true); + rvDoc->show(); -static string -rawURL (string bakedUrl) -{ - static const char *bakedPrefix = "rvlink://baked/"; - static const char *rawPrefix = "rvlink://"; +#ifndef PLATFORM_LINUX + rvDoc->raise(); +#endif + } - if (!strncmp(bakedPrefix, bakedUrl.c_str(), strlen(bakedPrefix))) - // - // URL is baked, so un-bake - // + rvapp->processNetworkOpts(false); + } + + bool decodeUrlString(string s, string& newUrl) { - char *buf = new char[bakedUrl.size()]; - strcpy (buf, rawPrefix); + bool didDecodeSomething = false; - char *bakedP = ((char *) (bakedUrl.c_str())) + strlen(bakedPrefix); - char *rawP = buf + strlen(rawPrefix); - char *lim = ((char *) (bakedUrl.c_str())) + bakedUrl.size() - -1; + newUrl = ""; - while (bakedP < lim) + int len = s.size(); + for (int i = 0; i < len; ++i) { - if (isxdigit(*bakedP) && isxdigit(*(bakedP+1))) + if ('%' == s[i] && i < len - 2 && isxdigit(s[i + 1]) + && isxdigit(s[i + 2])) + // + // This is an escaped char. + // { - unsigned int c; - sscanf(bakedP, "%02x", &c); - *(rawP++) = (char) c; - bakedP += 2; + int cInt; + sscanf(s.c_str() + i + 1, "%02x", &cInt); + char c = cInt; + newUrl.push_back(c); + i += 2; + didDecodeSomething = true; } - else ++bakedP; + // + // XXX Hack! For some reason known only to bill gates, + // urls handled by windows (even ones that come from + // firefox) have a '/' tacked on the end. So we discard it + // here. + // + else if (i != len - 1 || s[i] != '/') + newUrl.push_back(s[i]); } - *rawP = '\0'; + // cerr << "decoded URL: '" << s << "' -> '" << newUrl << "'" << endl; - string bufs(buf); - delete [] buf; - return bufs; - } - else - { - string newUrl; - decodeUrlString (bakedUrl, newUrl); - return newUrl; + return didDecodeSomething; } -} - -void -RvApplication::parseURL (const char *s, vector &av) -{ - cerr << "INFO: received URL '" << s << "'" << endl; - string newUrl(rawURL(s)); - vector avNew; - - cerr << "INFO: decoded URL '" << newUrl << "'" << endl; - - bool inArg = false, inQuote = false; - int len = newUrl.size(); - string a; // - // Skip over the protocol 'name', ie everything up to and - // including the first ':'. + // Parse a string with embedded whitespace into an argument list. + // Any embedded whitespace or other special character is assumed to + // be represented as "%xx" where "xx" are the appropriate 2 hex + // digits. + // + // Supports on level of quoting, quote character is ' + // + // URL may be "baked" that is each byte of the contents transformed + // into a hex char pair. In that case "unbake" it first. // - int i = 0; - for (; i < len && ':' != newUrl[i]; ++i) ; - ++i; - // Skip over slashes - i += 2; - for (; i < len; ++i) + static string rawURL(string bakedUrl) { - if (inArg && !inQuote && isspace(newUrl[i])) + static const char* bakedPrefix = "rvlink://baked/"; + static const char* rawPrefix = "rvlink://"; + + if (!strncmp(bakedPrefix, bakedUrl.c_str(), strlen(bakedPrefix))) // - // An unquoted whitespace char terminates the current arg. + // URL is baked, so un-bake // { - // cerr << "adding '" << a << "'" << endl; - avNew.push_back (strdup(a.c_str())); + char* buf = new char[bakedUrl.size()]; + strcpy(buf, rawPrefix); - a.clear(); - inArg = false; - } - else - if ('\'' == newUrl[i]) - { - inQuote = (inQuote) ? false : true; - inArg = true; - // cerr << "quote found, inQuote " << inQuote << endl; + char* bakedP = ((char*)(bakedUrl.c_str())) + strlen(bakedPrefix); + char* rawP = buf + strlen(rawPrefix); + char* lim = ((char*)(bakedUrl.c_str())) + bakedUrl.size() - -1; + + while (bakedP < lim) + { + if (isxdigit(*bakedP) && isxdigit(*(bakedP + 1))) + { + unsigned int c; + sscanf(bakedP, "%02x", &c); + *(rawP++) = (char)c; + bakedP += 2; + } + else + ++bakedP; + } + *rawP = '\0'; + + string bufs(buf); + delete[] buf; + return bufs; } else - if (!isspace(newUrl[i]) || inQuote) { - a.push_back(newUrl[i]); - inArg = true; + string newUrl; + decodeUrlString(bakedUrl, newUrl); + return newUrl; } } - if (inArg && a.size()) - { - // cerr << "adding '" << a << "' " << endl; - avNew.push_back (strdup(a.c_str())); - } - for (int i = 0; i < avNew.size(); ++i) + void RvApplication::parseURL(const char* s, vector& av) { - string s(avNew[i]); - if (s == "-eval" || s == "-pyeval" && i < avNew.size()-1) + cerr << "INFO: received URL '" << s << "'" << endl; + string newUrl(rawURL(s)); + vector avNew; + + cerr << "INFO: decoded URL '" << newUrl << "'" << endl; + + bool inArg = false, inQuote = false; + int len = newUrl.size(); + string a; + + // + // Skip over the protocol 'name', ie everything up to and + // including the first ':'. + // + int i = 0; + for (; i < len && ':' != newUrl[i]; ++i) + ; + ++i; + // Skip over slashes + i += 2; + + for (; i < len; ++i) { + if (inArg && !inQuote && isspace(newUrl[i])) // - // Check for allowed evals (used by shotgrid). - // XXX in the long run we need to change shotgrid to not use these. + // An unquoted whitespace char terminates the current arg. // - string s2(avNew[i+1]); - string ok1("launchTimeline"); - string ok2("compareFromVersionIDs"); - string ok3("sessionFromVersionIDs"); - string ok4("shotgrid_review_app"); - - if (s2.find(ok1) != string::npos || - s2.find(ok2) != string::npos || - s2.find(ok3) != string::npos || - s2.find(ok4) != string::npos) + { + // cerr << "adding '" << a << "'" << endl; + avNew.push_back(strdup(a.c_str())); + + a.clear(); + inArg = false; + } + else if ('\'' == newUrl[i]) + { + inQuote = (inQuote) ? false : true; + inArg = true; + // cerr << "quote found, inQuote " << inQuote << endl; + } + else if (!isspace(newUrl[i]) || inQuote) + { + a.push_back(newUrl[i]); + inArg = true; + } + } + if (inArg && a.size()) + { + // cerr << "adding '" << a << "' " << endl; + avNew.push_back(strdup(a.c_str())); + } + + for (int i = 0; i < avNew.size(); ++i) + { + string s(avNew[i]); + if (s == "-eval" || s == "-pyeval" && i < avNew.size() - 1) { // - // When using -eval, we need to bootstrap the tk-rv engine synchronously + // Check for allowed evals (used by shotgrid). + // XXX in the long run we need to change shotgrid to not use + // these. // - setEnvVar("BOOTSTRAP_TK_ENGINE_SYNCHRO", "true"); - av.push_back(avNew[i]); - av.push_back(avNew[i+1]); + string s2(avNew[i + 1]); + string ok1("launchTimeline"); + string ok2("compareFromVersionIDs"); + string ok3("sessionFromVersionIDs"); + string ok4("shotgrid_review_app"); + + if (s2.find(ok1) != string::npos || s2.find(ok2) != string::npos + || s2.find(ok3) != string::npos + || s2.find(ok4) != string::npos) + { + // + // When using -eval, we need to bootstrap the tk-rv engine + // synchronously + // + setEnvVar("BOOTSTRAP_TK_ENGINE_SYNCHRO", "true"); + av.push_back(avNew[i]); + av.push_back(avNew[i + 1]); + } + else + cerr << "ERROR: sorry -eval/pyeval are no longer allowed " + "in rvlink URLs for security reasons." + << endl; + ++i; } - else cerr << "ERROR: sorry -eval/pyeval are no longer allowed in rvlink URLs for security reasons." << endl; - ++i; + else + av.push_back(avNew[i]); } - else av.push_back(avNew[i]); } -} - -void -RvApplication::processNetworkOpts(bool startup) -{ - Rv::Options& opts = Rv::Options::sharedOptions(); - if (startup && opts.networkOnStartup && !networkWindow()->serverRunning()) + void RvApplication::processNetworkOpts(bool startup) { - networkWindow()->toggleServer(); - } + Rv::Options& opts = Rv::Options::sharedOptions(); - if (opts.connectHost || opts.network) - { - if (!networkWindow()->serverRunning()) + if (startup && opts.networkOnStartup + && !networkWindow()->serverRunning()) { networkWindow()->toggleServer(); } - if (networkWindow()->serverRunning() && opts.connectHost) + + if (opts.connectHost || opts.network) { - networkWindow()->connectByName (opts.connectHost, opts.connectPort); + if (!networkWindow()->serverRunning()) + { + networkWindow()->toggleServer(); + } + if (networkWindow()->serverRunning() && opts.connectHost) + { + networkWindow()->connectByName(opts.connectHost, + opts.connectPort); + } } } -} - -static string -encodeURL (string url, bool encodeEverything = false) -{ - static bool first = true;; - static bool disallowed[256]; - if (first) + static string encodeURL(string url, bool encodeEverything = false) { - for (int i = 0; i < 128; disallowed[i++] = false); - - // Non-ascii chars disallowed - for (int i = 128; i < 256; disallowed[i++] = true); - - // Control chars disallowed - for (int i = 0; i < 32; disallowed[i++] = true); - - // Reserved chars disallowed - disallowed['$'] = true; - disallowed['&'] = true; - disallowed['+'] = true; - disallowed[','] = true; - disallowed['/'] = true; - disallowed[':'] = true; - disallowed[';'] = true; - disallowed['='] = true; - disallowed['?'] = true; - disallowed['@'] = true; - - // Unsafe chars disallowed - disallowed[' '] = true; - disallowed['"'] = true; - disallowed['<'] = true; - disallowed['>'] = true; - disallowed['{'] = true; - disallowed['}'] = true; - disallowed['|'] = true; - disallowed['\\'] = true; - disallowed['^'] = true; - disallowed['~'] = true; - disallowed['['] = true; - disallowed[']'] = true; - disallowed['`'] = true; - disallowed['%'] = true; - - first = false; - } + static bool first = true; + ; + static bool disallowed[256]; - string newURL; - char hexBuf[8]; - - for (int i = 0; i < url.size(); ++i) - { - if (encodeEverything) + if (first) { - sprintf (hexBuf, "%02x", int(url[i])); - newURL += string(hexBuf); + for (int i = 0; i < 128; disallowed[i++] = false) + ; + + // Non-ascii chars disallowed + for (int i = 128; i < 256; disallowed[i++] = true) + ; + + // Control chars disallowed + for (int i = 0; i < 32; disallowed[i++] = true) + ; + + // Reserved chars disallowed + disallowed['$'] = true; + disallowed['&'] = true; + disallowed['+'] = true; + disallowed[','] = true; + disallowed['/'] = true; + disallowed[':'] = true; + disallowed[';'] = true; + disallowed['='] = true; + disallowed['?'] = true; + disallowed['@'] = true; + + // Unsafe chars disallowed + disallowed[' '] = true; + disallowed['"'] = true; + disallowed['<'] = true; + disallowed['>'] = true; + disallowed['{'] = true; + disallowed['}'] = true; + disallowed['|'] = true; + disallowed['\\'] = true; + disallowed['^'] = true; + disallowed['~'] = true; + disallowed['['] = true; + disallowed[']'] = true; + disallowed['`'] = true; + disallowed['%'] = true; + + first = false; } - else - if (disallowed[url[i]]) + + string newURL; + char hexBuf[8]; + + for (int i = 0; i < url.size(); ++i) { - sprintf (hexBuf, "%%%02x", int(url[i])); - newURL += string(hexBuf); + if (encodeEverything) + { + sprintf(hexBuf, "%02x", int(url[i])); + newURL += string(hexBuf); + } + else if (disallowed[url[i]]) + { + sprintf(hexBuf, "%%%02x", int(url[i])); + newURL += string(hexBuf); + } + else + newURL.push_back(url[i]); } - else newURL.push_back(url[i]); + return newURL; } - return newURL; -} - -string -RvApplication::encodeCommandLineURL(int argc, char *argv[]) -{ - string prefix("rvlink://"); - string url; - for (int i = 1; i < argc; ++i) + string RvApplication::encodeCommandLineURL(int argc, char* argv[]) { - if (string("-encodeURL") != argv[i] && string("-bakeURL") != argv[i]) + string prefix("rvlink://"); + string url; + + for (int i = 1; i < argc; ++i) { - url = url + " " + argv[i]; + if (string("-encodeURL") != argv[i] + && string("-bakeURL") != argv[i]) + { + url = url + " " + argv[i]; + } } + cerr << "INFO: command line for encoding '" << url << "'" << endl; + url = encodeURL(url, false); + return prefix + url; } - cerr << "INFO: command line for encoding '" << url << "'" << endl; - url = encodeURL (url, false); - return prefix + url; -} -string -RvApplication::bakeCommandLineURL(int argc, char *argv[]) -{ - string prefix("rvlink://baked/"); - string url; - - for (int i = 1; i < argc; ++i) + string RvApplication::bakeCommandLineURL(int argc, char* argv[]) { - if (string("-encodeURL") != argv[i] && string("-bakeURL") != argv[i]) + string prefix("rvlink://baked/"); + string url; + + for (int i = 1; i < argc; ++i) { - url = url + " " + argv[i]; + if (string("-encodeURL") != argv[i] + && string("-bakeURL") != argv[i]) + { + url = url + " " + argv[i]; + } } + cerr << "INFO: command line for baking '" << url << "'" << endl; + url = encodeURL(url, true); + return prefix + url; } - cerr << "INFO: command line for baking '" << url << "'" << endl; - url = encodeURL (url, true); - return prefix + url; -} -void -RvApplication::putUrlOnClipboard(string url, string title, bool doEncode) -{ - QString qUrl(url.c_str()); - QStringList parts = qUrl.split("://"); - if (parts.size() != 2) - { - cerr << "ERROR: illegal url '" << url << "'" << endl; - return; - } - // - // Bake rvlink urls, others are merely web-encoded. - // - string urlPart; - if (doEncode) + void RvApplication::putUrlOnClipboard(string url, string title, + bool doEncode) { - if (parts[0] == "rvlink") urlPart = "baked/" + encodeURL(parts[1].toUtf8().data(), true); - else urlPart = encodeURL(parts[1].toUtf8().data(), false); - } - else urlPart = parts[1].toUtf8().data(); + QString qUrl(url.c_str()); + QStringList parts = qUrl.split("://"); + if (parts.size() != 2) + { + cerr << "ERROR: illegal url '" << url << "'" << endl; + return; + } + // + // Bake rvlink urls, others are merely web-encoded. + // + string urlPart; + if (doEncode) + { + if (parts[0] == "rvlink") + urlPart = "baked/" + encodeURL(parts[1].toUtf8().data(), true); + else + urlPart = encodeURL(parts[1].toUtf8().data(), false); + } + else + urlPart = parts[1].toUtf8().data(); - QString fullUrl(parts[0] + "://" + urlPart.c_str()); + QString fullUrl(parts[0] + "://" + urlPart.c_str()); - #if defined(PLATFORM_DARWIN) +#if defined(PLATFORM_DARWIN) (*putUrlOnMacPasteboardPointer)(fullUrl.toUtf8().data(), title); - #elif defined(PLATFORM_WINDOWS) - QClipboard *clipboard = QApplication::clipboard(); - clipboard->clear (QClipboard::Clipboard); +#elif defined(PLATFORM_WINDOWS) + QClipboard* clipboard = QApplication::clipboard(); + clipboard->clear(QClipboard::Clipboard); clipboard->setText(fullUrl, QClipboard::Clipboard); - #else - QClipboard *clipboard = QApplication::clipboard(); - clipboard->clear (QClipboard::Selection); +#else + QClipboard* clipboard = QApplication::clipboard(); + clipboard->clear(QClipboard::Selection); clipboard->setText(fullUrl, QClipboard::Selection); - clipboard->clear (QClipboard::Clipboard); + clipboard->clear(QClipboard::Clipboard); clipboard->setText(fullUrl, QClipboard::Clipboard); - #endif -} +#endif + } -void -RvApplication::initializeQSettings(string altPath) -{ - QString home = QDir::homePath(); + void RvApplication::initializeQSettings(string altPath) + { + QString home = QDir::homePath(); - #if defined(PLATFORM_DARWIN) +#if defined(PLATFORM_DARWIN) QString config(home + "/Library/Preferences"); - if (altPath.size()) config = altPath.c_str(); - QSettings::setPath(QSettings::NativeFormat, QSettings::UserScope, config); - QSettings::setPath(QSettings::NativeFormat, QSettings::SystemScope, config); - #elif defined(PLATFORM_WINDOWS) - QString config = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation); - if (altPath.size()) config = altPath.c_str(); + if (altPath.size()) + config = altPath.c_str(); + QSettings::setPath(QSettings::NativeFormat, QSettings::UserScope, + config); + QSettings::setPath(QSettings::NativeFormat, QSettings::SystemScope, + config); +#elif defined(PLATFORM_WINDOWS) + QString config = + QStandardPaths::writableLocation(QStandardPaths::AppDataLocation); + if (altPath.size()) + config = altPath.c_str(); QSettings::setPath(QSettings::IniFormat, QSettings::UserScope, config); - QSettings::setPath(QSettings::IniFormat, QSettings::SystemScope, config); - #else + QSettings::setPath(QSettings::IniFormat, QSettings::SystemScope, + config); +#else QString config(home + "/.config"); - if (altPath.size()) config = altPath.c_str(); - QSettings::setPath(QSettings::NativeFormat, QSettings::UserScope, config); - QSettings::setPath(QSettings::NativeFormat, QSettings::SystemScope, config); - #endif -} - -std::string -RvApplication::queryDriverAttribute(const std::string& var) -{ - return ""; -} - - -void -RvApplication::setDriverAttribute(const std::string& var, const std::string& val) -{ -} + if (altPath.size()) + config = altPath.c_str(); + QSettings::setPath(QSettings::NativeFormat, QSettings::UserScope, + config); + QSettings::setPath(QSettings::NativeFormat, QSettings::SystemScope, + config); +#endif + } -void -RvApplication::setPresentationMode(bool value) -{ - // Note: prefDialog() initializes m_prefDialog if it isn't already - // initialized. This is why we are checking m_prefDialog first. - // Otherwise it is a total waste of time and resources to instantiate - // the prefDialog here for this simple visibility check. - if (m_prefDialog && prefDialog()->isVisible()) + std::string RvApplication::queryDriverAttribute(const std::string& var) { - // - // Not allowed to set while prefs are up - // - - return; + return ""; } - if (m_presentationMode != value) + void RvApplication::setDriverAttribute(const std::string& var, + const std::string& val) { - m_presentationMode = value; } - Rv::Options& opts = Rv::Options::sharedOptions(); - TwkApp::Document* doc = TwkApp::Document::activeDocument(); - Rv::Session* session = static_cast(doc); - RvDocument *rvDoc = (RvDocument *)session->opaquePointer(); - - if (m_presentationMode) + void RvApplication::setPresentationMode(bool value) { - if (VideoDevice* d = findPresentationDevice(opts.presentDevice)) + // Note: prefDialog() initializes m_prefDialog if it isn't already + // initialized. This is why we are checking m_prefDialog first. + // Otherwise it is a total waste of time and resources to instantiate + // the prefDialog here for this simple visibility check. + if (m_prefDialog && prefDialog()->isVisible()) + { + // + // Not allowed to set while prefs are up + // + + return; + } + + if (m_presentationMode != value) + { + m_presentationMode = value; + } + + Rv::Options& opts = Rv::Options::sharedOptions(); + TwkApp::Document* doc = TwkApp::Document::activeDocument(); + Rv::Session* session = static_cast(doc); + RvDocument* rvDoc = (RvDocument*)session->opaquePointer(); + + if (m_presentationMode) { - //rvDoc->warnOnDriverVSync(); + if (VideoDevice* d = findPresentationDevice(opts.presentDevice)) + { + // rvDoc->warnOnDriverVSync(); #if 0 if (opts.vsync && !rvDoc->vsyncDisabled()) @@ -1530,96 +1582,129 @@ RvApplication::setPresentationMode(bool value) } #endif - string optionArgs = setVideoDeviceStateFromSettings(d); - rvDoc->view()->videoDevice()->makeCurrent(); + string optionArgs = setVideoDeviceStateFromSettings(d); + rvDoc->view()->videoDevice()->makeCurrent(); - try - { - if (!d->isOpen()) + try { - const DesktopVideoDevice* dd = dynamic_cast(d); - - if (dd && dd->qtScreen() == qApp->desktop()->QDesktopWidget::screenNumber(rvDoc)) + if (!d->isOpen()) { - TWK_THROW_EXC_STREAM("Cannot open presentation device for the same screen the controller is on"); + const DesktopVideoDevice* dd = + dynamic_cast(d); + + if (dd + && dd->qtScreen() + == qApp->desktop() + ->QDesktopWidget::screenNumber(rvDoc)) + { + TWK_THROW_EXC_STREAM( + "Cannot open presentation device for the same " + "screen the controller is on"); + } + + StringVector vargs; + algorithm::split(vargs, optionArgs, + is_any_of(string(" \t\n\r")), + token_compress_on); + d->open(vargs); } - StringVector vargs; - algorithm::split(vargs, optionArgs, is_any_of(string(" \t\n\r")), token_compress_on); - d->open(vargs); - } - #ifdef PLATFORM_DARWIN - //cout << "INFO: disabling double buffer in controller" << endl; - //rvDoc->setDoubleBuffer(false); + // cout << "INFO: disabling double buffer in controller" << + // endl; rvDoc->setDoubleBuffer(false); #endif - try - { - session->setOutputVideoDevice(d); + try + { + session->setOutputVideoDevice(d); + } + catch (std::exception& exc) + { + QWidget* parent = 0; + if (doc) + parent = (RvDocument*)doc->opaquePointer(); + QMessageBox box(parent); + box.setWindowTitle( + tr(UI_APPLICATION_NAME ": Presentation Mode")); + QString baseText = + QString("The presentation device (%1/%2) is busy " + "or cannot be opened.") + .arg(d->module()->name().c_str()) + .arg(d->name().c_str()); + QString detailedText = + QString( + UI_APPLICATION_NAME + " failed to open or bind the presentation " + "device (%1/%2)." + " Check to see if another program is using the " + "device" + " and that the parameters are valid in the " + "preferences." + " You can start RV with -noPrefs or " + "-resetPrefs if you" + " suspect that the preferences are corrupted.\n" + " The presentation device video module is " + "\"%1\"," + " the device is \"%2\"") + .arg(d->module()->name().c_str()) + .arg(d->name().c_str()); + box.setText(baseText + "\n\n" + detailedText); + box.setWindowModality(Qt::WindowModal); + QPushButton* b0 = + box.addButton(tr("Ok"), QMessageBox::AcceptRole); + box.setIconPixmap( + QPixmap(qApp->applicationDirPath() + + QString(RV_ICON_PATH_SUFFIX)) + .scaledToHeight(64)); + box.exec(); + + m_presentationMode = false; + } } catch (std::exception& exc) { QWidget* parent = 0; - if (doc) parent = (RvDocument *)doc->opaquePointer(); + if (doc) + parent = (RvDocument*)doc->opaquePointer(); QMessageBox box(parent); - box.setWindowTitle(tr(UI_APPLICATION_NAME ": Presentation Mode")); - QString baseText = QString("The presentation device (%1/%2) is busy or cannot be opened.") - .arg(d->module()->name().c_str()).arg(d->name().c_str()); - QString detailedText = QString(UI_APPLICATION_NAME " failed to open or bind the presentation device (%1/%2)." - " Check to see if another program is using the device" - " and that the parameters are valid in the preferences." - " You can start RV with -noPrefs or -resetPrefs if you" - " suspect that the preferences are corrupted.\n" - " The presentation device video module is \"%1\"," - " the device is \"%2\"") - .arg(d->module()->name().c_str()).arg(d->name().c_str()); - box.setText(baseText + "\n\n" + detailedText); + box.setWindowTitle( + tr(UI_APPLICATION_NAME ": Presentation Mode")); + QString baseText = + QString( + "The presentation device (%1/%2) failed to open.") + .arg(d->module()->name().c_str()) + .arg(d->name().c_str()); + box.setText(baseText + "\n\n" + exc.what()); box.setWindowModality(Qt::WindowModal); - QPushButton* b0 = box.addButton(tr("Ok"), QMessageBox::AcceptRole); - box.setIconPixmap(QPixmap(qApp->applicationDirPath() + QString(RV_ICON_PATH_SUFFIX)).scaledToHeight(64)); + QPushButton* b0 = + box.addButton(tr("Ok"), QMessageBox::AcceptRole); + box.setIconPixmap(QPixmap(qApp->applicationDirPath() + + QString(RV_ICON_PATH_SUFFIX)) + .scaledToHeight(64)); box.exec(); m_presentationMode = false; } } - catch (std::exception& exc) + else { - QWidget* parent = 0; - if (doc) parent = (RvDocument *)doc->opaquePointer(); - QMessageBox box(parent); - box.setWindowTitle(tr(UI_APPLICATION_NAME ": Presentation Mode")); - QString baseText = QString("The presentation device (%1/%2) failed to open.") - .arg(d->module()->name().c_str()).arg(d->name().c_str()); - box.setText(baseText + "\n\n" + exc.what()); - box.setWindowModality(Qt::WindowModal); - QPushButton* b0 = box.addButton(tr("Ok"), QMessageBox::AcceptRole); - box.setIconPixmap(QPixmap(qApp->applicationDirPath() + QString(RV_ICON_PATH_SUFFIX)).scaledToHeight(64)); - box.exec(); - + cerr << "ERROR: presentation device not found." << endl; m_presentationMode = false; } } else { - cerr << "ERROR: presentation device not found." << endl; - m_presentationMode = false; - } - } - else - { - const VideoDevice* d = session->outputVideoDevice(); + const VideoDevice* d = session->outputVideoDevice(); - if (d != session->controlVideoDevice()) - { - const_cast(d)->close(); + if (d != session->controlVideoDevice()) + { + const_cast(d)->close(); #ifdef PLATFORM_DARWIN - //rvDoc->setDoubleBuffer(true); + // rvDoc->setDoubleBuffer(true); #endif - } - - session->setOutputVideoDevice(session->controlVideoDevice()); + } + session->setOutputVideoDevice(session->controlVideoDevice()); #if 0 if (opts.vsync && !rvDoc->vsyncDisabled()) @@ -1631,186 +1716,188 @@ RvApplication::setPresentationMode(bool value) rvDoc->setVSync(true); } #endif + } } -} -string -RvApplication::setVideoDeviceStateFromSettings(VideoDevice* d) const -{ - Rv::Options& opts = Rv::Options::sharedOptions(); - ostringstream str; - str << d->module()->name() << "/" << d->name(); - - QString optFormat = opts.presentFormat; - QString optData = opts.presentData; - - RV_QSETTINGS; - settings.beginGroup(str.str().c_str()); - int vformat = settings.value("videoFormat", -1).toInt(); - int v4KTransport = settings.value("video4KTransport", -1).toInt(); - int dformat = settings.value("dataFormat", -1).toInt(); - int syncmode = settings.value("syncMode", -1).toInt(); - int syncsrc = settings.value("syncSource", -1).toInt(); - int dispMode = settings.value("displayMode", -1).toInt(); - int aformat = settings.value("audioFormat", -1).toInt(); - bool useaudio = settings.value("useAsAudioDevice", false).toBool(); - bool uselatency = settings.value("useLatencyForAudio", false).toBool(); - bool swapStereoEyes = settings.value("swapStereoEyes", false).toBool(); - double xl = settings.value("fixedLatency", double(0.0)).toDouble(); - double fl = settings.value("frameLatency", double(0.0)).toDouble(); - QString options = settings.value("additionalOptions", "").toString(); - settings.endGroup(); - - if (opts.presentAudio != -1) useaudio = opts.presentAudio != 0; - - if (optFormat != "") + string RvApplication::setVideoDeviceStateFromSettings(VideoDevice* d) const { - // - // Look for exact match first - // - int foundVFormat = -1; - for (size_t i = 0; i < d->numVideoFormats(); i++) - { - QString desc = d->videoFormatAtIndex(i).description.c_str(); - - if (desc == optFormat) - { - foundVFormat = i; - break; - } - } - if (foundVFormat != -1) vformat = foundVFormat; - else + Rv::Options& opts = Rv::Options::sharedOptions(); + ostringstream str; + str << d->module()->name() << "/" << d->name(); + + QString optFormat = opts.presentFormat; + QString optData = opts.presentData; + + RV_QSETTINGS; + settings.beginGroup(str.str().c_str()); + int vformat = settings.value("videoFormat", -1).toInt(); + int v4KTransport = settings.value("video4KTransport", -1).toInt(); + int dformat = settings.value("dataFormat", -1).toInt(); + int syncmode = settings.value("syncMode", -1).toInt(); + int syncsrc = settings.value("syncSource", -1).toInt(); + int dispMode = settings.value("displayMode", -1).toInt(); + int aformat = settings.value("audioFormat", -1).toInt(); + bool useaudio = settings.value("useAsAudioDevice", false).toBool(); + bool uselatency = settings.value("useLatencyForAudio", false).toBool(); + bool swapStereoEyes = settings.value("swapStereoEyes", false).toBool(); + double xl = settings.value("fixedLatency", double(0.0)).toDouble(); + double fl = settings.value("frameLatency", double(0.0)).toDouble(); + QString options = settings.value("additionalOptions", "").toString(); + settings.endGroup(); + + if (opts.presentAudio != -1) + useaudio = opts.presentAudio != 0; + + if (optFormat != "") { // - // No exact match found, so look for approximate match + // Look for exact match first // + int foundVFormat = -1; for (size_t i = 0; i < d->numVideoFormats(); i++) { QString desc = d->videoFormatAtIndex(i).description.c_str(); - if (desc.contains(optFormat)) + if (desc == optFormat) { - vformat = i; + foundVFormat = i; break; } } - } - } - - if (optData != "") - { - // - // Look for exact match first - // - int foundDFormat = -1; - for (size_t i = 0; i < d->numDataFormats(); i++) - { - QString desc = d->dataFormatAtIndex(i).description.c_str(); - - if (desc == optData) + if (foundVFormat != -1) + vformat = foundVFormat; + else { - foundDFormat = i; - break; + // + // No exact match found, so look for approximate match + // + for (size_t i = 0; i < d->numVideoFormats(); i++) + { + QString desc = d->videoFormatAtIndex(i).description.c_str(); + + if (desc.contains(optFormat)) + { + vformat = i; + break; + } + } } } - if (foundDFormat != -1) dformat = foundDFormat; - else + + if (optData != "") { // - // No exact match found, so look for approximate match + // Look for exact match first // + int foundDFormat = -1; for (size_t i = 0; i < d->numDataFormats(); i++) { QString desc = d->dataFormatAtIndex(i).description.c_str(); - if (desc.contains(optData)) + if (desc == optData) { - dformat = i; + foundDFormat = i; break; } } - } - } - - if (vformat >= 0 && vformat < d->numVideoFormats()) d->setVideoFormat(vformat); - if (v4KTransport >= 0 && v4KTransport < d->numVideo4KTransports()) d->setVideo4KTransport(v4KTransport); - if (aformat >= 0 && aformat < d->numAudioFormats()) d->setAudioFormat(aformat); - if (dformat >= 0 && dformat < d->numDataFormats()) d->setDataFormat(dformat); - if (syncmode >= 0 && syncmode < d->numSyncModes()) d->setSyncMode(syncmode); - if (syncsrc >= 0 && syncsrc < d->numSyncSources()) d->setSyncSource(syncsrc); - if (dispMode >= 0 && dispMode < int(VideoDevice::NotADisplayMode)) d->setDisplayMode((VideoDevice::DisplayMode)dispMode); - d->setAudioOutputEnabled(useaudio); - d->setUseLatencyForAudio(uselatency); - d->setFixedLatency(xl); - d->setFrameLatency(fl); - d->setSwapStereoEyes(swapStereoEyes); - return options.toUtf8().constData(); -} + if (foundDFormat != -1) + dformat = foundDFormat; + else + { + // + // No exact match found, so look for approximate match + // + for (size_t i = 0; i < d->numDataFormats(); i++) + { + QString desc = d->dataFormatAtIndex(i).description.c_str(); -bool -RvApplication::isInPresentationMode() -{ - return m_presentationMode; -} + if (desc.contains(optData)) + { + dformat = i; + break; + } + } + } + } + if (vformat >= 0 && vformat < d->numVideoFormats()) + d->setVideoFormat(vformat); + if (v4KTransport >= 0 && v4KTransport < d->numVideo4KTransports()) + d->setVideo4KTransport(v4KTransport); + if (aformat >= 0 && aformat < d->numAudioFormats()) + d->setAudioFormat(aformat); + if (dformat >= 0 && dformat < d->numDataFormats()) + d->setDataFormat(dformat); + if (syncmode >= 0 && syncmode < d->numSyncModes()) + d->setSyncMode(syncmode); + if (syncsrc >= 0 && syncsrc < d->numSyncSources()) + d->setSyncSource(syncsrc); + if (dispMode >= 0 && dispMode < int(VideoDevice::NotADisplayMode)) + d->setDisplayMode((VideoDevice::DisplayMode)dispMode); + d->setAudioOutputEnabled(useaudio); + d->setUseLatencyForAudio(uselatency); + d->setFixedLatency(xl); + d->setFrameLatency(fl); + d->setSwapStereoEyes(swapStereoEyes); + return options.toUtf8().constData(); + } -int -RvApplication::findVideoModuleIndexByName(const string& name) const -{ - const VideoModules& mods = videoModules(); + bool RvApplication::isInPresentationMode() { return m_presentationMode; } - for (size_t i = 0; i < mods.size(); i++) + int RvApplication::findVideoModuleIndexByName(const string& name) const { - if (mods[i]->name() == name) return i; - } + const VideoModules& mods = videoModules(); - return -1; -} - -TwkApp::VideoDevice* -RvApplication::findPresentationDevice(const std::string& dpath) const -{ - QString p(dpath.c_str()); - QStringList parts = p.split("/"); + for (size_t i = 0; i < mods.size(); i++) + { + if (mods[i]->name() == name) + return i; + } - // - // Allow for case where the device name itself contained a "/" - // - if (parts.size() > 2) - { - QStringList newParts; - newParts.append(parts[0]); - parts.removeAt(0); - newParts.append(parts.join("/")); - parts = newParts; + return -1; } - if (parts.size() == 2) + TwkApp::VideoDevice* + RvApplication::findPresentationDevice(const std::string& dpath) const { - int mindex = findVideoModuleIndexByName(parts[0].toUtf8().constData()); + QString p(dpath.c_str()); + QStringList parts = p.split("/"); - if (mindex >= 0) + // + // Allow for case where the device name itself contained a "/" + // + if (parts.size() > 2) { - VideoModule* m = videoModules()[mindex].get(); - openVideoModule(m); - const VideoModule::VideoDevices& devs = m->devices(); - string dname = parts[1].toUtf8().constData(); + QStringList newParts; + newParts.append(parts[0]); + parts.removeAt(0); + newParts.append(parts.join("/")); + parts = newParts; + } - for (size_t i = 0; i < devs.size(); i++) + if (parts.size() == 2) + { + int mindex = + findVideoModuleIndexByName(parts[0].toUtf8().constData()); + + if (mindex >= 0) { - if (devs[i]->name() == dname) + VideoModule* m = videoModules()[mindex].get(); + openVideoModule(m); + const VideoModule::VideoDevices& devs = m->devices(); + string dname = parts[1].toUtf8().constData(); + + for (size_t i = 0; i < devs.size(); i++) { - return devs[i]; + if (devs[i]->name() == dname) + { + return devs[i]; + } } } } - } - - return 0; -} - + return 0; + } -} // Rv - +} // namespace Rv diff --git a/src/lib/app/RvCommon/RvBottomViewToolBar.cpp b/src/lib/app/RvCommon/RvBottomViewToolBar.cpp index 30e09d854..3daafa0d0 100644 --- a/src/lib/app/RvCommon/RvBottomViewToolBar.cpp +++ b/src/lib/app/RvCommon/RvBottomViewToolBar.cpp @@ -1,9 +1,9 @@ // -// Copyright (c) 2012 Tweak Software. +// Copyright (c) 2012 Tweak Software. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// // #include #include @@ -24,230 +24,241 @@ #include -namespace Rv { -using namespace IPCore; -using namespace std; -using namespace TwkApp; -using namespace TwkContainer; -using namespace boost; -using namespace TwkQtCoreUtil; - -RvBottomViewToolBar::RvBottomViewToolBar(QWidget* parent) - : QToolBar("bottom", parent), - EventNode("bottomToolBar"), - m_session(0), - m_audioMenu(0) +namespace Rv { - // if we don't build up front the style sheet doesn't quite work - build(); - setObjectName("bottomToolBar"); -} + using namespace IPCore; + using namespace std; + using namespace TwkApp; + using namespace TwkContainer; + using namespace boost; + using namespace TwkQtCoreUtil; + + RvBottomViewToolBar::RvBottomViewToolBar(QWidget* parent) + : QToolBar("bottom", parent) + , EventNode("bottomToolBar") + , m_session(0) + , m_audioMenu(0) + { + // if we don't build up front the style sheet doesn't quite work + build(); + setObjectName("bottomToolBar"); + } -void -RvBottomViewToolBar::makeActiveFromSettings() -{ - RV_QSETTINGS; - settings.beginGroup("ViewToolBars"); + void RvBottomViewToolBar::makeActiveFromSettings() + { + RV_QSETTINGS; + settings.beginGroup("ViewToolBars"); - // Policy is visible by default. - bool b = settings.value("bottom", true).toBool(); + // Policy is visible by default. + bool b = settings.value("bottom", true).toBool(); - settings.endGroup(); - makeActive(b); -} + settings.endGroup(); + makeActive(b); + } -void -RvBottomViewToolBar::makeActive(bool b) -{ - if (!m_audioMenu && b) build(); - setVisible(b); -} + void RvBottomViewToolBar::makeActive(bool b) + { + if (!m_audioMenu && b) + build(); + setVisible(b); + } -static QVariant -enumCodeMap(int enumVal, QString codeVal) -{ - QVariantMap m; + static QVariant enumCodeMap(int enumVal, QString codeVal) + { + QVariantMap m; - m["enum"] = enumVal; - m["code"] = codeVal; + m["enum"] = enumVal; + m["code"] = codeVal; - return QVariant(m); -} + return QVariant(m); + } -void -RvBottomViewToolBar::build() -{ - if (m_audioMenu) return; + void RvBottomViewToolBar::build() + { + if (m_audioMenu) + return; - Options& opts = Options::sharedOptions(); + Options& opts = Options::sharedOptions(); - // Initialize QIcons - m_playModeOnceIcon = QIcon(":/images/playmode_once_48x48.png"); - m_playModeLoopIcon = QIcon(":/images/playmode_loop_48x48.png"); - m_playModePingPongIcon = QIcon(":/images/playmode_pingpong_48x48.png"); + // Initialize QIcons + m_playModeOnceIcon = QIcon(":/images/playmode_once_48x48.png"); + m_playModeLoopIcon = QIcon(":/images/playmode_loop_48x48.png"); + m_playModePingPongIcon = QIcon(":/images/playmode_pingpong_48x48.png"); - m_volumeZeroIcon = QIcon(":/images/volume_zero_48x48.png"); - m_volumeLowIcon = QIcon(":/images/volume_low_48x48.png"); - m_volumeMediumIcon = QIcon(":/images/volume_medium_48x48.png"); - m_volumeHighIcon = QIcon(":/images/volume_high_48x48.png"); - m_volumeHighMutedIcon = QIcon(":/images/volume_high_muted_48x48.png"); + m_volumeZeroIcon = QIcon(":/images/volume_zero_48x48.png"); + m_volumeLowIcon = QIcon(":/images/volume_low_48x48.png"); + m_volumeMediumIcon = QIcon(":/images/volume_medium_48x48.png"); + m_volumeHighIcon = QIcon(":/images/volume_high_48x48.png"); + m_volumeHighMutedIcon = QIcon(":/images/volume_high_muted_48x48.png"); - setProperty("tbstyle", QVariant(QString("play_controls"))); + setProperty("tbstyle", QVariant(QString("play_controls"))); - QAction* a; - QMenu* m; - QToolButton* b; - QFrame* qf; + QAction* a; + QMenu* m; + QToolButton* b; + QFrame* qf; - for (size_t i = 0; i < 6; i++) - { + for (size_t i = 0; i < 6; i++) + { + a = addAction(""); + b = dynamic_cast(widgetForAction(a)); + b->setIcon(m_playModeLoopIcon); + b->setToolButtonStyle(Qt::ToolButtonIconOnly); + b->setProperty("tbstyle", QVariant(QString("interior"))); + + switch (i) + { + case 0: + b->setProperty("tbstyle", QVariant(QString("left"))); + a->setIcon(QIcon(":/images/smanager.png")); + a->setToolTip("Toggle Session Manager"); + m_smAction = a; + break; + case 1: + a->setIcon(QIcon(":/images/paint_48x48.png")); + a->setToolTip("Toggle Annotation tools"); + m_paintAction = a; + break; + case 2: + a->setIcon(QIcon(":/images/about_48x48.png")); + a->setToolTip("Toggle Image Info"); + m_infoAction = a; + break; + case 3: + a->setIcon(QIcon(":/images/ntwrk_48x48.png")); + a->setToolTip("Toggle RV Networking Dialog"); + m_networkAction = a; + break; + case 4: + a->setIcon(QIcon(":/images/timeline_mag.png")); + a->setToolTip("Toggle Timeline Magnifier"); + m_timelineMagAction = a; + break; + case 5: + a->setIcon(QIcon(":/images/timeline.png")); + a->setToolTip("Toggle Timeline"); + b->setProperty("tbstyle", QVariant(QString("right"))); + m_timelineAction = a; + break; + } + } + + connect(m_smAction, SIGNAL(triggered(bool)), this, + SLOT(smActionTriggered(bool))); + connect(m_paintAction, SIGNAL(triggered(bool)), this, + SLOT(paintActionTriggered(bool))); + connect(m_infoAction, SIGNAL(triggered(bool)), this, + SLOT(infoActionTriggered(bool))); + connect(m_timelineAction, SIGNAL(triggered(bool)), this, + SLOT(timelineActionTriggered(bool))); + connect(m_timelineMagAction, SIGNAL(triggered(bool)), this, + SLOT(timelineMagActionTriggered(bool))); + connect(m_networkAction, SIGNAL(triggered(bool)), this, + SLOT(networkActionTriggered(bool))); + + // + // Add some expanding space before the play buttons + // + qf = new QFrame(this); + qf->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); + qf->setMinimumWidth(0); + qf->setFrameStyle(QFrame::Plain | QFrame::NoFrame); + qf->setStyleSheet("background-color: transparent"); + addWidget(qf); + + // play buts a = addAction(""); b = dynamic_cast(widgetForAction(a)); - b->setIcon(m_playModeLoopIcon); - b->setToolButtonStyle(Qt::ToolButtonIconOnly); - b->setProperty("tbstyle", QVariant(QString("interior"))); + b->setIcon(QIcon(":/images/control_bstep.png")); + b->setToolTip("Step back one frame"); + b->setProperty("tbstyle", QVariant(QString("left"))); + b->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); + m_backStepAction = a; - switch (i) - { - case 0: - b->setProperty("tbstyle", QVariant(QString("left"))); - a->setIcon(QIcon(":/images/smanager.png")); - a->setToolTip("Toggle Session Manager"); - m_smAction = a; - break; - case 1: - a->setIcon(QIcon(":/images/paint_48x48.png")); - a->setToolTip("Toggle Annotation tools"); - m_paintAction = a; - break; - case 2: - a->setIcon(QIcon(":/images/about_48x48.png")); - a->setToolTip("Toggle Image Info"); - m_infoAction = a; - break; - case 3: - a->setIcon(QIcon(":/images/ntwrk_48x48.png")); - a->setToolTip("Toggle RV Networking Dialog"); - m_networkAction = a; - break; - case 4: - a->setIcon(QIcon(":/images/timeline_mag.png")); - a->setToolTip("Toggle Timeline Magnifier"); - m_timelineMagAction = a; - break; - case 5: - a->setIcon(QIcon(":/images/timeline.png")); - a->setToolTip("Toggle Timeline"); - b->setProperty("tbstyle", QVariant(QString("right"))); - m_timelineAction = a; - break; - } - } + a = addAction(""); + b = dynamic_cast(widgetForAction(a)); + b->setIcon(QIcon(":/images/control_fstep.png")); + b->setToolTip("Step forward one frame"); + b->setProperty("tbstyle", QVariant(QString("right"))); + b->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); + m_forwardStepAction = a; - connect(m_smAction, SIGNAL(triggered(bool)), this, SLOT(smActionTriggered(bool))); - connect(m_paintAction, SIGNAL(triggered(bool)), this, SLOT(paintActionTriggered(bool))); - connect(m_infoAction, SIGNAL(triggered(bool)), this, SLOT(infoActionTriggered(bool))); - connect(m_timelineAction, SIGNAL(triggered(bool)), this, SLOT(timelineActionTriggered(bool))); - connect(m_timelineMagAction, SIGNAL(triggered(bool)), this, SLOT(timelineMagActionTriggered(bool))); - connect(m_networkAction, SIGNAL(triggered(bool)), this, SLOT(networkActionTriggered(bool))); + a = addAction(""); + b = dynamic_cast(widgetForAction(a)); + b->setIcon(QIcon(":/images/control_bplay.png")); + b->setToolTip("Play backwards"); + b->setProperty("tbstyle", QVariant(QString("left"))); + b->setProperty("tbsize", QVariant(QString("double"))); + b->setToolButtonStyle(Qt::ToolButtonIconOnly); + m_backPlayAction = a; - // - // Add some expanding space before the play buttons - // - qf = new QFrame(this); - qf->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); - qf->setMinimumWidth(0); - qf->setFrameStyle(QFrame::Plain | QFrame::NoFrame); - qf->setStyleSheet("background-color: transparent"); - addWidget(qf); - - // play buts - a = addAction(""); - b = dynamic_cast(widgetForAction(a)); - b->setIcon(QIcon(":/images/control_bstep.png")); - b->setToolTip("Step back one frame"); - b->setProperty("tbstyle", QVariant(QString("left"))); - b->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); - m_backStepAction = a; - - a = addAction(""); - b = dynamic_cast(widgetForAction(a)); - b->setIcon(QIcon(":/images/control_fstep.png")); - b->setToolTip("Step forward one frame"); - b->setProperty("tbstyle", QVariant(QString("right"))); - b->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); - m_forwardStepAction = a; - - a = addAction(""); - b = dynamic_cast(widgetForAction(a)); - b->setIcon(QIcon(":/images/control_bplay.png")); - b->setToolTip("Play backwards"); - b->setProperty("tbstyle", QVariant(QString("left"))); - b->setProperty("tbsize", QVariant(QString("double"))); - b->setToolButtonStyle(Qt::ToolButtonIconOnly); - m_backPlayAction = a; - - a = addAction(""); - b = dynamic_cast(widgetForAction(a)); - b->setIcon(QIcon(":/images/control_play.png")); - b->setToolTip("Play forwards"); - b->setProperty("tbstyle", QVariant(QString("right"))); - b->setProperty("tbsize", QVariant(QString("double"))); - b->setToolButtonStyle(Qt::ToolButtonIconOnly); - m_forwardPlayAction = a; - - a = addAction(""); - b = dynamic_cast(widgetForAction(a)); - b->setIcon(QIcon(":/images/control_bmark.png")); - b->setToolTip("Skip to start of sequence"); - b->setProperty("tbstyle", QVariant(QString("left"))); - b->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); - m_backMarkAction = a; - - a = addAction(""); - b = dynamic_cast(widgetForAction(a)); - b->setIcon(QIcon(":/images/control_fmark.png")); - b->setToolTip("Skip to end of sequence"); - b->setProperty("tbstyle", QVariant(QString("right"))); - b->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); - m_forwardMarkAction = a; - - connect(m_backStepAction, SIGNAL(triggered()), this, SLOT(backStepTriggered())); - connect(m_forwardStepAction, SIGNAL(triggered()), this, SLOT(forwardStepTriggered())); - connect(m_backPlayAction, SIGNAL(triggered()), this, SLOT(backPlayTriggered())); - connect(m_forwardPlayAction, SIGNAL(triggered()), this, SLOT(forwardPlayTriggered())); - connect(m_backMarkAction, SIGNAL(triggered()), this, SLOT(backMarkTriggered())); - connect(m_forwardMarkAction, SIGNAL(triggered()), this, SLOT(forwardMarkTriggered())); + a = addAction(""); + b = dynamic_cast(widgetForAction(a)); + b->setIcon(QIcon(":/images/control_play.png")); + b->setToolTip("Play forwards"); + b->setProperty("tbstyle", QVariant(QString("right"))); + b->setProperty("tbsize", QVariant(QString("double"))); + b->setToolButtonStyle(Qt::ToolButtonIconOnly); + m_forwardPlayAction = a; - // - // Add some expanding space after the play buttons - // - qf = new QFrame(this); - qf->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); - qf->setMinimumWidth(0); - qf->setFrameStyle(QFrame::Plain | QFrame::NoFrame); - qf->setStyleSheet("background-color: transparent"); - addWidget(qf); + a = addAction(""); + b = dynamic_cast(widgetForAction(a)); + b->setIcon(QIcon(":/images/control_bmark.png")); + b->setToolTip("Skip to start of sequence"); + b->setProperty("tbstyle", QVariant(QString("left"))); + b->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); + m_backMarkAction = a; - // - // This expanding space will not go to more than 90 pixels. It's to - // "counter balance" the buttons on the other side, so the play control - // buttons stay in the center of the view (roughly). - // - qf = new QFrame(this); - qf->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); - qf->setMinimumWidth(0); - qf->setMaximumWidth(90); - qf->setFrameStyle(QFrame::Plain | QFrame::NoFrame); - qf->setStyleSheet("background-color: transparent"); - addWidget(qf); - - m_playModeAction = addAction(""); - m_playModeAction->setToolTip("Select playback style"); - b = dynamic_cast(widgetForAction(m_playModeAction)); - - switch (static_cast(opts.loopMode)) - { + a = addAction(""); + b = dynamic_cast(widgetForAction(a)); + b->setIcon(QIcon(":/images/control_fmark.png")); + b->setToolTip("Skip to end of sequence"); + b->setProperty("tbstyle", QVariant(QString("right"))); + b->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); + m_forwardMarkAction = a; + + connect(m_backStepAction, SIGNAL(triggered()), this, + SLOT(backStepTriggered())); + connect(m_forwardStepAction, SIGNAL(triggered()), this, + SLOT(forwardStepTriggered())); + connect(m_backPlayAction, SIGNAL(triggered()), this, + SLOT(backPlayTriggered())); + connect(m_forwardPlayAction, SIGNAL(triggered()), this, + SLOT(forwardPlayTriggered())); + connect(m_backMarkAction, SIGNAL(triggered()), this, + SLOT(backMarkTriggered())); + connect(m_forwardMarkAction, SIGNAL(triggered()), this, + SLOT(forwardMarkTriggered())); + + // + // Add some expanding space after the play buttons + // + qf = new QFrame(this); + qf->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); + qf->setMinimumWidth(0); + qf->setFrameStyle(QFrame::Plain | QFrame::NoFrame); + qf->setStyleSheet("background-color: transparent"); + addWidget(qf); + + // + // This expanding space will not go to more than 90 pixels. It's to + // "counter balance" the buttons on the other side, so the play control + // buttons stay in the center of the view (roughly). + // + qf = new QFrame(this); + qf->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); + qf->setMinimumWidth(0); + qf->setMaximumWidth(90); + qf->setFrameStyle(QFrame::Plain | QFrame::NoFrame); + qf->setStyleSheet("background-color: transparent"); + addWidget(qf); + + m_playModeAction = addAction(""); + m_playModeAction->setToolTip("Select playback style"); + b = dynamic_cast(widgetForAction(m_playModeAction)); + + switch (static_cast(opts.loopMode)) + { case Session::PlayOnce: b->setIcon(m_playModeOnceIcon); break; @@ -258,143 +269,161 @@ RvBottomViewToolBar::build() default: case Session::PlayLoop: - b->setIcon(m_playModeLoopIcon); - break; + b->setIcon(m_playModeLoopIcon); + break; + } + + b->setProperty("tbstyle", QVariant(QString("left_menu"))); + b->setToolButtonStyle(Qt::ToolButtonIconOnly); + b->setPopupMode(QToolButton::InstantPopup); + + m_playModeMenu = new QMenu(b); + m_playModeMenu->addAction("Playback")->setDisabled(true); + m_playModeMenu->addAction(" Once")->setData( + enumCodeMap(Session::PlayOnce, "commands.setPlayMode(PlayOnce)")); + m_playModeMenu->addAction(" Loop")->setData( + enumCodeMap(Session::PlayLoop, "commands.setPlayMode(PlayLoop)")); + m_playModeMenu->addAction(" PingPong") + ->setData(enumCodeMap(Session::PlayPingPong, + "commands.setPlayMode(PlayPingPong)")); + // m_playModeMenu->addAction(" Loop with Black 0.5 Second"); + // m_playModeMenu->addAction(" Loop with Black 1.0 Second"); + + b->setMenu(m_playModeMenu); + + connect(m_playModeMenu, SIGNAL(triggered(QAction*)), this, + SLOT(playModeMenuTriggered(QAction*))); + connect(m_playModeMenu, SIGNAL(aboutToShow()), this, + SLOT(playModeMenuUpdate())); + + int volumeLevel = + (int)(100.0f * IPCore::SoundTrackIPNode::defaultVolume); + m_audioAction = addAction(""); + m_audioAction->setToolTip("Audio control"); + b = dynamic_cast(widgetForAction(m_audioAction)); + setVolumeLevel(*b, volumeLevel); + b->setProperty("tbstyle", QVariant(QString("right_menu"))); + b->setToolButtonStyle(Qt::ToolButtonIconOnly); + b->setPopupMode(QToolButton::InstantPopup); + m = new QMenu(b); + m->setProperty("menuStyle", QVariant(QString("slim"))); + QAction* audio = m->addAction("Volume"); + audio->setDisabled(true); + QWidgetAction* wa = new QWidgetAction(b); + setVolumeLevel(*wa, volumeLevel); + m_audioSlider = new QSlider(b); + m_audioSlider->setProperty("sliderStyle", QVariant(QString("menu"))); + m_audioSlider->setTickInterval(10); + wa->setDefaultWidget(m_audioSlider); + m->addAction(wa); + m->addSeparator(); + m_muteAction = m->addAction("Mute"); + m_muteAction->setIcon(QIcon(":/images/mute_32x32.png")); + m_muteAction->setCheckable(true); + b->setMenu(m); + m_audioMenu = m; + + connect(m_muteAction, SIGNAL(triggered(bool)), this, + SLOT(audioMuteTriggered(bool))); + connect(m_audioMenu, SIGNAL(aboutToShow()), this, + SLOT(audioMenuTriggered())); + connect(m_audioSlider, SIGNAL(valueChanged(int)), this, + SLOT(audioSliderChanged(int))); + connect(m_audioSlider, SIGNAL(sliderReleased()), this, + SLOT(audioSliderReleased())); + + if (m_session) + setSession(m_session); } - b->setProperty("tbstyle", QVariant(QString("left_menu"))); - b->setToolButtonStyle(Qt::ToolButtonIconOnly); - b->setPopupMode(QToolButton::InstantPopup); - - m_playModeMenu = new QMenu(b); - m_playModeMenu->addAction("Playback")->setDisabled(true); - m_playModeMenu->addAction(" Once") ->setData(enumCodeMap(Session::PlayOnce, "commands.setPlayMode(PlayOnce)")); - m_playModeMenu->addAction(" Loop") ->setData(enumCodeMap(Session::PlayLoop, "commands.setPlayMode(PlayLoop)")); - m_playModeMenu->addAction(" PingPong")->setData(enumCodeMap(Session::PlayPingPong, "commands.setPlayMode(PlayPingPong)")); - // m_playModeMenu->addAction(" Loop with Black 0.5 Second"); - // m_playModeMenu->addAction(" Loop with Black 1.0 Second"); - - b->setMenu(m_playModeMenu); - - connect(m_playModeMenu, SIGNAL(triggered(QAction*)), this, SLOT(playModeMenuTriggered(QAction*))); - connect(m_playModeMenu, SIGNAL(aboutToShow()), this, SLOT(playModeMenuUpdate())); - - int volumeLevel = (int) ( 100.0f * IPCore::SoundTrackIPNode::defaultVolume); - m_audioAction = addAction(""); - m_audioAction->setToolTip("Audio control"); - b = dynamic_cast(widgetForAction(m_audioAction)); - setVolumeLevel(*b, volumeLevel); - b->setProperty("tbstyle", QVariant(QString("right_menu"))); - b->setToolButtonStyle(Qt::ToolButtonIconOnly); - b->setPopupMode(QToolButton::InstantPopup); - m = new QMenu(b); - m->setProperty("menuStyle", QVariant(QString("slim"))); - QAction* audio = m->addAction("Volume"); - audio->setDisabled(true); - QWidgetAction* wa = new QWidgetAction(b); - setVolumeLevel(*wa, volumeLevel); - m_audioSlider = new QSlider(b); - m_audioSlider->setProperty("sliderStyle", QVariant(QString("menu"))); - m_audioSlider->setTickInterval(10); - wa->setDefaultWidget(m_audioSlider); - m->addAction(wa); - m->addSeparator(); - m_muteAction = m->addAction("Mute"); - m_muteAction->setIcon(QIcon(":/images/mute_32x32.png")); - m_muteAction->setCheckable(true); - b->setMenu(m); - m_audioMenu = m; - - connect(m_muteAction, SIGNAL(triggered(bool)), this, SLOT(audioMuteTriggered(bool))); - connect(m_audioMenu, SIGNAL(aboutToShow()), this, SLOT(audioMenuTriggered())); - connect(m_audioSlider, SIGNAL(valueChanged(int)), this, SLOT(audioSliderChanged(int))); - connect(m_audioSlider, SIGNAL(sliderReleased()), this, SLOT(audioSliderReleased())); - - if (m_session) setSession(m_session); -} - - -RvBottomViewToolBar::~RvBottomViewToolBar() {} - -void -RvBottomViewToolBar::setSession(Session* s) -{ - m_session = s; + RvBottomViewToolBar::~RvBottomViewToolBar() {} - if (m_audioMenu) + void RvBottomViewToolBar::setSession(Session* s) { - listenTo(s); + m_session = s; + + if (m_audioMenu) + { + listenTo(s); + } } -} -EventNode::Result -RvBottomViewToolBar::receiveEvent(const Event& event) -{ - if (const GenericStringEvent* gevent = - dynamic_cast(&event)) + EventNode::Result RvBottomViewToolBar::receiveEvent(const Event& event) { - const string& name = event.name(); - const string& contents = gevent->stringContent(); - - if (name == "graph-state-change") + if (const GenericStringEvent* gevent = + dynamic_cast(&event)) { - vector parts; - algorithm::split(parts, contents, is_any_of(string("."))); - IPGraph::PropertyVector props; - - IPNode* node = m_session->graph().findNode(parts.front()); - m_session->graph().findProperty(m_session->currentFrame(), props, contents); - - if (!node) - { - cout << "ERROR: can't find node " << parts.front() << endl; - return EventAcceptAndContinue; - } + const string& name = event.name(); + const string& contents = gevent->stringContent(); - if (dynamic_cast(node)) + if (name == "graph-state-change") { - if (parts.back() == "volume" && parts[parts.size()-2] == "audio") + vector parts; + algorithm::split(parts, contents, is_any_of(string("."))); + IPGraph::PropertyVector props; + + IPNode* node = m_session->graph().findNode(parts.front()); + m_session->graph().findProperty(m_session->currentFrame(), + props, contents); + + if (!node) { - if (FloatProperty* fp = dynamic_cast(props[0])) - { - m_audioSlider->setValue(fp->front() * 99.0); - } + cout << "ERROR: can't find node " << parts.front() << endl; + return EventAcceptAndContinue; } - if (parts.back() == "mute" && parts[parts.size()-2] == "audio") + if (dynamic_cast(node)) { - setVolumeIcon(); + if (parts.back() == "volume" + && parts[parts.size() - 2] == "audio") + { + if (FloatProperty* fp = + dynamic_cast(props[0])) + { + m_audioSlider->setValue(fp->front() * 99.0); + } + } + + if (parts.back() == "mute" + && parts[parts.size() - 2] == "audio") + { + setVolumeIcon(); + } } } - } - else if (name == "play-start") - { - QToolButton* bb = dynamic_cast(widgetForAction(m_backPlayAction)); - QToolButton* bf = dynamic_cast(widgetForAction(m_forwardPlayAction)); - - if (m_session->inc() == -1) + else if (name == "play-start") { - bb->setIcon(QIcon(":/images/control_pause.png")); + QToolButton* bb = dynamic_cast( + widgetForAction(m_backPlayAction)); + QToolButton* bf = dynamic_cast( + widgetForAction(m_forwardPlayAction)); + + if (m_session->inc() == -1) + { + bb->setIcon(QIcon(":/images/control_pause.png")); + } + else + { + bf->setIcon(QIcon(":/images/control_pause.png")); + } } - else + else if (name == "play-stop") { - bf->setIcon(QIcon(":/images/control_pause.png")); - } - } - else if (name == "play-stop") - { - QToolButton* bb = dynamic_cast(widgetForAction(m_backPlayAction)); - QToolButton* bf = dynamic_cast(widgetForAction(m_forwardPlayAction)); + QToolButton* bb = dynamic_cast( + widgetForAction(m_backPlayAction)); + QToolButton* bf = dynamic_cast( + widgetForAction(m_forwardPlayAction)); - bb->setIcon(QIcon(":/images/control_bplay.png")); - bf->setIcon(QIcon(":/images/control_play.png")); - } - else if (name == "play-mode-changed") - { - if (QToolButton*b = dynamic_cast(widgetForAction(m_playModeAction))) + bb->setIcon(QIcon(":/images/control_bplay.png")); + bf->setIcon(QIcon(":/images/control_play.png")); + } + else if (name == "play-mode-changed") { - switch (m_session->playMode()) + if (QToolButton* b = dynamic_cast( + widgetForAction(m_playModeAction))) { + switch (m_session->playMode()) + { case 0: // Session::PlayLoop b->setIcon(m_playModeLoopIcon); break; @@ -404,221 +433,227 @@ RvBottomViewToolBar::receiveEvent(const Event& event) case 2: // Session::PlayPingPong b->setIcon(m_playModePingPongIcon); break; + } } } } - } - return EventAcceptAndContinue; -} -// -// SLOTS -// - -void -RvBottomViewToolBar::smActionTriggered(bool b) -{ - m_session->userGenericEvent("mode-manager-toggle-mode", "session_manager"); -} - -void -RvBottomViewToolBar::paintActionTriggered(bool b) -{ - m_session->userGenericEvent("mode-manager-toggle-mode", "annotate_mode"); -} - -void -RvBottomViewToolBar::infoActionTriggered(bool) -{ - m_session->userGenericEvent("toggle-hud-info-widget", ""); -} - -void -RvBottomViewToolBar::timelineActionTriggered(bool) -{ - m_session->userGenericEvent("toggle-hud-timeline-widget", ""); -} - -void -RvBottomViewToolBar::timelineMagActionTriggered(bool) -{ - m_session->userGenericEvent("toggle-hud-timeline-mag-widget", ""); -} - -void -RvBottomViewToolBar::networkActionTriggered(bool) -{ - RvApp()->showNetworkDialog(); -} - -void -RvBottomViewToolBar::backStepTriggered() -{ - m_session->userGenericEvent("remote-eval", "extra_commands.stepBackward(1)"); -} - -void -RvBottomViewToolBar::forwardStepTriggered() -{ - m_session->userGenericEvent("remote-eval", "extra_commands.stepForward(1)"); -} + return EventAcceptAndContinue; + } -void -RvBottomViewToolBar::backPlayTriggered() -{ // - // Don't configure button state here, since that'll happen when we get the - // resulting events, if the session does in fact begin to play, or stop. + // SLOTS // - if (m_session->isPlaying() && m_session->inc() == -1) + void RvBottomViewToolBar::smActionTriggered(bool b) { - m_session->userGenericEvent("remote-eval", "commands.stop()"); + m_session->userGenericEvent("mode-manager-toggle-mode", + "session_manager"); } - else + + void RvBottomViewToolBar::paintActionTriggered(bool b) { - // If we are going from scrubbing to play; we must turn off scrubbing. - if (m_session->isScrubbingAudio()) m_session->userGenericEvent("remote-eval", "commands.scrubAudio(false); commands.setInc(-1); commands.play();"); - else m_session->userGenericEvent("remote-eval", "commands.setInc(-1); commands.play();"); + m_session->userGenericEvent("mode-manager-toggle-mode", + "annotate_mode"); } -} - -void -RvBottomViewToolBar::forwardPlayTriggered() -{ - // - // Don't configure button state here, since that'll happen when we get the - // resulting events, if the session does in fact begin to play, or stop. - // - if (m_session->isPlaying() && m_session->inc() == 1) + void RvBottomViewToolBar::infoActionTriggered(bool) { - m_session->userGenericEvent("remote-eval", "commands.stop()"); + m_session->userGenericEvent("toggle-hud-info-widget", ""); } - else + + void RvBottomViewToolBar::timelineActionTriggered(bool) { - // If we are going from scrubbing to play; we must turn off scrubbing. - if (m_session->isScrubbingAudio()) m_session->userGenericEvent("remote-eval", "commands.scrubAudio(false); commands.setInc(1); commands.play();"); - else m_session->userGenericEvent("remote-eval", "commands.setInc(1); commands.play();"); + m_session->userGenericEvent("toggle-hud-timeline-widget", ""); } -} -void -RvBottomViewToolBar::backMarkTriggered() -{ - m_session->userGenericEvent("remote-eval", "rvui.previousMarkedFrame()"); -} - -void -RvBottomViewToolBar::forwardMarkTriggered() -{ - m_session->userGenericEvent("remote-eval", "rvui.nextMarkedFrame()"); -} + void RvBottomViewToolBar::timelineMagActionTriggered(bool) + { + m_session->userGenericEvent("toggle-hud-timeline-mag-widget", ""); + } -void -RvBottomViewToolBar::audioSliderReleased() -{ - // - // More mac-like -- hude the "menu" immediately after using - // + void RvBottomViewToolBar::networkActionTriggered(bool) + { + RvApp()->showNetworkDialog(); + } - m_audioMenu->hide(); -} + void RvBottomViewToolBar::backStepTriggered() + { + m_session->userGenericEvent("remote-eval", + "extra_commands.stepBackward(1)"); + } -void -RvBottomViewToolBar::audioSliderChanged(int value) -{ - // turn off mute first - audioMuteTriggered(false); - m_muteAction->setChecked(false); + void RvBottomViewToolBar::forwardStepTriggered() + { + m_session->userGenericEvent("remote-eval", + "extra_commands.stepForward(1)"); + } - float v = float(value) / 99.0; - FloatPropertyEditor editor(m_session->graph(), - m_session->currentFrame(), - "#RVSoundTrack.audio.volume"); - editor.setValue(v); -} + void RvBottomViewToolBar::backPlayTriggered() + { + // + // Don't configure button state here, since that'll happen when we get + // the resulting events, if the session does in fact begin to play, or + // stop. + // + if (m_session->isPlaying() && m_session->inc() == -1) + { + m_session->userGenericEvent("remote-eval", "commands.stop()"); + } + else + { + // If we are going from scrubbing to play; we must turn off + // scrubbing. + if (m_session->isScrubbingAudio()) + m_session->userGenericEvent( + "remote-eval", "commands.scrubAudio(false); " + "commands.setInc(-1); commands.play();"); + else + m_session->userGenericEvent( + "remote-eval", "commands.setInc(-1); commands.play();"); + } + } -void -RvBottomViewToolBar::setVolumeIcon() -{ - if ( QToolButton* b = dynamic_cast(widgetForAction(m_audioAction)) ) + void RvBottomViewToolBar::forwardPlayTriggered() { - IntPropertyEditor editor(m_session->graph(), - m_session->currentFrame(), - "#RVSoundTrack.audio.mute"); + // + // Don't configure button state here, since that'll happen when we get + // the resulting events, if the session does in fact begin to play, or + // stop. + // - if (editor.value()) + if (m_session->isPlaying() && m_session->inc() == 1) { - b->setIcon(m_volumeHighMutedIcon); + m_session->userGenericEvent("remote-eval", "commands.stop()"); } else { - int volumeLevel = m_audioSlider->value(); // 0 - 99; - - setVolumeLevel(*b, volumeLevel); + // If we are going from scrubbing to play; we must turn off + // scrubbing. + if (m_session->isScrubbingAudio()) + m_session->userGenericEvent( + "remote-eval", "commands.scrubAudio(false); " + "commands.setInc(1); commands.play();"); + else + m_session->userGenericEvent( + "remote-eval", "commands.setInc(1); commands.play();"); } } -} -void -RvBottomViewToolBar::audioMuteTriggered(bool v) -{ - IntPropertyEditor editor(m_session->graph(), - m_session->currentFrame(), - "#RVSoundTrack.audio.mute"); - editor.setValue(v ? 1 : 0); + void RvBottomViewToolBar::backMarkTriggered() + { + m_session->userGenericEvent("remote-eval", + "rvui.previousMarkedFrame()"); + } - setVolumeIcon(); -} + void RvBottomViewToolBar::forwardMarkTriggered() + { + m_session->userGenericEvent("remote-eval", "rvui.nextMarkedFrame()"); + } -void -RvBottomViewToolBar::audioMenuTriggered() -{ - FloatPropertyEditor veditor(m_session->graph(), - m_session->currentFrame(), - "#RVSoundTrack.audio.volume"); + void RvBottomViewToolBar::audioSliderReleased() + { + // + // More mac-like -- hude the "menu" immediately after using + // + + m_audioMenu->hide(); + } - IntPropertyEditor meditor(m_session->graph(), - m_session->currentFrame(), - "#RVSoundTrack.audio.mute"); + void RvBottomViewToolBar::audioSliderChanged(int value) + { + // turn off mute first + audioMuteTriggered(false); + m_muteAction->setChecked(false); + + float v = float(value) / 99.0; + FloatPropertyEditor editor(m_session->graph(), + m_session->currentFrame(), + "#RVSoundTrack.audio.volume"); + editor.setValue(v); + } - m_audioSlider->setValue(veditor.value() * 99.0); + void RvBottomViewToolBar::setVolumeIcon() + { + if (QToolButton* b = + dynamic_cast(widgetForAction(m_audioAction))) + { + IntPropertyEditor editor(m_session->graph(), + m_session->currentFrame(), + "#RVSoundTrack.audio.mute"); + + if (editor.value()) + { + b->setIcon(m_volumeHighMutedIcon); + } + else + { + int volumeLevel = m_audioSlider->value(); // 0 - 99; - m_muteAction->setCheckable(true); - m_muteAction->setChecked(meditor.value() == 1); + setVolumeLevel(*b, volumeLevel); + } + } + } - setVolumeIcon(); -} + void RvBottomViewToolBar::audioMuteTriggered(bool v) + { + IntPropertyEditor editor(m_session->graph(), m_session->currentFrame(), + "#RVSoundTrack.audio.mute"); + editor.setValue(v ? 1 : 0); -void -RvBottomViewToolBar::playModeMenuUpdate() -{ - if (!m_session) return; + setVolumeIcon(); + } - for (int i = 0; i < m_playModeMenu->actions().size(); ++i) + void RvBottomViewToolBar::audioMenuTriggered() { - QAction* a = m_playModeMenu->actions()[i]; + FloatPropertyEditor veditor(m_session->graph(), + m_session->currentFrame(), + "#RVSoundTrack.audio.volume"); - if (!a->isEnabled()) continue; + IntPropertyEditor meditor(m_session->graph(), m_session->currentFrame(), + "#RVSoundTrack.audio.mute"); - a->setCheckable(true); - a->setChecked(a->data().toMap()["enum"].toInt() == m_session->playMode()); + m_audioSlider->setValue(veditor.value() * 99.0); + + m_muteAction->setCheckable(true); + m_muteAction->setChecked(meditor.value() == 1); + + setVolumeIcon(); } -} -void -RvBottomViewToolBar::playModeMenuTriggered(QAction* a) -{ - if (!m_session) return; + void RvBottomViewToolBar::playModeMenuUpdate() + { + if (!m_session) + return; + + for (int i = 0; i < m_playModeMenu->actions().size(); ++i) + { + QAction* a = m_playModeMenu->actions()[i]; - m_session->userGenericEvent("remote-eval", UTF8::qconvert(a->data().toMap()["code"].toString())); + if (!a->isEnabled()) + continue; + + a->setCheckable(true); + a->setChecked(a->data().toMap()["enum"].toInt() + == m_session->playMode()); + } + } - if (QToolButton*b = dynamic_cast(widgetForAction(m_playModeAction))) + void RvBottomViewToolBar::playModeMenuTriggered(QAction* a) { - switch (m_session->playMode()) + if (!m_session) + return; + + m_session->userGenericEvent( + "remote-eval", + UTF8::qconvert(a->data().toMap()["code"].toString())); + + if (QToolButton* b = + dynamic_cast(widgetForAction(m_playModeAction))) { + switch (m_session->playMode()) + { case Session::PlayOnce: b->setIcon(m_playModeOnceIcon); break; @@ -630,9 +665,8 @@ RvBottomViewToolBar::playModeMenuTriggered(QAction* a) case Session::PlayPingPong: b->setIcon(m_playModePingPongIcon); break; + } } } -} - -} // +} // namespace Rv diff --git a/src/lib/app/RvCommon/RvCommon/CGDesktopVideoDevice.h b/src/lib/app/RvCommon/RvCommon/CGDesktopVideoDevice.h index 78a8fccd5..4c9d4017e 100644 --- a/src/lib/app/RvCommon/RvCommon/CGDesktopVideoDevice.h +++ b/src/lib/app/RvCommon/RvCommon/CGDesktopVideoDevice.h @@ -1,9 +1,9 @@ // -// Copyright (c) 2011 Tweak Software. +// Copyright (c) 2011 Tweak Software. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// // #ifndef __RvCommon__CGDesktopVideoDevice__h__ #define __RvCommon__CGDesktopVideoDevice__h__ @@ -14,69 +14,68 @@ #include #include -namespace Rv { +namespace Rv +{ -// -// CGDesktopVideoDevice -// -// OS X only: Wraps each CGDirectDisplayID as a DesktopVideoDevice -// + // + // CGDesktopVideoDevice + // + // OS X only: Wraps each CGDirectDisplayID as a DesktopVideoDevice + // -class CGDesktopVideoDevice : public DesktopVideoDevice -{ - public: - typedef std::map IOModeMap; + class CGDesktopVideoDevice : public DesktopVideoDevice + { + public: + typedef std::map IOModeMap; - CGDesktopVideoDevice(TwkApp::VideoModule*, - const std::string& name, - CGDirectDisplayID cgScreen, - int qtScreen, - const QTGLVideoDevice* share); + CGDesktopVideoDevice(TwkApp::VideoModule*, const std::string& name, + CGDirectDisplayID cgScreen, int qtScreen, + const QTGLVideoDevice* share); - virtual ~CGDesktopVideoDevice(); + virtual ~CGDesktopVideoDevice(); - virtual void makeCurrent() const; + virtual void makeCurrent() const; - // - // VideoDevice API - // + // + // VideoDevice API + // - virtual Resolution resolution() const; - virtual Offset offset() const; - virtual Timing timing() const; - virtual VideoFormat format() const; + virtual Resolution resolution() const; + virtual Offset offset() const; + virtual Timing timing() const; + virtual VideoFormat format() const; - virtual size_t width() const; - virtual size_t height() const; - virtual float pixelScale() const; + virtual size_t width() const; + virtual size_t height() const; + virtual float pixelScale() const; - virtual void open(const StringVector&); - virtual void close(); - virtual bool isOpen() const; + virtual void open(const StringVector&); + virtual void close(); + virtual bool isOpen() const; - virtual void syncBuffers() const; - virtual bool isSyncing() const; + virtual void syncBuffers() const; + virtual bool isSyncing() const; - virtual int qtScreen() const { return m_qtScreen; } + virtual int qtScreen() const { return m_qtScreen; } - const CGDirectDisplayID cgDisplay() const { return m_cgScreen; } + const CGDirectDisplayID cgDisplay() const { return m_cgScreen; } - virtual ColorProfile colorProfile() const; + virtual ColorProfile colorProfile() const; - void createFormats(); + void createFormats(); - private: - CGDirectDisplayID m_cgScreen; - IOModeMap m_ioModeMap; - int m_qtScreen; - CGLContextObj m_context; - CGLPixelFormatObj m_pfo; - GLint m_npfo; - CFArrayRef m_modes; - CGDisplayModeRef m_savedMode; - mutable ColorProfile m_colorProfile; -}; + private: + CGDirectDisplayID m_cgScreen; + IOModeMap m_ioModeMap; + int m_qtScreen; + CGLContextObj m_context; + CGLPixelFormatObj m_pfo; + GLint m_npfo; + CFArrayRef m_modes; + CGDisplayModeRef m_savedMode; + mutable ColorProfile m_colorProfile; + }; -} // Rv +} // namespace Rv #endif // __RvCommon__CGDesktopVideoDevice__h__ diff --git a/src/lib/app/RvCommon/RvCommon/DesktopVideoDevice.h b/src/lib/app/RvCommon/RvCommon/DesktopVideoDevice.h index 366a156a5..c0dc38166 100644 --- a/src/lib/app/RvCommon/RvCommon/DesktopVideoDevice.h +++ b/src/lib/app/RvCommon/RvCommon/DesktopVideoDevice.h @@ -1,10 +1,10 @@ // -// Copyright (c) 2011 Tweak Software. +// Copyright (c) 2011 Tweak Software. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// // #ifndef __RvCommon__DesktopVideoDevice__h__ #define __RvCommon__DesktopVideoDevice__h__ @@ -17,191 +17,203 @@ #include #include -namespace Rv { - -// -// DesktopVideoDevice -// -// This is the base class for desktop video devices. Currently there -// are three: -// -// QTDesktopVideoDevice: generic Qt only device uses QScreen -// CGDesktopVideoDevice: OS X CoreGraphics video device -// -// The QTDesktopVideoDevice is the fallback on windows and linux when -// the NVIDIA driver is not present. On the mac it always uses -// CGDesktopVideoDevice. -// -// This class implements the GL guts shared by all of the above and -// holds on to the static data structs for formats, etc. -// - -class DesktopVideoDevice : public TwkGLF::GLBindableVideoDevice +namespace Rv { - public: // - // Types + // DesktopVideoDevice // - - typedef std::map FBOMap; - typedef boost::mutex Mutex; - typedef boost::mutex::scoped_lock ScopedLock; - - enum DesktopStereoMode - { - Mono, - QuadBufferStereo, - TopBottomStereo, - SideBySideStereo, - ScanlineStereo, - CheckerStereo, - FramePacked - }; - - enum GLSyncMode - { - NoSync, - VSync - }; - - struct DesktopDataFormat : public TwkApp::VideoDevice::DataFormat - { - DesktopDataFormat(const std::string& desc, DesktopStereoMode fms) - : DataFormat(desc), stereoMode(fms) {} - - DesktopStereoMode stereoMode; - }; - - struct DesktopVideoFormat : public TwkApp::VideoDevice::VideoFormat - { - DesktopVideoFormat(size_t w, size_t h, float pa, float ps, - float hertz, - const std::string& desc, - void* xtradata=0) - : TwkApp::VideoDevice::VideoFormat(w, h, pa, ps, hertz, desc), - data(xtradata) {} - - DesktopVideoFormat(const TwkApp::VideoDevice::VideoFormat& v, void* xtradata=0) - : TwkApp::VideoDevice::VideoFormat(v.width, - v.height, - v.pixelAspect, - v.pixelScale, - v.hz, - v.description), - - data(xtradata) {} - - void* data; - }; - - typedef std::vector DesktopDataFormats; - typedef std::vector DesktopVideoFormats; - + // This is the base class for desktop video devices. Currently there + // are three: // + // QTDesktopVideoDevice: generic Qt only device uses QScreen + // CGDesktopVideoDevice: OS X CoreGraphics video device // + // The QTDesktopVideoDevice is the fallback on windows and linux when + // the NVIDIA driver is not present. On the mac it always uses + // CGDesktopVideoDevice. // - - DesktopVideoDevice(TwkApp::VideoModule*, - const std::string& name, - const QTGLVideoDevice* share); - - virtual ~DesktopVideoDevice(); - - virtual void redraw() const; - virtual void redrawImmediately() const; - virtual int qtScreen() const { return -1; } - - const QTGLVideoDevice* shareDevice() const { return m_share; } - void setViewDevice(TwkGLF::GLVideoDevice* d) { m_viewDevice = d; } - void setShareDevice(QTGLVideoDevice* d) { m_share = d; } - - // - // These can differ from the usual output versions in the case of - // frame packed. + // This class implements the GL guts shared by all of the above and + // holds on to the static data structs for formats, etc. // - virtual Resolution internalResolution() const; - virtual VideoFormat internalFormat() const; - virtual size_t internalHeight() const; - - // - // This will try and lock the sync mutex - // - - virtual void blockUntilSyncComplete() const; - - // - // GLBindableVideoDevice API - // - - virtual bool isStereo() const; - virtual bool isDualStereo() const; + class DesktopVideoDevice : public TwkGLF::GLBindableVideoDevice + { + public: + // + // Types + // + + typedef std::map FBOMap; + typedef boost::mutex Mutex; + typedef boost::mutex::scoped_lock ScopedLock; + + enum DesktopStereoMode + { + Mono, + QuadBufferStereo, + TopBottomStereo, + SideBySideStereo, + ScanlineStereo, + CheckerStereo, + FramePacked + }; + + enum GLSyncMode + { + NoSync, + VSync + }; + + struct DesktopDataFormat : public TwkApp::VideoDevice::DataFormat + { + DesktopDataFormat(const std::string& desc, DesktopStereoMode fms) + : DataFormat(desc) + , stereoMode(fms) + { + } + + DesktopStereoMode stereoMode; + }; + + struct DesktopVideoFormat : public TwkApp::VideoDevice::VideoFormat + { + DesktopVideoFormat(size_t w, size_t h, float pa, float ps, + float hertz, const std::string& desc, + void* xtradata = 0) + : TwkApp::VideoDevice::VideoFormat(w, h, pa, ps, hertz, desc) + , data(xtradata) + { + } + + DesktopVideoFormat(const TwkApp::VideoDevice::VideoFormat& v, + void* xtradata = 0) + : TwkApp::VideoDevice::VideoFormat(v.width, v.height, + v.pixelAspect, v.pixelScale, + v.hz, v.description) + , + + data(xtradata) + { + } + + void* data; + }; + + typedef std::vector DesktopDataFormats; + typedef std::vector DesktopVideoFormats; + + // + // + // + + DesktopVideoDevice(TwkApp::VideoModule*, const std::string& name, + const QTGLVideoDevice* share); + + virtual ~DesktopVideoDevice(); + + virtual void redraw() const; + virtual void redrawImmediately() const; + + virtual int qtScreen() const { return -1; } + + const QTGLVideoDevice* shareDevice() const { return m_share; } + + void setViewDevice(TwkGLF::GLVideoDevice* d) { m_viewDevice = d; } + + void setShareDevice(QTGLVideoDevice* d) { m_share = d; } + + // + // These can differ from the usual output versions in the case of + // frame packed. + // + + virtual Resolution internalResolution() const; + virtual VideoFormat internalFormat() const; + virtual size_t internalHeight() const; + + // + // This will try and lock the sync mutex + // + + virtual void blockUntilSyncComplete() const; + + // + // GLBindableVideoDevice API + // + + virtual bool isStereo() const; + virtual bool isDualStereo() const; + + // virtual bool willBlockOnTransfer() const; + virtual void bind(const TwkGLF::GLVideoDevice*) const; + virtual void bind2(const TwkGLF::GLVideoDevice*, + const TwkGLF::GLVideoDevice*) const; + virtual void transfer(const TwkGLF::GLFBO*) const; + virtual void transfer2(const TwkGLF::GLFBO*, + const TwkGLF::GLFBO*) const; + + virtual void unbind() const; + + virtual void clearCaches() const {} + + // + // Configurations + // + + virtual size_t numVideoFormats() const; + virtual VideoFormat videoFormatAtIndex(size_t) const; + virtual VideoFormat videoFormatFromData(void*) const; + virtual void setVideoFormat(size_t); + virtual size_t currentVideoFormat() const; + + virtual size_t numDataFormats() const; + virtual DataFormat dataFormatAtIndex(size_t) const; + virtual void setDataFormat(size_t); + virtual size_t currentDataFormat() const; + + virtual size_t numSyncModes() const; + virtual SyncMode syncModeAtIndex(size_t) const; + virtual void setSyncMode(size_t); + virtual size_t currentSyncMode() const; + + virtual size_t numSyncSources() const; + virtual SyncSource syncSourceAtIndex(size_t) const; + virtual void setSyncSource(size_t); + virtual size_t currentSyncSource() const; + + protected: + void addDefaultDataFormats(size_t bits = 8); + void sortVideoFormatsByWidth(); - //virtual bool willBlockOnTransfer() const; - virtual void bind(const TwkGLF::GLVideoDevice*) const; - virtual void bind2(const TwkGLF::GLVideoDevice*, const TwkGLF::GLVideoDevice*) const; - virtual void transfer(const TwkGLF::GLFBO*) const; - virtual void transfer2(const TwkGLF::GLFBO*, const TwkGLF::GLFBO*) const; + void setupModelviewAndProjection(float w, float h, + TwkGLF::GLPipeline*) const; + void fillWithTexture(const TwkGLF::GLFBO*, size_t, float, float, + TwkGLF::GLPipeline*) const; + void fillWithTexture2(const TwkGLF::GLFBO*, const TwkGLF::GLFBO*, + size_t, float, float, TwkGLF::GLPipeline*) const; - virtual void unbind() const; + bool maybeFramePacked(const TwkApp::VideoDevice::VideoFormat&) const; - virtual void clearCaches() const {} + private: + void addDataFormatAtDepth(size_t depth, DesktopStereoMode m); - // - // Configurations - // + protected: + const QTGLVideoDevice* m_share; + const TwkGLF::GLVideoDevice* m_viewDevice; + DesktopStereoMode m_stereoMode; + mutable FBOMap m_fboMap; + TwkGLF::GLState* m_glGlobalState; + DesktopVideoFormats m_videoFormats; + DesktopDataFormats m_dataFormats; + size_t m_videoFormatIndex; + size_t m_dataFormatIndex; + bool m_vsync; + mutable bool m_syncing; + mutable Mutex m_mutex; + mutable Mutex m_syncTestMutex; + }; - virtual size_t numVideoFormats() const; - virtual VideoFormat videoFormatAtIndex(size_t) const; - virtual VideoFormat videoFormatFromData(void*) const; - virtual void setVideoFormat(size_t); - virtual size_t currentVideoFormat() const; - - virtual size_t numDataFormats() const; - virtual DataFormat dataFormatAtIndex(size_t) const; - virtual void setDataFormat(size_t); - virtual size_t currentDataFormat() const; - - virtual size_t numSyncModes() const; - virtual SyncMode syncModeAtIndex(size_t) const; - virtual void setSyncMode(size_t); - virtual size_t currentSyncMode() const; - - virtual size_t numSyncSources() const; - virtual SyncSource syncSourceAtIndex(size_t) const; - virtual void setSyncSource(size_t); - virtual size_t currentSyncSource() const; - - protected: - void addDefaultDataFormats(size_t bits=8); - void sortVideoFormatsByWidth(); - - void setupModelviewAndProjection(float w, float h, TwkGLF::GLPipeline*) const; - void fillWithTexture(const TwkGLF::GLFBO*, size_t, float, float, TwkGLF::GLPipeline*) const; - void fillWithTexture2(const TwkGLF::GLFBO*, const TwkGLF::GLFBO*, size_t, float, float, TwkGLF::GLPipeline*) const; - - bool maybeFramePacked(const TwkApp::VideoDevice::VideoFormat&) const; - - private: - void addDataFormatAtDepth(size_t depth, DesktopStereoMode m); - - protected: - const QTGLVideoDevice* m_share; - const TwkGLF::GLVideoDevice* m_viewDevice; - DesktopStereoMode m_stereoMode; - mutable FBOMap m_fboMap; - TwkGLF::GLState* m_glGlobalState; - DesktopVideoFormats m_videoFormats; - DesktopDataFormats m_dataFormats; - size_t m_videoFormatIndex; - size_t m_dataFormatIndex; - bool m_vsync; - mutable bool m_syncing; - mutable Mutex m_mutex; - mutable Mutex m_syncTestMutex; -}; - -} // Rv +} // namespace Rv #endif // __RvCommon__DesktopVideoDevice__h__ diff --git a/src/lib/app/RvCommon/RvCommon/DesktopVideoModule.h b/src/lib/app/RvCommon/RvCommon/DesktopVideoModule.h index 7052b6172..8bdd95774 100644 --- a/src/lib/app/RvCommon/RvCommon/DesktopVideoModule.h +++ b/src/lib/app/RvCommon/RvCommon/DesktopVideoModule.h @@ -1,9 +1,9 @@ // -// Copyright (c) 2011 Tweak Software. +// Copyright (c) 2011 Tweak Software. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// // #ifndef __RvCommon__DesktopVideoModule__h__ #define __RvCommon__DesktopVideoModule__h__ @@ -11,40 +11,41 @@ #include #include -namespace Rv { +namespace Rv +{ -// -// class DesktopVideoModule -// -// This instantiates whichever video devices it can based on the -// platform and availability. -// -// DARWIN: uses CGDesktopVideoDevice -// LINUX: uses QTDesktopVideoDevice -// WINDOWS: uses QTDesktopVideoDevice -// + // + // class DesktopVideoModule + // + // This instantiates whichever video devices it can based on the + // platform and availability. + // + // DARWIN: uses CGDesktopVideoDevice + // LINUX: uses QTDesktopVideoDevice + // WINDOWS: uses QTDesktopVideoDevice + // -class QTGLVideoDevice; + class QTGLVideoDevice; -class DesktopVideoModule : public TwkApp::VideoModule -{ - public: - DesktopVideoModule(NativeDisplayPtr np, QTGLVideoDevice* shareDevice); - virtual ~DesktopVideoModule(); + class DesktopVideoModule : public TwkApp::VideoModule + { + public: + DesktopVideoModule(NativeDisplayPtr np, QTGLVideoDevice* shareDevice); + virtual ~DesktopVideoModule(); - virtual std::string name() const; - virtual void open(); - virtual void close(); - virtual bool isOpen() const; + virtual std::string name() const; + virtual void open(); + virtual void close(); + virtual bool isOpen() const; - // - // If possible, derive the appropriate refresh rate or devicefrom - // the absolute position of the window on the desktop. - // + // + // If possible, derive the appropriate refresh rate or devicefrom + // the absolute position of the window on the desktop. + // - virtual TwkApp::VideoDevice* deviceFromPosition (int x, int y) const; -}; + virtual TwkApp::VideoDevice* deviceFromPosition(int x, int y) const; + }; -} // Rv +} // namespace Rv #endif // __RvCommon__DesktopVideoModule__h__ diff --git a/src/lib/app/RvCommon/RvCommon/DisplayLink.h b/src/lib/app/RvCommon/RvCommon/DisplayLink.h index 51b139c3e..e5cc9749b 100644 --- a/src/lib/app/RvCommon/RvCommon/DisplayLink.h +++ b/src/lib/app/RvCommon/RvCommon/DisplayLink.h @@ -10,41 +10,43 @@ #include #include -namespace IPCore { -class Session; +namespace IPCore +{ + class Session; } -namespace Rv { +namespace Rv +{ -class CGDesktopVideoDevice; + class CGDesktopVideoDevice; -class DisplayLink : public QObject -{ - Q_OBJECT -public: - explicit DisplayLink(QObject *parent = 0); - virtual ~DisplayLink(); - bool isValid() const; - bool isActive() const; - -public Q_SLOTS: - void start(IPCore::Session*, const CGDesktopVideoDevice*); - void stop(); - -Q_SIGNALS: - void tick(const CVTimeStamp &ts); - -public: - void displayLinkEvent(const CVTimeStamp*, const CVTimeStamp *); - -private: - CVDisplayLinkRef m_displayLink; - bool m_isActive; - IPCore::Session* m_session; - size_t m_serial; -}; + class DisplayLink : public QObject + { + Q_OBJECT + public: + explicit DisplayLink(QObject* parent = 0); + virtual ~DisplayLink(); + bool isValid() const; + bool isActive() const; -} + public Q_SLOTS: + void start(IPCore::Session*, const CGDesktopVideoDevice*); + void stop(); + + Q_SIGNALS: + void tick(const CVTimeStamp& ts); + + public: + void displayLinkEvent(const CVTimeStamp*, const CVTimeStamp*); + + private: + CVDisplayLinkRef m_displayLink; + bool m_isActive; + IPCore::Session* m_session; + size_t m_serial; + }; + +} // namespace Rv #endif // DISPLAYLINK_H diff --git a/src/lib/app/RvCommon/RvCommon/FileTypeTraits.h b/src/lib/app/RvCommon/RvCommon/FileTypeTraits.h index 50783fd4f..39aacfbec 100644 --- a/src/lib/app/RvCommon/RvCommon/FileTypeTraits.h +++ b/src/lib/app/RvCommon/RvCommon/FileTypeTraits.h @@ -1,9 +1,9 @@ // -// Copyright (c) 2008 Tweak Software. +// Copyright (c) 2008 Tweak Software. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// // #ifndef __RvCommon__FileTypeTraits__h__ #define __RvCommon__FileTypeTraits__h__ @@ -12,102 +12,104 @@ #include #include -namespace Rv { - -/// Used by RvFileDialog and MediaDirModel to inspect files, get icons - -/// -/// FileTypeTraits principally takes the place of the usual list of -/// regular expressions typically passed to a file dialog to express -/// the accepted file types. In addition, it supplies icons, preview -/// images, and file attribtues in a content aware manner. For -/// example, known image file headers are read and their contents -/// displayed in the preview. -/// - -class FileTypeTraits +namespace Rv { - public: - FileTypeTraits(); - virtual ~FileTypeTraits(); - - /// - /// Make a new FileTypeTraits object of the same type as the one - /// being called. - /// - - virtual FileTypeTraits* copyTraits() const; - - /// - /// Return a human readable list of file types - /// - - virtual QStringList typeDescriptions(); - - /// - /// Return true if the passed in filename is "known" by the type - /// description corresponding to the index (which is relative to - /// the list returned by typeDescriptions). - /// - virtual bool isKnown(size_t index, const QString&) const; + /// Used by RvFileDialog and MediaDirModel to inspect files, get icons /// - /// Return attributes of file. The string list alternates between - /// the attribute name and value (as a string). So its length - /// should be even. + /// FileTypeTraits principally takes the place of the usual list of + /// regular expressions typically passed to a file dialog to express + /// the accepted file types. In addition, it supplies icons, preview + /// images, and file attribtues in a content aware manner. For + /// example, known image file headers are read and their contents + /// displayed in the preview. /// - virtual QStringList fileAttributes(const QString&) const; - - /// - /// Return a suitable file icon for the passed in filename or file - /// info. If you know the type of the file, pass it in. - /// - - QIcon fileIcon(const QString &, - QFileIconProvider::IconType knownType = QFileIconProvider::Trashcan) const; - virtual QIcon fileInfoIcon( - const QFileInfo &, - QFileIconProvider::IconType knownType = QFileIconProvider::Trashcan) const; - - /// - /// If a preview image is available for the file indicate that and - /// possible produce it. - /// - - virtual bool hasImage(const QString&) const; - virtual QImage fileImage(const QString&) const; - - /// - /// Icon Mode control whether QIconProvider is used or - /// not. Looking up icons can be very time consuming on some - /// platforms. - /// - - enum IconMode + class FileTypeTraits { - SystemIcons, - GenericIcons, - NoIcons + public: + FileTypeTraits(); + virtual ~FileTypeTraits(); + + /// + /// Make a new FileTypeTraits object of the same type as the one + /// being called. + /// + + virtual FileTypeTraits* copyTraits() const; + + /// + /// Return a human readable list of file types + /// + + virtual QStringList typeDescriptions(); + + /// + /// Return true if the passed in filename is "known" by the type + /// description corresponding to the index (which is relative to + /// the list returned by typeDescriptions). + /// + + virtual bool isKnown(size_t index, const QString&) const; + + /// + /// Return attributes of file. The string list alternates between + /// the attribute name and value (as a string). So its length + /// should be even. + /// + + virtual QStringList fileAttributes(const QString&) const; + + /// + /// Return a suitable file icon for the passed in filename or file + /// info. If you know the type of the file, pass it in. + /// + + QIcon fileIcon(const QString&, QFileIconProvider::IconType knownType = + QFileIconProvider::Trashcan) const; + virtual QIcon fileInfoIcon(const QFileInfo&, + QFileIconProvider::IconType knownType = + QFileIconProvider::Trashcan) const; + + /// + /// If a preview image is available for the file indicate that and + /// possible produce it. + /// + + virtual bool hasImage(const QString&) const; + virtual QImage fileImage(const QString&) const; + + /// + /// Icon Mode control whether QIconProvider is used or + /// not. Looking up icons can be very time consuming on some + /// platforms. + /// + + enum IconMode + { + SystemIcons, + GenericIcons, + NoIcons + }; + + void setIconMode(IconMode); + IconMode iconMode() const; + + /// + /// Returns true if the traits are the sames, false otherwise + /// Optimization - Optional + /// Note: This is exclusively used for optimization purposes and is + /// therefore optional. It is perfectly valid to return false all the + /// time. In which case the new traits will be considered different from + /// the current ones. + /// + virtual bool sameAs(const FileTypeTraits*) const { return false; } + + private: + IconMode m_iconMode; }; - void setIconMode(IconMode); - IconMode iconMode() const; - - /// - /// Returns true if the traits are the sames, false otherwise - /// Optimization - Optional - /// Note: This is exclusively used for optimization purposes and is therefore optional. - /// It is perfectly valid to return false all the time. - /// In which case the new traits will be considered different from the current ones. - /// - virtual bool sameAs(const FileTypeTraits*) const { return false; } - - private: - IconMode m_iconMode; -}; - -} // Rv +} // namespace Rv #endif // __RvCommon__FileTypeTraits__h__ diff --git a/src/lib/app/RvCommon/RvCommon/GLSLSyntaxHighlighter.h b/src/lib/app/RvCommon/RvCommon/GLSLSyntaxHighlighter.h index aef4c24e2..21c35972d 100644 --- a/src/lib/app/RvCommon/RvCommon/GLSLSyntaxHighlighter.h +++ b/src/lib/app/RvCommon/RvCommon/GLSLSyntaxHighlighter.h @@ -1,9 +1,9 @@ // -// Copyright (c) 2013 Tweak Software. +// Copyright (c) 2013 Tweak Software. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// // #ifndef __RvCommon__GLSLSyntaxHighlighter__h__ #define __RvCommon__GLSLSyntaxHighlighter__h__ @@ -14,40 +14,39 @@ class QTextDocument; -namespace Rv { - -class GLSLSyntaxHighlighter : public QSyntaxHighlighter +namespace Rv { - Q_OBJECT - - public: - struct HighlightingRule + class GLSLSyntaxHighlighter : public QSyntaxHighlighter { - QRegExp pattern; - QTextCharFormat format; + Q_OBJECT + + public: + struct HighlightingRule + { + QRegExp pattern; + QTextCharFormat format; + }; + + GLSLSyntaxHighlighter(QTextDocument* parent = 0); + + protected: + void highlightBlock(const QString& text); + + private: + QVector m_highlightingRules; + QRegExp m_commentStartExpression; + QRegExp m_commentEndExpression; + QTextCharFormat m_typeFormat; + QTextCharFormat m_keywordFormat; + QTextCharFormat m_builtInFormat; + QTextCharFormat m_imageFormat; + QTextCharFormat m_commentFormat; + QTextCharFormat m_quotationFormat; + QTextCharFormat m_functionFormat; + QTextCharFormat m_preProcessorFormat; }; - GLSLSyntaxHighlighter(QTextDocument *parent = 0); - - protected: - void highlightBlock(const QString &text); - - private: - - QVector m_highlightingRules; - QRegExp m_commentStartExpression; - QRegExp m_commentEndExpression; - QTextCharFormat m_typeFormat; - QTextCharFormat m_keywordFormat; - QTextCharFormat m_builtInFormat; - QTextCharFormat m_imageFormat; - QTextCharFormat m_commentFormat; - QTextCharFormat m_quotationFormat; - QTextCharFormat m_functionFormat; - QTextCharFormat m_preProcessorFormat; -}; - -} // Rv +} // namespace Rv #endif // __RvCommon__GLSLSyntaxHighlighter__h__ diff --git a/src/lib/app/RvCommon/RvCommon/GLView.h b/src/lib/app/RvCommon/RvCommon/GLView.h index d74952ec5..cf2e65c3d 100644 --- a/src/lib/app/RvCommon/RvCommon/GLView.h +++ b/src/lib/app/RvCommon/RvCommon/GLView.h @@ -1,9 +1,9 @@ //****************************************************************************** -// Copyright (c) 2007 Tweak Inc. +// Copyright (c) 2007 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #ifndef __rv_qt__GLView__h__ #define __rv_qt__GLView__h__ @@ -14,93 +14,84 @@ #include #include -namespace Rv { -class RvDocument; -class QTFrameBuffer; -class QTGLVideoDevice; - -class GLView : public QGLWidget +namespace Rv { - Q_OBJECT - -public: - typedef TwkUtil::Timer Timer; - - GLView(QWidget* parent, - const QGLWidget* share, - RvDocument* doc, - bool stereo=false, - bool vsync=true, - bool doubleBuffer=true, - int red=0, - int green=0, - int blue=0, - int alpha=0, - bool noResize=true); - ~GLView(); - - static QGLFormat rvGLFormat(bool stereo=false, - bool vsync=true, - bool doubleBuffer=true, - int red=8, - int green=8, - int blue=8, - int alpha=8); - - void absolutePosition(int& x, int& y) const; - - //QTFrameBuffer* frameBuffer() const { return m_frameBuffer; } - QTGLVideoDevice* videoDevice() const { return m_videoDevice; } - - void stopProcessingEvents(); - - virtual bool event(QEvent*); - virtual bool eventFilter(QObject *object, QEvent *event); - - bool firstPaintCompleted() const { return m_firstPaintCompleted; }; - - void setContentSize(int w, int h) { m_csize = QSize(w,h); } - void setMinimumContentSize(int w, int h) { m_msize = QSize(w,h); } - - virtual QSize sizeHint() const; - virtual QSize minimumSizeHint() const; - - void* syncClosure() const { return m_syncThreadData; } - -public slots: - void eventProcessingTimeout(); - -protected: - void initializeGL(); - void resizeGL(int w, int h); - void paintGL(); - void swapBuffersNoSync(); - -private: - RvDocument* m_doc; - //QTFrameBuffer* m_frameBuffer; - boost::thread m_swapThread; - QTGLVideoDevice* m_videoDevice; - unsigned int m_lastKey; - QEvent::Type m_lastKeyType; - Timer m_activityTimer; - Timer m_renderTimer; - QTimer m_eventProcessingTimer; - bool m_userActive; - size_t m_renderCount; - Timer m_activationTimer; - bool m_firstPaintCompleted; - QSize m_csize; - QSize m_msize; - int m_red; - int m_green; - int m_blue; - int m_alpha; - bool m_postFirstNonEmptyRender; - bool m_stopProcessingEvents; - void* m_syncThreadData; -}; - -} // Rv + class RvDocument; + class QTFrameBuffer; + class QTGLVideoDevice; + + class GLView : public QGLWidget + { + Q_OBJECT + + public: + typedef TwkUtil::Timer Timer; + + GLView(QWidget* parent, const QGLWidget* share, RvDocument* doc, + bool stereo = false, bool vsync = true, bool doubleBuffer = true, + int red = 0, int green = 0, int blue = 0, int alpha = 0, + bool noResize = true); + ~GLView(); + + static QGLFormat rvGLFormat(bool stereo = false, bool vsync = true, + bool doubleBuffer = true, int red = 8, + int green = 8, int blue = 8, int alpha = 8); + + void absolutePosition(int& x, int& y) const; + + // QTFrameBuffer* frameBuffer() const { return m_frameBuffer; } + QTGLVideoDevice* videoDevice() const { return m_videoDevice; } + + void stopProcessingEvents(); + + virtual bool event(QEvent*); + virtual bool eventFilter(QObject* object, QEvent* event); + + bool firstPaintCompleted() const { return m_firstPaintCompleted; }; + + void setContentSize(int w, int h) { m_csize = QSize(w, h); } + + void setMinimumContentSize(int w, int h) { m_msize = QSize(w, h); } + + virtual QSize sizeHint() const; + virtual QSize minimumSizeHint() const; + + void* syncClosure() const { return m_syncThreadData; } + + public slots: + void eventProcessingTimeout(); + + protected: + void initializeGL(); + void resizeGL(int w, int h); + void paintGL(); + void swapBuffersNoSync(); + + private: + RvDocument* m_doc; + // QTFrameBuffer* m_frameBuffer; + boost::thread m_swapThread; + QTGLVideoDevice* m_videoDevice; + unsigned int m_lastKey; + QEvent::Type m_lastKeyType; + Timer m_activityTimer; + Timer m_renderTimer; + QTimer m_eventProcessingTimer; + bool m_userActive; + size_t m_renderCount; + Timer m_activationTimer; + bool m_firstPaintCompleted; + QSize m_csize; + QSize m_msize; + int m_red; + int m_green; + int m_blue; + int m_alpha; + bool m_postFirstNonEmptyRender; + bool m_stopProcessingEvents; + void* m_syncThreadData; + }; + +} // namespace Rv #endif // __rv-qt__GLView__h__ diff --git a/src/lib/app/RvCommon/RvCommon/InitGL.h b/src/lib/app/RvCommon/RvCommon/InitGL.h index 3d2f4d588..9044d10a3 100644 --- a/src/lib/app/RvCommon/RvCommon/InitGL.h +++ b/src/lib/app/RvCommon/RvCommon/InitGL.h @@ -1,16 +1,17 @@ //****************************************************************************** -// Copyright (c) 2013 Tweak Software. +// Copyright (c) 2013 Tweak Software. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #ifndef __RvCommon__initGL__h__ #define __RvCommon__initGL__h__ -namespace Rv { +namespace Rv +{ -void initializeGLExtensions(); + void initializeGLExtensions(); } diff --git a/src/lib/app/RvCommon/RvCommon/MediaDirModel.h b/src/lib/app/RvCommon/RvCommon/MediaDirModel.h index 5c0b918da..1524ae2b8 100644 --- a/src/lib/app/RvCommon/RvCommon/MediaDirModel.h +++ b/src/lib/app/RvCommon/RvCommon/MediaDirModel.h @@ -1,94 +1,99 @@ // -// Copyright (c) 2008 Tweak Software. +// Copyright (c) 2008 Tweak Software. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// // #ifndef __RvCommon__MediaDirModel__h__ #define __RvCommon__MediaDirModel__h__ #include #include -namespace Rv { -struct MediaDirItem; -class FileTypeTraits; - -/// An item model which handles a directory tree (like QDirModel) for media files - -/// -/// MediaDirModel acts similarily to QDirModel except that it will also -/// handle sequences as pseudo directories and show media file information -/// in columns like rvls -l -/// - -class MediaDirModel : public QAbstractItemModel +namespace Rv { - Q_OBJECT + struct MediaDirItem; + class FileTypeTraits; - public: - // - // Constructors - // + /// An item model which handles a directory tree (like QDirModel) for media + /// files - enum Details + /// + /// MediaDirModel acts similarily to QDirModel except that it will also + /// handle sequences as pseudo directories and show media file information + /// in columns like rvls -l + /// + + class MediaDirModel : public QAbstractItemModel { - NoDetails, - BasicFileDetails, - MediaDetails + Q_OBJECT + + public: + // + // Constructors + // + + enum Details + { + NoDetails, + BasicFileDetails, + MediaDetails + }; + + MediaDirModel(const QDir& dir, + FileTypeTraits* traits, // becomes owned by MediaDirModel + Details, QObject* parent = 0); + + MediaDirModel(FileTypeTraits* traits, // becomes owned by MediaDirModel + QObject* parent = 0); + + virtual ~MediaDirModel(); + + void setDirectory(const QDir& dir, Details); + + FileTypeTraits* fileTraits() const { return m_fileTraits; } + + void setFileTraitsIndex(size_t); + void setFileTraits(FileTypeTraits*); + + void setShowHiddenFiles(bool); + + // + // Minimum API + // + + virtual int + columnCount(const QModelIndex& parent = QModelIndex()) const; + virtual QVariant data(const QModelIndex& index, + int role = Qt::DisplayRole) const; + virtual QModelIndex + index(int row, int column, + const QModelIndex& parent = QModelIndex()) const; + virtual QModelIndex parent(const QModelIndex& index) const; + virtual int rowCount(const QModelIndex& parent = QModelIndex()) const; + virtual QVariant headerData(int section, Qt::Orientation orientation, + int role = Qt::DisplayRole) const; + + virtual bool + hasChildren(const QModelIndex& index = QModelIndex()) const; + + virtual Qt::ItemFlags flags(const QModelIndex& index) const; + virtual QMap itemData(const QModelIndex& index) const; + + void setSortFlags(QDir::SortFlags); + QString absoluteFilePath(const QModelIndex&) const; + QModelIndex indexOfPath(const QFileInfo&); + void reload(); + + private: + QDir::SortFlags m_sortFlags; + MediaDirItem* m_root; + Details m_detail; + bool m_hidden; + FileTypeTraits* m_fileTraits; + size_t m_fileTraitsIndex; }; - MediaDirModel(const QDir& dir, - FileTypeTraits* traits, // becomes owned by MediaDirModel - Details, QObject* parent=0); - - MediaDirModel(FileTypeTraits* traits, // becomes owned by MediaDirModel - QObject* parent=0); - - virtual ~MediaDirModel(); - - void setDirectory(const QDir& dir, Details); - - FileTypeTraits* fileTraits() const { return m_fileTraits; } - void setFileTraitsIndex(size_t); - void setFileTraits(FileTypeTraits*); - - void setShowHiddenFiles(bool); - - // - // Minimum API - // - - virtual int columnCount(const QModelIndex& parent = QModelIndex()) const; - virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const; - virtual QModelIndex index(int row, - int column, - const QModelIndex& parent = QModelIndex()) const; - virtual QModelIndex parent(const QModelIndex & index) const; - virtual int rowCount(const QModelIndex & parent = QModelIndex()) const; - virtual QVariant headerData(int section, - Qt::Orientation orientation, - int role = Qt::DisplayRole) const; - - virtual bool hasChildren(const QModelIndex& index = QModelIndex()) const; - - virtual Qt::ItemFlags flags(const QModelIndex &index) const; - virtual QMap itemData(const QModelIndex &index) const; - - void setSortFlags(QDir::SortFlags); - QString absoluteFilePath(const QModelIndex&) const; - QModelIndex indexOfPath(const QFileInfo&); - void reload(); - - private: - QDir::SortFlags m_sortFlags; - MediaDirItem* m_root; - Details m_detail; - bool m_hidden; - FileTypeTraits* m_fileTraits; - size_t m_fileTraitsIndex; -}; - -} // Rv +} // namespace Rv #endif // __RvCommon__MediaDirModel__h__ diff --git a/src/lib/app/RvCommon/RvCommon/MediaFileTypes.h b/src/lib/app/RvCommon/RvCommon/MediaFileTypes.h index 4ea878b09..4f1947db0 100644 --- a/src/lib/app/RvCommon/RvCommon/MediaFileTypes.h +++ b/src/lib/app/RvCommon/RvCommon/MediaFileTypes.h @@ -1,9 +1,9 @@ // -// Copyright (c) 2008 Tweak Software. +// Copyright (c) 2008 Tweak Software. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// // #ifndef __RvCommon__MediaFileTypes__h__ #define __RvCommon__MediaFileTypes__h__ @@ -11,54 +11,53 @@ #include #include -namespace Rv { - -class MediaFileTypes : public FileTypeTraits +namespace Rv { - public: - typedef FileTypeTraits Parent; - MediaFileTypes(bool readable, - bool writeable, - const QString& defaultExt = ""); + class MediaFileTypes : public FileTypeTraits + { + public: + typedef FileTypeTraits Parent; + + MediaFileTypes(bool readable, bool writeable, + const QString& defaultExt = ""); + + MediaFileTypes(bool readable, bool writeable, + const QList>& files, + const QString& defaultExt = ""); + + virtual ~MediaFileTypes(); - MediaFileTypes(bool readable, - bool writeable, - const QList >& files, - const QString& defaultExt = ""); + virtual FileTypeTraits* copyTraits() const; - virtual ~MediaFileTypes(); + size_t defaultIndex() const; - virtual FileTypeTraits* copyTraits() const; + virtual QStringList typeDescriptions(); + virtual QString extension(int index); + virtual QString description(int index); + virtual bool isKnown(size_t index, const QString&) const; + virtual QStringList fileAttributes(const QString&) const; - size_t defaultIndex() const; + QIcon fileIcon(const QString&) const; + virtual QIcon fileInfoIcon(const QFileInfo&) const; - virtual QStringList typeDescriptions(); - virtual QString extension(int index); - virtual QString description(int index); - virtual bool isKnown(size_t index, const QString&) const; - virtual QStringList fileAttributes(const QString&) const; - - QIcon fileIcon(const QString&) const; - virtual QIcon fileInfoIcon(const QFileInfo&) const; - - virtual bool hasImage(const QString&) const; - virtual QImage fileImage(const QString&) const; + virtual bool hasImage(const QString&) const; + virtual QImage fileImage(const QString&) const; - bool sameAs(const FileTypeTraits*) const override; + bool sameAs(const FileTypeTraits*) const override; - protected: - MediaFileTypes(const MediaFileTypes*); + protected: + MediaFileTypes(const MediaFileTypes*); - private: - bool m_readable; - bool m_writeable; - QSet m_extSet; - QStringList m_exts; - QStringList m_formats; - QString m_defaultExt; -}; + private: + bool m_readable; + bool m_writeable; + QSet m_extSet; + QStringList m_exts; + QStringList m_formats; + QString m_defaultExt; + }; -} // Rv +} // namespace Rv #endif // __RvCommon__MediaFileTypes__h__ diff --git a/src/lib/app/RvCommon/RvCommon/MuUICommands.h b/src/lib/app/RvCommon/RvCommon/MuUICommands.h index 33dce9457..73d377274 100644 --- a/src/lib/app/RvCommon/RvCommon/MuUICommands.h +++ b/src/lib/app/RvCommon/RvCommon/MuUICommands.h @@ -1,9 +1,9 @@ //****************************************************************************** -// Copyright (c) 2005 Tweak Inc. +// Copyright (c) 2005 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #ifndef __RV__MuUICommands__h__ #define __RV__MuUICommands__h__ @@ -12,84 +12,84 @@ #include #include -namespace Rv { +namespace Rv +{ -void initUICommands(); + void initUICommands(); -NODE_DECLARATION(resizeFit, void); -NODE_DECLARATION(setViewSize, void); -NODE_DECLARATION(startupResize, bool); -NODE_DECLARATION(popupMenu, void); -NODE_DECLARATION(popupMenuAtPoint, void); -NODE_DECLARATION(setWindowTitle, void); -NODE_DECLARATION(center, void); -NODE_DECLARATION(close, void); -NODE_DECLARATION(toggleMenuBar, void); -NODE_DECLARATION(isMenuBarVisible, bool); -NODE_DECLARATION(openMediaFileDialog, Mu::Pointer); -NODE_DECLARATION(openFileDialog, Mu::Pointer); -NODE_DECLARATION(saveFileDialog, Mu::Pointer); -NODE_DECLARATION(setCursor, void); -NODE_DECLARATION(alertPanel, int); -NODE_DECLARATION(stereoSupported, bool); -NODE_DECLARATION(watchFile, void); -NODE_DECLARATION(showNetworkDialog, void); -NODE_DECLARATION(showConsole, void); -NODE_DECLARATION(isConsoleVisible, bool); -NODE_DECLARATION(remoteSendMessage, void); -NODE_DECLARATION(remoteSendEvent, void); -NODE_DECLARATION(remoteSendDataEvent, void); -NODE_DECLARATION(remoteConnections, Mu::Pointer); -NODE_DECLARATION(remoteApplications, Mu::Pointer); -NODE_DECLARATION(remoteContacts, Mu::Pointer); -NODE_DECLARATION(remoteLocalContactName, Mu::Pointer); -NODE_DECLARATION(setRemoteLocalContactName, void); -NODE_DECLARATION(remoteConnect, void); -NODE_DECLARATION(remoteDisconnect, void); -NODE_DECLARATION(remoteNetwork, void); -NODE_DECLARATION(remoteNetworkStatus, int); -NODE_DECLARATION(remoteDefaultPermission, int); -NODE_DECLARATION(setRemoteDefaultPermission, void); -NODE_DECLARATION(remoteConnectionIsIncoming, bool); -NODE_DECLARATION(spoofConnectionStream, void); -NODE_DECLARATION(writeSetting, void); -NODE_DECLARATION(readSetting, Mu::Pointer); -NODE_DECLARATION(httpGet, void); -NODE_DECLARATION(httpPostString, void); -NODE_DECLARATION(httpPostData, void); -NODE_DECLARATION(httpPutString, void); -NODE_DECLARATION(httpPutData, void); -NODE_DECLARATION(sessionFromUrl, void); -NODE_DECLARATION(putUrlOnClipboard, void); -NODE_DECLARATION(myNetworkPort, int); -NODE_DECLARATION(myNetworkHost, Mu::Pointer); -NODE_DECLARATION(encodePassword, Mu::Pointer); -NODE_DECLARATION(decodePassword, Mu::Pointer); -NODE_DECLARATION(cacheDir, Mu::Pointer); -NODE_DECLARATION(openUrl, void); -NODE_DECLARATION(openUrlFromUrl, void); -NODE_DECLARATION(mainWindowWidget, Mu::Pointer); -NODE_DECLARATION(mainViewWidget, Mu::Pointer); -NODE_DECLARATION(prefTabWidget, Mu::Pointer); -NODE_DECLARATION(sessionBottomToolBar, Mu::Pointer); -NODE_DECLARATION(networkAccessManager, Mu::Pointer); -NODE_DECLARATION(queryDriverAttribute, Mu::Pointer); -NODE_DECLARATION(setDriverAttribute, void); -NODE_DECLARATION(setPresentationMode, void); -NODE_DECLARATION(presentationMode, bool); -NODE_DECLARATION(packageListFromSetting, Mu::Pointer); -NODE_DECLARATION(showTopViewToolbar, void); -NODE_DECLARATION(showBottomViewToolbar, void); -NODE_DECLARATION(isTopViewToolbarVisible, bool); -NODE_DECLARATION(isBottomViewToolbarVisible, bool); -NODE_DECLARATION(editNodeSource, void); -NODE_DECLARATION(editProfiles, void); -NODE_DECLARATION(validateShotgunToken, Mu::Pointer); -NODE_DECLARATION(launchTLI, void); -NODE_DECLARATION(rvioSetup, void); -NODE_DECLARATION(javascriptMuExport, void); + NODE_DECLARATION(resizeFit, void); + NODE_DECLARATION(setViewSize, void); + NODE_DECLARATION(startupResize, bool); + NODE_DECLARATION(popupMenu, void); + NODE_DECLARATION(popupMenuAtPoint, void); + NODE_DECLARATION(setWindowTitle, void); + NODE_DECLARATION(center, void); + NODE_DECLARATION(close, void); + NODE_DECLARATION(toggleMenuBar, void); + NODE_DECLARATION(isMenuBarVisible, bool); + NODE_DECLARATION(openMediaFileDialog, Mu::Pointer); + NODE_DECLARATION(openFileDialog, Mu::Pointer); + NODE_DECLARATION(saveFileDialog, Mu::Pointer); + NODE_DECLARATION(setCursor, void); + NODE_DECLARATION(alertPanel, int); + NODE_DECLARATION(stereoSupported, bool); + NODE_DECLARATION(watchFile, void); + NODE_DECLARATION(showNetworkDialog, void); + NODE_DECLARATION(showConsole, void); + NODE_DECLARATION(isConsoleVisible, bool); + NODE_DECLARATION(remoteSendMessage, void); + NODE_DECLARATION(remoteSendEvent, void); + NODE_DECLARATION(remoteSendDataEvent, void); + NODE_DECLARATION(remoteConnections, Mu::Pointer); + NODE_DECLARATION(remoteApplications, Mu::Pointer); + NODE_DECLARATION(remoteContacts, Mu::Pointer); + NODE_DECLARATION(remoteLocalContactName, Mu::Pointer); + NODE_DECLARATION(setRemoteLocalContactName, void); + NODE_DECLARATION(remoteConnect, void); + NODE_DECLARATION(remoteDisconnect, void); + NODE_DECLARATION(remoteNetwork, void); + NODE_DECLARATION(remoteNetworkStatus, int); + NODE_DECLARATION(remoteDefaultPermission, int); + NODE_DECLARATION(setRemoteDefaultPermission, void); + NODE_DECLARATION(remoteConnectionIsIncoming, bool); + NODE_DECLARATION(spoofConnectionStream, void); + NODE_DECLARATION(writeSetting, void); + NODE_DECLARATION(readSetting, Mu::Pointer); + NODE_DECLARATION(httpGet, void); + NODE_DECLARATION(httpPostString, void); + NODE_DECLARATION(httpPostData, void); + NODE_DECLARATION(httpPutString, void); + NODE_DECLARATION(httpPutData, void); + NODE_DECLARATION(sessionFromUrl, void); + NODE_DECLARATION(putUrlOnClipboard, void); + NODE_DECLARATION(myNetworkPort, int); + NODE_DECLARATION(myNetworkHost, Mu::Pointer); + NODE_DECLARATION(encodePassword, Mu::Pointer); + NODE_DECLARATION(decodePassword, Mu::Pointer); + NODE_DECLARATION(cacheDir, Mu::Pointer); + NODE_DECLARATION(openUrl, void); + NODE_DECLARATION(openUrlFromUrl, void); + NODE_DECLARATION(mainWindowWidget, Mu::Pointer); + NODE_DECLARATION(mainViewWidget, Mu::Pointer); + NODE_DECLARATION(prefTabWidget, Mu::Pointer); + NODE_DECLARATION(sessionBottomToolBar, Mu::Pointer); + NODE_DECLARATION(networkAccessManager, Mu::Pointer); + NODE_DECLARATION(queryDriverAttribute, Mu::Pointer); + NODE_DECLARATION(setDriverAttribute, void); + NODE_DECLARATION(setPresentationMode, void); + NODE_DECLARATION(presentationMode, bool); + NODE_DECLARATION(packageListFromSetting, Mu::Pointer); + NODE_DECLARATION(showTopViewToolbar, void); + NODE_DECLARATION(showBottomViewToolbar, void); + NODE_DECLARATION(isTopViewToolbarVisible, bool); + NODE_DECLARATION(isBottomViewToolbarVisible, bool); + NODE_DECLARATION(editNodeSource, void); + NODE_DECLARATION(editProfiles, void); + NODE_DECLARATION(validateShotgunToken, Mu::Pointer); + NODE_DECLARATION(launchTLI, void); + NODE_DECLARATION(rvioSetup, void); + NODE_DECLARATION(javascriptMuExport, void); - -} // Rv +} // namespace Rv #endif // __RV__MuUICommands__h__ diff --git a/src/lib/app/RvCommon/RvCommon/PermDelegate.h b/src/lib/app/RvCommon/RvCommon/PermDelegate.h index 7a83ac446..e0abfb1a6 100644 --- a/src/lib/app/RvCommon/RvCommon/PermDelegate.h +++ b/src/lib/app/RvCommon/RvCommon/PermDelegate.h @@ -1,9 +1,9 @@ // -// Copyright (c) 2008 Tweak Software. +// Copyright (c) 2008 Tweak Software. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// // #ifndef __RvCommon__PermDelegate__h__ #define __RvCommon__PermDelegate__h__ @@ -11,33 +11,33 @@ #include #include -namespace Rv { +namespace Rv +{ -// -// Permissions combo delegate for editing the contacts UI -// + // + // Permissions combo delegate for editing the contacts UI + // -class PermDelegate : public QItemDelegate -{ - Q_OBJECT - public: - PermDelegate(QObject *parent = 0); + class PermDelegate : public QItemDelegate + { + Q_OBJECT + public: + PermDelegate(QObject* parent = 0); - QWidget *createEditor(QWidget *parent, - const QStyleOptionViewItem &option, - const QModelIndex &index) const; + QWidget* createEditor(QWidget* parent, + const QStyleOptionViewItem& option, + const QModelIndex& index) const; - void setEditorData(QWidget *editor, const QModelIndex &index) const; + void setEditorData(QWidget* editor, const QModelIndex& index) const; - void setModelData(QWidget *editor, - QAbstractItemModel *model, - const QModelIndex &index) const; + void setModelData(QWidget* editor, QAbstractItemModel* model, + const QModelIndex& index) const; - void updateEditorGeometry(QWidget *editor, - const QStyleOptionViewItem &option, - const QModelIndex &index) const; -}; + void updateEditorGeometry(QWidget* editor, + const QStyleOptionViewItem& option, + const QModelIndex& index) const; + }; -} // Rv +} // namespace Rv #endif // __RvCommon__PermDelegate__h__ diff --git a/src/lib/app/RvCommon/RvCommon/PyUICommands.h b/src/lib/app/RvCommon/RvCommon/PyUICommands.h index ac70ff4ad..077da1c86 100644 --- a/src/lib/app/RvCommon/RvCommon/PyUICommands.h +++ b/src/lib/app/RvCommon/RvCommon/PyUICommands.h @@ -1,18 +1,19 @@ // -// Copyright (c) 2011 Tweak Software. +// Copyright (c) 2011 Tweak Software. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// // #ifndef __RvCommon__PyUICommands__h__ #define __RvCommon__PyUICommands__h__ #include -namespace Rv { +namespace Rv +{ -void* pyUICommands(); + void* pyUICommands(); -} // Rv +} // namespace Rv #endif // __RvCommon__PyUICommands__h__ diff --git a/src/lib/app/RvCommon/RvCommon/QTDesktopVideoDevice.h b/src/lib/app/RvCommon/RvCommon/QTDesktopVideoDevice.h index b4299a1bd..304cbdb7e 100644 --- a/src/lib/app/RvCommon/RvCommon/QTDesktopVideoDevice.h +++ b/src/lib/app/RvCommon/RvCommon/QTDesktopVideoDevice.h @@ -1,9 +1,9 @@ // -// Copyright (c) 2011 Tweak Software. +// Copyright (c) 2011 Tweak Software. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// // #ifndef __RvCommon__QTDesktopVideoDevice__h__ #define __RvCommon__QTDesktopVideoDevice__h__ @@ -15,79 +15,85 @@ #include #include -namespace Rv { +namespace Rv +{ -// -// QTDesktopVideoDevice -// -// Wraps QDesktop "screens" as DesktopVideoDevices. The underlying -// code will create a fullscreen widget when bound and tree the -// "screen" like one giant output. The QTDesktopVideoDevice cannot -// change output resolution, etc, it can only report the existing -// desktop setup. -// -// QTDesktopVideoDevice is the fall back screen device when -// CoreGraphics, NVApi, or NvCtrl are not available (i.e. its an ATI -// card on linux or windows). -// -// See also: CGDesktopVideoDevice and NVDesktopVideoDevice which are -// both preferred over QTDesktopVideoDevice since they allow the user -// to control the screen more directly. -// + // + // QTDesktopVideoDevice + // + // Wraps QDesktop "screens" as DesktopVideoDevices. The underlying + // code will create a fullscreen widget when bound and tree the + // "screen" like one giant output. The QTDesktopVideoDevice cannot + // change output resolution, etc, it can only report the existing + // desktop setup. + // + // QTDesktopVideoDevice is the fall back screen device when + // CoreGraphics, NVApi, or NvCtrl are not available (i.e. its an ATI + // card on linux or windows). + // + // See also: CGDesktopVideoDevice and NVDesktopVideoDevice which are + // both preferred over QTDesktopVideoDevice since they allow the user + // to control the screen more directly. + // -class QTDesktopVideoDevice : public DesktopVideoDevice -{ - public: - QTDesktopVideoDevice(TwkApp::VideoModule*, - const std::string& name, - int screen, - const QTGLVideoDevice* share); + class QTDesktopVideoDevice : public DesktopVideoDevice + { + public: + QTDesktopVideoDevice(TwkApp::VideoModule*, const std::string& name, + int screen, const QTGLVideoDevice* share); - virtual ~QTDesktopVideoDevice(); + virtual ~QTDesktopVideoDevice(); - // From QTGLVideoDevice + // From QTGLVideoDevice - void setWidget(QGLWidget*); - QGLWidget* widget() const { return m_view; } + void setWidget(QGLWidget*); - virtual void makeCurrent() const; - const QTTranslator& translator() const { return *m_translator; } - virtual void redraw() const; - virtual void redrawImmediately() const; + QGLWidget* widget() const { return m_view; } - void setAbsolutePosition(int x, int y) { m_x = x; m_y = y; } + virtual void makeCurrent() const; - // - // VideoDevice API - // + const QTTranslator& translator() const { return *m_translator; } + + virtual void redraw() const; + virtual void redrawImmediately() const; + + void setAbsolutePosition(int x, int y) + { + m_x = x; + m_y = y; + } + + // + // VideoDevice API + // - virtual Resolution resolution() const; - virtual Offset offset() const; - virtual Timing timing() const; - virtual VideoFormat format() const; + virtual Resolution resolution() const; + virtual Offset offset() const; + virtual Timing timing() const; + virtual VideoFormat format() const; - virtual size_t width() const; - virtual size_t height() const; + virtual size_t width() const; + virtual size_t height() const; - virtual void open(const StringVector&); - virtual void close(); - virtual bool isOpen() const; + virtual void open(const StringVector&); + virtual void close(); + virtual bool isOpen() const; - virtual void syncBuffers() const; + virtual void syncBuffers() const; - virtual int qtScreen() const { return m_screen; } + virtual int qtScreen() const { return m_screen; } #ifdef PLATFORM_WINDOWS - virtual ColorProfile colorProfile() const; + virtual ColorProfile colorProfile() const; #endif - private: - int m_screen; - int m_x; - int m_y; - QGLWidget* m_view; - QTTranslator* m_translator; - mutable ColorProfile m_colorProfile; -}; - -} // Rv + private: + int m_screen; + int m_x; + int m_y; + QGLWidget* m_view; + QTTranslator* m_translator; + mutable ColorProfile m_colorProfile; + }; + +} // namespace Rv #endif // __RvCommon__QTDesktopVideoDevice__h__ diff --git a/src/lib/app/RvCommon/RvCommon/QTFrameBuffer.h b/src/lib/app/RvCommon/RvCommon/QTFrameBuffer.h index ffd0b619b..fc069bb20 100644 --- a/src/lib/app/RvCommon/RvCommon/QTFrameBuffer.h +++ b/src/lib/app/RvCommon/RvCommon/QTFrameBuffer.h @@ -1,9 +1,9 @@ //****************************************************************************** -// Copyright (c) 2004 Tweak Inc. +// Copyright (c) 2004 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #ifndef __mu_usf__QTFrameBuffer__h__ #define __mu_usf__QTFrameBuffer__h__ @@ -12,37 +12,41 @@ #include #include -namespace Rv { - -class QTFrameBuffer : public TwkGLF::FrameBuffer +namespace Rv { -public: - QTFrameBuffer(QGLWidget *view); - ~QTFrameBuffer(); - - virtual size_t width() const; - virtual size_t height() const; - virtual int x() const; - virtual int y() const; + class QTFrameBuffer : public TwkGLF::FrameBuffer + { + public: + QTFrameBuffer(QGLWidget* view); + ~QTFrameBuffer(); + + virtual size_t width() const; + virtual size_t height() const; + + virtual int x() const; + virtual int y() const; - virtual void makeCurrent() const; + virtual void makeCurrent() const; - const QTTranslator& translator() const { return m_translator; } + const QTTranslator& translator() const { return m_translator; } - virtual void redraw(); - virtual void redrawImmediately(); + virtual void redraw(); + virtual void redrawImmediately(); - void setAbsolutePosition(int x, int y) { m_x = x; m_y = y; } - -private: - int m_x; - int m_y; - QGLWidget* m_view; - QTTranslator m_translator; -}; + void setAbsolutePosition(int x, int y) + { + m_x = x; + m_y = y; + } + private: + int m_x; + int m_y; + QGLWidget* m_view; + QTTranslator m_translator; + }; -} // Rv +} // namespace Rv #endif // __mu_usf__QTFrameBuffer__h__ diff --git a/src/lib/app/RvCommon/RvCommon/QTGLVideoDevice.h b/src/lib/app/RvCommon/RvCommon/QTGLVideoDevice.h index f59fae2db..c04e2d956 100644 --- a/src/lib/app/RvCommon/RvCommon/QTGLVideoDevice.h +++ b/src/lib/app/RvCommon/RvCommon/QTGLVideoDevice.h @@ -1,9 +1,9 @@ // -// Copyright (c) 2011 Tweak Software. +// Copyright (c) 2011 Tweak Software. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// // #ifndef __RvCommon__QTGLVideoDevice__h__ #define __RvCommon__QTGLVideoDevice__h__ @@ -13,66 +13,73 @@ #include #include -namespace Rv { +namespace Rv +{ -// -// QTGLVideoDevice -// -// Wraps a QGLWidget as a TwkGLF::GLVideoDevice. This gives a handle -// on a concrete window system device. QTGLVideoDevice can generate -// events from the window system -// + // + // QTGLVideoDevice + // + // Wraps a QGLWidget as a TwkGLF::GLVideoDevice. This gives a handle + // on a concrete window system device. QTGLVideoDevice can generate + // events from the window system + // -class QTGLVideoDevice : public TwkGLF::GLVideoDevice -{ - public: - QTGLVideoDevice(TwkApp::VideoModule*, const std::string& name, QGLWidget* view); - QTGLVideoDevice(TwkApp::VideoModule*, const std::string& name); - virtual ~QTGLVideoDevice(); - - void setWidget(QGLWidget*); - QGLWidget* widget() const { return m_view; } + class QTGLVideoDevice : public TwkGLF::GLVideoDevice + { + public: + QTGLVideoDevice(TwkApp::VideoModule*, const std::string& name, + QGLWidget* view); + QTGLVideoDevice(TwkApp::VideoModule*, const std::string& name); + virtual ~QTGLVideoDevice(); - virtual void makeCurrent() const; - const QTTranslator& translator() const { return *m_translator; } - virtual void redraw() const; - virtual void redrawImmediately() const; + void setWidget(QGLWidget*); - void setAbsolutePosition(int x, int y); + QGLWidget* widget() const { return m_view; } - // - // VideoDevice API - // + virtual void makeCurrent() const; + + const QTTranslator& translator() const { return *m_translator; } + + virtual void redraw() const; + virtual void redrawImmediately() const; + + void setAbsolutePosition(int x, int y); - virtual GLVideoDevice* newSharedContextWorkerDevice() const; - virtual Resolution resolution() const; - virtual Offset offset() const; - virtual Timing timing() const; - virtual VideoFormat format() const; + // + // VideoDevice API + // - virtual size_t width() const; - virtual size_t height() const; + virtual GLVideoDevice* newSharedContextWorkerDevice() const; + virtual Resolution resolution() const; + virtual Offset offset() const; + virtual Timing timing() const; + virtual VideoFormat format() const; - virtual void open(const StringVector&); - virtual void close(); - virtual bool isOpen() const; + virtual size_t width() const; + virtual size_t height() const; - virtual void syncBuffers() const; + virtual void open(const StringVector&); + virtual void close(); + virtual bool isOpen() const; - bool isWorkerDevice() const { return Capabilities(capabilities()) == NoCapabilities; } + virtual void syncBuffers() const; - protected: - QTGLVideoDevice(const std::string& name, QGLWidget* view); + bool isWorkerDevice() const + { + return Capabilities(capabilities()) == NoCapabilities; + } - protected: - int m_x; - int m_y; - float m_refresh; - QGLWidget* m_view; - QTTranslator* m_translator; -}; + protected: + QTGLVideoDevice(const std::string& name, QGLWidget* view); + protected: + int m_x; + int m_y; + float m_refresh; + QGLWidget* m_view; + QTTranslator* m_translator; + }; -} // Rv +} // namespace Rv #endif // __RvCommon__QTGLVideoDevice__h__ diff --git a/src/lib/app/RvCommon/RvCommon/QTTranslator.h b/src/lib/app/RvCommon/RvCommon/QTTranslator.h index b1d8a0a05..2fdcb6a2a 100644 --- a/src/lib/app/RvCommon/RvCommon/QTTranslator.h +++ b/src/lib/app/RvCommon/RvCommon/QTTranslator.h @@ -1,9 +1,9 @@ //****************************************************************************** -// Copyright (c) 2004 Tweak Inc. +// Copyright (c) 2004 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #ifndef __mu_usf__QTTranslator__h__ #define __mu_usf__QTTranslator__h__ @@ -14,78 +14,83 @@ #include #include -namespace Rv { - -// -// A TwkApp::Event Translator for a given Fl_Widget -// - -class QTTranslator +namespace Rv { -public: - QTTranslator(TwkApp::EventNode*, QWidget* w=0); - void setWidet(QWidget* w) { m_widget=w; } - - void sendEvent(const TwkApp::Event&) const; // - // Here's the QT entry point + // A TwkApp::Event Translator for a given Fl_Widget // - bool sendQTEvent(QEvent* event, float activationTime=0.0) const; + class QTTranslator + { + public: + QTTranslator(TwkApp::EventNode*, QWidget* w = 0); + + void setWidet(QWidget* w) { m_widget = w; } + + void sendEvent(const TwkApp::Event&) const; + + // + // Here's the QT entry point + // + + bool sendQTEvent(QEvent* event, float activationTime = 0.0) const; + + bool sendTabletEvent(QEvent* event) const; + bool sendKeyEvent(QEvent* event) const; + bool sendMouseEvent(QEvent* event, float activationTime = 0.0) const; + bool sendMouseWheelEvent(QEvent* event) const; + bool sendEnterLeaveEvent(QEvent* event) const; + bool sendDNDEvent(QEvent* event) const; + unsigned int modifiers(QInputEvent* event) const; - bool sendTabletEvent(QEvent* event) const; - bool sendKeyEvent(QEvent* event) const; - bool sendMouseEvent(QEvent* event, float activationTime=0.0) const; - bool sendMouseWheelEvent(QEvent* event) const; - bool sendEnterLeaveEvent(QEvent* event) const; - bool sendDNDEvent(QEvent* event) const; - unsigned int modifiers(QInputEvent* event) const; + void resetModifiers() const; + unsigned int modifiers(Qt::KeyboardModifiers) const; + unsigned int buttons() const; + Qt::MouseButtons qbuttons(unsigned int) const; + std::string modifierString(Qt::KeyboardModifiers, bool) const; + int key(int) const; + int pointer(int) const; + std::string pointerString(bool, bool, bool, QEvent::Type, + Qt::KeyboardModifiers, Qt::MouseButtons, + bool) const; - void resetModifiers() const; - unsigned int modifiers(Qt::KeyboardModifiers) const; - unsigned int buttons() const; - Qt::MouseButtons qbuttons(unsigned int) const; - std::string modifierString(Qt::KeyboardModifiers, bool) const; - int key(int) const; - int pointer(int) const; - std::string pointerString(bool, bool, bool, - QEvent::Type, - Qt::KeyboardModifiers, - Qt::MouseButtons, bool) const; + void setRelativeDomain(float w, float h) const; + void setScaleAndOffset(float x, float y, float sx, float sy) const; - void setRelativeDomain(float w, float h) const; - void setScaleAndOffset(float x, float y, float sx, float sy) const; + Qt::KeyboardModifiers currentModifiers() const { return m_modifiers; }; - Qt::KeyboardModifiers currentModifiers() const { return m_modifiers; }; - void setCurrentModifiers(Qt::KeyboardModifiers m) const { m_modifiers = m; }; + void setCurrentModifiers(Qt::KeyboardModifiers m) const + { + m_modifiers = m; + }; -private: - TwkApp::EventNode* m_node; - QWidget* m_widget; - mutable Qt::KeyboardModifiers m_modifiers; - mutable QEvent::Type m_lastType; - mutable Qt::KeyboardModifiers m_lastMods; - mutable unsigned int m_lastButtons; - mutable bool m_firstTime; - mutable bool m_b1; - mutable bool m_b2; - mutable bool m_b3; - mutable bool m_tabletPushed; - mutable int m_pushx; - mutable int m_pushy; - mutable int m_x; - mutable int m_y; - mutable int m_lastx; - mutable int m_lasty; - mutable float m_xscale; - mutable float m_yscale; - mutable float m_xoffset; - mutable float m_yoffset; - mutable int m_width; - mutable int m_height; -}; + private: + TwkApp::EventNode* m_node; + QWidget* m_widget; + mutable Qt::KeyboardModifiers m_modifiers; + mutable QEvent::Type m_lastType; + mutable Qt::KeyboardModifiers m_lastMods; + mutable unsigned int m_lastButtons; + mutable bool m_firstTime; + mutable bool m_b1; + mutable bool m_b2; + mutable bool m_b3; + mutable bool m_tabletPushed; + mutable int m_pushx; + mutable int m_pushy; + mutable int m_x; + mutable int m_y; + mutable int m_lastx; + mutable int m_lasty; + mutable float m_xscale; + mutable float m_yscale; + mutable float m_xoffset; + mutable float m_yoffset; + mutable int m_width; + mutable int m_height; + }; -} // Rv +} // namespace Rv #endif // __mu_usf__QTTranslator__h__ diff --git a/src/lib/app/RvCommon/RvCommon/QTUtils.h b/src/lib/app/RvCommon/RvCommon/QTUtils.h index c18218946..f4caa5fba 100644 --- a/src/lib/app/RvCommon/RvCommon/QTUtils.h +++ b/src/lib/app/RvCommon/RvCommon/QTUtils.h @@ -1,9 +1,9 @@ //****************************************************************************** -// Copyright (c) 2007 Tweak Inc. +// Copyright (c) 2007 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #ifndef __rv_qt__QTPaletteDump__h__ #define __rv_qt__QTPaletteDump__h__ @@ -12,31 +12,31 @@ #include #include -namespace Rv { +namespace Rv +{ -// -// Return an icon from a resource path or file. The icon will be -// inverted if the background is darker than HSV value < 0.5 -// + // + // Return an icon from a resource path or file. The icon will be + // inverted if the background is darker than HSV value < 0.5 + // -QPixmap colorAdjustedPixmap(const QString&, bool invertSense=false); -QIcon colorAdjustedIcon(const QString&, bool invertSense=false); + QPixmap colorAdjustedPixmap(const QString&, bool invertSense = false); + QIcon colorAdjustedIcon(const QString&, bool invertSense = false); -// -// Call to make a copy of the default palette -// - -void initializeDefaultPalette(); -void setDefaultPalette(); + // + // Call to make a copy of the default palette + // -// -// Hard coded "dark" palette -// + void initializeDefaultPalette(); + void setDefaultPalette(); -void installApplicationPalette(); -void dumpApplicationPalette(); + // + // Hard coded "dark" palette + // + void installApplicationPalette(); + void dumpApplicationPalette(); -} // Rv +} // namespace Rv #endif // __rv_qt__QTPaletteDump__h__ diff --git a/src/lib/app/RvCommon/RvCommon/RvApplication.h b/src/lib/app/RvCommon/RvCommon/RvApplication.h index c35f8c794..faf2457cf 100644 --- a/src/lib/app/RvCommon/RvCommon/RvApplication.h +++ b/src/lib/app/RvCommon/RvCommon/RvApplication.h @@ -1,9 +1,9 @@ //****************************************************************************** // Copyright (c) 2005 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #ifndef __rv__RvApplication__h__ #define __rv__RvApplication__h__ @@ -23,149 +23,174 @@ #include #include -namespace TwkApp { -class VideoModule; +namespace TwkApp +{ + class VideoModule; } -namespace Rv { -class RvDocument; -class RvPreferences; -class RvProfileManager; -class RvConsoleWindow; -class RvNetworkDialog; -class RvWebManager; -class RvSession; -class QTGLVideoDevice; -class DesktopVideoModule; - -// -// class RvApplication -// -// Qt application + RvConsoleApplication (Rv::Application) -// - -class RvApplication : public QObject, public RvConsoleApplication +namespace Rv { - Q_OBJECT + class RvDocument; + class RvPreferences; + class RvProfileManager; + class RvConsoleWindow; + class RvNetworkDialog; + class RvWebManager; + class RvSession; + class QTGLVideoDevice; + class DesktopVideoModule; - public: - // - // Types // - - typedef std::vector NewSessionQueue; - typedef std::set RvDocSet; - typedef std::vector VideoDeviceVector; - typedef TwkUtil::Timer Timer; - typedef std::map DispatchMap; - typedef std::mutex DispatchMutex; - + // class RvApplication // - // Constructors + // Qt application + RvConsoleApplication (Rv::Application) // - RvApplication(int argc, char** argv); - virtual ~RvApplication(); - - void createNewSessionFromFiles(const StringVector&) override; - DispatchID dispatchToMainThread(DispatchCallback callback) override; - void undispatchToMainThread(DispatchID dispatchID, double maxDuration) override; - bool isDispatchExecuting(DispatchID dispatchID); - - RvDocument* newSessionFromFiles(const StringVector&); - RvDocument* rebuildSessionFromFiles(RvSession *s, const StringVector&); - - QMenuBar* macMenuBar() const { return m_macMenuBar; } - QMenu* macRVMenu() const { return m_macRVMenu; } - QAction* aboutAction() const { return m_aboutAct; } - QAction* quitAction() const { return m_quitAct; } - QAction* prefAction() const { return m_prefAct; } - QAction* networkAction() const { return m_networkAct; } - - virtual bool eventFilter(QObject* o, QEvent* event) override; - - RvConsoleWindow* console(); - RvNetworkDialog* networkWindow(); - RvWebManager* webManager(); - RvPreferences* prefDialog(); - RvProfileManager* profileManager(); - - bool networkDialogRunning() const { return m_networkDialog ? true : false; } - - void processNetworkOpts(bool startup = true); - - virtual void stopTimer(); - virtual void startTimer(); - - static void parseURL (const char *s, std::vector &av); - static void sessionFromUrl (std::string url); - static void putUrlOnClipboard (std::string url, std::string title, bool doEncode=true); - static std::string encodeCommandLineURL (int argc, char *argv[]); - static std::string bakeCommandLineURL (int argc, char *argv[]); - static void initializeQSettings (std::string altPath); - - void setExecutableNameCaps (std::string nm) { m_executableNameCaps = nm; } - - static std::string queryDriverAttribute(const std::string& var); - static void setDriverAttribute(const std::string& var, const std::string& val); - - void openVideoModule(VideoModule*) const; - int findVideoModuleIndexByName(const std::string&) const; - TwkApp::VideoDevice* findPresentationDevice(const std::string& dpath) const; - std::string setVideoDeviceStateFromSettings(TwkApp::VideoDevice*) const; - - void setPresentationMode(bool); - bool isInPresentationMode(); - - DesktopVideoModule* desktopVideoModule() const { return m_desktopModule; } - - static int parseInFiles(int argc, char *argv[]); - virtual VideoModule* primaryVideoModule() const override; - - public slots: - void showNetworkDialog(); - void heartbeat(); - void runCreateSession(); - void about(); - void prefs(); - void quitAll(); - void lazyBuild(); - void dispatchTimeout(); - - private: - NewSessionQueue m_newSessions; - RvDocSet m_deleteDocs; - QTimer* m_timer; - QTimer* m_newTimer; - QTimer* m_lazyBuildTimer; - Timer m_fireTimer; - RvPreferences* m_prefDialog; - RvProfileManager* m_profileDialog; - QMenuBar* m_macMenuBar; - QMenu* m_macRVMenu; - QAction* m_aboutAct; - QAction* m_quitAct; - QAction* m_prefAct; - QAction* m_networkAct; - RvConsoleWindow* m_console; - RvNetworkDialog* m_networkDialog; - RvWebManager* m_webManager; - TwkApp::VideoDevice* m_presentationDevice; - bool m_presentationMode; - mutable pthread_mutex_t m_deleteLock; - std::string m_executableNameCaps; - DesktopVideoModule* m_desktopModule; - QTimer* m_pingTimer; - QTimer* m_dispatchTimer; - DispatchMutex m_dispatchMutex; - DispatchID m_nextDispatchID {1}; - DispatchMap m_dispatchMap; - DispatchMap m_executingMap; - std::atomic m_dispatchAtomicInt; -}; - -inline RvApplication* RvApp() { return static_cast(IPCore::App()); } - -} // Rv + class RvApplication + : public QObject + , public RvConsoleApplication + { + Q_OBJECT + + public: + // + // Types + // + + typedef std::vector NewSessionQueue; + typedef std::set RvDocSet; + typedef std::vector VideoDeviceVector; + typedef TwkUtil::Timer Timer; + typedef std::map DispatchMap; + typedef std::mutex DispatchMutex; + + // + // Constructors + // + + RvApplication(int argc, char** argv); + virtual ~RvApplication(); + + void createNewSessionFromFiles(const StringVector&) override; + DispatchID dispatchToMainThread(DispatchCallback callback) override; + void undispatchToMainThread(DispatchID dispatchID, + double maxDuration) override; + bool isDispatchExecuting(DispatchID dispatchID); + + RvDocument* newSessionFromFiles(const StringVector&); + RvDocument* rebuildSessionFromFiles(RvSession* s, const StringVector&); + + QMenuBar* macMenuBar() const { return m_macMenuBar; } + + QMenu* macRVMenu() const { return m_macRVMenu; } + + QAction* aboutAction() const { return m_aboutAct; } + + QAction* quitAction() const { return m_quitAct; } + + QAction* prefAction() const { return m_prefAct; } + + QAction* networkAction() const { return m_networkAct; } + + virtual bool eventFilter(QObject* o, QEvent* event) override; + + RvConsoleWindow* console(); + RvNetworkDialog* networkWindow(); + RvWebManager* webManager(); + RvPreferences* prefDialog(); + RvProfileManager* profileManager(); + + bool networkDialogRunning() const + { + return m_networkDialog ? true : false; + } + + void processNetworkOpts(bool startup = true); + + virtual void stopTimer(); + virtual void startTimer(); + + static void parseURL(const char* s, std::vector& av); + static void sessionFromUrl(std::string url); + static void putUrlOnClipboard(std::string url, std::string title, + bool doEncode = true); + static std::string encodeCommandLineURL(int argc, char* argv[]); + static std::string bakeCommandLineURL(int argc, char* argv[]); + static void initializeQSettings(std::string altPath); + + void setExecutableNameCaps(std::string nm) + { + m_executableNameCaps = nm; + } + + static std::string queryDriverAttribute(const std::string& var); + static void setDriverAttribute(const std::string& var, + const std::string& val); + + void openVideoModule(VideoModule*) const; + int findVideoModuleIndexByName(const std::string&) const; + TwkApp::VideoDevice* + findPresentationDevice(const std::string& dpath) const; + std::string setVideoDeviceStateFromSettings(TwkApp::VideoDevice*) const; + + void setPresentationMode(bool); + bool isInPresentationMode(); + + DesktopVideoModule* desktopVideoModule() const + { + return m_desktopModule; + } + + static int parseInFiles(int argc, char* argv[]); + virtual VideoModule* primaryVideoModule() const override; + + public slots: + void showNetworkDialog(); + void heartbeat(); + void runCreateSession(); + void about(); + void prefs(); + void quitAll(); + void lazyBuild(); + void dispatchTimeout(); + + private: + NewSessionQueue m_newSessions; + RvDocSet m_deleteDocs; + QTimer* m_timer; + QTimer* m_newTimer; + QTimer* m_lazyBuildTimer; + Timer m_fireTimer; + RvPreferences* m_prefDialog; + RvProfileManager* m_profileDialog; + QMenuBar* m_macMenuBar; + QMenu* m_macRVMenu; + QAction* m_aboutAct; + QAction* m_quitAct; + QAction* m_prefAct; + QAction* m_networkAct; + RvConsoleWindow* m_console; + RvNetworkDialog* m_networkDialog; + RvWebManager* m_webManager; + TwkApp::VideoDevice* m_presentationDevice; + bool m_presentationMode; + mutable pthread_mutex_t m_deleteLock; + std::string m_executableNameCaps; + DesktopVideoModule* m_desktopModule; + QTimer* m_pingTimer; + QTimer* m_dispatchTimer; + DispatchMutex m_dispatchMutex; + DispatchID m_nextDispatchID{1}; + DispatchMap m_dispatchMap; + DispatchMap m_executingMap; + std::atomic m_dispatchAtomicInt; + }; + + inline RvApplication* RvApp() + { + return static_cast(IPCore::App()); + } + +} // namespace Rv #endif // __rv__RvApplication__h__ diff --git a/src/lib/app/RvCommon/RvCommon/RvBottomViewToolBar.h b/src/lib/app/RvCommon/RvCommon/RvBottomViewToolBar.h index d6377afe7..3f3addbf3 100644 --- a/src/lib/app/RvCommon/RvCommon/RvBottomViewToolBar.h +++ b/src/lib/app/RvCommon/RvCommon/RvBottomViewToolBar.h @@ -1,9 +1,9 @@ // -// Copyright (c) 2012 Tweak Software. +// Copyright (c) 2012 Tweak Software. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// // #ifndef __RvCommon__RvBottomViewToolBar__h__ #define __RvCommon__RvBottomViewToolBar__h__ @@ -14,110 +14,111 @@ #include #include -namespace IPCore { -class Session; +namespace IPCore +{ + class Session; } -namespace Rv { - -class RvBottomViewToolBar : public QToolBar, public TwkApp::EventNode +namespace Rv { - Q_OBJECT - - public: - RvBottomViewToolBar(QWidget*); - virtual ~RvBottomViewToolBar(); - - void setSession(IPCore::Session*); - virtual Result receiveEvent(const TwkApp::Event&); - - void build(); - void makeActive(bool); - void makeActiveFromSettings(); - - private slots: - void smActionTriggered(bool); - void paintActionTriggered(bool); - void infoActionTriggered(bool); - void timelineActionTriggered(bool); - void timelineMagActionTriggered(bool); - void networkActionTriggered(bool); - - void backStepTriggered(); - void forwardStepTriggered(); - void backPlayTriggered(); - void forwardPlayTriggered(); - void backMarkTriggered(); - void forwardMarkTriggered(); - - void audioSliderChanged(int); - void audioSliderReleased(); - void audioMuteTriggered(bool); - void audioMenuTriggered(); - void playModeMenuTriggered(QAction *); - void playModeMenuUpdate(); - - private: + class RvBottomViewToolBar + : public QToolBar + , public TwkApp::EventNode + { + Q_OBJECT + + public: + RvBottomViewToolBar(QWidget*); + virtual ~RvBottomViewToolBar(); + + void setSession(IPCore::Session*); + virtual Result receiveEvent(const TwkApp::Event&); + + void build(); + void makeActive(bool); + void makeActiveFromSettings(); + + private slots: + void smActionTriggered(bool); + void paintActionTriggered(bool); + void infoActionTriggered(bool); + void timelineActionTriggered(bool); + void timelineMagActionTriggered(bool); + void networkActionTriggered(bool); + + void backStepTriggered(); + void forwardStepTriggered(); + void backPlayTriggered(); + void forwardPlayTriggered(); + void backMarkTriggered(); + void forwardMarkTriggered(); + + void audioSliderChanged(int); + void audioSliderReleased(); + void audioMuteTriggered(bool); + void audioMenuTriggered(); + + void playModeMenuTriggered(QAction*); + void playModeMenuUpdate(); + + private: + template void setVolumeLevel(T& inst, int level); + + void setVolumeIcon(); + + IPCore::Session* m_session; + QAction* m_smAction; + QAction* m_paintAction; + QAction* m_infoAction; + QAction* m_networkAction; + QAction* m_timelineMagAction; + QAction* m_timelineAction; + QAction* m_backStepAction; + QAction* m_forwardStepAction; + QAction* m_backPlayAction; + QAction* m_forwardPlayAction; + QAction* m_backMarkAction; + QAction* m_forwardMarkAction; + QAction* m_playModeAction; + QMenu* m_playModeMenu; + QAction* m_audioAction; + QSlider* m_audioSlider; + QMenu* m_audioMenu; + QAction* m_muteAction; + + QIcon m_playModeOnceIcon; + QIcon m_playModeLoopIcon; + QIcon m_playModePingPongIcon; + + QIcon m_volumeZeroIcon; + QIcon m_volumeLowIcon; + QIcon m_volumeMediumIcon; + QIcon m_volumeHighIcon; + QIcon m_volumeHighMutedIcon; + }; template - void setVolumeLevel (T& inst, int level); - - void setVolumeIcon(); - - IPCore::Session* m_session; - QAction* m_smAction; - QAction* m_paintAction; - QAction* m_infoAction; - QAction* m_networkAction; - QAction* m_timelineMagAction; - QAction* m_timelineAction; - QAction* m_backStepAction; - QAction* m_forwardStepAction; - QAction* m_backPlayAction; - QAction* m_forwardPlayAction; - QAction* m_backMarkAction; - QAction* m_forwardMarkAction; - QAction* m_playModeAction; - QMenu* m_playModeMenu; - QAction* m_audioAction; - QSlider* m_audioSlider; - QMenu* m_audioMenu; - QAction* m_muteAction; - - QIcon m_playModeOnceIcon; - QIcon m_playModeLoopIcon; - QIcon m_playModePingPongIcon; - - QIcon m_volumeZeroIcon; - QIcon m_volumeLowIcon; - QIcon m_volumeMediumIcon; - QIcon m_volumeHighIcon; - QIcon m_volumeHighMutedIcon; - -}; - -template -void RvBottomViewToolBar::setVolumeLevel(T& inst, int level) -{ - if (level > 67) - { - inst.setIcon(m_volumeHighIcon); - } - else if (level > 33) + void RvBottomViewToolBar::setVolumeLevel(T& inst, int level) { - inst.setIcon(m_volumeMediumIcon); + if (level > 67) + { + inst.setIcon(m_volumeHighIcon); + } + else if (level > 33) + { + inst.setIcon(m_volumeMediumIcon); + } + else if (level > 0) + { + inst.setIcon(m_volumeLowIcon); + } + else + { + inst.setIcon(m_volumeZeroIcon); + } } - else if (level > 0) - { - inst.setIcon(m_volumeLowIcon); - } - else - { - inst.setIcon(m_volumeZeroIcon); - } -} -} // Rv +} // namespace Rv #endif // __RvCommon__RvBottomViewToolBar__h__ diff --git a/src/lib/app/RvCommon/RvCommon/RvConsoleApplication.h b/src/lib/app/RvCommon/RvCommon/RvConsoleApplication.h index 815011f4f..05ec9ff45 100644 --- a/src/lib/app/RvCommon/RvCommon/RvConsoleApplication.h +++ b/src/lib/app/RvCommon/RvCommon/RvConsoleApplication.h @@ -13,13 +13,13 @@ namespace Rv { - class RvConsoleApplication : public IPCore::Application - { - public: - RvConsoleApplication(); - virtual ~RvConsoleApplication() = default; - - private: - TwkMediaLibrary::PyMediaLibrary m_pyLibrary; - }; -} // namespace Rv \ No newline at end of file + class RvConsoleApplication : public IPCore::Application + { + public: + RvConsoleApplication(); + virtual ~RvConsoleApplication() = default; + + private: + TwkMediaLibrary::PyMediaLibrary m_pyLibrary; + }; +} // namespace Rv diff --git a/src/lib/app/RvCommon/RvCommon/RvConsoleWindow.h b/src/lib/app/RvCommon/RvCommon/RvConsoleWindow.h index 3576d15e9..a678cd9ea 100644 --- a/src/lib/app/RvCommon/RvCommon/RvConsoleWindow.h +++ b/src/lib/app/RvCommon/RvCommon/RvConsoleWindow.h @@ -1,9 +1,9 @@ //****************************************************************************** -// Copyright (c) 2008 Tweak Inc. +// Copyright (c) 2008 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #ifndef __RvCommon__RvConsoleWindow__h__ #define __RvCommon__RvConsoleWindow__h__ @@ -14,70 +14,73 @@ #include #include - -namespace Rv { - -class RvConsoleWindow: public QDialog +namespace Rv { - Q_OBJECT -public: - - class ConsoleBuf : public std::streambuf + class RvConsoleWindow : public QDialog { - public: - ConsoleBuf(RvConsoleWindow *w) : m_console(w) {} - int sync(); - int overflow( int ch ); - std::streamsize xsputn(char *text, std::streamsize n); - - void sendLine(); - - RvConsoleWindow* m_console; - std::string m_lineBuffer; - QMutex m_mutex; + Q_OBJECT + + public: + class ConsoleBuf : public std::streambuf + { + public: + ConsoleBuf(RvConsoleWindow* w) + : m_console(w) + { + } + + int sync(); + int overflow(int ch); + std::streamsize xsputn(char* text, std::streamsize n); + + void sendLine(); + + RvConsoleWindow* m_console; + std::string m_lineBuffer; + QMutex m_mutex; + }; + + RvConsoleWindow(QWidget* parent = 0); + virtual ~RvConsoleWindow(); + + int append(const char* text, size_t n); + void append(const std::string& text); + + QTextEdit* textEdit() const { return m_ui.textEdit; } + + void appendLine(const std::string&); + bool processLine(std::string&, QString& html); + bool processAndDisplayLine(std::string&); + + void processTimer(); + + // To be called in place of processTextBuffer (see below) prior to + // exiting the process exit(-1). This will prevent some funny business + // in the exit() function such as trying to start QtTimers in + // ConsoleBuf::sync() for example + void processLastTextBuffer(); + + public slots: + void processTextBuffer(); + + private: + void closeEvent(QCloseEvent*); + + private: + QMutex m_lock; + Ui::RvConsoleDialog m_ui; + std::ostream* m_cout; + std::ostream* m_cerr; + std::streambuf* m_stdoutBuf; + std::streambuf* m_stderrBuf; + ConsoleBuf* m_consoleBuf; + std::stringstream m_textBuffer; + QTimer* m_processTimer; + bool m_processTimerRunning; + TwkUtil::FileLogger m_fileLogger; }; - RvConsoleWindow(QWidget* parent=0); - virtual ~RvConsoleWindow(); - - int append(const char* text, size_t n); - void append(const std::string& text); - - QTextEdit* textEdit() const { return m_ui.textEdit; } - - void appendLine(const std::string&); - bool processLine(std::string&, QString& html); - bool processAndDisplayLine(std::string&); - - void processTimer(); - - // To be called in place of processTextBuffer (see below) prior to exiting - // the process exit(-1). This will prevent some funny business in the exit() - // function such as trying to start QtTimers in ConsoleBuf::sync() for example - void processLastTextBuffer(); - -public slots: - void processTextBuffer(); - -private: - void closeEvent(QCloseEvent*); - -private: - QMutex m_lock; - Ui::RvConsoleDialog m_ui; - std::ostream* m_cout; - std::ostream* m_cerr; - std::streambuf* m_stdoutBuf; - std::streambuf* m_stderrBuf; - ConsoleBuf* m_consoleBuf; - std::stringstream m_textBuffer; - QTimer* m_processTimer; - bool m_processTimerRunning; - TwkUtil::FileLogger m_fileLogger; - -}; - -} // Rv +} // namespace Rv #endif // __RvCommon__RvConsoleWindow__h__ diff --git a/src/lib/app/RvCommon/RvCommon/RvDocument.h b/src/lib/app/RvCommon/RvCommon/RvDocument.h index c3bd773fb..9771cff1b 100644 --- a/src/lib/app/RvCommon/RvCommon/RvDocument.h +++ b/src/lib/app/RvCommon/RvCommon/RvDocument.h @@ -1,9 +1,9 @@ //****************************************************************************** -// Copyright (c) 2007 Tweak Inc. +// Copyright (c) 2007 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #ifndef __rv_qt__RvDocument__h__ #define __rv_qt__RvDocument__h__ @@ -21,155 +21,169 @@ class QLabel; class QMenu; class QToolBar; -namespace TwkApp { -class Menu; +namespace TwkApp +{ + class Menu; } -namespace Rv { -class GLView; -class DesktopVideoModule; -class DesktopVideoDevice; -class RvTopViewToolBar; -class RvBottomViewToolBar; -class RvSourceEditor; -class DisplayLink; - -class RvDocument : public QMainWindow, public TwkUtil::Notifier +namespace Rv { - Q_OBJECT + class GLView; + class DesktopVideoModule; + class DesktopVideoDevice; + class RvTopViewToolBar; + class RvBottomViewToolBar; + class RvSourceEditor; + class DisplayLink; + + class RvDocument + : public QMainWindow + , public TwkUtil::Notifier + { + Q_OBJECT - public: - RvDocument(); - virtual ~RvDocument(); + public: + RvDocument(); + virtual ~RvDocument(); - virtual std::string name() const { return "RvDocument"; } + virtual std::string name() const { return "RvDocument"; } - RvSession *session() const { return m_session; } + RvSession* session() const { return m_session; } - virtual QRect childrenRect(); - void center(); - void resizeToFit(bool placement=false, bool firstTime=false); - void resizeView(int w, int h); - void toggleFullscreen(bool firstTime=false); - void toggleMenuBar(); - bool menuBarShown() const { return m_menuBarShown; }; - bool startupResize() const { return m_startupResize; }; - bool aggressiveSizing() { return m_aggressiveSizing; }; - void setAggressiveSizing(bool v) { m_aggressiveSizing = v; }; - QMenu* mainPopup() const { return m_mainPopup; } - GLView* view() const; - const QAction* lastPopupAction() const { return m_lastPopupAction; } + virtual QRect childrenRect(); + void center(); + void resizeToFit(bool placement = false, bool firstTime = false); + void resizeView(int w, int h); + void toggleFullscreen(bool firstTime = false); + void toggleMenuBar(); - RvTopViewToolBar* topViewToolBar() const { return m_topViewToolBar; }; - RvBottomViewToolBar* bottomViewToolBar() const { return m_bottomViewToolBar; } + bool menuBarShown() const { return m_menuBarShown; }; - void setDocumentDisabled(bool window, bool menuBarOnly=false); + bool startupResize() const { return m_startupResize; }; - QMenuBar* mb(); + bool aggressiveSizing() { return m_aggressiveSizing; }; - void addWatchFile(const std::string&); - void removeWatchFile(const std::string&); + void setAggressiveSizing(bool v) { m_aggressiveSizing = v; }; - void viewSizeChanged(int w, int h); + QMenu* mainPopup() const { return m_mainPopup; } - // - // The resulting popup is associated with this RvDocument only - // and is owned by it. The TwkApp::Menu* will be deleted by the - // document at some later time. the Menu is only used once. - // + GLView* view() const; - void popupMenu(TwkApp::Menu*, QPoint point, bool shortcuts=true); + const QAction* lastPopupAction() const { return m_lastPopupAction; } + RvTopViewToolBar* topViewToolBar() const { return m_topViewToolBar; }; - enum DisplayOutputType - { - OpenGLDefaultFormat, // whatever you get - OpenGL8888, // 8 bits per channel + (maybe) alpha - OpenGL1010102 // 10 bits per channel + (maybe) 2 bits alpha + RvBottomViewToolBar* bottomViewToolBar() const + { + return m_bottomViewToolBar; + } + + void setDocumentDisabled(bool window, bool menuBarOnly = false); + + QMenuBar* mb(); + + void addWatchFile(const std::string&); + void removeWatchFile(const std::string&); + + void viewSizeChanged(int w, int h); + + // + // The resulting popup is associated with this RvDocument only + // and is owned by it. The TwkApp::Menu* will be deleted by the + // document at some later time. the Menu is only used once. + // + + void popupMenu(TwkApp::Menu*, QPoint point, bool shortcuts = true); + + enum DisplayOutputType + { + OpenGLDefaultFormat, // whatever you get + OpenGL8888, // 8 bits per channel + (maybe) alpha + OpenGL1010102 // 10 bits per channel + (maybe) 2 bits alpha + }; + + void setStereo(bool); + void setVSync(bool); + void setDoubleBuffer(bool); + void setDisplayOutput(DisplayOutputType); + + void disconnectActions(const QList&); + + void resetGLStateAndPrefs(); + + bool vsyncDisabled() const { return m_vsyncDisabled; } + + bool queryDriverVSync() const; + void checkDriverVSync(); + void warnOnDriverVSync(); + + void editSourceNode(const std::string&); + + void physicalVideoDeviceChangedSlot(const TwkApp::VideoDevice*); + void playStartSlot(const std::string&); + void playStopSlot(const std::string&); + + protected: + // Overrides for TwkUtil::Notifier + virtual bool receive(Notifier*, Notifier*, MessageId, MessageData*); + + void enableActions(bool, QMenu*); + + private slots: + void menuActivated(); + void aboutToShowMenu(); + void buildMenu(); + void watchedFileChanged(const QString&); + void frameChanged(); + void resetSizePolicy(); + void lazyDeleteGLView(); + + private: + void purgeMenus(); + void mergeMenu(const TwkApp::Menu*, bool shortcuts = true); + void convert(QMenu*, const TwkApp::Menu*, bool shortcuts); + + void closeEvent(QCloseEvent*); + void changeEvent(QEvent*); + bool event(QEvent*); + void moveEvent(QMoveEvent*); + + void setBuildMenu(); + + void rebuildGLView(bool stereo, bool vsync, bool dbl, int, int, int, + int); + + private: + RvSession* m_session; + QMenu* m_rvMenu; + QMenu* m_mainPopup; + QMenu* m_userPopup; + TwkApp::Menu* m_userMenu; + GLView* m_glView; + GLView* m_oldGLView; + QWidget* m_viewContainerWidget; + RvTopViewToolBar* m_topViewToolBar; + RvBottomViewToolBar* m_bottomViewToolBar; + QWidget* m_centralWidget; + QStackedLayout* m_stackedLayout; + int m_menuBarHeight; + bool m_menuBarDisable; + bool m_menuBarShown; + bool m_startupResize; + bool m_aggressiveSizing; + int m_menuExecuting; + QTimer* m_menuTimer; + QTimer* m_frameChangedTimer; + QTimer* m_resetPolicyTimer; + const QAction* m_lastPopupAction; + QFileSystemWatcher* m_watcher; + bool m_currentlyClosing; + bool m_closeEventReceived; + bool m_vsyncDisabled; + RvSourceEditor* m_sourceEditor; + DisplayLink* m_displayLink; }; - void setStereo(bool); - void setVSync(bool); - void setDoubleBuffer(bool); - void setDisplayOutput(DisplayOutputType); - - void disconnectActions(const QList &); - - void resetGLStateAndPrefs(); - - bool vsyncDisabled() const { return m_vsyncDisabled; } - - bool queryDriverVSync() const; - void checkDriverVSync(); - void warnOnDriverVSync(); - - void editSourceNode(const std::string&); - - void physicalVideoDeviceChangedSlot(const TwkApp::VideoDevice*); - void playStartSlot(const std::string&); - void playStopSlot(const std::string&); - - protected: - // Overrides for TwkUtil::Notifier - virtual bool receive( Notifier *, Notifier *, MessageId, MessageData * ); - - void enableActions(bool, QMenu*); - - private slots: - void menuActivated(); - void aboutToShowMenu(); - void buildMenu(); - void watchedFileChanged(const QString&); - void frameChanged(); - void resetSizePolicy(); - void lazyDeleteGLView(); - - private: - void purgeMenus(); - void mergeMenu(const TwkApp::Menu*, bool shortcuts=true); - void convert(QMenu*, const TwkApp::Menu*, bool shortcuts); - - void closeEvent(QCloseEvent*); - void changeEvent(QEvent*); - bool event(QEvent*); - void moveEvent(QMoveEvent*); - - void setBuildMenu(); - - void rebuildGLView(bool stereo, bool vsync, bool dbl, int, int, int, int); - - private: - RvSession* m_session; - QMenu* m_rvMenu; - QMenu* m_mainPopup; - QMenu* m_userPopup; - TwkApp::Menu* m_userMenu; - GLView* m_glView; - GLView* m_oldGLView; - QWidget* m_viewContainerWidget; - RvTopViewToolBar* m_topViewToolBar; - RvBottomViewToolBar* m_bottomViewToolBar; - QWidget* m_centralWidget; - QStackedLayout* m_stackedLayout; - int m_menuBarHeight; - bool m_menuBarDisable; - bool m_menuBarShown; - bool m_startupResize; - bool m_aggressiveSizing; - int m_menuExecuting; - QTimer* m_menuTimer; - QTimer* m_frameChangedTimer; - QTimer* m_resetPolicyTimer; - const QAction* m_lastPopupAction; - QFileSystemWatcher* m_watcher; - bool m_currentlyClosing; - bool m_closeEventReceived; - bool m_vsyncDisabled; - RvSourceEditor* m_sourceEditor; - DisplayLink* m_displayLink; -}; - - -} // Rv +} // namespace Rv #endif // __rv-qt__RvDocument__h__ diff --git a/src/lib/app/RvCommon/RvCommon/RvFileDialog.h b/src/lib/app/RvCommon/RvCommon/RvFileDialog.h index 3e0698afb..3df212edb 100644 --- a/src/lib/app/RvCommon/RvCommon/RvFileDialog.h +++ b/src/lib/app/RvCommon/RvCommon/RvFileDialog.h @@ -1,9 +1,9 @@ // -// Copyright (c) 2008 Tweak Software. +// Copyright (c) 2008 Tweak Software. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// // #ifndef __RvCommon__RvFileDialog__h__ #define __RvCommon__RvFileDialog__h__ @@ -19,170 +19,172 @@ #include -namespace Rv { -class MediaDirModel; -class FileTypeTraits; - -/// Replacement Qt File Dialog with Preview - -/// -/// This class replaces the default Qt file dialog. It does three -/// things that are majorly different: NeXT-like multiple-list -/// scrolling navigation (list mode), preview area, and handles -/// sequences as a single item. Otherwise, it tries to be mostly -/// compatible with the Qt API. -/// - -class RvFileDialog : public QDialog +namespace Rv { - Q_OBJECT + class MediaDirModel; + class FileTypeTraits; - public: - enum FileMode - { - OneExistingFile, - ManyExistingFiles, - ManyExistingFilesAndDirectories, - OneFileName, - OneDirectory, - OneDirectoryName - }; - - enum ViewMode - { - ColumnView, - DetailedFileView, - DetailedMediaView, - NoViewMode - }; + /// Replacement Qt File Dialog with Preview + + /// + /// This class replaces the default Qt file dialog. It does three + /// things that are majorly different: NeXT-like multiple-list + /// scrolling navigation (list mode), preview area, and handles + /// sequences as a single item. Otherwise, it tries to be mostly + /// compatible with the Qt API. + /// - enum Role + class RvFileDialog : public QDialog { - OpenFileRole, - SaveFileRole + Q_OBJECT + + public: + enum FileMode + { + OneExistingFile, + ManyExistingFiles, + ManyExistingFilesAndDirectories, + OneFileName, + OneDirectory, + OneDirectoryName + }; + + enum ViewMode + { + ColumnView, + DetailedFileView, + DetailedMediaView, + NoViewMode + }; + + enum Role + { + OpenFileRole, + SaveFileRole + }; + + RvFileDialog(QWidget* parent, FileTypeTraits*, Role role, + Qt::WindowFlags flags = Qt::Sheet, + QString settingsGroup = "FileDialog"); + + virtual ~RvFileDialog(); + + void setDirectory(const QString& dir, bool force = false); + void setCurrentFile(const QString& file); + + void setFileTypeTraits(FileTypeTraits*); + void setFileTypeIndex(size_t); + + void setFileMode(FileMode m); + void setFilter(QDir::Filters filters); + void setViewMode(ViewMode v); + void lockViewMode(bool lock); + void setRole(Role r); + void setTitleLabel(const QString&); + + QString existingFileChoice() const { return m_currentFile; } + + QStringList selectedFiles() const; + void centerOverApp(); + + public slots: + void reloadTimeout(); + void sidePanelTimeout(); + void columnViewTimeout(); + void pathComboChanged(int); + void inputPathEntry(); + void reload(bool); + void autoRefreshChanged(int); + void watchedDirChanged(const QString&); + + void sidePanelInserted(const QModelIndex&, int, int); + void sidePanelPopup(const QPoint&); + void sidePanelGo(bool); + void sidePanelAccept(bool); + void sidePanelRemove(bool); + void sidePanelClick(QListWidgetItem*); + void sidePanelDoubleClick(QListWidgetItem*); + + void viewComboChanged(int); + void sortComboChanged(int); + + void columnSelectionChanged(const QItemSelection&, + const QItemSelection&); + void columnUpdatePreview(const QModelIndex&); + + void treeSelectionChanged(const QItemSelection&, const QItemSelection&); + + void iconViewChanged(QAction*); + + void doubleClickAccept(const QModelIndex&); + + void accept(); + void reject(); + + void fileTypeChanged(int); + + void hiddenViewChanged(bool); + + void prevButtonTrigger(QAction*); + void nextButtonTrigger(QAction*); + + void resizeColumns(const QModelIndex&); + + public: + void done(int); + + protected: + virtual bool eventFilter(QObject* object, QEvent* event); + virtual bool event(QEvent*); + void saveSidePanel(); + void loadSidePanel(); + + QFileInfoList findMountPoints(); + + QListWidgetItem* newItemForFile(const QFileInfo&); + QIcon iconForFile(const QFileInfo&); + + private: + FileMode m_fileMode; + ViewMode m_viewMode; + bool m_viewModeLocked; + Role m_role; + QDir::Filters m_filters; + QString m_currentFile; + QString m_settingsGroup; + QStringList m_dirPrev; + QStringList m_dirNext; + Ui::RvFileDialog m_ui; + bool m_building; + QTimer* m_reloadTimer; + QTimer* m_sidePanelTimer; + QTimer* m_columnViewTimer; + QString m_columnViewFile; + QListWidgetItem* m_newCurrent; + int m_sideInsertStart; + int m_sideInsertEnd; + QMenu* m_sidePanelPopup; + bool m_sidePanelAccept; + QTreeView* m_detailTree; + QColumnView* m_columnView; + QTextEdit* m_columnPreview; + MediaDirModel* m_detailFileModel; + MediaDirModel* m_detailMediaModel; + MediaDirModel* m_columnModel; + FileTypeTraits* m_fileTraits; + QProcess m_process; + QMenu* m_configPopup; + QAction* m_cpSystem; + QAction* m_cpGeneric; + QAction* m_cpNone; + QAction* m_cpHidden; + QSet m_drives; + QFileSystemWatcher* m_watcher; + static QMap m_iconMap; + static QStringList m_visited; + bool m_allowAutoRefresh; }; - RvFileDialog ( QWidget* parent, - FileTypeTraits*, - Role role, - Qt::WindowFlags flags=Qt::Sheet, - QString settingsGroup="FileDialog"); - - virtual ~RvFileDialog(); - - void setDirectory(const QString& dir, bool force=false); - void setCurrentFile(const QString& file); - - void setFileTypeTraits(FileTypeTraits*); - void setFileTypeIndex(size_t); - - void setFileMode(FileMode m); - void setFilter(QDir::Filters filters); - void setViewMode(ViewMode v); - void lockViewMode(bool lock); - void setRole(Role r); - void setTitleLabel(const QString&); - - QString existingFileChoice() const { return m_currentFile; } - QStringList selectedFiles() const; - void centerOverApp(); - - public slots: - void reloadTimeout(); - void sidePanelTimeout(); - void columnViewTimeout(); - void pathComboChanged(int); - void inputPathEntry(); - void reload(bool); - void autoRefreshChanged(int); - void watchedDirChanged(const QString&); - - void sidePanelInserted(const QModelIndex&,int,int); - void sidePanelPopup(const QPoint&); - void sidePanelGo(bool); - void sidePanelAccept(bool); - void sidePanelRemove(bool); - void sidePanelClick(QListWidgetItem*); - void sidePanelDoubleClick(QListWidgetItem*); - - void viewComboChanged(int); - void sortComboChanged(int); - - void columnSelectionChanged(const QItemSelection&, const QItemSelection&); - void columnUpdatePreview(const QModelIndex&); - - void treeSelectionChanged(const QItemSelection&, const QItemSelection&); - - void iconViewChanged(QAction*); - - void doubleClickAccept(const QModelIndex&); - - void accept(); - void reject(); - - void fileTypeChanged(int); - - void hiddenViewChanged(bool); - - void prevButtonTrigger(QAction*); - void nextButtonTrigger(QAction*); - - void resizeColumns(const QModelIndex&); - public: - void done(int); - - protected: - virtual bool eventFilter(QObject *object, QEvent *event); - virtual bool event(QEvent*); - void saveSidePanel(); - void loadSidePanel(); - - QFileInfoList findMountPoints(); - - QListWidgetItem* newItemForFile(const QFileInfo&); - QIcon iconForFile(const QFileInfo&); - - private: - FileMode m_fileMode; - ViewMode m_viewMode; - bool m_viewModeLocked; - Role m_role; - QDir::Filters m_filters; - QString m_currentFile; - QString m_settingsGroup; - QStringList m_dirPrev; - QStringList m_dirNext; - Ui::RvFileDialog m_ui; - bool m_building; - QTimer* m_reloadTimer; - QTimer* m_sidePanelTimer; - QTimer* m_columnViewTimer; - QString m_columnViewFile; - QListWidgetItem* m_newCurrent; - int m_sideInsertStart; - int m_sideInsertEnd; - QMenu* m_sidePanelPopup; - bool m_sidePanelAccept; - QTreeView* m_detailTree; - QColumnView* m_columnView; - QTextEdit* m_columnPreview; - MediaDirModel* m_detailFileModel; - MediaDirModel* m_detailMediaModel; - MediaDirModel* m_columnModel; - FileTypeTraits* m_fileTraits; - QProcess m_process; - QMenu* m_configPopup; - QAction* m_cpSystem; - QAction* m_cpGeneric; - QAction* m_cpNone; - QAction* m_cpHidden; - QSet m_drives; - QFileSystemWatcher* m_watcher; - static QMap m_iconMap; - static QStringList m_visited; - bool m_allowAutoRefresh; -}; - -} // Rv +} // namespace Rv #endif // __RvCommon__RvFileDialog__h__ diff --git a/src/lib/app/RvCommon/RvCommon/RvJavaScriptObject.h b/src/lib/app/RvCommon/RvCommon/RvJavaScriptObject.h index aec7cc414..380c72121 100644 --- a/src/lib/app/RvCommon/RvCommon/RvJavaScriptObject.h +++ b/src/lib/app/RvCommon/RvCommon/RvJavaScriptObject.h @@ -1,9 +1,9 @@ // -// Copyright (c) 2009 Tweak Software. +// Copyright (c) 2009 Tweak Software. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// // #ifndef __RvCommon__RvJavaScriptObject__h__ #define __RvCommon__RvJavaScriptObject__h__ @@ -15,84 +15,80 @@ class QWebEnginePage; class QWebChannel; -namespace Rv { -class RvDocument; - -class RvJavaScriptObject : public QObject, public TwkApp::EventNode +namespace Rv { - Q_OBJECT - - public: - RvJavaScriptObject(RvDocument*, QWebEnginePage* frame); - virtual ~RvJavaScriptObject(); - - virtual Result receiveEvent(const TwkApp::Event&); - - public slots: - QString evaluate(const QString& mu); - QString pyevaluate(const QString& py); - void pyexec(const QString& py); - QString sendInternalEvent(const QString& eventName, - const QString& contents, - const QString& sender); - void bindToRegex(const QString& nameRegex); - void unbindRegex(const QString& nameRegex); - bool hasBinding(const QString& nameRegex); - void emitReady(); - - signals: - // - // These are the TwkApp::Event types: - // - // ActivityChangeEvent DragDropEvent - // Event GenericStringEvent - // KeyEvent KeyPressEvent - // KeyReleaseEvent ModifierEvent - // PointerButtonPressEvent - // PointerButtonReleaseEvent PointerEvent - // RawDataEvent RenderContextChangeEvent - // RenderEvent TabletEvent - // - // Each of these should become a signal with the relevant info as - // args. Some of them can be merged (e.g. PointerButtonPressEvent - // and PointerButtonReleaseEvent) by just supplying the name of - // the event as well. So in the pointer case we only need a - // pointerEvent() in javascript which indicates which of the - // pointer events it actually was along with the data. - // - - void eventString(const QString& eventName, - const QString& contents, - const QString& senderName); - - void eventKey(const QString& eventName, - unsigned int key, - unsigned int modifiers); - - void eventPointer(const QString& eventName, - int x, int y, int w, int h, - int startX, int startY, - int buttonStates, - float activationTime); - - void eventDragDrop(const QString& eventName, - int x, int y, int w, int h, - int startX, int startY, - int buttonStates, - const QString& dragDropType, - const QString& contentType, - const QString& contents); - - private: - RvDocument* m_doc; - - QWebChannel* m_channel; - - QWebEnginePage* m_frame; - - QList m_eventNames; -}; - -} // Rv + class RvDocument; + + class RvJavaScriptObject + : public QObject + , public TwkApp::EventNode + { + Q_OBJECT + + public: + RvJavaScriptObject(RvDocument*, QWebEnginePage* frame); + virtual ~RvJavaScriptObject(); + + virtual Result receiveEvent(const TwkApp::Event&); + + public slots: + QString evaluate(const QString& mu); + QString pyevaluate(const QString& py); + void pyexec(const QString& py); + QString sendInternalEvent(const QString& eventName, + const QString& contents, + const QString& sender); + void bindToRegex(const QString& nameRegex); + void unbindRegex(const QString& nameRegex); + bool hasBinding(const QString& nameRegex); + void emitReady(); + + signals: + // + // These are the TwkApp::Event types: + // + // ActivityChangeEvent DragDropEvent + // Event GenericStringEvent + // KeyEvent KeyPressEvent + // KeyReleaseEvent ModifierEvent + // PointerButtonPressEvent + // PointerButtonReleaseEvent PointerEvent + // RawDataEvent RenderContextChangeEvent + // RenderEvent TabletEvent + // + // Each of these should become a signal with the relevant info as + // args. Some of them can be merged (e.g. PointerButtonPressEvent + // and PointerButtonReleaseEvent) by just supplying the name of + // the event as well. So in the pointer case we only need a + // pointerEvent() in javascript which indicates which of the + // pointer events it actually was along with the data. + // + + void eventString(const QString& eventName, const QString& contents, + const QString& senderName); + + void eventKey(const QString& eventName, unsigned int key, + unsigned int modifiers); + + void eventPointer(const QString& eventName, int x, int y, int w, int h, + int startX, int startY, int buttonStates, + float activationTime); + + void eventDragDrop(const QString& eventName, int x, int y, int w, int h, + int startX, int startY, int buttonStates, + const QString& dragDropType, + const QString& contentType, const QString& contents); + + private: + RvDocument* m_doc; + + QWebChannel* m_channel; + + QWebEnginePage* m_frame; + + QList m_eventNames; + }; + +} // namespace Rv #endif // __RvCommon__RvJavaScriptObject__h__ diff --git a/src/lib/app/RvCommon/RvCommon/RvNetworkDialog.h b/src/lib/app/RvCommon/RvCommon/RvNetworkDialog.h index 2e50d0479..7c0cd2092 100644 --- a/src/lib/app/RvCommon/RvCommon/RvNetworkDialog.h +++ b/src/lib/app/RvCommon/RvCommon/RvNetworkDialog.h @@ -1,9 +1,9 @@ // -// Copyright (c) 2008 Tweak Software. +// Copyright (c) 2008 Tweak Software. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// // #ifndef __RvCommon__RvNetworkDialog__h__ #define __RvCommon__RvNetworkDialog__h__ @@ -17,110 +17,123 @@ #include -namespace TwkQtChat { -class Client; -class Connection; -} - -namespace Rv { - -class RvNetworkDialog : public QWidget +namespace TwkQtChat { - Q_OBJECT + class Client; + class Connection; +} // namespace TwkQtChat - public: - typedef TwkQtChat::Client Client; - typedef QMap ContactMap; - typedef std::map SessionMap; +namespace Rv +{ - enum ConnectPermission + class RvNetworkDialog : public QWidget { - AskConnect = 0, - AllowConnect, - DenyConnect, - CurrentConnect + Q_OBJECT + + public: + typedef TwkQtChat::Client Client; + typedef QMap ContactMap; + typedef std::map SessionMap; + + enum ConnectPermission + { + AskConnect = 0, + AllowConnect, + DenyConnect, + CurrentConnect + }; + + RvNetworkDialog(QWidget*); + ~RvNetworkDialog(); + + TwkQtChat::Client* client() { return m_client; } + + std::vector contacts() const; + std::vector connections() const; + std::vector applications() const; + std::vector sessions(); + + void spoofConnectionStream(const QString& fileName, + float timeScale = 1.0, bool verbose = false); + + std::string localContactName() + { + return std::string(m_ui.nameLineEdit->text().toUtf8().constData()); + } + + void setLocalContactName(std::string n) + { + m_ui.nameLineEdit->setText(n.c_str()); + } + + int defaultPermission() { return m_ui.permissionCombo->currentIndex(); } + + void setDefaultPermission(int i) + { + m_ui.permissionCombo->setCurrentIndex(i); + } + + public slots: + void newRemoteContact(const QString&); + void newData(const QString&, const QString&, const QByteArray&); + void newMessage(const QString&, const QString&); + void remoteContactLeft(const QString&); + void toggleServer(); + + bool serverRunning() { return (m_client != 0); }; + + int myPort(); + void connectByName(std::string host, int port); + void requestConnection(TwkQtChat::Connection*); + void startConnect(); + void popupConnect(bool); + void popupDelete(bool); + void popupDisconnect(bool); + void popup(const QPoint&); + void doubleClickContact(const QModelIndex&); + void resetConfig(); + void contactError(const QString&, const QString&, const QString&); + + void shutdownServer(); + void sessionDeleted(const char* name); + + private: + void startConnectDialog(const QString&); + void updateStatus(); + void loadSettings(); + void saveSettings(); + void closeEvent(QCloseEvent* event); + + int findContact(const QString& name, const QString& host); + + void addContact(const QString& name, const QString& host, + TwkQtChat::Connection* connection, unsigned int perms, + const QString& capp, bool checkForExisting = true); + + ConnectPermission contactPermission(const QStringList& parts); + + void sendSessionEvent(const QString&, const QString&, const QString&); + + bool confirmDisconnect(const QString&); + std::set selectedContacts(); + + IPCore::Session* targetSession(QString sender, + bool doDisconnect = true); + + void savePortNumber(); + void deletePortNumberFile(); + + private: + Ui::RvNetworkDialog m_ui; + QDialog m_connectDialog; + Ui::RvNetworkConnect m_connectUI; + Client* m_client; + QStandardItemModel* m_contactsModel; + QMenu* m_contactPopup; + SessionMap m_sessionMap; + QString m_portFile; }; - RvNetworkDialog(QWidget*); - ~RvNetworkDialog(); - - TwkQtChat::Client* client() { return m_client; } - - std::vector contacts() const; - std::vector connections() const; - std::vector applications() const; - std::vector sessions(); - - void spoofConnectionStream (const QString& fileName, float timeScale=1.0, bool verbose=false); - - std::string localContactName() { return std::string(m_ui.nameLineEdit->text().toUtf8().constData()); } - void setLocalContactName(std::string n) { m_ui.nameLineEdit->setText(n.c_str()); } - - int defaultPermission() { return m_ui.permissionCombo->currentIndex(); } - void setDefaultPermission(int i) { m_ui.permissionCombo->setCurrentIndex(i); } - - public slots: - void newRemoteContact(const QString&); - void newData(const QString&, const QString&, const QByteArray&); - void newMessage(const QString&, const QString&); - void remoteContactLeft(const QString&); - void toggleServer(); - bool serverRunning() { return (m_client != 0); }; - int myPort(); - void connectByName(std::string host, int port); - void requestConnection(TwkQtChat::Connection*); - void startConnect(); - void popupConnect(bool); - void popupDelete(bool); - void popupDisconnect(bool); - void popup(const QPoint&); - void doubleClickContact(const QModelIndex&); - void resetConfig(); - void contactError(const QString&, const QString&, const QString&); - - void shutdownServer(); - void sessionDeleted(const char* name); - - private: - void startConnectDialog(const QString&); - void updateStatus(); - void loadSettings(); - void saveSettings(); - void closeEvent(QCloseEvent* event); - - int findContact(const QString& name, - const QString& host); - - void addContact(const QString& name, - const QString& host, - TwkQtChat::Connection* connection, - unsigned int perms, - const QString& capp, - bool checkForExisting=true); - - ConnectPermission contactPermission(const QStringList& parts); - - void sendSessionEvent(const QString&, const QString&, const QString&); - - bool confirmDisconnect(const QString&); - std::set selectedContacts(); - - IPCore::Session* targetSession(QString sender, bool doDisconnect=true); - - void savePortNumber(); - void deletePortNumberFile(); - - private: - Ui::RvNetworkDialog m_ui; - QDialog m_connectDialog; - Ui::RvNetworkConnect m_connectUI; - Client* m_client; - QStandardItemModel* m_contactsModel; - QMenu* m_contactPopup; - SessionMap m_sessionMap; - QString m_portFile; -}; - -} // Rv +} // namespace Rv #endif // __RvCommon__RvNetworkDialog__h__ diff --git a/src/lib/app/RvCommon/RvCommon/RvPreferences.h b/src/lib/app/RvCommon/RvCommon/RvPreferences.h index 23f81937b..44b4eef16 100644 --- a/src/lib/app/RvCommon/RvCommon/RvPreferences.h +++ b/src/lib/app/RvCommon/RvCommon/RvPreferences.h @@ -1,9 +1,9 @@ //****************************************************************************** -// Copyright (c) 2008 Tweak Inc. +// Copyright (c) 2008 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #ifndef __RvCommon__RvPreferences__h__ #define __RvCommon__RvPreferences__h__ @@ -23,215 +23,225 @@ class QSettings; -namespace TwkApp { -class VideoDevice; -class VideoModule; -} - -namespace Rv { - -class RvPreferences: public QDialog, public PackageManager -{ - Q_OBJECT - -public: - RvPreferences(QWidget* parent=0); - virtual ~RvPreferences(); - - void update(); - - static void loadSettingsIntoOptions(Options&); - - static void resetPreferencesFile(); - - QTabWidget* tabWidget() const { return m_ui.tabWidget; } - - // - // PackageManager API - // - - virtual bool fixLoadability(const QString& msg); - virtual bool fixUnloadability(const QString& msg); - virtual bool overwriteExistingFiles(const QString& msg); - virtual bool installDependantPackages(const QString& msg); - virtual void errorMissingPackageDependancies(const QString& msg); - virtual bool uninstallDependantPackages(const QString& msg); - virtual void informCannotRemoveSomeFiles(const QString& msg); - virtual void errorModeFileWriteFailed(const QString& file); - virtual void informPackageFailedToCopy(const QString& msg); - virtual void declarePackage(Package&, size_t); - virtual bool uninstallForRemoval(const QString& msg); - - virtual void loadPackages(); - - void updateVideo(); - void updateVideoFormat(TwkApp::VideoDevice*); - void updateVideo4KTransport(TwkApp::VideoDevice*); - void updateVideoDataFormat(TwkApp::VideoDevice*); - void updateVideoSync(TwkApp::VideoDevice*); - void updateVideoSyncSource(TwkApp::VideoDevice*); - void updateVideoAudioFormat(TwkApp::VideoDevice*); - - void updateVideoProfiles(TwkApp::VideoDevice*); - void updateVideoOptions(TwkApp::VideoDevice*); - - TwkApp::VideoDevice* currentVideoDevice() const; - - void updateStyleSheet(); - -public slots: - void write(); - void exrAutoThreads(int state); - void exrThreadNumChanged(const QString& text); - void addPackageItem(const Package&, size_t); - void packageSelection(const QItemSelection&, const QItemSelection&); - void clickedPackage(QModelIndex); - void addPackage(bool); - void removePackage(bool); - void showHiddenPackages(bool); - - void stylusAsMouseChanged(int); - void startupResizeChanged(int); - - void audioModuleChanged(int index); - void audioDeviceChanged(int index); - void audioChannelsChanged(int index); - void audioFormatChanged(int index); - void audioRateChanged(int index); - void audioHoldOpenChanged(int); - void audioVideoSyncChanged(int); - void audioPreRollChanged(int); - void audioDevicePacketChanged(); - void audioCachePacketChanged(); - void audioOffsetFinished(); - void audioDeviceLatencyFinished(); - - - void lookaheadCacheSizeFinisihed(); - void regionCacheSizeFinisihed(); - void bufferWaitFinished(); - void lookBehindFinished(); - void rthreadFinished(); - void cacheOutsideRegionChanged(int); - - void bitDepthChanged(int); - void allowFloatChanged(int); - void newGLSLlutInterpChanged(int); - void swapScanlinesChanged(int); - void prefetchChanged(int); - void appleClientStorageChanged(int); - void useThreadedUploadChanged(int); - void videoSyncChanged(int); - void displayOutputChanged(int); - - void exrRGBAChanged(int); - void exrInheritChanged(int); - void exrPlanar3ChannelChanged(int); - void exrNoOneChannelChanged(int); - void exrReadWindowIsDisplayWindowChanged(int); - void exrNumThreadsFinished(); - void exrChunkSizeFinished(); - void exrMaxInFlightFinished(); - void exrIOMethodChanged(int); - void exrReadWindowChanged(int); - - void cinChunkSizeFinished(); - void cinMaxInFlightFinished(); - void cinIOMethodChanged(int); - void cinChromaChanged(int); - void cinPixelsChanged(int); - - void dpxChunkSizeFinished(); - void dpxMaxInFlightFinished(); - void dpxIOMethodChanged(int); - void dpxChromaChanged(int); - void dpxPixelsChanged(int); - - void tgaChunkSizeFinished(); - void tgaMaxInFlightFinished(); - void tgaIOMethodChanged(int); - - void tiffChunkSizeFinished(); - void tiffMaxInFlightFinished(); - void tiffIOMethodChanged(int); - - void jpegChunkSizeFinished(); - void jpegMaxInFlightFinished(); - void jpegIOMethodChanged(int); - void jpegRGBAChanged(int); - - void videoModuleChanged(int); - void videoDeviceChanged(int); - void videoFormatChanged(int); - void video4KTransportChanged(int); - void videoDataFormatChanged(int); - void syncMethodChanged(int); - void syncSourceChanged(int); - void presentationCheckBoxChanged(int); - void videoAudioCheckBoxChanged(int); - void videoAudioFormatChanged(int); - void videoSwapStereoEyesChanged(int); - void videoUseLatencyCheckBoxChanged(int); - void videoAdditionalOptionsChanged(); - - void modProfileChanged(int); - void devProfileChanged(int); - void formatProfileChanged(int); - - void configVideoLatency(); - - void fixedLatencyChanged(const QString&); - void frameLatencyChanged(const QString&); - - void fontChanged(); - -private: - void closeEvent(QCloseEvent*); - static void loadSettingsIntoOptions(RvSettings&, Options&); - static void write(QSettings&); - void latencyChanged(const QString&, bool); - - bool initAudioDeviceMenu(IPCore::AudioRenderer::RendererParameters ¶ms, - const IPCore::AudioRenderer::DeviceVector &devices, - const std::string ¤tDeviceName); - - bool initAudioLayoutMenu(IPCore::AudioRenderer::RendererParameters ¶ms, - const IPCore::AudioRenderer::LayoutsVector &layouts, - const IPCore::AudioRenderer::Layout ¤tLayout); - - bool initAudioFormatMenu(IPCore::AudioRenderer::RendererParameters ¶ms, - const IPCore::AudioRenderer::FormatVector &formats, - const IPCore::AudioRenderer::Format ¤tFormat); - - bool initAudioRatesMenu(IPCore::AudioRenderer::RendererParameters ¶ms, - const IPCore::AudioRenderer::RateVector &rates, - const size_t ¤tRate); - -private: - Ui::RvPreferences m_ui; - Ui::packageLocationDialog m_packageLocationUI; - Ui::PrefVideoLatencyDialog m_videoLatencyUI; - QDialog* m_packageLocationDialog; - QDialog* m_videoLatencyDialog; - QStandardItemModel* m_packageModel; - int m_currentVideoModule; - int m_currentVideoDevice; - bool m_showHiddenPackages; - bool m_updated; - bool m_lockPresentCheck; -}; - -class ScrollEventEater : public QObject +namespace TwkApp { - Q_OBJECT + class VideoDevice; + class VideoModule; +} // namespace TwkApp - public: - ScrollEventEater (QObject *obj) : QObject(obj) {} - - protected: - bool eventFilter(QObject *obj, QEvent *event); -}; +namespace Rv +{ -} // Rv + class RvPreferences + : public QDialog + , public PackageManager + { + Q_OBJECT + + public: + RvPreferences(QWidget* parent = 0); + virtual ~RvPreferences(); + + void update(); + + static void loadSettingsIntoOptions(Options&); + + static void resetPreferencesFile(); + + QTabWidget* tabWidget() const { return m_ui.tabWidget; } + + // + // PackageManager API + // + + virtual bool fixLoadability(const QString& msg); + virtual bool fixUnloadability(const QString& msg); + virtual bool overwriteExistingFiles(const QString& msg); + virtual bool installDependantPackages(const QString& msg); + virtual void errorMissingPackageDependancies(const QString& msg); + virtual bool uninstallDependantPackages(const QString& msg); + virtual void informCannotRemoveSomeFiles(const QString& msg); + virtual void errorModeFileWriteFailed(const QString& file); + virtual void informPackageFailedToCopy(const QString& msg); + virtual void declarePackage(Package&, size_t); + virtual bool uninstallForRemoval(const QString& msg); + + virtual void loadPackages(); + + void updateVideo(); + void updateVideoFormat(TwkApp::VideoDevice*); + void updateVideo4KTransport(TwkApp::VideoDevice*); + void updateVideoDataFormat(TwkApp::VideoDevice*); + void updateVideoSync(TwkApp::VideoDevice*); + void updateVideoSyncSource(TwkApp::VideoDevice*); + void updateVideoAudioFormat(TwkApp::VideoDevice*); + + void updateVideoProfiles(TwkApp::VideoDevice*); + void updateVideoOptions(TwkApp::VideoDevice*); + + TwkApp::VideoDevice* currentVideoDevice() const; + + void updateStyleSheet(); + + public slots: + void write(); + void exrAutoThreads(int state); + void exrThreadNumChanged(const QString& text); + void addPackageItem(const Package&, size_t); + void packageSelection(const QItemSelection&, const QItemSelection&); + void clickedPackage(QModelIndex); + void addPackage(bool); + void removePackage(bool); + void showHiddenPackages(bool); + + void stylusAsMouseChanged(int); + void startupResizeChanged(int); + + void audioModuleChanged(int index); + void audioDeviceChanged(int index); + void audioChannelsChanged(int index); + void audioFormatChanged(int index); + void audioRateChanged(int index); + void audioHoldOpenChanged(int); + void audioVideoSyncChanged(int); + void audioPreRollChanged(int); + void audioDevicePacketChanged(); + void audioCachePacketChanged(); + void audioOffsetFinished(); + void audioDeviceLatencyFinished(); + + void lookaheadCacheSizeFinisihed(); + void regionCacheSizeFinisihed(); + void bufferWaitFinished(); + void lookBehindFinished(); + void rthreadFinished(); + void cacheOutsideRegionChanged(int); + + void bitDepthChanged(int); + void allowFloatChanged(int); + void newGLSLlutInterpChanged(int); + void swapScanlinesChanged(int); + void prefetchChanged(int); + void appleClientStorageChanged(int); + void useThreadedUploadChanged(int); + void videoSyncChanged(int); + void displayOutputChanged(int); + + void exrRGBAChanged(int); + void exrInheritChanged(int); + void exrPlanar3ChannelChanged(int); + void exrNoOneChannelChanged(int); + void exrReadWindowIsDisplayWindowChanged(int); + void exrNumThreadsFinished(); + void exrChunkSizeFinished(); + void exrMaxInFlightFinished(); + void exrIOMethodChanged(int); + void exrReadWindowChanged(int); + + void cinChunkSizeFinished(); + void cinMaxInFlightFinished(); + void cinIOMethodChanged(int); + void cinChromaChanged(int); + void cinPixelsChanged(int); + + void dpxChunkSizeFinished(); + void dpxMaxInFlightFinished(); + void dpxIOMethodChanged(int); + void dpxChromaChanged(int); + void dpxPixelsChanged(int); + + void tgaChunkSizeFinished(); + void tgaMaxInFlightFinished(); + void tgaIOMethodChanged(int); + + void tiffChunkSizeFinished(); + void tiffMaxInFlightFinished(); + void tiffIOMethodChanged(int); + + void jpegChunkSizeFinished(); + void jpegMaxInFlightFinished(); + void jpegIOMethodChanged(int); + void jpegRGBAChanged(int); + + void videoModuleChanged(int); + void videoDeviceChanged(int); + void videoFormatChanged(int); + void video4KTransportChanged(int); + void videoDataFormatChanged(int); + void syncMethodChanged(int); + void syncSourceChanged(int); + void presentationCheckBoxChanged(int); + void videoAudioCheckBoxChanged(int); + void videoAudioFormatChanged(int); + void videoSwapStereoEyesChanged(int); + void videoUseLatencyCheckBoxChanged(int); + void videoAdditionalOptionsChanged(); + + void modProfileChanged(int); + void devProfileChanged(int); + void formatProfileChanged(int); + + void configVideoLatency(); + + void fixedLatencyChanged(const QString&); + void frameLatencyChanged(const QString&); + + void fontChanged(); + + private: + void closeEvent(QCloseEvent*); + static void loadSettingsIntoOptions(RvSettings&, Options&); + static void write(QSettings&); + void latencyChanged(const QString&, bool); + + bool + initAudioDeviceMenu(IPCore::AudioRenderer::RendererParameters& params, + const IPCore::AudioRenderer::DeviceVector& devices, + const std::string& currentDeviceName); + + bool + initAudioLayoutMenu(IPCore::AudioRenderer::RendererParameters& params, + const IPCore::AudioRenderer::LayoutsVector& layouts, + const IPCore::AudioRenderer::Layout& currentLayout); + + bool + initAudioFormatMenu(IPCore::AudioRenderer::RendererParameters& params, + const IPCore::AudioRenderer::FormatVector& formats, + const IPCore::AudioRenderer::Format& currentFormat); + + bool + initAudioRatesMenu(IPCore::AudioRenderer::RendererParameters& params, + const IPCore::AudioRenderer::RateVector& rates, + const size_t& currentRate); + + private: + Ui::RvPreferences m_ui; + Ui::packageLocationDialog m_packageLocationUI; + Ui::PrefVideoLatencyDialog m_videoLatencyUI; + QDialog* m_packageLocationDialog; + QDialog* m_videoLatencyDialog; + QStandardItemModel* m_packageModel; + int m_currentVideoModule; + int m_currentVideoDevice; + bool m_showHiddenPackages; + bool m_updated; + bool m_lockPresentCheck; + }; + + class ScrollEventEater : public QObject + { + Q_OBJECT + + public: + ScrollEventEater(QObject* obj) + : QObject(obj) + { + } + + protected: + bool eventFilter(QObject* obj, QEvent* event); + }; + +} // namespace Rv #endif // __RvCommon__RvPreferences__h__ diff --git a/src/lib/app/RvCommon/RvCommon/RvProfileManager.h b/src/lib/app/RvCommon/RvCommon/RvProfileManager.h index dcb1877d1..1d85a0434 100644 --- a/src/lib/app/RvCommon/RvCommon/RvProfileManager.h +++ b/src/lib/app/RvCommon/RvCommon/RvProfileManager.h @@ -1,9 +1,9 @@ // -// Copyright (c) 2013 Tweak Software. +// Copyright (c) 2013 Tweak Software. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// // #ifndef __RvCommon__RvProfileManager__h__ #define __RvCommon__RvProfileManager__h__ @@ -13,43 +13,45 @@ #include #include -namespace IPCore { -class Profile; +namespace IPCore +{ + class Profile; } -namespace Rv { - -class RvProfileManager : public QDialog +namespace Rv { - Q_OBJECT - public: - typedef QPair QStringPair; - typedef std::vector ProfileVector; + class RvProfileManager : public QDialog + { + Q_OBJECT + + public: + typedef QPair QStringPair; + typedef std::vector ProfileVector; - RvProfileManager(QObject*); - virtual ~RvProfileManager(); + RvProfileManager(QObject*); + virtual ~RvProfileManager(); - void loadModel(); + void loadModel(); - public slots: - void addProfile(); - void deleteProfile(); - void selectionChanged(const QItemSelection&,const QItemSelection&); - void applyProfile(); + public slots: + void addProfile(); + void deleteProfile(); + void selectionChanged(const QItemSelection&, const QItemSelection&); + void applyProfile(); - private: - void clear(); - IPCore::Profile* currentProfile(); + private: + void clear(); + IPCore::Profile* currentProfile(); - private: - Ui::RvProfileManager m_ui; - Ui::CreateProfileDialog m_createDialogUI; - QDialog* m_createDialog; - QStandardItemModel* m_model; - ProfileVector m_profiles; -}; + private: + Ui::RvProfileManager m_ui; + Ui::CreateProfileDialog m_createDialogUI; + QDialog* m_createDialog; + QStandardItemModel* m_model; + ProfileVector m_profiles; + }; -} // Rv +} // namespace Rv #endif // __RvCommon__RvProfileManager__h__ diff --git a/src/lib/app/RvCommon/RvCommon/RvSourceEditor.h b/src/lib/app/RvCommon/RvCommon/RvSourceEditor.h index 7221fbc66..223290cce 100644 --- a/src/lib/app/RvCommon/RvCommon/RvSourceEditor.h +++ b/src/lib/app/RvCommon/RvCommon/RvSourceEditor.h @@ -1,9 +1,9 @@ // -// Copyright (c) 2013 Tweak Software. +// Copyright (c) 2013 Tweak Software. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// // #ifndef __RvCommon__RvSourceEditor__h__ #define __RvCommon__RvSourceEditor__h__ @@ -17,71 +17,79 @@ class QTextEdit; class QSyntaxHighlighter; class QComboBox; -namespace IPCore { -class Session; -class DynamicIPNode; -} - -namespace Rv { - -class RvSourceEditor : public QMainWindow, public TwkApp::EventNode +namespace IPCore { - Q_OBJECT + class Session; + class DynamicIPNode; +} // namespace IPCore - public: +namespace Rv +{ - struct NodeEditState + class RvSourceEditor + : public QMainWindow + , public TwkApp::EventNode { - NodeEditState(IPCore::DynamicIPNode* n=0, const std::string& s="") - : node(n), source(s) {} - IPCore::DynamicIPNode* node; - std::string source; - }; + Q_OBJECT + + public: + struct NodeEditState + { + NodeEditState(IPCore::DynamicIPNode* n = 0, + const std::string& s = "") + : node(n) + , source(s) + { + } - typedef std::map NodeEditStateMap; + IPCore::DynamicIPNode* node; + std::string source; + }; - RvSourceEditor(IPCore::Session*, QWidget* parent = 0); - virtual ~RvSourceEditor(); + typedef std::map NodeEditStateMap; - virtual Result receiveEvent(const TwkApp::Event&); + RvSourceEditor(IPCore::Session*, QWidget* parent = 0); + virtual ~RvSourceEditor(); - void editNode(const std::string& node); - void initFromNode(IPCore::DynamicIPNode*); + virtual Result receiveEvent(const TwkApp::Event&); - private: - void updateSourceMargin(bool); + void editNode(const std::string& node); + void initFromNode(IPCore::DynamicIPNode*); - public slots: - void compile(); - void typeChanged(int); - void sourceChanged(); - void importFile(); - void publish(); - void publishAccepted(); - void revert(); - void deselectAll(); - void downLine(); - void upLine(); - void forwardWord(); - void backWord(); - void tabChanged(int); - void tabClosed(int); + private: + void updateSourceMargin(bool); - private: - Ui::RvSourceEditor m_ui; - Ui::PublishDialog m_publishUI; - QDialog* m_publishDialog; - QTextEdit* m_textEdit; - IPCore::Session* m_session; - QSyntaxHighlighter* m_highlighter; - QComboBox* m_typeComboBox; - NodeEditStateMap m_stateMap; - QWidget* m_currentPage; - IPCore::DynamicIPNode* m_node; - bool m_changeLock; - bool m_updateLock; -}; + public slots: + void compile(); + void typeChanged(int); + void sourceChanged(); + void importFile(); + void publish(); + void publishAccepted(); + void revert(); + void deselectAll(); + void downLine(); + void upLine(); + void forwardWord(); + void backWord(); + void tabChanged(int); + void tabClosed(int); + + private: + Ui::RvSourceEditor m_ui; + Ui::PublishDialog m_publishUI; + QDialog* m_publishDialog; + QTextEdit* m_textEdit; + IPCore::Session* m_session; + QSyntaxHighlighter* m_highlighter; + QComboBox* m_typeComboBox; + NodeEditStateMap m_stateMap; + QWidget* m_currentPage; + IPCore::DynamicIPNode* m_node; + bool m_changeLock; + bool m_updateLock; + }; -} // Rv +} // namespace Rv #endif // __RvCommon__RvSourceEditor__h__ diff --git a/src/lib/app/RvCommon/RvCommon/RvTopViewToolBar.h b/src/lib/app/RvCommon/RvCommon/RvTopViewToolBar.h index 84579458a..558f26455 100644 --- a/src/lib/app/RvCommon/RvCommon/RvTopViewToolBar.h +++ b/src/lib/app/RvCommon/RvCommon/RvTopViewToolBar.h @@ -1,9 +1,9 @@ // -// Copyright (c) 2012 Tweak Software. +// Copyright (c) 2012 Tweak Software. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// // #ifndef __RvCommon__RvTopViewToolBar__h__ #define __RvCommon__RvTopViewToolBar__h__ @@ -17,181 +17,185 @@ #include #include -namespace TwkApp { -class VideoDevice; +namespace TwkApp +{ + class VideoDevice; } -namespace IPCore { -class Session; +namespace IPCore +{ + class Session; } -namespace Rv { - -class RvTopViewToolBar : public QToolBar, public TwkApp::EventNode +namespace Rv { - Q_OBJECT - - public: - typedef std::vector QActionVector; - typedef QMap QIconMap; - typedef TwkApp::VideoDevice VideoDevice; - - RvTopViewToolBar(QWidget*); - virtual ~RvTopViewToolBar(); - - void build(); - void makeActive(bool); - void makeActiveFromSettings(); - - void setSession(IPCore::Session*); - virtual Result receiveEvent(const TwkApp::Event&); - - bool isInPresentationMode() const; - - void setStereo(const std::string&); - void setChannel(int); - - void setDevice(const VideoDevice* d) { m_device = d; } - void setTransferFunction(const std::string&, float); - void setPrimaries(const TwkMath::Chromaticities&); - - void setFullscreen(bool); - - - virtual bool event(QEvent*); - void bgMenuUpdate2(); - - private slots: - void nextViewNode(); - void previousViewNode(); - void frame(); - void fullscreen(); - - void viewMenuUpdate(); - void viewMenuChanged(QAction*); - void frameMenuChanged(QAction*); - - void bgMenuUpdate(); - void bgBlack(); - void bg18(); - void bg50(); - void bgWhite(); - void bgChecker(); - void bgHatch(); - - void stereoMenuUpdate(); - void monoStereo(); - void anaglyphStereo(); - void lumanaglyphStereo(); - void sideBySideStereo(); - void mirroredStereo(); - void checkerStereo(); - void scanlineStereo(); - void leftStereo(); - void rightStereo(); - void shutterStereo(); - void swapEyes(); - - void channelMenuUpdate(); - void channelsRGB(); - void channelsR(); - void channelsG(); - void channelsB(); - void channelsA(); - void channelsL(); - - void monitorMenuUpdate(); - - void monitorMenuRVUpdate(); - void monitorMenuOCIOUpdate(); - void transferNone(); - void transferSRGB(); - void transferRec709(); - void transfer22(); - void transfer24(); - void transfer26(); - void primaries709(); - void primariesP3(); - void primariesSMPTEC(); - void primariesXYZ(); - void primariesAdobeRGB(); - void primariesDreamColor(); - void ditherOff(); - void dither8(); - void dither10(); - - bool hasStandardDisplayPipeline(); - - private: - void updateActionToolButton(QAction* action, - const std::string& text, - const std::string& icon, - bool forceRepaint=false); - - private: - IPCore::Session* m_session; - QAction* m_viewBackAction; - QAction* m_viewForwardAction; - QComboBox* m_viewCombo; - QMenu* m_viewMenu; - QAction* m_fullScreenAction; - QAction* m_frameAction; - QAction* m_bgMenuAction; - QAction* m_blackBGAction; - QAction* m_18GreyBGAction; - QAction* m_50GreyBGAction; - QAction* m_whiteBGAction; - QAction* m_checkerBGAction; - QAction* m_crossHatchBGAction; - QAction* m_stereoMenuAction; - QAction* m_monoStereoAction; - QAction* m_anaglyphStereoAction; - QAction* m_lumanaglyphStereoAction; - QAction* m_sideBySideStereoAction; - QAction* m_mirroredSideBySideStereoAction; - QAction* m_checkerStereoAction; - QAction* m_scanlineStereoAction; - QAction* m_leftStereoAction; - QAction* m_rightStereoAction; - QAction* m_shutterStereoAction; - QAction* m_swapStereoAction; - QActionVector m_stereoActions; - QAction* m_channelMenuAction; - QAction* m_viewMenuAction; - QAction* m_RGBChannelAction; - QAction* m_RChannelAction; - QAction* m_GChannelAction; - QAction* m_BChannelAction; - QAction* m_AChannelAction; - QAction* m_LChannelAction; - QMenu* m_monitorMenu; - QAction* m_monitorMenuAction; - QLabel* m_monitorInfoLabel; - QAction* m_transferTitleAction; - QAction* m_primariesTitleAction; - QAction* m_ditherTitleAction; - QAction* m_noTransferAction; - QAction* m_srgbAction; - QAction* m_rec709Action; - QAction* m_g22Action; - QAction* m_g24Action; - QAction* m_g26Action; - QAction* m_gOtherAction; - QAction* m_primaries709Action; - QAction* m_primariesP3Action; - QAction* m_primariesXYZAction; - QAction* m_primariesSMPTECAction; - QAction* m_primariesAdobeRGBAction; - QAction* m_primariesDreamColorAction; - QAction* m_ditherOff; - QAction* m_dither8; - QAction* m_dither10; - bool m_loading; - QIconMap m_iconMap; - const VideoDevice* m_device; - const VideoDevice* m_outputDevice; -}; - -} // Rv + + class RvTopViewToolBar + : public QToolBar + , public TwkApp::EventNode + { + Q_OBJECT + + public: + typedef std::vector QActionVector; + typedef QMap QIconMap; + typedef TwkApp::VideoDevice VideoDevice; + + RvTopViewToolBar(QWidget*); + virtual ~RvTopViewToolBar(); + + void build(); + void makeActive(bool); + void makeActiveFromSettings(); + + void setSession(IPCore::Session*); + virtual Result receiveEvent(const TwkApp::Event&); + + bool isInPresentationMode() const; + + void setStereo(const std::string&); + void setChannel(int); + + void setDevice(const VideoDevice* d) { m_device = d; } + + void setTransferFunction(const std::string&, float); + void setPrimaries(const TwkMath::Chromaticities&); + + void setFullscreen(bool); + + virtual bool event(QEvent*); + void bgMenuUpdate2(); + + private slots: + void nextViewNode(); + void previousViewNode(); + void frame(); + void fullscreen(); + + void viewMenuUpdate(); + void viewMenuChanged(QAction*); + void frameMenuChanged(QAction*); + + void bgMenuUpdate(); + void bgBlack(); + void bg18(); + void bg50(); + void bgWhite(); + void bgChecker(); + void bgHatch(); + + void stereoMenuUpdate(); + void monoStereo(); + void anaglyphStereo(); + void lumanaglyphStereo(); + void sideBySideStereo(); + void mirroredStereo(); + void checkerStereo(); + void scanlineStereo(); + void leftStereo(); + void rightStereo(); + void shutterStereo(); + void swapEyes(); + + void channelMenuUpdate(); + void channelsRGB(); + void channelsR(); + void channelsG(); + void channelsB(); + void channelsA(); + void channelsL(); + + void monitorMenuUpdate(); + + void monitorMenuRVUpdate(); + void monitorMenuOCIOUpdate(); + void transferNone(); + void transferSRGB(); + void transferRec709(); + void transfer22(); + void transfer24(); + void transfer26(); + void primaries709(); + void primariesP3(); + void primariesSMPTEC(); + void primariesXYZ(); + void primariesAdobeRGB(); + void primariesDreamColor(); + void ditherOff(); + void dither8(); + void dither10(); + + bool hasStandardDisplayPipeline(); + + private: + void updateActionToolButton(QAction* action, const std::string& text, + const std::string& icon, + bool forceRepaint = false); + + private: + IPCore::Session* m_session; + QAction* m_viewBackAction; + QAction* m_viewForwardAction; + QComboBox* m_viewCombo; + QMenu* m_viewMenu; + QAction* m_fullScreenAction; + QAction* m_frameAction; + QAction* m_bgMenuAction; + QAction* m_blackBGAction; + QAction* m_18GreyBGAction; + QAction* m_50GreyBGAction; + QAction* m_whiteBGAction; + QAction* m_checkerBGAction; + QAction* m_crossHatchBGAction; + QAction* m_stereoMenuAction; + QAction* m_monoStereoAction; + QAction* m_anaglyphStereoAction; + QAction* m_lumanaglyphStereoAction; + QAction* m_sideBySideStereoAction; + QAction* m_mirroredSideBySideStereoAction; + QAction* m_checkerStereoAction; + QAction* m_scanlineStereoAction; + QAction* m_leftStereoAction; + QAction* m_rightStereoAction; + QAction* m_shutterStereoAction; + QAction* m_swapStereoAction; + QActionVector m_stereoActions; + QAction* m_channelMenuAction; + QAction* m_viewMenuAction; + QAction* m_RGBChannelAction; + QAction* m_RChannelAction; + QAction* m_GChannelAction; + QAction* m_BChannelAction; + QAction* m_AChannelAction; + QAction* m_LChannelAction; + QMenu* m_monitorMenu; + QAction* m_monitorMenuAction; + QLabel* m_monitorInfoLabel; + QAction* m_transferTitleAction; + QAction* m_primariesTitleAction; + QAction* m_ditherTitleAction; + QAction* m_noTransferAction; + QAction* m_srgbAction; + QAction* m_rec709Action; + QAction* m_g22Action; + QAction* m_g24Action; + QAction* m_g26Action; + QAction* m_gOtherAction; + QAction* m_primaries709Action; + QAction* m_primariesP3Action; + QAction* m_primariesXYZAction; + QAction* m_primariesSMPTECAction; + QAction* m_primariesAdobeRGBAction; + QAction* m_primariesDreamColorAction; + QAction* m_ditherOff; + QAction* m_dither8; + QAction* m_dither10; + bool m_loading; + QIconMap m_iconMap; + const VideoDevice* m_device; + const VideoDevice* m_outputDevice; + }; + +} // namespace Rv #endif // __RvCommon__RvTopViewToolBar__h__ diff --git a/src/lib/app/RvCommon/RvCommon/RvViewerWidget.h b/src/lib/app/RvCommon/RvCommon/RvViewerWidget.h index db5cab577..98ff0b2f7 100644 --- a/src/lib/app/RvCommon/RvCommon/RvViewerWidget.h +++ b/src/lib/app/RvCommon/RvCommon/RvViewerWidget.h @@ -1,9 +1,9 @@ // -// Copyright (c) 2012 Tweak Software. +// Copyright (c) 2012 Tweak Software. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// // #ifndef __RvCommon__RvViewerWidget__h__ #define __RvCommon__RvViewerWidget__h__ @@ -11,19 +11,20 @@ #include #include -namespace Rv { - -class RvViewerWidget : public QWidget +namespace Rv { - public: - RvViewerWidget(); - private: - QToolBar* m_topToolBar; - QToolBar* m_bottomToolBar; - GLView* m_glView; -} + class RvViewerWidget : public QWidget + { + public: + RvViewerWidget(); + + private: + QToolBar* m_topToolBar; + QToolBar* m_bottomToolBar; + GLView* m_glView; + } -} // Rv +} // namespace Rv #endif // __RvCommon__RvViewerWidget__h__ diff --git a/src/lib/app/RvCommon/RvCommon/RvWebManager.h b/src/lib/app/RvCommon/RvCommon/RvWebManager.h index 158383309..07d4a4ec2 100644 --- a/src/lib/app/RvCommon/RvCommon/RvWebManager.h +++ b/src/lib/app/RvCommon/RvCommon/RvWebManager.h @@ -1,9 +1,9 @@ // -// Copyright (c) 2009 Tweak Software. +// Copyright (c) 2009 Tweak Software. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// // #ifndef __RvCommon__RvWebManager__h__ #define __RvCommon__RvWebManager__h__ @@ -13,115 +13,110 @@ #include #include -namespace IPCore { -class Session; +namespace IPCore +{ + class Session; } -namespace Rv { - -class LocalNetworkAccessManager : public QNetworkAccessManager +namespace Rv { - Q_OBJECT - - public: - LocalNetworkAccessManager(QObject* parent) : QNetworkAccessManager(parent) {}; - - virtual QNetworkReply* createRequest( - QNetworkAccessManager::Operation operation, - const QNetworkRequest& request, - QIODevice* device); -}; - -class RvWebManager : public QObject -{ - Q_OBJECT - - public: - typedef QPair StringPair; - typedef QList HeaderList; - struct ReplyData + class LocalNetworkAccessManager : public QNetworkAccessManager { - ReplyData() : session(0), callback(0) {} - IPCore::Session* session; - QUrl url; - QString replyEvent; - QString authenticationEvent; - QString progressEvent; - bool ignoreSslErrors; - void (*callback)(); - QString tag; + Q_OBJECT + + public: + LocalNetworkAccessManager(QObject* parent) + : QNetworkAccessManager(parent) {}; + + virtual QNetworkReply* + createRequest(QNetworkAccessManager::Operation operation, + const QNetworkRequest& request, QIODevice* device); }; - typedef QMap ReplyMap; - - RvWebManager (QObject* parent = 0); - virtual ~RvWebManager (); - - void httpGet(const QString& url, - const HeaderList& headers, - IPCore::Session* session, - const QString& replyEvent, - const QString& authenticationEvent, - const QString& progressEvent, - bool ignoreSslErrors = false, - bool urlIsEncoded = false); - - void httpPost(const QString& url, - const HeaderList& headers, - const QByteArray& postData, - IPCore::Session* session, - const QString& replyEvent, - const QString& authenticationEvent, - const QString& progressEvent, - bool ignoreSslErrors = false, - bool urlIsEncoded = false, - void (*callback)() = 0, - QString tag = ""); - - void httpPut( const QString& url, - const HeaderList& headers, - const QByteArray& putData, - IPCore::Session* session, - const QString& replyEvent, - const QString& authenticationEvent, - const QString& progressEvent, - bool ignoreSslErrors = false, - bool urlIsEncoded = false, - void (*callback)() = 0, - QString tag = ""); - - QNetworkAccessManager* netManager() const { return m_netManager; } - - public slots: - void replyDone(QNetworkReply*); - void replyRead(); - void replyError(QNetworkReply::NetworkError); - void replySSLErrors(QList); - void managerSSLErrors(QNetworkReply*, QList); - void replyAuthentication(QNetworkReply*,QAuthenticator*); - - private: - LocalNetworkAccessManager* m_netManager; - ReplyMap m_replyMap; -}; - -class NetworkReplyTimeout : public QObject -{ - Q_OBJECT + class RvWebManager : public QObject + { + Q_OBJECT + + public: + typedef QPair StringPair; + typedef QList HeaderList; + + struct ReplyData + { + ReplyData() + : session(0) + , callback(0) + { + } + + IPCore::Session* session; + QUrl url; + QString replyEvent; + QString authenticationEvent; + QString progressEvent; + bool ignoreSslErrors; + void (*callback)(); + QString tag; + }; + + typedef QMap ReplyMap; + + RvWebManager(QObject* parent = 0); + virtual ~RvWebManager(); + + void httpGet(const QString& url, const HeaderList& headers, + IPCore::Session* session, const QString& replyEvent, + const QString& authenticationEvent, + const QString& progressEvent, bool ignoreSslErrors = false, + bool urlIsEncoded = false); + + void httpPost(const QString& url, const HeaderList& headers, + const QByteArray& postData, IPCore::Session* session, + const QString& replyEvent, + const QString& authenticationEvent, + const QString& progressEvent, + bool ignoreSslErrors = false, bool urlIsEncoded = false, + void (*callback)() = 0, QString tag = ""); + + void httpPut(const QString& url, const HeaderList& headers, + const QByteArray& putData, IPCore::Session* session, + const QString& replyEvent, + const QString& authenticationEvent, + const QString& progressEvent, bool ignoreSslErrors = false, + bool urlIsEncoded = false, void (*callback)() = 0, + QString tag = ""); + + QNetworkAccessManager* netManager() const { return m_netManager; } + + public slots: + void replyDone(QNetworkReply*); + void replyRead(); + void replyError(QNetworkReply::NetworkError); + void replySSLErrors(QList); + void managerSSLErrors(QNetworkReply*, QList); + void replyAuthentication(QNetworkReply*, QAuthenticator*); + + private: + LocalNetworkAccessManager* m_netManager; + ReplyMap m_replyMap; + }; - public: - NetworkReplyTimeout(QNetworkReply* reply, const int timeout); - ~NetworkReplyTimeout(); + class NetworkReplyTimeout : public QObject + { + Q_OBJECT - private slots: - void timeout(); + public: + NetworkReplyTimeout(QNetworkReply* reply, const int timeout); + ~NetworkReplyTimeout(); - private: - QString m_tag; -}; + private slots: + void timeout(); + private: + QString m_tag; + }; -} // Rv +} // namespace Rv #endif // __RvCommon__RvWebManager__h__ diff --git a/src/lib/app/RvCommon/RvCommon/StreamConnection.h b/src/lib/app/RvCommon/RvCommon/StreamConnection.h index 4d8555e96..c839bd043 100644 --- a/src/lib/app/RvCommon/RvCommon/StreamConnection.h +++ b/src/lib/app/RvCommon/RvCommon/StreamConnection.h @@ -1,9 +1,9 @@ // -// Copyright (c) 2008 Tweak Software. +// Copyright (c) 2008 Tweak Software. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// // #ifndef __RvCommon__StreamConnection__h__ #define __RvCommon__StreamConnection__h__ @@ -16,72 +16,73 @@ class QFile; class QDataStream; -namespace Rv { - -class StreamConnection : public TwkQtChat::Connection +namespace Rv { - Q_OBJECT - public: - - enum StreamItemType + class StreamConnection : public TwkQtChat::Connection { - MessageItemType, - DataItemType - }; + Q_OBJECT - enum StreamState - { - NormalState, - StoringState, - SpoofingState - }; + public: + enum StreamItemType + { + MessageItemType, + DataItemType + }; - StreamConnection(QObject *parent, bool pingpong); - ~StreamConnection(); + enum StreamState + { + NormalState, + StoringState, + SpoofingState + }; - static TwkQtChat::Connection* connectionFactory(QObject*, bool); + StreamConnection(QObject* parent, bool pingpong); + ~StreamConnection(); - void storeStream(const std::string& baseDir); + static TwkQtChat::Connection* connectionFactory(QObject*, bool); - bool spoofStream(const std::string& fileName, bool verbose); - void startSpoofing(float timeScale=1.0); + void storeStream(const std::string& baseDir); - void dumpStream(const std::string& fileName); + bool spoofStream(const std::string& fileName, bool verbose); + void startSpoofing(float timeScale = 1.0); - StreamState streamState() { return m_streamState; } + void dumpStream(const std::string& fileName); - // - // TwkQtChat::Connection API - // + StreamState streamState() { return m_streamState; } - virtual bool sendMessage(const QString &message); - virtual bool sendData(const QString& interp, const QByteArray& data); + // + // TwkQtChat::Connection API + // - virtual bool isLocal(); - virtual const QString& remoteName() const; - virtual const QString& remoteApp() const; - virtual const QString& remoteContactName() const; + virtual bool sendMessage(const QString& message); + virtual bool sendData(const QString& interp, const QByteArray& data); - private slots: - void handleNextEvent(); + virtual bool isLocal(); + virtual const QString& remoteName() const; + virtual const QString& remoteApp() const; + virtual const QString& remoteContactName() const; - private: - StreamState m_streamState; // Normal, Storing, or Spoofing - QFile* m_streamFile; - QDataStream* m_streamDataStream; // Write tream for storage or Read stream for spoofing. - TwkUtil::Timer m_eventTimer; // Absolute time. - QTimer m_intervalTimer; // For spacing out spoofed events. + private slots: + void handleNextEvent(); - QString m_name; - QString m_app; - QString m_contactName; + private: + StreamState m_streamState; // Normal, Storing, or Spoofing + QFile* m_streamFile; + QDataStream* m_streamDataStream; // Write tream for storage or Read + // stream for spoofing. + TwkUtil::Timer m_eventTimer; // Absolute time. + QTimer m_intervalTimer; // For spacing out spoofed events. - float m_currentTime; // Scheduled time of current event. - float m_timeScale; // Smaller is faster - bool m_verbose; -}; + QString m_name; + QString m_app; + QString m_contactName; + + float m_currentTime; // Scheduled time of current event. + float m_timeScale; // Smaller is faster + bool m_verbose; + }; -}; +}; // namespace Rv #endif //__RvCommon__StreamConnection__h__ diff --git a/src/lib/app/RvCommon/RvCommon/TwkQTAction.h b/src/lib/app/RvCommon/RvCommon/TwkQTAction.h index 672ea034b..5f1ca3131 100644 --- a/src/lib/app/RvCommon/RvCommon/TwkQTAction.h +++ b/src/lib/app/RvCommon/RvCommon/TwkQTAction.h @@ -1,9 +1,9 @@ //****************************************************************************** -// Copyright (c) 2007 Tweak Inc. +// Copyright (c) 2007 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #ifndef __rv_qt__TwkQTAction__h__ #define __rv_qt__TwkQTAction__h__ @@ -12,31 +12,32 @@ #include #include -namespace TwkApp { -class Action; +namespace TwkApp +{ + class Action; } -namespace Rv { -class RvDocument; - -class TwkQTAction : public QAction +namespace Rv { - Q_OBJECT - -public: - TwkQTAction(const TwkApp::Menu::Item*, - RvDocument* document, - QObject* parent); + class RvDocument; + + class TwkQTAction : public QAction + { + Q_OBJECT + + public: + TwkQTAction(const TwkApp::Menu::Item*, RvDocument* document, + QObject* parent); - const TwkApp::Menu::Item* item() const { return m_item; } - RvDocument* doc() const { return m_doc; } + const TwkApp::Menu::Item* item() const { return m_item; } -private: - RvDocument* m_doc; - const TwkApp::Menu::Item* m_item; -}; + RvDocument* doc() const { return m_doc; } + private: + RvDocument* m_doc; + const TwkApp::Menu::Item* m_item; + }; -} // Rv +} // namespace Rv #endif // __rv-qt__TwkQTAction__h__ diff --git a/src/lib/app/RvCommon/RvConsoleApplication.cpp b/src/lib/app/RvCommon/RvConsoleApplication.cpp index 0df6dc35c..68f0f5ffb 100644 --- a/src/lib/app/RvCommon/RvConsoleApplication.cpp +++ b/src/lib/app/RvCommon/RvConsoleApplication.cpp @@ -11,10 +11,11 @@ namespace Rv { - RvConsoleApplication::RvConsoleApplication() - : IPCore::Application(), m_pyLibrary( INTERNAL_APPLICATION_NAME ) - { - m_pyLibrary.setName( "py-media-library" ); - } + RvConsoleApplication::RvConsoleApplication() + : IPCore::Application() + , m_pyLibrary(INTERNAL_APPLICATION_NAME) + { + m_pyLibrary.setName("py-media-library"); + } -} // namespace Rv \ No newline at end of file +} // namespace Rv diff --git a/src/lib/app/RvCommon/RvConsoleWindow.cpp b/src/lib/app/RvCommon/RvConsoleWindow.cpp index b4295483b..8058d1408 100644 --- a/src/lib/app/RvCommon/RvConsoleWindow.cpp +++ b/src/lib/app/RvCommon/RvConsoleWindow.cpp @@ -16,410 +16,421 @@ namespace { - //-------------------------------------------------------------------------- - // - bool stringPotentiallyContainsHtml( const std::string& s ) - { - return !s.empty() && s.find( '<' ) != std::string::npos && - s.find( '>' ) != std::string::npos; - } -} // namespace + //-------------------------------------------------------------------------- + // + bool stringPotentiallyContainsHtml(const std::string& s) + { + return !s.empty() && s.find('<') != std::string::npos + && s.find('>') != std::string::npos; + } +} // namespace namespace Rv { - using namespace std; - - int RvConsoleWindow::ConsoleBuf::sync() - { - m_console->processTimer(); - streamsize n = pptr() - pbase(); - return ( n && m_console->append( pbase(), n ) != n ) ? EOF : 0; - } - - void RvConsoleWindow::ConsoleBuf::sendLine() - { - m_console->processTimer(); - m_console->appendLine( m_lineBuffer ); - m_lineBuffer.clear(); - } - - int RvConsoleWindow::ConsoleBuf::overflow( int ch ) - { - QMutexLocker l( &m_mutex ); - streamsize n = pptr() - pbase(); - - if( n && sync() ) return EOF; - - if( ch != EOF ) + using namespace std; + + int RvConsoleWindow::ConsoleBuf::sync() { - m_lineBuffer.append( 1, (char)ch ); - if( ch == '\n' ) sendLine(); + m_console->processTimer(); + streamsize n = pptr() - pbase(); + return (n && m_console->append(pbase(), n) != n) ? EOF : 0; } - pbump( -n ); // Reset pptr(). - return 0; - } - - streamsize RvConsoleWindow::ConsoleBuf::xsputn( char* text, streamsize n ) - { - QMutexLocker l( &m_mutex ); - return sync() == EOF ? 0 : m_console->append( text, n ); - } - - //---------------------------------------------------------------------- - - static QThread* mainThread = 0; - - RvConsoleWindow::RvConsoleWindow( QWidget* parent ) - : QDialog( parent, Qt::Window ), - m_consoleBuf( 0 ), - m_processTimerRunning( false ), - m_cout( 0 ), - m_cerr( 0 ), - m_stdoutBuf( 0 ), - m_stderrBuf( 0 ) - { - mainThread = QThread::currentThread(); - m_processTimer = new QTimer( this ); - m_processTimer->setSingleShot( true ); - m_processTimer->setInterval( 500 ); - connect( m_processTimer, SIGNAL( timeout() ), this, - SLOT( processTextBuffer() ) ); - - m_ui.setupUi( this ); - m_ui.biggerButton->setIcon( - colorAdjustedIcon( ":images/zoomi_32x32.png" ) ); - m_ui.smallerButton->setIcon( - colorAdjustedIcon( ":images/zoomo_32x32.png" ) ); - m_ui.clearButton->setIcon( colorAdjustedIcon( ":images/del_32x32.png" ) ); - m_ui.textEdit->setReadOnly( true ); - // - // Set focus to combo box, otherwise focus defaults to the "clear" - // push button, and if you happen to hit "space" (on linux) it - // triggers the button. - // - m_ui.showComboBox->setFocus(); - - setWindowTitle( UI_APPLICATION_NAME " Console" ); - setWindowIcon(QIcon(qApp->applicationDirPath() + QString(RV_ICON_PATH_SUFFIX))); - setSizeGripEnabled( true ); - bool doRedirect = ( getenv( "RV_NO_CONSOLE_REDIRECT" ) == 0 ); - // setAttribute(Qt::WA_MacBrushedMetal); - -#if defined( NDEBUG ) || defined( PLATFORM_WINDOWS ) - if( doRedirect ) + void RvConsoleWindow::ConsoleBuf::sendLine() { - m_stdoutBuf = cout.rdbuf(); - m_stderrBuf = cerr.rdbuf(); - - m_consoleBuf = new ConsoleBuf( this ); - - cout.rdbuf( m_consoleBuf ); - cerr.rdbuf( m_consoleBuf ); - - m_cout = new ostream( m_stdoutBuf ); - m_cerr = new ostream( m_stderrBuf ); + m_console->processTimer(); + m_console->appendLine(m_lineBuffer); + m_lineBuffer.clear(); } -#endif - - RV_QSETTINGS; - settings.beginGroup( "Console" ); - m_ui.showComboBox->setCurrentIndex( settings.value( "showOn", 0 ).toInt() ); - settings.endGroup(); - int showIndex = m_ui.showComboBox->currentIndex(); - } + int RvConsoleWindow::ConsoleBuf::overflow(int ch) + { + QMutexLocker l(&m_mutex); + streamsize n = pptr() - pbase(); - RvConsoleWindow::~RvConsoleWindow() - { - if( m_consoleBuf ) m_consoleBuf->sync(); - processTextBuffer(); + if (n && sync()) + return EOF; -#if defined( NDEBUG ) || !defined( PLATFORM_WINDOWS ) - if( m_stdoutBuf ) cout.rdbuf( m_stdoutBuf ); - if( m_stderrBuf ) cerr.rdbuf( m_stderrBuf ); -#endif - } + if (ch != EOF) + { + m_lineBuffer.append(1, (char)ch); + if (ch == '\n') + sendLine(); + } - void RvConsoleWindow::processTimer() - { - if( !m_processTimerRunning ) - { - // - // Only allow the thread that created the timer (the main - // display thread) to start the timer (other threads don't - // have event loops). - // - if( QThread::currentThread() == mainThread ) - { - m_processTimer->start(); - m_processTimerRunning = true; - } + pbump(-n); // Reset pptr(). + return 0; } - } - - void RvConsoleWindow::closeEvent( QCloseEvent* event ) - { - int showIndex = m_ui.showComboBox->currentIndex(); - - RV_QSETTINGS; - - settings.beginGroup( "Console" ); - settings.setValue( "showOn", showIndex ); - settings.endGroup(); - settings.sync(); - - QWidget::closeEvent( event ); - } - - int RvConsoleWindow::append( const char* text, size_t n ) - { - QMutexLocker l( &m_lock ); - for( int i = 0; i < n; i++ ) m_textBuffer << text[i]; - return n; - } - - void RvConsoleWindow::append( const string& text ) - { - QMutexLocker l( &m_lock ); - m_textBuffer << text; - } - - void RvConsoleWindow::appendLine( const std::string& lineBuffer ) - { - if( m_cout ) + + streamsize RvConsoleWindow::ConsoleBuf::xsputn(char* text, streamsize n) { - QMutexLocker l( &m_lock ); - m_textBuffer << lineBuffer; + QMutexLocker l(&m_mutex); + return sync() == EOF ? 0 : m_console->append(text, n); } - } - void RvConsoleWindow::processTextBuffer() - { - if( !m_textBuffer.str().empty() ) - { - vector lines; - stl_ext::tokenize( lines, m_textBuffer.str(), "\n\r" ); + //---------------------------------------------------------------------- - bool shouldShow = false; + static QThread* mainThread = 0; - textEdit()->moveCursor( QTextCursor::End, QTextCursor::MoveAnchor ); + RvConsoleWindow::RvConsoleWindow(QWidget* parent) + : QDialog(parent, Qt::Window) + , m_consoleBuf(0) + , m_processTimerRunning(false) + , m_cout(0) + , m_cerr(0) + , m_stdoutBuf(0) + , m_stderrBuf(0) + { + mainThread = QThread::currentThread(); + m_processTimer = new QTimer(this); + m_processTimer->setSingleShot(true); + m_processTimer->setInterval(500); + connect(m_processTimer, SIGNAL(timeout()), this, + SLOT(processTextBuffer())); + + m_ui.setupUi(this); + m_ui.biggerButton->setIcon( + colorAdjustedIcon(":images/zoomi_32x32.png")); + m_ui.smallerButton->setIcon( + colorAdjustedIcon(":images/zoomo_32x32.png")); + m_ui.clearButton->setIcon(colorAdjustedIcon(":images/del_32x32.png")); + m_ui.textEdit->setReadOnly(true); + // + // Set focus to combo box, otherwise focus defaults to the "clear" + // push button, and if you happen to hit "space" (on linux) it + // triggers the button. + // + m_ui.showComboBox->setFocus(); + + setWindowTitle(UI_APPLICATION_NAME " Console"); + setWindowIcon( + QIcon(qApp->applicationDirPath() + QString(RV_ICON_PATH_SUFFIX))); + setSizeGripEnabled(true); + bool doRedirect = (getenv("RV_NO_CONSOLE_REDIRECT") == 0); + // setAttribute(Qt::WA_MacBrushedMetal); + +#if defined(NDEBUG) || defined(PLATFORM_WINDOWS) + if (doRedirect) + { + m_stdoutBuf = cout.rdbuf(); + m_stderrBuf = cerr.rdbuf(); - // QTextEdit::insertHtml() is slow so we use it only when necessary - if( stringPotentiallyContainsHtml( m_textBuffer.str() ) ) - { - QString html; + m_consoleBuf = new ConsoleBuf(this); - for( int i = 0; i < lines.size(); i++ ) - { - lines[i] += "\n"; - shouldShow |= processLine( lines[i], html ); - } - html += "
"; + cout.rdbuf(m_consoleBuf); + cerr.rdbuf(m_consoleBuf); - textEdit()->insertHtml( html ); - } - else - { - for( int i = 0; i < lines.size(); i++ ) - { - lines[i] += "\n"; - shouldShow |= processAndDisplayLine( lines[i] ); + m_cout = new ostream(m_stdoutBuf); + m_cerr = new ostream(m_stderrBuf); } - } +#endif - if( shouldShow ) - { - show(); - raise(); - } + RV_QSETTINGS; - m_textBuffer.str( "" ); + settings.beginGroup("Console"); + m_ui.showComboBox->setCurrentIndex(settings.value("showOn", 0).toInt()); + settings.endGroup(); + int showIndex = m_ui.showComboBox->currentIndex(); } - if( m_processTimerRunning ) + RvConsoleWindow::~RvConsoleWindow() { - m_processTimer->stop(); - m_processTimerRunning = false; + if (m_consoleBuf) + m_consoleBuf->sync(); + processTextBuffer(); + +#if defined(NDEBUG) || !defined(PLATFORM_WINDOWS) + if (m_stdoutBuf) + cout.rdbuf(m_stdoutBuf); + if (m_stderrBuf) + cerr.rdbuf(m_stderrBuf); +#endif } - } - void RvConsoleWindow::processLastTextBuffer() - { - processTextBuffer(); - - if( m_consoleBuf ) + void RvConsoleWindow::processTimer() { - if( m_stdoutBuf ) cout.rdbuf( m_stdoutBuf ); - m_stdoutBuf = nullptr; - if( m_stderrBuf ) cerr.rdbuf( m_stderrBuf ); - m_stderrBuf = nullptr; - - delete m_consoleBuf; - m_consoleBuf = nullptr; + if (!m_processTimerRunning) + { + // + // Only allow the thread that created the timer (the main + // display thread) to start the timer (other threads don't + // have event loops). + // + if (QThread::currentThread() == mainThread) + { + m_processTimer->start(); + m_processTimerRunning = true; + } + } } - } - bool RvConsoleWindow::processLine( string& line, QString& html ) - { - bool qtimerwarning = - line.find( "Application asked to unregister timer" ) != string::npos; - bool qfilesystemwatcher = - line.find( "QFileSystemWatcher:" ) != string::npos; + void RvConsoleWindow::closeEvent(QCloseEvent* event) + { + int showIndex = m_ui.showComboBox->currentIndex(); - // filter this - if( qtimerwarning || qfilesystemwatcher ) return false; + RV_QSETTINGS; - static spdlog::level::level_enum lineLogLevel = spdlog::level::info; - ostream* out = m_cout; + settings.beginGroup("Console"); + settings.setValue("showOn", showIndex); + settings.endGroup(); + settings.sync(); - if( line.find( "ERROR:" ) == 0 ) - { - lineLogLevel = spdlog::level::err; - line.erase( 0, 6 ); - out = m_cerr; - *out << "ERROR: "; - } - else if( line.find( "WARNING:" ) == 0 ) - { - lineLogLevel = spdlog::level::warn; - line.erase( 0, 8 ); - out = m_cerr; - *out << "WARNING: "; - } - else if( line.find( "INFO:" ) == 0 ) - { - lineLogLevel = spdlog::level::info; - line.erase( 0, 5 ); - *out << "INFO: "; - } - else if( line.find( "DEBUG:" ) == 0 ) - { - lineLogLevel = spdlog::level::debug; - line.erase( 0, 6 ); - *out << "DEBUG: "; + QWidget::closeEvent(event); } - // We removed the message type from the line, let's make sure - // that we also remove the space between the type and the line - if( std::isspace( line.at( 0 ) ) ) + int RvConsoleWindow::append(const char* text, size_t n) { - line.erase( 0, 1 ); + QMutexLocker l(&m_lock); + for (int i = 0; i < n; i++) + m_textBuffer << text[i]; + return n; } - if( lineLogLevel == spdlog::level::err ) + void RvConsoleWindow::append(const string& text) { - html += "ERROR: "; + QMutexLocker l(&m_lock); + m_textBuffer << text; } - else if( lineLogLevel == spdlog::level::warn ) + + void RvConsoleWindow::appendLine(const std::string& lineBuffer) { - html += "WARNING: "; + if (m_cout) + { + QMutexLocker l(&m_lock); + m_textBuffer << lineBuffer; + } } - else if( lineLogLevel == spdlog::level::info ) + + void RvConsoleWindow::processTextBuffer() { - html += "INFO: "; + if (!m_textBuffer.str().empty()) + { + vector lines; + stl_ext::tokenize(lines, m_textBuffer.str(), "\n\r"); + + bool shouldShow = false; + + textEdit()->moveCursor(QTextCursor::End, QTextCursor::MoveAnchor); + + // QTextEdit::insertHtml() is slow so we use it only when necessary + if (stringPotentiallyContainsHtml(m_textBuffer.str())) + { + QString html; + + for (int i = 0; i < lines.size(); i++) + { + lines[i] += "\n"; + shouldShow |= processLine(lines[i], html); + } + html += "
"; + + textEdit()->insertHtml(html); + } + else + { + for (int i = 0; i < lines.size(); i++) + { + lines[i] += "\n"; + shouldShow |= processAndDisplayLine(lines[i]); + } + } + + if (shouldShow) + { + show(); + raise(); + } + + m_textBuffer.str(""); + } + + if (m_processTimerRunning) + { + m_processTimer->stop(); + m_processTimerRunning = false; + } } - else if( lineLogLevel == spdlog::level::debug ) + + void RvConsoleWindow::processLastTextBuffer() { - html += "DEBUG: "; + processTextBuffer(); + + if (m_consoleBuf) + { + if (m_stdoutBuf) + cout.rdbuf(m_stdoutBuf); + m_stdoutBuf = nullptr; + if (m_stderrBuf) + cerr.rdbuf(m_stderrBuf); + m_stderrBuf = nullptr; + + delete m_consoleBuf; + m_consoleBuf = nullptr; + } } - html += line.c_str(); - m_fileLogger.logToFile( lineLogLevel, line ); - if( line.size() && line[0] != '<' ) + bool RvConsoleWindow::processLine(string& line, QString& html) { - *out << line; - html += "
"; - } + bool qtimerwarning = + line.find("Application asked to unregister timer") != string::npos; + bool qfilesystemwatcher = + line.find("QFileSystemWatcher:") != string::npos; - int showIndex = m_ui.showComboBox->currentIndex(); + // filter this + if (qtimerwarning || qfilesystemwatcher) + return false; - // - // Should we show the Console as a result of this line ? - // - return ( showIndex != 4 && - ( ( lineLogLevel == spdlog::level::err && showIndex <= 3 ) || - ( lineLogLevel == spdlog::level::warn && showIndex <= 3 && - showIndex >= 1 ) || - ( lineLogLevel == spdlog::level::info && showIndex <= 3 && - showIndex >= 2 ) || - showIndex == 3 ) ); - } - - bool RvConsoleWindow::processAndDisplayLine( string& line ) - { - bool qtimerwarning = - line.find( "Application asked to unregister timer" ) != string::npos; - bool qfilesystemwatcher = - line.find( "QFileSystemWatcher:" ) != string::npos; - - // filter this - if( qtimerwarning || qfilesystemwatcher ) return false; - - static spdlog::level::level_enum lineLogLevel = spdlog::level::info; - - ostream* out = m_cout; - - if( line.find( "ERROR:" ) == 0 ) - { - textEdit()->setTextColor( Qt::red ); - textEdit()->insertPlainText( "ERROR: " ); - line.erase( 0, 6 ); - out = m_cerr; - *out << "ERROR: "; - lineLogLevel = spdlog::level::err; - } - else if( line.find( "WARNING:" ) == 0 ) - { - static const QColor orangeColor( 255, 175, 0 ); - textEdit()->setTextColor( orangeColor ); - textEdit()->insertPlainText( "WARNING: " ); - line.erase( 0, 8 ); - out = m_cerr; - *out << "WARNING: "; - lineLogLevel = spdlog::level::warn; - } - else if( line.find( "INFO:" ) == 0 ) - { - textEdit()->setTextColor( Qt::cyan ); - textEdit()->insertPlainText( "INFO: " ); - line.erase( 0, 5 ); - *out << "INFO: "; - lineLogLevel = spdlog::level::info; - } - else if( line.find( "DEBUG:" ) == 0 ) - { - textEdit()->setTextColor( Qt::green ); - textEdit()->insertPlainText( "DEBUG: " ); - line.erase( 0, 6 ); - *out << "DEBUG: "; - lineLogLevel = spdlog::level::debug; + static spdlog::level::level_enum lineLogLevel = spdlog::level::info; + ostream* out = m_cout; + + if (line.find("ERROR:") == 0) + { + lineLogLevel = spdlog::level::err; + line.erase(0, 6); + out = m_cerr; + *out << "ERROR: "; + } + else if (line.find("WARNING:") == 0) + { + lineLogLevel = spdlog::level::warn; + line.erase(0, 8); + out = m_cerr; + *out << "WARNING: "; + } + else if (line.find("INFO:") == 0) + { + lineLogLevel = spdlog::level::info; + line.erase(0, 5); + *out << "INFO: "; + } + else if (line.find("DEBUG:") == 0) + { + lineLogLevel = spdlog::level::debug; + line.erase(0, 6); + *out << "DEBUG: "; + } + + // We removed the message type from the line, let's make sure + // that we also remove the space between the type and the line + if (std::isspace(line.at(0))) + { + line.erase(0, 1); + } + + if (lineLogLevel == spdlog::level::err) + { + html += "ERROR: "; + } + else if (lineLogLevel == spdlog::level::warn) + { + html += "WARNING: "; + } + else if (lineLogLevel == spdlog::level::info) + { + html += "INFO: "; + } + else if (lineLogLevel == spdlog::level::debug) + { + html += "DEBUG: "; + } + + html += line.c_str(); + m_fileLogger.logToFile(lineLogLevel, line); + if (line.size() && line[0] != '<') + { + *out << line; + html += "
"; + } + + int showIndex = m_ui.showComboBox->currentIndex(); + + // + // Should we show the Console as a result of this line ? + // + return (showIndex != 4 + && ((lineLogLevel == spdlog::level::err && showIndex <= 3) + || (lineLogLevel == spdlog::level::warn && showIndex <= 3 + && showIndex >= 1) + || (lineLogLevel == spdlog::level::info && showIndex <= 3 + && showIndex >= 2) + || showIndex == 3)); } - // We removed the message type from the line, let's make sure - // that we also remove the space between the type and the line - if( std::isspace( line.at( 0 ) ) ) + bool RvConsoleWindow::processAndDisplayLine(string& line) { - line.erase( 0, 1 ); - } + bool qtimerwarning = + line.find("Application asked to unregister timer") != string::npos; + bool qfilesystemwatcher = + line.find("QFileSystemWatcher:") != string::npos; - textEdit()->setTextColor( Qt::white ); - textEdit()->insertPlainText( line.c_str() ); - *out << line; - m_fileLogger.logToFile( lineLogLevel, line ); + // filter this + if (qtimerwarning || qfilesystemwatcher) + return false; - int showIndex = m_ui.showComboBox->currentIndex(); + static spdlog::level::level_enum lineLogLevel = spdlog::level::info; - // - // Should we show the Console as a result of this line ? - // - return ( showIndex != 4 && - ( ( lineLogLevel == spdlog::level::err && showIndex <= 3 ) || - ( lineLogLevel == spdlog::level::warn && showIndex <= 3 && - showIndex >= 1 ) || - ( lineLogLevel == spdlog::level::info && showIndex <= 3 && - showIndex >= 2 ) || - showIndex == 3 ) ); - } - -} // namespace Rv + ostream* out = m_cout; + + if (line.find("ERROR:") == 0) + { + textEdit()->setTextColor(Qt::red); + textEdit()->insertPlainText("ERROR: "); + line.erase(0, 6); + out = m_cerr; + *out << "ERROR: "; + lineLogLevel = spdlog::level::err; + } + else if (line.find("WARNING:") == 0) + { + static const QColor orangeColor(255, 175, 0); + textEdit()->setTextColor(orangeColor); + textEdit()->insertPlainText("WARNING: "); + line.erase(0, 8); + out = m_cerr; + *out << "WARNING: "; + lineLogLevel = spdlog::level::warn; + } + else if (line.find("INFO:") == 0) + { + textEdit()->setTextColor(Qt::cyan); + textEdit()->insertPlainText("INFO: "); + line.erase(0, 5); + *out << "INFO: "; + lineLogLevel = spdlog::level::info; + } + else if (line.find("DEBUG:") == 0) + { + textEdit()->setTextColor(Qt::green); + textEdit()->insertPlainText("DEBUG: "); + line.erase(0, 6); + *out << "DEBUG: "; + lineLogLevel = spdlog::level::debug; + } + + // We removed the message type from the line, let's make sure + // that we also remove the space between the type and the line + if (std::isspace(line.at(0))) + { + line.erase(0, 1); + } + + textEdit()->setTextColor(Qt::white); + textEdit()->insertPlainText(line.c_str()); + *out << line; + m_fileLogger.logToFile(lineLogLevel, line); + + int showIndex = m_ui.showComboBox->currentIndex(); + + // + // Should we show the Console as a result of this line ? + // + return (showIndex != 4 + && ((lineLogLevel == spdlog::level::err && showIndex <= 3) + || (lineLogLevel == spdlog::level::warn && showIndex <= 3 + && showIndex >= 1) + || (lineLogLevel == spdlog::level::info && showIndex <= 3 + && showIndex >= 2) + || showIndex == 3)); + } + +} // namespace Rv diff --git a/src/lib/app/RvCommon/RvDocument.cpp b/src/lib/app/RvCommon/RvDocument.cpp index 73eb8d8bf..21fd93281 100644 --- a/src/lib/app/RvCommon/RvDocument.cpp +++ b/src/lib/app/RvCommon/RvDocument.cpp @@ -1,9 +1,9 @@ // -// Copyright (c) 2007 Tweak Inc. +// Copyright (c) 2007 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// // #include @@ -16,15 +16,15 @@ #include #include #include -//#include +// #include #include #include #include #include #ifdef PLATFORM_WINDOWS - #include +#include #endif -#include // WINDOWS: include AFTER other stuff +#include // WINDOWS: include AFTER other stuff #include #include #include @@ -59,542 +59,622 @@ #include #endif -namespace Rv { -using namespace std; -using namespace TwkMath; -using namespace IPCore; +namespace Rv +{ + using namespace std; + using namespace TwkMath; + using namespace IPCore; #if 0 -#define DB_ICON 0x01 -#define DB_ALL 0xff +#define DB_ICON 0x01 +#define DB_ALL 0xff // #define DB_LEVEL (DB_ALL & (~ DB_ICON)) -#define DB_LEVEL DB_ALL +#define DB_LEVEL DB_ALL -#define DB(x) cerr << x << endl -#define DBL(level, x) if (level & DB_LEVEL) cerr << x << endl +#define DB(x) cerr << x << endl +#define DBL(level, x) \ + if (level & DB_LEVEL) \ + cerr << x << endl #else -#define DB(x) +#define DB(x) #define DBL(level, x) #endif -inline QString utf8(const std::string& us) -{ - return QString::fromUtf8(us.c_str()); -} - -static int sessionCount = 0; - -namespace { -bool workAroundActionLeak = false; -}; - -RvDocument::RvDocument() - : QMainWindow(), - TwkUtil::Notifier(), - m_rvMenu(0), - m_lastPopupAction(0), - m_menuBarHeight(0), - m_mainPopup(0), - m_menuBarDisable(false), - m_menuBarShown(true), - m_startupResize(false), - m_aggressiveSizing(false), - m_menuTimer(0), - m_menuExecuting(0), - m_userMenu(0), - m_userPopup(0), - m_watcher(0), - m_resetPolicyTimer(0), - m_session(0), - m_currentlyClosing(false), - m_closeEventReceived(false), - m_vsyncDisabled(false), - m_oldGLView(0), - m_glView(0), - m_sourceEditor(0), - m_displayLink(0) -{ - DB ("RvDocument constructed"); - - if (getenv("RV_WORKAROUND_ACTION_LEAK")) - { - workAroundActionLeak = true; - } - else - { + inline QString utf8(const std::string& us) + { + return QString::fromUtf8(us.c_str()); + } + + static int sessionCount = 0; + + namespace + { + bool workAroundActionLeak = false; + }; + + RvDocument::RvDocument() + : QMainWindow() + , TwkUtil::Notifier() + , m_rvMenu(0) + , m_lastPopupAction(0) + , m_menuBarHeight(0) + , m_mainPopup(0) + , m_menuBarDisable(false) + , m_menuBarShown(true) + , m_startupResize(false) + , m_aggressiveSizing(false) + , m_menuTimer(0) + , m_menuExecuting(0) + , m_userMenu(0) + , m_userPopup(0) + , m_watcher(0) + , m_resetPolicyTimer(0) + , m_session(0) + , m_currentlyClosing(false) + , m_closeEventReceived(false) + , m_vsyncDisabled(false) + , m_oldGLView(0) + , m_glView(0) + , m_sourceEditor(0) + , m_displayLink(0) + { + DB("RvDocument constructed"); + + if (getenv("RV_WORKAROUND_ACTION_LEAK")) + { + workAroundActionLeak = true; + } + else + { #ifdef PLATFORM_DARWIN - workAroundActionLeak = true; + workAroundActionLeak = true; #else - workAroundActionLeak = false; + workAroundActionLeak = false; #endif - } + } -#if !defined(PLATFORM_DARWIN) - setMenuBar(new QMenuBar(0)); +#if !defined(PLATFORM_DARWIN) + setMenuBar(new QMenuBar(0)); #endif - const TwkApp::Application::Documents& docs = TwkApp::App()->documents(); + const TwkApp::Application::Documents& docs = TwkApp::App()->documents(); - setWindowIcon(QIcon(qApp->applicationDirPath() + QString(RV_ICON_PATH_SUFFIX))); + setWindowIcon( + QIcon(qApp->applicationDirPath() + QString(RV_ICON_PATH_SUFFIX))); - Rv::Options& opts = Options::sharedOptions(); - - bool resetGLPrefs = false; - m_startupResize = (opts.width == -1 && opts.height == -1 && opts.startupResize); - - checkDriverVSync(); + Rv::Options& opts = Options::sharedOptions(); - m_viewContainerWidget = new QWidget(this); - m_centralWidget = new QWidget(m_viewContainerWidget); - m_topViewToolBar = new RvTopViewToolBar(m_viewContainerWidget); - m_bottomViewToolBar = new RvBottomViewToolBar(m_viewContainerWidget); - QVBoxLayout* vlayout = new QVBoxLayout(m_viewContainerWidget); + bool resetGLPrefs = false; + m_startupResize = + (opts.width == -1 && opts.height == -1 && opts.startupResize); - vlayout->addWidget(m_topViewToolBar); - vlayout->addWidget(m_centralWidget); - vlayout->addWidget(m_bottomViewToolBar); + checkDriverVSync(); - vlayout->setSpacing(0); - vlayout->setContentsMargins(0,0,0,0); + m_viewContainerWidget = new QWidget(this); + m_centralWidget = new QWidget(m_viewContainerWidget); + m_topViewToolBar = new RvTopViewToolBar(m_viewContainerWidget); + m_bottomViewToolBar = new RvBottomViewToolBar(m_viewContainerWidget); + QVBoxLayout* vlayout = new QVBoxLayout(m_viewContainerWidget); - m_topViewToolBar->makeActiveFromSettings(); - m_bottomViewToolBar->makeActiveFromSettings(); + vlayout->addWidget(m_topViewToolBar); + vlayout->addWidget(m_centralWidget); + vlayout->addWidget(m_bottomViewToolBar); - // - // + vlayout->setSpacing(0); + vlayout->setContentsMargins(0, 0, 0, 0); - if (docs.empty()) - { - m_glView = new GLView(this, - 0, - this, - opts.stereoMode && !strcmp(opts.stereoMode, "hardware"), - opts.vsync != 0 && !m_vsyncDisabled, - true, - opts.dispRedBits, - opts.dispGreenBits, - opts.dispBlueBits, - opts.dispAlphaBits, - !m_startupResize - ); + m_topViewToolBar->makeActiveFromSettings(); + m_bottomViewToolBar->makeActiveFromSettings(); // - // Make the GL context valid ASAP so we can query it later // - if (!m_glView->isValid()) + if (docs.empty()) { - delete m_glView; - //cout << "ERROR: reverting to known GL state" << endl; - //cout << "ERROR: check the rendering preferences" << endl; - m_glView = new GLView(this, 0, this); - resetGLPrefs = true; + m_glView = new GLView( + this, 0, this, + opts.stereoMode && !strcmp(opts.stereoMode, "hardware"), + opts.vsync != 0 && !m_vsyncDisabled, true, opts.dispRedBits, + opts.dispGreenBits, opts.dispBlueBits, opts.dispAlphaBits, + !m_startupResize); + + // + // Make the GL context valid ASAP so we can query it later + // + + if (!m_glView->isValid()) + { + delete m_glView; + // cout << "ERROR: reverting to known GL state" << endl; + // cout << "ERROR: check the rendering preferences" << endl; + m_glView = new GLView(this, 0, this); + resetGLPrefs = true; + } } - } - else - { - RvSession* s = static_cast(docs.front()); - RvDocument *rvDoc = (RvDocument*)s->opaquePointer(); - m_glView = new GLView(this, rvDoc->view(), this, - opts.stereoMode && !strcmp(opts.stereoMode, "hardware"), - opts.vsync != 0 && !m_vsyncDisabled, - true, // double buffer - opts.dispRedBits, - opts.dispGreenBits, - opts.dispBlueBits, - opts.dispAlphaBits, - !m_startupResize - ); - - if (!m_glView->isValid()) - { - delete m_glView; - //cout << "ERROR: reverting to known GL state" << endl; - //cout << "ERROR: check the rendering preferences" << endl; - m_glView = new GLView(this, rvDoc->view(), this); - resetGLPrefs = true; + else + { + RvSession* s = static_cast(docs.front()); + RvDocument* rvDoc = (RvDocument*)s->opaquePointer(); + m_glView = new GLView( + this, rvDoc->view(), this, + opts.stereoMode && !strcmp(opts.stereoMode, "hardware"), + opts.vsync != 0 && !m_vsyncDisabled, + true, // double buffer + opts.dispRedBits, opts.dispGreenBits, opts.dispBlueBits, + opts.dispAlphaBits, !m_startupResize); + + if (!m_glView->isValid()) + { + delete m_glView; + // cout << "ERROR: reverting to known GL state" << endl; + // cout << "ERROR: check the rendering preferences" << endl; + m_glView = new GLView(this, rvDoc->view(), this); + resetGLPrefs = true; + } } - } - - m_stackedLayout = new QStackedLayout(m_centralWidget); - m_stackedLayout->setStackingMode(QStackedLayout::StackAll); - m_stackedLayout->addWidget(m_glView); + m_stackedLayout = new QStackedLayout(m_centralWidget); + m_stackedLayout->setStackingMode(QStackedLayout::StackAll); + m_stackedLayout->addWidget(m_glView); - setCentralWidget(m_viewContainerWidget); + setCentralWidget(m_viewContainerWidget); - //QTFrameBuffer* fb = m_glView->frameBuffer(); - m_glView->setFocus(Qt::OtherFocusReason); - //qApp->installEventFilter(m_glView); + // QTFrameBuffer* fb = m_glView->frameBuffer(); + m_glView->setFocus(Qt::OtherFocusReason); + // qApp->installEventFilter(m_glView); - m_resetPolicyTimer = new QTimer(this); - m_resetPolicyTimer->setSingleShot(true); - connect(m_resetPolicyTimer, SIGNAL(timeout()), this, SLOT(resetSizePolicy())); + m_resetPolicyTimer = new QTimer(this); + m_resetPolicyTimer->setSingleShot(true); + connect(m_resetPolicyTimer, SIGNAL(timeout()), this, + SLOT(resetSizePolicy())); - m_frameChangedTimer = new QTimer(this); - m_frameChangedTimer->setSingleShot(true); - connect(m_frameChangedTimer, SIGNAL(timeout()), this, SLOT(frameChanged())); + m_frameChangedTimer = new QTimer(this); + m_frameChangedTimer->setSingleShot(true); + connect(m_frameChangedTimer, SIGNAL(timeout()), this, + SLOT(frameChanged())); - m_menuTimer = new QTimer(this); - m_menuTimer->setInterval(50); - connect(m_menuTimer, SIGNAL(timeout()), this, SLOT(buildMenu())); + m_menuTimer = new QTimer(this); + m_menuTimer->setInterval(50); + connect(m_menuTimer, SIGNAL(timeout()), this, SLOT(buildMenu())); - m_glView->makeCurrent(); - initializeGLExtensions(); + m_glView->makeCurrent(); + initializeGLExtensions(); - m_session = new RvSession; - //m_session->setFrameBuffer(fb); + m_session = new RvSession; + // m_session->setFrameBuffer(fb); #ifdef PLATFORM_DARWIN - m_displayLink = new DisplayLink(this); - if (m_displayLink) m_session->useExternalVSyncTiming(true); + m_displayLink = new DisplayLink(this); + if (m_displayLink) + m_session->useExternalVSyncTiming(true); #endif - //RvApp()->addVideoDevice(m_glView->videoDevice()); - m_session->setControlVideoDevice(m_glView->videoDevice()); - - m_session->setRendererType("Composite"); - m_session->setOpaquePointer( this ); - m_session->makeActive(); - m_session->postInitialize(); - char nm[64]; - sprintf (nm, "session%03d", sessionCount++); - m_session->setEventNodeName(nm); - setObjectName(QString("rv-") + QString(nm)); - - mergeMenu(m_session->menu()); - - setAttribute(Qt::WA_DeleteOnClose); - setAttribute(Qt::WA_QuitOnClose); - - m_topViewToolBar->setSession(m_session); - m_bottomViewToolBar->setSession(m_session); - - // 10.5 looks better without it (no longer has the 100% white top) - //setAttribute(Qt::WA_MacBrushedMetal); - - m_session->addNotification(this, IPCore::Session::updateMessage()); - m_session->addNotification(this, IPCore::Session::updateLoadingMessage()); - m_session->addNotification(this, IPCore::Session::fullScreenOnMessage()); - m_session->addNotification(this, IPCore::Session::fullScreenOffMessage()); - m_session->addNotification(this, IPCore::Session::stereoHardwareOnMessage()); - m_session->addNotification(this, IPCore::Session::stereoHardwareOffMessage()); - m_session->addNotification(this, TwkApp::Document::deleteMessage()); - m_session->addNotification(this, TwkApp::Document::menuChangedMessage()); - m_session->addNotification(this, TwkApp::Document::activeMessage()); - m_session->addNotification(this, TwkApp::Document::filenameChangedMessage()); - m_session->addNotification(this, IPCore::Session::audioUnavailbleMessage()); - m_session->addNotification(this, IPCore::Session::eventDeviceChangedMessage()); - m_session->addNotification(this, IPCore::Session::stopPlayMessage()); - - m_session->playStartSignal().connect(boost::bind(&RvDocument::playStartSlot, this, std::placeholders::_1)); - m_session->playStopSignal().connect(boost::bind(&RvDocument::playStopSlot, this, std::placeholders::_1)); - m_session->physicalVideoDeviceChangedSignal().connect(boost::bind(&RvDocument::physicalVideoDeviceChangedSlot, this, std::placeholders::_1)); - - if (resetGLPrefs) resetGLStateAndPrefs(); + // RvApp()->addVideoDevice(m_glView->videoDevice()); + m_session->setControlVideoDevice(m_glView->videoDevice()); + + m_session->setRendererType("Composite"); + m_session->setOpaquePointer(this); + m_session->makeActive(); + m_session->postInitialize(); + char nm[64]; + sprintf(nm, "session%03d", sessionCount++); + m_session->setEventNodeName(nm); + setObjectName(QString("rv-") + QString(nm)); + + mergeMenu(m_session->menu()); + + setAttribute(Qt::WA_DeleteOnClose); + setAttribute(Qt::WA_QuitOnClose); + + m_topViewToolBar->setSession(m_session); + m_bottomViewToolBar->setSession(m_session); + + // 10.5 looks better without it (no longer has the 100% white top) + // setAttribute(Qt::WA_MacBrushedMetal); + + m_session->addNotification(this, IPCore::Session::updateMessage()); + m_session->addNotification(this, + IPCore::Session::updateLoadingMessage()); + m_session->addNotification(this, + IPCore::Session::fullScreenOnMessage()); + m_session->addNotification(this, + IPCore::Session::fullScreenOffMessage()); + m_session->addNotification(this, + IPCore::Session::stereoHardwareOnMessage()); + m_session->addNotification(this, + IPCore::Session::stereoHardwareOffMessage()); + m_session->addNotification(this, TwkApp::Document::deleteMessage()); + m_session->addNotification(this, + TwkApp::Document::menuChangedMessage()); + m_session->addNotification(this, TwkApp::Document::activeMessage()); + m_session->addNotification(this, + TwkApp::Document::filenameChangedMessage()); + m_session->addNotification(this, + IPCore::Session::audioUnavailbleMessage()); + m_session->addNotification( + this, IPCore::Session::eventDeviceChangedMessage()); + m_session->addNotification(this, IPCore::Session::stopPlayMessage()); + + m_session->playStartSignal().connect(boost::bind( + &RvDocument::playStartSlot, this, std::placeholders::_1)); + m_session->playStopSignal().connect(boost::bind( + &RvDocument::playStopSlot, this, std::placeholders::_1)); + m_session->physicalVideoDeviceChangedSignal().connect( + boost::bind(&RvDocument::physicalVideoDeviceChangedSlot, this, + std::placeholders::_1)); + + if (resetGLPrefs) + resetGLStateAndPrefs(); #ifdef PLATFORM_LINUX - int op_ret, ev_ret, er_ret; + int op_ret, ev_ret, er_ret; - bool haveNV = XQueryExtension (QX11Info::display(), - "NV-GLX", &op_ret, &ev_ret, &er_ret); + bool haveNV = XQueryExtension(QX11Info::display(), "NV-GLX", &op_ret, + &ev_ret, &er_ret); - if (!haveNV) - { - cerr << endl; - cerr << "ERROR:******* NV-GLX Extension Missing ***********" << endl; - cerr << " If you're using an Nvidia card, please install" << endl; - cerr << " the optimized NVIDIA binary driver." << endl; - cerr << " If you're using an ATI card, please be aware " << endl; - cerr << " that RV has not been tested with ATI cards." << endl; - cerr << "**************************************************" << endl; - cerr << endl; - } + if (!haveNV) + { + cerr << endl; + cerr << "ERROR:******* NV-GLX Extension Missing ***********" + << endl; + cerr << " If you're using an Nvidia card, please install" + << endl; + cerr << " the optimized NVIDIA binary driver." << endl; + cerr << " If you're using an ATI card, please be aware " << endl; + cerr << " that RV has not been tested with ATI cards." << endl; + cerr << "**************************************************" + << endl; + cerr << endl; + } #endif - if (opts.noBorders) - { - Qt::WindowFlags flags = windowFlags(); - setWindowFlags(flags | Qt::FramelessWindowHint); + if (opts.noBorders) + { + Qt::WindowFlags flags = windowFlags(); + setWindowFlags(flags | Qt::FramelessWindowHint); + } } -} -RvDocument::~RvDocument() -{ - if (IPCore::debugProfile) + RvDocument::~RvDocument() { - Rv::Options& opts = Options::sharedOptions(); - //RvPreferences* prefs = RvApp()->prefDialog(); - //prefs->loadSettingsIntoOptions(opts); - - QString dt = QDateTime::currentDateTime().toString("yyMMddhhmmss"); - QString host = QHostInfo::localHostName(); - host.replace(".", "_"); - - ostringstream out; - out << "rv_"; - out << TWK_DEPLOY_MAJOR_VERSION(); - out << "_"; - out << TWK_DEPLOY_MINOR_VERSION(); - out << "_"; - out << TWK_DEPLOY_PATCH_LEVEL(); - out << "_"; - out << host.toUtf8().constData(); - out << "_"; - out << dt.toUtf8().constData(); - out << ".rvprof"; - - ofstream file(UNICODE_C_STR(out.str().c_str())); - - if (file) - { - file << "# RV playback debug data" << endl; - file << "# version " << TWK_DEPLOY_MAJOR_VERSION() - << "." << TWK_DEPLOY_MINOR_VERSION() - << "." << TWK_DEPLOY_PATCH_LEVEL() - << endl; - file << "# -------------------------------------------" << endl; - file << "# PLATFORM = " << PLATFORM_STRING << endl; - file << "# COMPILER = " << COMPILER_STRING << endl; - file << "# ARCH = " << ARCH_STRING << endl; - file << "# CXXFLAGS = " << CXXFLAGS_STRING << endl; - file << "# HEAD = " << GIT_HEAD << endl; - file << "# RELEASE = " << RELEASE_DESCRIPTION << endl; - file << "# " << endl; - file << "# options" << endl; - - opts.output(file); - - file << "# -------------------------------------------" << endl; - - m_session->dumpProfilingToFile(file); - - cout << "INFO: wrote profiling file" << endl; - } - else + if (IPCore::debugProfile) { - cout << "ERROR: failed to write profiling file" << endl; + Rv::Options& opts = Options::sharedOptions(); + // RvPreferences* prefs = RvApp()->prefDialog(); + // prefs->loadSettingsIntoOptions(opts); + + QString dt = QDateTime::currentDateTime().toString("yyMMddhhmmss"); + QString host = QHostInfo::localHostName(); + host.replace(".", "_"); + + ostringstream out; + out << "rv_"; + out << TWK_DEPLOY_MAJOR_VERSION(); + out << "_"; + out << TWK_DEPLOY_MINOR_VERSION(); + out << "_"; + out << TWK_DEPLOY_PATCH_LEVEL(); + out << "_"; + out << host.toUtf8().constData(); + out << "_"; + out << dt.toUtf8().constData(); + out << ".rvprof"; + + ofstream file(UNICODE_C_STR(out.str().c_str())); + + if (file) + { + file << "# RV playback debug data" << endl; + file << "# version " << TWK_DEPLOY_MAJOR_VERSION() << "." + << TWK_DEPLOY_MINOR_VERSION() << "." + << TWK_DEPLOY_PATCH_LEVEL() << endl; + file << "# -------------------------------------------" << endl; + file << "# PLATFORM = " << PLATFORM_STRING << endl; + file << "# COMPILER = " << COMPILER_STRING << endl; + file << "# ARCH = " << ARCH_STRING << endl; + file << "# CXXFLAGS = " << CXXFLAGS_STRING << endl; + file << "# HEAD = " << GIT_HEAD << endl; + file << "# RELEASE = " << RELEASE_DESCRIPTION << endl; + file << "# " << endl; + file << "# options" << endl; + + opts.output(file); + + file << "# -------------------------------------------" << endl; + + m_session->dumpProfilingToFile(file); + + cout << "INFO: wrote profiling file" << endl; + } + else + { + cout << "ERROR: failed to write profiling file" << endl; + } } - } #ifdef PLATFORM_DARWIN - if (m_displayLink && - m_displayLink->isValid() && - m_displayLink->isActive()) - { - m_displayLink->stop(); - delete m_displayLink; - m_displayLink = 0; - } + if (m_displayLink && m_displayLink->isValid() + && m_displayLink->isActive()) + { + m_displayLink->stop(); + delete m_displayLink; + m_displayLink = 0; + } #endif - lazyDeleteGLView(); + lazyDeleteGLView(); - purgeMenus(); - m_session->setOutputVideoDevice(0); - m_session->setControlVideoDevice(0); - m_session->removeNotification(this); + purgeMenus(); + m_session->setOutputVideoDevice(0); + m_session->setControlVideoDevice(0); + m_session->removeNotification(this); - if (m_sourceEditor) m_sourceEditor->hide(); - delete m_sourceEditor; + if (m_sourceEditor) + m_sourceEditor->hide(); + delete m_sourceEditor; - if (RvNetworkDialog* d = RvApp()->networkWindow()) - { - d->sessionDeleted(m_session->name().c_str()); - } - - m_currentlyClosing = true; + if (RvNetworkDialog* d = RvApp()->networkWindow()) + { + d->sessionDeleted(m_session->name().c_str()); + } - if (RvApp()->isInPresentationMode()) - { - RvApp()->setPresentationMode(false); - } + m_currentlyClosing = true; - DB ("RvDocument::~RvDocument docs " << RvApp()->documents().size()); + if (RvApp()->isInPresentationMode()) + { + RvApp()->setPresentationMode(false); + } - if (RvApp()->documents().size() == 1) - { - // - // Then this is the last document, so shutdown network - // + DB("RvDocument::~RvDocument docs " << RvApp()->documents().size()); - if (RvNetworkDialog* d = RvApp()->networkWindow()) + if (RvApp()->documents().size() == 1) { - if (d->serverRunning()) d->shutdownServer(); - d->close(); - } + // + // Then this is the last document, so shutdown network + // - if (RvApp()->console()) RvApp()->console()->close(); - if (RvApp()->prefDialog()) RvApp()->prefDialog()->close(); - if (RvApp()->profileManager()) RvApp()->profileManager()->close(); + if (RvNetworkDialog* d = RvApp()->networkWindow()) + { + if (d->serverRunning()) + d->shutdownServer(); + d->close(); + } - RvSettings::cleanupGlobalSettings(); - } + if (RvApp()->console()) + RvApp()->console()->close(); + if (RvApp()->prefDialog()) + RvApp()->prefDialog()->close(); + if (RvApp()->profileManager()) + RvApp()->profileManager()->close(); + + RvSettings::cleanupGlobalSettings(); + } - delete m_session; + delete m_session; - delete m_menuTimer; - delete m_watcher; - delete m_userMenu; - delete m_userPopup; - m_session = 0; - -} + delete m_menuTimer; + delete m_watcher; + delete m_userMenu; + delete m_userPopup; + m_session = 0; + } -QMenuBar* -RvDocument::mb() -{ + QMenuBar* RvDocument::mb() + { #if defined(PLATFORM_DARWIN) - return RvApp()->macMenuBar(); + return RvApp()->macMenuBar(); #else - return menuBar(); + return menuBar(); #endif -} - -void -RvDocument::physicalVideoDeviceChangedSlot(const TwkApp::VideoDevice* device) -{ -#ifdef PLATFORM_DARWIN - if (m_displayLink && m_displayLink->isActive()) - { - playStopSlot(""); - playStartSlot(""); } -#endif -} - -void -RvDocument::playStartSlot(const std::string&) -{ - // - // Unlike the notifier messages, the boost playStartSignal will - // only be emitted when playback is occuring. The notifier signal - // happens when ever updating (including animation) is - // happening. We only want DisplayLink with actual playback - // -#ifdef PLATFORM_DARWIN - if (CGDesktopVideoDevice* cgdevice = - dynamic_cast(m_glView->videoDevice()->physicalDevice())) + void RvDocument::physicalVideoDeviceChangedSlot( + const TwkApp::VideoDevice* device) { - if (m_displayLink) m_displayLink->start(m_session, cgdevice); - } -#endif -} - -void -RvDocument::playStopSlot(const std::string&) -{ #ifdef PLATFORM_DARWIN - if (m_displayLink) m_displayLink->stop(); + if (m_displayLink && m_displayLink->isActive()) + { + playStopSlot(""); + playStartSlot(""); + } #endif -} - -bool -RvDocument::receive( Notifier *originator, - Notifier *sender, - MessageId m, - MessageData *data ) -{ - // - // Don't respond to messages if we're closing. - // - if (m_currentlyClosing) return true; - - if (m == IPCore::Session::updateLoadingMessage()) - { - if (m_session->loadCount() == 0) setDocumentDisabled(true, true); - m_session->update( 5.0 /*5 secs*/, true /* update in any playing mode*/); - qApp->processEvents(QEventLoop::ExcludeUserInputEvents); - if (m_session->loadCount() >= m_session->loadTotal()-1) setDocumentDisabled(false, false); - } - else if (m == IPCore::Session::updateMessage()) - { - view()->videoDevice()->redraw(); } - else if (m == IPCore::Session::eventDeviceChangedMessage()) + + void RvDocument::playStartSlot(const std::string&) { - if (m_session->eventVideoDevice() && m_glView->videoDevice()) + // + // Unlike the notifier messages, the boost playStartSignal will + // only be emitted when playback is occuring. The notifier signal + // happens when ever updating (including animation) is + // happening. We only want DisplayLink with actual playback + // + +#ifdef PLATFORM_DARWIN + if (CGDesktopVideoDevice* cgdevice = + dynamic_cast( + m_glView->videoDevice()->physicalDevice())) { - m_glView->videoDevice()->translator() - .setRelativeDomain(m_session->eventVideoDevice()->width(), - m_session->eventVideoDevice()->height()); + if (m_displayLink) + m_displayLink->start(m_session, cgdevice); } +#endif } - else if (m == TwkApp::Document::filenameChangedMessage()) - { - string t = stl_ext::basename(m_session->fileName()); - setWindowTitle(utf8(t)); - } - else if (m == IPCore::Session::fullScreenOnMessage()) - { - toggleFullscreen(); - } - else if (m == IPCore::Session::fullScreenOffMessage()) - { - toggleFullscreen(); - } - else if (m == IPCore::Session::stereoHardwareOffMessage()) - { - setStereo(false); - } - else if (m == IPCore::Session::stereoHardwareOnMessage()) - { - setStereo(true); - } - else if (m == TwkApp::Document::deleteMessage()) - { - m_session = 0; - } - else if (m == TwkApp::Document::menuChangedMessage()) + + void RvDocument::playStopSlot(const std::string&) { - if (!m_menuExecuting) mergeMenu(m_session->menu()); - else setBuildMenu(); +#ifdef PLATFORM_DARWIN + if (m_displayLink) + m_displayLink->stop(); +#endif } - else if (m == TwkApp::Document::activeMessage()) + + bool RvDocument::receive(Notifier* originator, Notifier* sender, + MessageId m, MessageData* data) { -#if defined(PLATFORM_DARWIN) // - // On Darwin, we may need to rebuild the main menu when - // focus changes, because different sesssions can have - // different menu structures. On other OSes, it's a - // waste of time. + // Don't respond to messages if we're closing. // - static RvDocument* lastActiveDocument = this; - if ( lastActiveDocument != this ) + if (m_currentlyClosing) + return true; + + if (m == IPCore::Session::updateLoadingMessage()) + { + if (m_session->loadCount() == 0) + setDocumentDisabled(true, true); + m_session->update(5.0 /*5 secs*/, + true /* update in any playing mode*/); + qApp->processEvents(QEventLoop::ExcludeUserInputEvents); + if (m_session->loadCount() >= m_session->loadTotal() - 1) + setDocumentDisabled(false, false); + } + else if (m == IPCore::Session::updateMessage()) + { + view()->videoDevice()->redraw(); + } + else if (m == IPCore::Session::eventDeviceChangedMessage()) + { + if (m_session->eventVideoDevice() && m_glView->videoDevice()) + { + m_glView->videoDevice()->translator().setRelativeDomain( + m_session->eventVideoDevice()->width(), + m_session->eventVideoDevice()->height()); + } + } + else if (m == TwkApp::Document::filenameChangedMessage()) + { + string t = stl_ext::basename(m_session->fileName()); + setWindowTitle(utf8(t)); + } + else if (m == IPCore::Session::fullScreenOnMessage()) + { + toggleFullscreen(); + } + else if (m == IPCore::Session::fullScreenOffMessage()) + { + toggleFullscreen(); + } + else if (m == IPCore::Session::stereoHardwareOffMessage()) { - lastActiveDocument = this; - setBuildMenu(); + setStereo(false); } + else if (m == IPCore::Session::stereoHardwareOnMessage()) + { + setStereo(true); + } + else if (m == TwkApp::Document::deleteMessage()) + { + m_session = 0; + } + else if (m == TwkApp::Document::menuChangedMessage()) + { + if (!m_menuExecuting) + mergeMenu(m_session->menu()); + else + setBuildMenu(); + } + else if (m == TwkApp::Document::activeMessage()) + { +#if defined(PLATFORM_DARWIN) + // + // On Darwin, we may need to rebuild the main menu when + // focus changes, because different sesssions can have + // different menu structures. On other OSes, it's a + // waste of time. + // + static RvDocument* lastActiveDocument = this; + if (lastActiveDocument != this) + { + lastActiveDocument = this; + setBuildMenu(); + } #endif - m_glView->setFocus(Qt::OtherFocusReason); + m_glView->setFocus(Qt::OtherFocusReason); + } + else if (m == IPCore::Session::audioUnavailbleMessage()) + { + QMessageBox box(this); + box.setWindowTitle(tr(UI_APPLICATION_NAME ": Audio Failure")); + QString baseText = tr("Audio Device is Currently Unavailable"); + QString detailedText = + tr("Another program (maybe another copy of RV?) " + "is blocking use of the audio device. " + "If you quit the other program you may be " + "able to use the audio again if you restart RV.\n " + "You might also try other audio devices in the preferences " + "audio tab. " +#ifdef PLATFORM_LINUX + "For example, the ALSA \"default\" and \"dmix\" " + "devices allow sharing of audio." +#endif + ); + box.setText(baseText + "\n\n" + detailedText); + box.setWindowModality(Qt::WindowModal); + // QPushButton* b1 = box.addButton(tr("Keep Trying"), + // QMessageBox::AcceptRole); + QPushButton* b2 = + box.addButton(tr("Turn Off Audio"), QMessageBox::AcceptRole); + +#ifdef PLATFORM_LINUX + // Show the RV Icon-- otherwise the user has no idea where + // this came from if RV isn't up yet. + box.setIconPixmap(QPixmap(qApp->applicationDirPath() + + QString(RV_ICON_PATH_SUFFIX)) + .scaledToHeight(64)); +#else + box.setIcon(QMessageBox::Critical); +#endif + + box.exec(); + + if (box.clickedButton() == b2) + { + IPCore::AudioRenderer::setAudioNever(true); + } + // else if (box.clickedButton() == b1) + // { + // Rv::AudioRenderer::setNoAudio(true); + // } + + IPCore::AudioRenderer::reset(); + } + + return true; } - else if (m == IPCore::Session::audioUnavailbleMessage()) + + void RvDocument::resetGLStateAndPrefs() { QMessageBox box(this); - box.setWindowTitle(tr(UI_APPLICATION_NAME ": Audio Failure")); - QString baseText = tr("Audio Device is Currently Unavailable"); - QString detailedText = tr("Another program (maybe another copy of RV?) " - "is blocking use of the audio device. " - "If you quit the other program you may be " - "able to use the audio again if you restart RV.\n " - "You might also try other audio devices in the preferences audio tab. " + box.setWindowTitle( + tr(UI_APPLICATION_NAME ": Invalid Display Configuration")); + QString baseText = tr("Display Configuration is Invalid"); + QString detailedText = + tr("The display configuration in the preferences is\n" + "incompatible with this driver and/or graphics " + "hardware.\n" UI_APPLICATION_NAME + " will use the default display configuration to continue.\n" #ifdef PLATFORM_LINUX - "For example, the ALSA \"default\" and \"dmix\" " - "devices allow sharing of audio." + "You can check available display possibilities\n" + "using the glxinfo command with the -t option from a shell\n" + "or use the driver configuration UI.\n" #endif - ); + "You have a choice: reset the preference automatically\n" + "or use the Rendering preferences to change it manually.\n"); + box.setText(baseText + "\n\n" + detailedText); box.setWindowModality(Qt::WindowModal); - //QPushButton* b1 = box.addButton(tr("Keep Trying"), QMessageBox::AcceptRole); - QPushButton* b2 = box.addButton(tr("Turn Off Audio"), QMessageBox::AcceptRole); + QPushButton* b1 = + box.addButton(tr("Reset Automatically"), QMessageBox::RejectRole); + QPushButton* b2 = box.addButton(tr("Change Preferences Manually"), + QMessageBox::AcceptRole); #ifdef PLATFORM_LINUX // Show the RV Icon-- otherwise the user has no idea where // this came from if RV isn't up yet. - box.setIconPixmap(QPixmap(qApp->applicationDirPath() + QString(RV_ICON_PATH_SUFFIX)).scaledToHeight(64)); + box.setIconPixmap( + QPixmap(qApp->applicationDirPath() + QString(RV_ICON_PATH_SUFFIX)) + .scaledToHeight(64)); #else box.setIcon(QMessageBox::Critical); #endif @@ -603,1268 +683,1283 @@ RvDocument::receive( Notifier *originator, if (box.clickedButton() == b2) { - IPCore::AudioRenderer::setAudioNever(true); + RvApp()->prefs(); + RvApp()->prefDialog()->tabWidget()->setCurrentIndex(2); + RvApp()->prefDialog()->raise(); } - // else if (box.clickedButton() == b1) - // { - // Rv::AudioRenderer::setNoAudio(true); - // } - - IPCore::AudioRenderer::reset(); - } - - return true; -} - -void -RvDocument::resetGLStateAndPrefs() -{ - QMessageBox box(this); - box.setWindowTitle(tr(UI_APPLICATION_NAME ": Invalid Display Configuration")); - QString baseText = tr("Display Configuration is Invalid"); - QString detailedText = tr("The display configuration in the preferences is\n" - "incompatible with this driver and/or graphics hardware.\n" - UI_APPLICATION_NAME " will use the default display configuration to continue.\n" -#ifdef PLATFORM_LINUX - "You can check available display possibilities\n" - "using the glxinfo command with the -t option from a shell\n" - "or use the driver configuration UI.\n" -#endif - "You have a choice: reset the preference automatically\n" - "or use the Rendering preferences to change it manually.\n" - ); - - box.setText(baseText + "\n\n" + detailedText); - box.setWindowModality(Qt::WindowModal); - QPushButton* b1 = box.addButton(tr("Reset Automatically"), QMessageBox::RejectRole); - QPushButton* b2 = box.addButton(tr("Change Preferences Manually"), QMessageBox::AcceptRole); - -#ifdef PLATFORM_LINUX - // Show the RV Icon-- otherwise the user has no idea where - // this came from if RV isn't up yet. - box.setIconPixmap(QPixmap(qApp->applicationDirPath() + QString(RV_ICON_PATH_SUFFIX)).scaledToHeight(64)); -#else - box.setIcon(QMessageBox::Critical); -#endif + else + { + Rv::Options& opts = Options::sharedOptions(); + opts.dispRedBits = 0; + opts.dispGreenBits = 0; + opts.dispBlueBits = 0; + opts.dispAlphaBits = 0; - box.exec(); + { + RV_QSETTINGS; + settings.beginGroup("Display"); + settings.setValue("dispRedBits", 0); + settings.setValue("dispGreenBits", 0); + settings.setValue("dispBlueBits", 0); + settings.setValue("dispAlphaBits", 0); + settings.endGroup(); + } - if (box.clickedButton() == b2) - { - RvApp()->prefs(); - RvApp()->prefDialog()->tabWidget()->setCurrentIndex(2); - RvApp()->prefDialog()->raise(); + RvApp()->prefDialog()->update(); + RvApp()->prefDialog()->write(); + RvApp()->prefDialog()->raise(); + } } - else + + void RvDocument::enableActions(bool b, QMenu* menu) { - Rv::Options& opts = Options::sharedOptions(); - opts.dispRedBits = 0; - opts.dispGreenBits = 0; - opts.dispBlueBits = 0; - opts.dispAlphaBits = 0; + QList actions = menu->actions(); + for (size_t i = 0; i < actions.size(); i++) { - RV_QSETTINGS; - settings.beginGroup("Display"); - settings.setValue("dispRedBits", 0); - settings.setValue("dispGreenBits", 0); - settings.setValue("dispBlueBits", 0); - settings.setValue("dispAlphaBits", 0); - settings.endGroup(); - } + QAction* a = actions[i]; + if (a->menu()) + enableActions(b, a->menu()); - RvApp()->prefDialog()->update(); - RvApp()->prefDialog()->write(); - RvApp()->prefDialog()->raise(); + a->setEnabled(b); + } } -} - -void -RvDocument::enableActions(bool b, QMenu* menu) -{ - QList actions = menu->actions(); - for (size_t i = 0; i < actions.size(); i++) + void RvDocument::lazyDeleteGLView() { - QAction* a = actions[i]; - if (a->menu()) enableActions(b, a->menu()); + delete m_oldGLView; + m_oldGLView = 0; + } - a->setEnabled(b); + void RvDocument::resetSizePolicy() + { + m_glView->setMinimumContentSize(64, 64); + m_glView->setMinimumSize(QSize(64, 64)); + m_glView->setSizePolicy( + QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred)); } -} -void -RvDocument::lazyDeleteGLView() -{ - delete m_oldGLView; - m_oldGLView = 0; -} + void RvDocument::setDocumentDisabled(bool b, bool menuBarOnly) + { + // if (!menuBarOnly) setDisabled(b); -void -RvDocument::resetSizePolicy() -{ - m_glView->setMinimumContentSize(64,64); - m_glView->setMinimumSize(QSize(64,64)); - m_glView->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, - QSizePolicy::Preferred)); -} - -void -RvDocument::setDocumentDisabled(bool b, bool menuBarOnly) -{ - //if (!menuBarOnly) setDisabled(b); + m_menuBarDisable = b; - m_menuBarDisable = b; + QList actions = mb()->actions(); + for (size_t i = 0; i < actions.size(); i++) + { + QAction* a = actions[i]; + if (a->menu()) + enableActions(!b, a->menu()); + a->setEnabled(!b); + } + } - QList actions = mb()->actions(); - for (size_t i = 0; i < actions.size(); i++) + void RvDocument::rebuildGLView(bool stereo, bool vsync, bool doubleBuffer, + int red, int green, int blue, int alpha) { - QAction* a = actions[i]; - if (a->menu()) enableActions(!b, a->menu()); - a->setEnabled(!b); - } -} - -void -RvDocument::rebuildGLView(bool stereo, - bool vsync, - bool doubleBuffer, - int red, - int green, - int blue, - int alpha) -{ - // - // On the mac, we need to carefully replace the content GL widget so - // that Qt doesn't resize the dock widgets and everything - // else. Unforunately, when the content widget was the GLView and we - // put a new one in, we had no core dump. When we do this manually and - // delete the old widget it dumps core. The problem seems to be random - // events which are going to be sent this event processing round. - // - // The workaround is to lazily delete the old GLView. I have a feeling - // the main window class does something similar itself which is why - // our code didn't dump core before. At the bottom of this function - // there is a temp timer that fires in 100ms to delete it. Or if this - // function is called again before that time its deleted. - // + // + // On the mac, we need to carefully replace the content GL widget so + // that Qt doesn't resize the dock widgets and everything + // else. Unforunately, when the content widget was the GLView and we + // put a new one in, we had no core dump. When we do this manually and + // delete the old widget it dumps core. The problem seems to be random + // events which are going to be sent this event processing round. + // + // The workaround is to lazily delete the old GLView. I have a feeling + // the main window class does something similar itself which is why + // our code didn't dump core before. At the bottom of this function + // there is a temp timer that fires in 100ms to delete it. Or if this + // function is called again before that time its deleted. + // - lazyDeleteGLView(); + lazyDeleteGLView(); - GLView* oldGLView = m_glView; - Qt::KeyboardModifiers cur = m_glView->videoDevice()->translator().currentModifiers(); - oldGLView->stopProcessingEvents(); + GLView* oldGLView = m_glView; + Qt::KeyboardModifiers cur = + m_glView->videoDevice()->translator().currentModifiers(); + oldGLView->stopProcessingEvents(); - GLView* newGLView = new GLView(this, view(), this, - stereo, vsync, doubleBuffer, - red, green, blue, alpha); + GLView* newGLView = new GLView(this, view(), this, stereo, vsync, + doubleBuffer, red, green, blue, alpha); - newGLView->setContentSize(oldGLView->sizeHint().width(), - oldGLView->sizeHint().height()); + newGLView->setContentSize(oldGLView->sizeHint().width(), + oldGLView->sizeHint().height()); - newGLView->setMinimumSize(oldGLView->minimumSizeHint().width(), - oldGLView->minimumSizeHint().height()); + newGLView->setMinimumSize(oldGLView->minimumSizeHint().width(), + oldGLView->minimumSizeHint().height()); - bool resetGLPrefs = false; + bool resetGLPrefs = false; - size_t ow = centralWidget()->width(); - size_t oh = centralWidget()->height(); + size_t ow = centralWidget()->width(); + size_t oh = centralWidget()->height(); - if (!newGLView->isValid()) - { - delete newGLView; - newGLView = new GLView(this, view(), this); - resetGLPrefs = true; - } - - m_stackedLayout->addWidget(newGLView); - m_stackedLayout->removeWidget(oldGLView); - m_glView = newGLView; - m_glView->show(); - m_glView->setFocus(Qt::OtherFocusReason); + if (!newGLView->isValid()) + { + delete newGLView; + newGLView = new GLView(this, view(), this); + resetGLPrefs = true; + } - m_topViewToolBar->setDevice(m_glView->videoDevice()); + m_stackedLayout->addWidget(newGLView); + m_stackedLayout->removeWidget(oldGLView); + m_glView = newGLView; + m_glView->show(); + m_glView->setFocus(Qt::OtherFocusReason); - bool same = m_session->outputVideoDevice() == m_session->controlVideoDevice(); - m_session->setEventVideoDevice(0); - m_session->setOutputVideoDevice(0); - m_session->setControlVideoDevice(m_glView->videoDevice()); - if (same) m_session->setOutputVideoDevice(m_glView->videoDevice()); + m_topViewToolBar->setDevice(m_glView->videoDevice()); - m_glView->videoDevice()->sendEvent(TwkApp::RenderContextChangeEvent("gl-context-changed", m_glView->videoDevice())); + bool same = + m_session->outputVideoDevice() == m_session->controlVideoDevice(); + m_session->setEventVideoDevice(0); + m_session->setOutputVideoDevice(0); + m_session->setControlVideoDevice(m_glView->videoDevice()); + if (same) + m_session->setOutputVideoDevice(m_glView->videoDevice()); - if (resetGLPrefs) resetGLStateAndPrefs(); + m_glView->videoDevice()->sendEvent(TwkApp::RenderContextChangeEvent( + "gl-context-changed", m_glView->videoDevice())); - if (DesktopVideoModule* m = RvApp()->desktopVideoModule()) - { - const TwkApp::VideoModule::VideoDevices& devices = m->devices(); - - for (size_t i = 0; i < devices.size(); i++) + if (resetGLPrefs) + resetGLStateAndPrefs(); + + if (DesktopVideoModule* m = RvApp()->desktopVideoModule()) { - if (DesktopVideoDevice* d = dynamic_cast(devices[i])) + const TwkApp::VideoModule::VideoDevices& devices = m->devices(); + + for (size_t i = 0; i < devices.size(); i++) { - d->setShareDevice(m_glView->videoDevice()); + if (DesktopVideoDevice* d = + dynamic_cast(devices[i])) + { + d->setShareDevice(m_glView->videoDevice()); + } } } + + m_glView->videoDevice()->translator().setCurrentModifiers(cur); + m_oldGLView = oldGLView; + m_oldGLView->hide(); + QTimer::singleShot(100, this, SLOT(lazyDeleteGLView())); } - m_glView->videoDevice()->translator().setCurrentModifiers(cur); - m_oldGLView = oldGLView; - m_oldGLView->hide(); - QTimer::singleShot(100, this, SLOT(lazyDeleteGLView())); -} + void RvDocument::setStereo(bool b) + { + const bool vsync = m_glView->format().swapInterval() == 1; + const bool stereo = m_glView->format().stereo(); + const bool dbl = m_glView->format().doubleBuffer(); + const int red = m_glView->format().redBufferSize(); + const int green = m_glView->format().greenBufferSize(); + const int blue = m_glView->format().blueBufferSize(); + const int alpha = m_glView->format().alphaBufferSize(); + if (b != stereo) + rebuildGLView(b, vsync, dbl, red, green, blue, alpha); + } -void -RvDocument::setStereo(bool b) -{ - const bool vsync = m_glView->format().swapInterval() == 1; - const bool stereo = m_glView->format().stereo(); - const bool dbl = m_glView->format().doubleBuffer(); - const int red = m_glView->format().redBufferSize(); - const int green = m_glView->format().greenBufferSize(); - const int blue = m_glView->format().blueBufferSize(); - const int alpha = m_glView->format().alphaBufferSize(); - if (b != stereo) rebuildGLView(b, vsync, dbl, red, green, blue, alpha); -} - -void -RvDocument::setVSync(bool b) -{ - if (m_vsyncDisabled) return; - const bool vsync = m_glView->format().swapInterval() == 1; - const bool stereo = m_glView->format().stereo(); - const bool dbl = m_glView->format().doubleBuffer(); - const int red = m_glView->format().redBufferSize(); - const int green = m_glView->format().greenBufferSize(); - const int blue = m_glView->format().blueBufferSize(); - const int alpha = m_glView->format().alphaBufferSize(); - if (b != vsync) rebuildGLView(stereo, b, dbl, red, green, blue, alpha); -} - -void -RvDocument::setDoubleBuffer(bool b) -{ - bool vsync = m_glView->format().swapInterval() == 1; - const bool stereo = m_glView->format().stereo(); - const int red = m_glView->format().redBufferSize(); - const int green = m_glView->format().greenBufferSize(); - const int blue = m_glView->format().blueBufferSize(); - const int alpha = m_glView->format().alphaBufferSize(); + void RvDocument::setVSync(bool b) + { + if (m_vsyncDisabled) + return; + const bool vsync = m_glView->format().swapInterval() == 1; + const bool stereo = m_glView->format().stereo(); + const bool dbl = m_glView->format().doubleBuffer(); + const int red = m_glView->format().redBufferSize(); + const int green = m_glView->format().greenBufferSize(); + const int blue = m_glView->format().blueBufferSize(); + const int alpha = m_glView->format().alphaBufferSize(); + if (b != vsync) + rebuildGLView(stereo, b, dbl, red, green, blue, alpha); + } - if (!b) vsync = false; + void RvDocument::setDoubleBuffer(bool b) + { + bool vsync = m_glView->format().swapInterval() == 1; + const bool stereo = m_glView->format().stereo(); + const int red = m_glView->format().redBufferSize(); + const int green = m_glView->format().greenBufferSize(); + const int blue = m_glView->format().blueBufferSize(); + const int alpha = m_glView->format().alphaBufferSize(); - rebuildGLView(stereo, vsync, b, red, green, blue, alpha); -} + if (!b) + vsync = false; -void -RvDocument::setDisplayOutput(DisplayOutputType type) -{ - const bool vsync = m_glView->format().swapInterval() == 1; - const bool stereo = m_glView->format().stereo(); - const bool dbl = m_glView->format().doubleBuffer(); - int red = m_glView->format().redBufferSize(); - int green = m_glView->format().greenBufferSize(); - int blue = m_glView->format().blueBufferSize(); - int alpha = m_glView->format().alphaBufferSize(); - - switch (type) - { - default: - case OpenGLDefaultFormat: - if (red == 0) return; - red = 0; blue = 0; green = 0; alpha = 0; - break; - case OpenGL8888: - if (red == 8) return; - red = 8; blue = 8; green = 8; alpha = 8; - break; - case OpenGL1010102: - if (red == 10) return; - red = 10; green = 10; blue = 10; alpha = 2; - break; + rebuildGLView(stereo, vsync, b, red, green, blue, alpha); } - rebuildGLView(stereo, vsync, dbl, red, green, blue, alpha); -} + void RvDocument::setDisplayOutput(DisplayOutputType type) + { + const bool vsync = m_glView->format().swapInterval() == 1; + const bool stereo = m_glView->format().stereo(); + const bool dbl = m_glView->format().doubleBuffer(); + int red = m_glView->format().redBufferSize(); + int green = m_glView->format().greenBufferSize(); + int blue = m_glView->format().blueBufferSize(); + int alpha = m_glView->format().alphaBufferSize(); -GLView* -RvDocument::view() const -{ - return m_glView; -} + switch (type) + { + default: + case OpenGLDefaultFormat: + if (red == 0) + return; + red = 0; + blue = 0; + green = 0; + alpha = 0; + break; + case OpenGL8888: + if (red == 8) + return; + red = 8; + blue = 8; + green = 8; + alpha = 8; + break; + case OpenGL1010102: + if (red == 10) + return; + red = 10; + green = 10; + blue = 10; + alpha = 2; + break; + } -void -RvDocument::center() -{ - QDesktopWidget* desktop = QApplication::desktop(); - int screen = desktop->screenNumber(this); - QRect ssize = desktop->availableGeometry(screen); + rebuildGLView(stereo, vsync, dbl, red, green, blue, alpha); + } - int sw = ssize.width(); - int sh = ssize.height(); + GLView* RvDocument::view() const { return m_glView; } - int x = ssize.left() + int ((sw - frameGeometry().width()) / 2); - int y = ssize.top() + int ((sh - frameGeometry().height()) / 2); - DB ("center moving to x " << x << " y " << y); - move (x, y); -} + void RvDocument::center() + { + QDesktopWidget* desktop = QApplication::desktop(); + int screen = desktop->screenNumber(this); + QRect ssize = desktop->availableGeometry(screen); -void -RvDocument::resizeView(int w, int h) -{ - if (!m_session) return; + int sw = ssize.width(); + int sh = ssize.height(); - // - // Fit the window on to the screen so that all of its pixels are - // visible. If the contents is smaller than the screen, fit the - // window to the content size. If not, fit the window to the - // screen and leave some margin on each side so that the user can - // move the window. - // + int x = ssize.left() + int((sw - frameGeometry().width()) / 2); + int y = ssize.top() + int((sh - frameGeometry().height()) / 2); + DB("center moving to x " << x << " y " << y); + move(x, y); + } + + void RvDocument::resizeView(int w, int h) + { + if (!m_session) + return; + + // + // Fit the window on to the screen so that all of its pixels are + // visible. If the contents is smaller than the screen, fit the + // window to the content size. If not, fit the window to the + // screen and leave some margin on each side so that the user can + // move the window. + // #ifndef PLATFORM_LINUX - const int oversizeMargin = 0; + const int oversizeMargin = 0; #else - const int oversizeMargin = 60; + const int oversizeMargin = 60; #endif - const int overlap = 20; + const int overlap = 20; - // - // Get all top level windows so we can avoid placing this one on - // top of an existing one. - // + // + // Get all top level windows so we can avoid placing this one on + // top of an existing one. + // - QDesktopWidget* desktop = QApplication::desktop(); - int screen = desktop->screenNumber(this); - - QRect ssize = desktop->availableGeometry(screen); - QRect ts = desktop->screenGeometry(screen); - float sw = float(ssize.width()); - float sh = float(ssize.height()); + QDesktopWidget* desktop = QApplication::desktop(); + int screen = desktop->screenNumber(this); - if (h == 0) h = w; - if (w == 0) w = h; - if (w == 0) { w = 1024; h = 720; } + QRect ssize = desktop->availableGeometry(screen); + QRect ts = desktop->screenGeometry(screen); + float sw = float(ssize.width()); + float sh = float(ssize.height()); - m_session->userRenderEvent("layout"); - IPCore::Session::Margins margins = m_session->controlVideoDevice()->margins(); - float mw = int(margins.left + margins.right); - float mh = int(margins.top + margins.bottom); + if (h == 0) + h = w; + if (w == 0) + w = h; + if (w == 0) + { + w = 1024; + h = 720; + } - sw -= mw; - sh -= mh; + m_session->userRenderEvent("layout"); + IPCore::Session::Margins margins = + m_session->controlVideoDevice()->margins(); + float mw = int(margins.left + margins.right); + float mh = int(margins.top + margins.bottom); - // - // We'd like to compensate for the frame geometry (wm - // decorations) in our size request, but values returned are - // not reliable on linx. - // - #ifndef PLATFORM_LINUX - int frameW = int (frameGeometry().width()-width()); - int frameH = int (frameGeometry().height()-height()); - DB ("resizeView frame w " << frameW << " h " << frameH); + sw -= mw; + sh -= mh; + +// +// We'd like to compensate for the frame geometry (wm +// decorations) in our size request, but values returned are +// not reliable on linx. +// +#ifndef PLATFORM_LINUX + int frameW = int(frameGeometry().width() - width()); + int frameH = int(frameGeometry().height() - height()); + DB("resizeView frame w " << frameW << " h " << frameH); sw -= frameW; sh -= frameH; - #endif +#endif - // - // We'd like to compensate for the menubar height but it does - // not report it's size reliably on linux. On mac, we don't - // care. - // - #ifdef PLATFORM_WINDOWS +// +// We'd like to compensate for the menubar height but it does +// not report it's size reliably on linux. On mac, we don't +// care. +// +#ifdef PLATFORM_WINDOWS sh -= (menuBarShown()) ? mb()->height() : 0; - #endif - - float aspect = float(w) / float(h); +#endif - if (w >= sw - oversizeMargin) - { - w = int(sw - oversizeMargin); - if (!m_aggressiveSizing) h = int (float(w) / aspect); - } + float aspect = float(w) / float(h); - if (h > sh - oversizeMargin) - { - h = int(sh - oversizeMargin); - if (!m_aggressiveSizing) w = int(float(h) * aspect); - } - - h += int(mh); - w += int(mw); + if (w >= sw - oversizeMargin) + { + w = int(sw - oversizeMargin); + if (!m_aggressiveSizing) + h = int(float(w) / aspect); + } - m_glView->setContentSize(w, h); - m_glView->setMinimumContentSize(w, h); - m_glView->updateGeometry(); + if (h > sh - oversizeMargin) + { + h = int(sh - oversizeMargin); + if (!m_aggressiveSizing) + w = int(float(h) * aspect); + } - const int dh = m_glView->height() - h; - const int dw = m_glView->width() - w; + h += int(mh); + w += int(mw); - if (dh || dw) - { - resize(width() - dw, height() - dh); m_glView->setContentSize(w, h); m_glView->setMinimumContentSize(w, h); m_glView->updateGeometry(); - } - m_resetPolicyTimer->start(); -} + const int dh = m_glView->height() - h; + const int dw = m_glView->width() - w; -void -RvDocument::resizeToFit(bool placement, bool firstTime) -{ - DB ("resizeToFit first " << firstTime); - if (!m_session) return; + if (dh || dw) + { + resize(width() - dw, height() - dh); + m_glView->setContentSize(w, h); + m_glView->setMinimumContentSize(w, h); + m_glView->updateGeometry(); + } - // - // Fit the window on to the screen so that all of its pixels are - // visible. If the contents is smaller than the screen, fit the - // window to the content size. If not, fit the window to the - // screen and leave some margin on each side so that the user can - // move the window. - // + m_resetPolicyTimer->start(); + } + + void RvDocument::resizeToFit(bool placement, bool firstTime) + { + DB("resizeToFit first " << firstTime); + if (!m_session) + return; + + // + // Fit the window on to the screen so that all of its pixels are + // visible. If the contents is smaller than the screen, fit the + // window to the content size. If not, fit the window to the + // screen and leave some margin on each side so that the user can + // move the window. + // #ifndef PLATFORM_LINUX - const int oversizeMargin = 0; + const int oversizeMargin = 0; #else - const int oversizeMargin = 60; + const int oversizeMargin = 60; #endif - const int overlap = 20; - - // - // Get all top level windows so we can avoid placing this one on - // top of an existing one. - // - - const TwkApp::Application::Documents& docs = RvApp()->documents(); - vector windows; - - for (unsigned int i = 0; i < docs.size(); i++) - { - windows.push_back(reinterpret_cast(docs[i]->opaquePointer())); - } + const int overlap = 20; - float w = 0; - float h = 0; - - QDesktopWidget* desktop = QApplication::desktop(); - int screen = desktop->screenNumber(this); - - QRect ssize = desktop->availableGeometry(screen); - DB ("resizeToFit available geom w " << ssize.width() << " h " << ssize.height()); - QRect ts = desktop->screenGeometry(screen); - float sw = float(ssize.width()); - float sh = float(ssize.height()); - - /* - if (m_session->graph().viewNode()) - { - DB("resizeToFit using view node"); - IPNode *n = m_session->graph().viewNode(); - if (n->inputs().size()) { DB ("resizeToFit selecting input"); n = n->inputs()[0]; } - - IPNode::ImageStructureInfo info = - n->imageStructureInfo(m_session->graph().contextForFrame(m_session->currentFrame())); - w = int(info.width); - h = int(info.height); - DB ("resizeToFit node " << n->name() << " w " << w << " h " << h << endl); - } - */ - if (m_session->rootNode()) - { - DB("resizeToFit using root node"); // - // Find source nodes in eval path + // Get all top level windows so we can avoid placing this one on + // top of an existing one. // - IPNode::MetaEvalInfoVector evalInfos; - IPNode::MetaEvalClosestByTypeName collector(evalInfos, "RVSourceGroup"); - m_session->rootNode()->metaEvaluate(m_session->graph().contextForFrame(m_session->currentFrame()), collector); - if (evalInfos.size()) + + const TwkApp::Application::Documents& docs = RvApp()->documents(); + vector windows; + + for (unsigned int i = 0; i < docs.size(); i++) { - IPNode::ImageStructureInfo info = - evalInfos[0].node->imageStructureInfo(m_session->graph().contextForFrame(m_session->currentFrame())); - w = int(info.width); - h = int(info.height); - DB("resizeToFit w " << info.width << " h " << info.height); + windows.push_back( + reinterpret_cast(docs[i]->opaquePointer())); } - } - else if (!m_session->isEmpty()) - { - DB("resizeToFit using first source"); - IPGraph::NodeVector nodes; - m_session->graph().findNodesByTypeName(nodes, "RVSourceGroup"); - if (!nodes.empty()) + float w = 0; + float h = 0; + + QDesktopWidget* desktop = QApplication::desktop(); + int screen = desktop->screenNumber(this); + + QRect ssize = desktop->availableGeometry(screen); + DB("resizeToFit available geom w " << ssize.width() << " h " + << ssize.height()); + QRect ts = desktop->screenGeometry(screen); + float sw = float(ssize.width()); + float sh = float(ssize.height()); + + /* + if (m_session->graph().viewNode()) + { + DB("resizeToFit using view node"); + IPNode *n = m_session->graph().viewNode(); + if (n->inputs().size()) { DB ("resizeToFit selecting input"); n = + n->inputs()[0]; } + + IPNode::ImageStructureInfo info = + n->imageStructureInfo(m_session->graph().contextForFrame(m_session->currentFrame())); + w = int(info.width); + h = int(info.height); + DB ("resizeToFit node " << n->name() << " w " << w << " h " << h << + endl); + } + */ + if (m_session->rootNode()) { - IPNode* node = nodes.front(); - IPNode::ImageRangeInfo range = nodes.front()->imageRangeInfo(); - IPNode::ImageStructureInfo info = - node->imageStructureInfo(m_session->graph().contextForFrame(range.start)); - w = int(info.width); - h = int(info.height); - DB("resizeToFit source info w " << info.width << " h " << info.height); + DB("resizeToFit using root node"); + // + // Find source nodes in eval path + // + IPNode::MetaEvalInfoVector evalInfos; + IPNode::MetaEvalClosestByTypeName collector(evalInfos, + "RVSourceGroup"); + m_session->rootNode()->metaEvaluate( + m_session->graph().contextForFrame(m_session->currentFrame()), + collector); + if (evalInfos.size()) + { + IPNode::ImageStructureInfo info = + evalInfos[0].node->imageStructureInfo( + m_session->graph().contextForFrame( + m_session->currentFrame())); + w = int(info.width); + h = int(info.height); + DB("resizeToFit w " << info.width << " h " << info.height); + } } - } - if (w <= 0 || h <= 0) - { - DB ("resizeToFit bad initial dimensions: w " << w << " h " << h); - w = 854; - h = 480; - } - DB ("resizeToFit initial w " << w << " h " << h); + else if (!m_session->isEmpty()) + { + DB("resizeToFit using first source"); + IPGraph::NodeVector nodes; + m_session->graph().findNodesByTypeName(nodes, "RVSourceGroup"); - if (h == 0) h = w; - if (w == 0) w = h; - - if (w == 0) - { - w = 854; - h = 480; - } + if (!nodes.empty()) + { + IPNode* node = nodes.front(); + IPNode::ImageRangeInfo range = nodes.front()->imageRangeInfo(); + IPNode::ImageStructureInfo info = node->imageStructureInfo( + m_session->graph().contextForFrame(range.start)); + w = int(info.width); + h = int(info.height); + DB("resizeToFit source info w " << info.width << " h " + << info.height); + } + } + if (w <= 0 || h <= 0) + { + DB("resizeToFit bad initial dimensions: w " << w << " h " << h); + w = 854; + h = 480; + } + DB("resizeToFit initial w " << w << " h " << h); - m_session->userRenderEvent("layout"); - Session::Margins margins = m_glView->videoDevice()->margins(); - float mw = int(margins.left + margins.right); - float mh = int(margins.top + margins.bottom); + if (h == 0) + h = w; + if (w == 0) + w = h; - ensurePolished(); + if (w == 0) + { + w = 854; + h = 480; + } - sw -= mw; - sh -= mh; - - // - // We'd like to compensate for the frame geometry (wm - // decorations) in our size request, but values returned are - // not reliable on linx. - // + m_session->userRenderEvent("layout"); + Session::Margins margins = m_glView->videoDevice()->margins(); + float mw = int(margins.left + margins.right); + float mh = int(margins.top + margins.bottom); + + ensurePolished(); + + sw -= mw; + sh -= mh; + + // + // We'd like to compensate for the frame geometry (wm + // decorations) in our size request, but values returned are + // not reliable on linx. + // #ifndef PLATFORM_LINUX - int frameW = int (frameGeometry().width()-width()); - int frameH = int (frameGeometry().height()-height()); - DB ("resizeToFit frame w " << frameW << " h " << frameH); + int frameW = int(frameGeometry().width() - width()); + int frameH = int(frameGeometry().height() - height()); + DB("resizeToFit frame w " << frameW << " h " << frameH); - sw -= frameW; - sh -= frameH; + sw -= frameW; + sh -= frameH; #endif - // - // We'd like to compensate for the presence of the top and/or - // bottom toolbars as well. - // - if (m_topViewToolBar->isVisible()) - { - sh -= m_topViewToolBar->height(); - } - if (m_bottomViewToolBar->isVisible()) - { - sh -= m_bottomViewToolBar->height(); - } + // + // We'd like to compensate for the presence of the top and/or + // bottom toolbars as well. + // + if (m_topViewToolBar->isVisible()) + { + sh -= m_topViewToolBar->height(); + } + if (m_bottomViewToolBar->isVisible()) + { + sh -= m_bottomViewToolBar->height(); + } - // - // We'd like to compensate for the menubar height but it does - // not report it's size reliably on linux. On mac, we don't - // care. - // - mb()->ensurePolished(); - DB ("resizeToFit mb()->height() " << mb()->height()); + // + // We'd like to compensate for the menubar height but it does + // not report it's size reliably on linux. On mac, we don't + // care. + // + mb()->ensurePolished(); + DB("resizeToFit mb()->height() " << mb()->height()); #ifdef PLATFORM_WINDOWS - sh -= (menuBarShown()) ? mb()->height() : 0; - //sh -= (menuBarShown()) ? 26 : 0; + sh -= (menuBarShown()) ? mb()->height() : 0; + // sh -= (menuBarShown()) ? 26 : 0; #endif - float aspect = float(w) / float(h); - - if (w >= sw - oversizeMargin) - { - w = sw - oversizeMargin; - if (!m_aggressiveSizing) h = w / aspect; - } - - if (h > sh - oversizeMargin) - { - h = sh - oversizeMargin; - if (!m_aggressiveSizing) w = h * aspect; - } - - h += mh; - w += mw; + float aspect = float(w) / float(h); - DB ("resizeToFit final target w " << w << " h " << h); - - m_glView->setContentSize(int(w), int(h)); - m_glView->setMinimumContentSize(int(w), int(h)); - m_glView->updateGeometry(); + if (w >= sw - oversizeMargin) + { + w = sw - oversizeMargin; + if (!m_aggressiveSizing) + h = w / aspect; + } - DB ("resizeToFit resulting size w " << m_glView->width() << " h " << m_glView->height()); + if (h > sh - oversizeMargin) + { + h = sh - oversizeMargin; + if (!m_aggressiveSizing) + w = h * aspect; + } - const int dh = m_glView->height() - int(h); - const int dw = m_glView->width() - int(w); + h += mh; + w += mw; - // - // WHY? Dunno - // + DB("resizeToFit final target w " << w << " h " << h); - DB ("resizeToFit dw " << dw << " dh " << dh); - if (!firstTime && (dh || dw)) - //if ((dh || dw)) - { - resize(width() - dw, height() - dh); m_glView->setContentSize(int(w), int(h)); m_glView->setMinimumContentSize(int(w), int(h)); m_glView->updateGeometry(); - } - DB ("resizeToFit final resulting size w " << m_glView->width() << " h " << m_glView->height()); - m_resetPolicyTimer->start(); - - if (placement) - { - int x = ssize.left() + int ((sw - w) / 2); - int y = ssize.top() + int ((sh - h) / 2); + DB("resizeToFit resulting size w " << m_glView->width() << " h " + << m_glView->height()); + + const int dh = m_glView->height() - int(h); + const int dw = m_glView->width() - int(w); // - // Keep moving the window until its in a decent spot. This may - // move it to a partially occluded position, but it will not - // cover an existing window's frame. This mimics (kind-of) what - // Cocoa does. + // WHY? Dunno // - for (int i=0; i < windows.size(); i++) + DB("resizeToFit dw " << dw << " dh " << dh); + if (!firstTime && (dh || dw)) + // if ((dh || dw)) { - RvDocument* d = windows[i]; + resize(width() - dw, height() - dh); + m_glView->setContentSize(int(w), int(h)); + m_glView->setMinimumContentSize(int(w), int(h)); + m_glView->updateGeometry(); + } + DB("resizeToFit final resulting size w " << m_glView->width() << " h " + << m_glView->height()); + + m_resetPolicyTimer->start(); - if (d != this) + if (placement) + { + int x = ssize.left() + int((sw - w) / 2); + int y = ssize.top() + int((sh - h) / 2); + + // + // Keep moving the window until its in a decent spot. This may + // move it to a partially occluded position, but it will not + // cover an existing window's frame. This mimics (kind-of) what + // Cocoa does. + // + + for (int i = 0; i < windows.size(); i++) { - int dx = d->x() - x; - int dy = d->y() - y; - - if (abs(dx) < overlap || abs(dy) < overlap) + RvDocument* d = windows[i]; + + if (d != this) { - x += overlap; - y += overlap; - int i = -1; // start over + int dx = d->x() - x; + int dy = d->y() - y; + + if (abs(dx) < overlap || abs(dy) < overlap) + { + x += overlap; + y += overlap; + int i = -1; // start over + } } } - } - x = max (ssize.left(), x); - //y = max (frameH, y); - y = max (ssize.top(), y); - DB ("resizeToFit, moving to " << x << " " << y); - move(x, y); + x = max(ssize.left(), x); + // y = max (frameH, y); + y = max(ssize.top(), y); + DB("resizeToFit, moving to " << x << " " << y); + move(x, y); + } } -} -void -RvDocument::toggleFullscreen(bool firstTime) -{ - DB ("toggleFullScreen currently " << isFullScreen()); - QDesktopWidget* desktop = QApplication::desktop(); - int screen = desktop->screenNumber(this); - QRect ssize = desktop->screenGeometry(screen); - int sw = ssize.width(); - int sh = ssize.height(); + void RvDocument::toggleFullscreen(bool firstTime) + { + DB("toggleFullScreen currently " << isFullScreen()); + QDesktopWidget* desktop = QApplication::desktop(); + int screen = desktop->screenNumber(this); + QRect ssize = desktop->screenGeometry(screen); + int sw = ssize.width(); + int sh = ssize.height(); - resetSizePolicy(); + resetSizePolicy(); - if (m_topViewToolBar) - { - m_topViewToolBar->setFullscreen(!isFullScreen()); - } + if (m_topViewToolBar) + { + m_topViewToolBar->setFullscreen(!isFullScreen()); + } - if (isFullScreen()) - { - ssize = desktop->availableGeometry(screen); - showNormal(); - } - else - { - if (firstTime) + if (isFullScreen()) { - setWindowState(windowState() ^ Qt::WindowFullScreen); + ssize = desktop->availableGeometry(screen); + showNormal(); } else { - showFullScreen(); - setAcceptDrops(true); + if (firstTime) + { + setWindowState(windowState() ^ Qt::WindowFullScreen); + } + else + { + showFullScreen(); + setAcceptDrops(true); + } } + + m_glView->setFocus(Qt::OtherFocusReason); + activateWindow(); + raise(); + // + // On windows, sometimes returning from full-screen leaves us + // with a black screen unless we do the below. + // + m_session->askForRedraw(); } - m_glView->setFocus(Qt::OtherFocusReason); - activateWindow(); - raise(); - // - // On windows, sometimes returning from full-screen leaves us - // with a black screen unless we do the below. - // - m_session->askForRedraw(); -} + QRect RvDocument::childrenRect() + { + QRect mr = mb()->geometry(); + QRect vr = m_glView->geometry(); -QRect -RvDocument::childrenRect() -{ - QRect mr = mb()->geometry(); - QRect vr = m_glView->geometry(); + DB("RvDocument::childrenRect mb" + << " shown " << menuBarShown() << " vis " << mb()->isVisible() + << " w" << mr.width() << " h " << mr.height() + << " view " + " w" + << vr.width() << " vh " << vr.height()); - DB ("RvDocument::childrenRect mb" << - " shown " << menuBarShown() << " vis " << mb()->isVisible() << - " w" << mr.width() << " h " << mr.height() << " view " - " w" << vr.width() << " vh " << vr.height()); - - QRect r = QMainWindow::childrenRect(); - DB ("RvDocument::childrenRect r w " << r.width() << " h " << r.height()); + QRect r = QMainWindow::childrenRect(); + DB("RvDocument::childrenRect r w " << r.width() << " h " << r.height()); - // - // We don't want the menubar to drive the width of the window. - // And on macos, it doesn't come into it at all. - // - r.setWidth(vr.width()); - #ifndef PLATFORM_DARWIN - r.setHeight((menuBarShown()) ? (mr.height() + vr.height()) : vr.height()); - #else + // + // We don't want the menubar to drive the width of the window. + // And on macos, it doesn't come into it at all. + // + r.setWidth(vr.width()); +#ifndef PLATFORM_DARWIN + r.setHeight((menuBarShown()) ? (mr.height() + vr.height()) + : vr.height()); +#else r.setHeight(vr.height()); - #endif - return r; -} - -void -RvDocument::toggleMenuBar() -{ - DB ("RvDocument::toggleMenuBar, currently " << m_menuBarShown); - // - // Can't use "isVisible()" here, because visible state depends - // on the state of the mb's ancestors. - // - if (m_menuBarShown) - { - //m_menuBarHeight = mb()->height(); - mb()->hide(); - m_menuBarShown = false; - //if (!isFullScreen()) resize(ww, wh - m_menuBarHeight); +#endif + return r; } - else + + void RvDocument::toggleMenuBar() { - mb()->show(); - m_menuBarShown = true; - //if (!isFullScreen()) resize(ww, wh + m_menuBarHeight); + DB("RvDocument::toggleMenuBar, currently " << m_menuBarShown); + // + // Can't use "isVisible()" here, because visible state depends + // on the state of the mb's ancestors. + // + if (m_menuBarShown) + { + // m_menuBarHeight = mb()->height(); + mb()->hide(); + m_menuBarShown = false; + // if (!isFullScreen()) resize(ww, wh - m_menuBarHeight); + } + else + { + mb()->show(); + m_menuBarShown = true; + // if (!isFullScreen()) resize(ww, wh + m_menuBarHeight); + } } -} -//---------------------------------------------------------------------- -// -// Menus -// - -void -RvDocument::menuActivated() -{ - m_menuExecuting++; + //---------------------------------------------------------------------- + // + // Menus + // - if (!m_menuBarDisable && isEnabled()) + void RvDocument::menuActivated() { - if (TwkQTAction* a = dynamic_cast(sender())) + m_menuExecuting++; + + if (!m_menuBarDisable && isEnabled()) { - if (const QAction* qa = dynamic_cast(sender())) + if (TwkQTAction* a = dynamic_cast(sender())) { - m_lastPopupAction = qa; - } - - // - // There can be no action if the user set it to nil. - // In that case just ignore it. - // + if (const QAction* qa = dynamic_cast(sender())) + { + m_lastPopupAction = qa; + } - if (const TwkApp::Action* action = a->item()->action()) - { // - // Won't throw + // There can be no action if the user set it to nil. + // In that case just ignore it. // - a->doc()->session()->makeCurrentSession(); - action->execute(session(), TwkApp::Event("menu", 0)); + if (const TwkApp::Action* action = a->item()->action()) + { + // + // Won't throw + // + + a->doc()->session()->makeCurrentSession(); + action->execute(session(), TwkApp::Event("menu", 0)); + } + } + else + { + cout << "ERROR: menuActivated() failed to get TwkQTAction" + << endl; } } - else - { - cout << "ERROR: menuActivated() failed to get TwkQTAction" << endl; - } - } - m_menuExecuting--; -} + m_menuExecuting--; + } -void -RvDocument::aboutToShowMenu() -{ - if (QMenu* menu = dynamic_cast(sender())) + void RvDocument::aboutToShowMenu() { - QList actions = menu->actions(); - - for (int i=0; i < actions.size(); i++) + if (QMenu* menu = dynamic_cast(sender())) { - if (TwkQTAction* a = dynamic_cast(actions.at(i))) - { - TwkApp::Menu::Item* item = (TwkApp::Menu::Item*)a->item(); - TwkApp::Menu::StateFunc* S = item->stateFunc(); + QList actions = menu->actions(); - if (item && ((S && !S->error()) || !S)) + for (int i = 0; i < actions.size(); i++) + { + if (TwkQTAction* a = dynamic_cast(actions.at(i))) { - Session* d = a->doc()->session(); //TwkApp::Document::activeDocument(); - d->makeCurrentSession(); - int state = S ? (S->error() ? -1 : S->state()) : 0; + TwkApp::Menu::Item* item = (TwkApp::Menu::Item*)a->item(); + TwkApp::Menu::StateFunc* S = item->stateFunc(); - switch (state) + if (item && ((S && !S->error()) || !S)) { - case 0: - case 1: - a->setEnabled(true); - a->setChecked(false); - a->setCheckable(false); - break; - case 2: - a->setEnabled(true); - a->setCheckable(true); - a->setChecked(true); - break; - case 3: - a->setEnabled(true); - //[nsitem setState: NSMixedState]; - break; - case -1: - a->setEnabled(false); - break; - } - - if (S && S->error()) - { - a->setEnabled(false); - a->setIcon(colorAdjustedIcon(":images/del_32x32.png")); - a->setText(QString("ERROR : ") + a->text()); + Session* d = + a->doc() + ->session(); // TwkApp::Document::activeDocument(); + d->makeCurrentSession(); + int state = S ? (S->error() ? -1 : S->state()) : 0; + + switch (state) + { + case 0: + case 1: + a->setEnabled(true); + a->setChecked(false); + a->setCheckable(false); + break; + case 2: + a->setEnabled(true); + a->setCheckable(true); + a->setChecked(true); + break; + case 3: + a->setEnabled(true); + //[nsitem setState: NSMixedState]; + break; + case -1: + a->setEnabled(false); + break; + } + + if (S && S->error()) + { + a->setEnabled(false); + a->setIcon( + colorAdjustedIcon(":images/del_32x32.png")); + a->setText(QString("ERROR : ") + a->text()); + } } } } } + else + { + } } - else + + class runningTimer { - } -} + public: + void init() + { + goTime = totalTime = 0.0; + t.start(); + }; -class runningTimer -{ - public: - void init() {goTime = totalTime = 0.0; t.start();}; - void go() {goTime = t.elapsed(); }; - void stop() {totalTime += t.elapsed() - goTime; }; - float total() {return totalTime;}; + void go() { goTime = t.elapsed(); }; - TwkUtil::Timer t; - float goTime; - float totalTime; -}; + void stop() { totalTime += t.elapsed() - goTime; }; -runningTimer rt; + float total() { return totalTime; }; -static string -buildShortcutString (string keyText) -{ - string ret; + TwkUtil::Timer t; + float goTime; + float totalTime; + }; + + runningTimer rt; - if (keyText.find(' ') != string::npos) + static string buildShortcutString(string keyText) { - vector tokens; - stl_ext::tokenize(tokens, keyText); - bool control = false; - bool meta = false; - bool shift = false; - bool alt = false; - bool rarrow = false; - bool larrow = false; - bool uarrow = false; - bool darrow = false; - string key; - - for (int i=0; i < tokens.size(); i++) - { - const string& t = tokens[i]; - -//#ifdef PLATFORM_DARWIN -// if (t == "control") meta = true; -// else if (t == "command") control = true; -//#else - if (t == "command") meta = true; - else if (t == "control") control = true; -//#endif - - else if (t == "alt") alt = true; - else if (t == "shift") shift = true; - else if (t == "meta") meta = true; - else if (t == "rightArrow") rarrow = true; - else if (t == "leftArrow") larrow = true; - else if (t == "upArrow") uarrow = true; - else if (t == "downArrow") darrow = true; - else + string ret; + + if (keyText.find(' ') != string::npos) + { + vector tokens; + stl_ext::tokenize(tokens, keyText); + bool control = false; + bool meta = false; + bool shift = false; + bool alt = false; + bool rarrow = false; + bool larrow = false; + bool uarrow = false; + bool darrow = false; + string key; + + for (int i = 0; i < tokens.size(); i++) { - for (int j = i; j < tokens.size(); ++j) + const string& t = tokens[i]; + + // #ifdef PLATFORM_DARWIN + // if (t == "control") meta = true; + // else if (t == "command") control = true; + // #else + if (t == "command") + meta = true; + else if (t == "control") + control = true; + // #endif + + else if (t == "alt") + alt = true; + else if (t == "shift") + shift = true; + else if (t == "meta") + meta = true; + else if (t == "rightArrow") + rarrow = true; + else if (t == "leftArrow") + larrow = true; + else if (t == "upArrow") + uarrow = true; + else if (t == "downArrow") + darrow = true; + else { - if (j!=i) key += " "; - key += tokens[j]; + for (int j = i; j < tokens.size(); ++j) + { + if (j != i) + key += " "; + key += tokens[j]; + } + break; } - break; } - } - if (control) ret += "Ctrl+"; - if (meta) ret += "Meta+"; - if (alt) ret += "Alt+"; - if (shift || (key.size() == 1 && isupper(key[0]))) ret += "Shift+"; - - if (larrow) ret += "Left"; - else if (rarrow) ret += "Right"; - else if (uarrow) ret += "Up"; - else if (darrow) ret += "Down"; - else ret += key; - } - else - { - if (keyText.size() == 1 && isupper(keyText[0])) + if (control) + ret += "Ctrl+"; + if (meta) + ret += "Meta+"; + if (alt) + ret += "Alt+"; + if (shift || (key.size() == 1 && isupper(key[0]))) + ret += "Shift+"; + + if (larrow) + ret += "Left"; + else if (rarrow) + ret += "Right"; + else if (uarrow) + ret += "Up"; + else if (darrow) + ret += "Down"; + else + ret += key; + } + else { - ret = "Shift+" + keyText; + if (keyText.size() == 1 && isupper(keyText[0])) + { + ret = "Shift+" + keyText; + } + else + ret = keyText; } - else ret = keyText; - } - return ret; -} + return ret; + } -void -RvDocument::convert(QMenu* qmenu, const TwkApp::Menu* menu, bool shortcuts) -{ - for (int i=0; i < menu->items().size(); i++) + void RvDocument::convert(QMenu* qmenu, const TwkApp::Menu* menu, + bool shortcuts) { - const TwkApp::Menu::Item* item = menu->items()[i]; - - if (item->subMenu()) - { - QMenu* subMenu = qmenu->addMenu(utf8(item->title())); - subMenu->setFont(qmenu->font()); - // rt.go(); - connect(subMenu, SIGNAL(aboutToShow()), this, SLOT(aboutToShowMenu())); - // rt.stop(); - convert(subMenu, item->subMenu(), shortcuts); - subMenu->menuAction()->setMenuRole(QAction::NoRole); - } - else if (item->title() == "_") + for (int i = 0; i < menu->items().size(); i++) { - qmenu->addSeparator(); - } - else - { - TwkQTAction* a = new TwkQTAction(item, this, qmenu); + const TwkApp::Menu::Item* item = menu->items()[i]; - if ((item->stateFunc() && item->stateFunc()->error()) || - (item->action() && item->action()->error())) + if (item->subMenu()) { - a->setText(QString("ERROR : ") + utf8(item->title())); - a->setIcon(colorAdjustedIcon(":images/del_32x32.png")); - a->setEnabled(false); + QMenu* subMenu = qmenu->addMenu(utf8(item->title())); + subMenu->setFont(qmenu->font()); + // rt.go(); + connect(subMenu, SIGNAL(aboutToShow()), this, + SLOT(aboutToShowMenu())); + // rt.stop(); + convert(subMenu, item->subMenu(), shortcuts); + subMenu->menuAction()->setMenuRole(QAction::NoRole); } - else + else if (item->title() == "_") { - a->setText(utf8(item->title())); + qmenu->addSeparator(); } - - if (shortcuts) + else { - string sc = buildShortcutString (item->key()); - a->setShortcut(QString(sc.c_str())); - if (sc.size() == 1 && QString("") == a->shortcut().toString()) + TwkQTAction* a = new TwkQTAction(item, this, qmenu); + + if ((item->stateFunc() && item->stateFunc()->error()) + || (item->action() && item->action()->error())) { - // - // setShortcut takes a QKeySequence, and when - // we make one out of a single key in a - // Qstring, it doesn't work for some keys (like - // "`", so we give it the key instead. This - // seems to work for all ascii keys. - // - a->setShortcut(sc[0]); + a->setText(QString("ERROR : ") + utf8(item->title())); + a->setIcon(colorAdjustedIcon(":images/del_32x32.png")); + a->setEnabled(false); + } + else + { + a->setText(utf8(item->title())); } - } - // rt.go(); - connect(a, SIGNAL(triggered()), this, SLOT(menuActivated())); - // rt.stop(); - a->setMenuRole(QAction::NoRole); - qmenu->addAction(a); + if (shortcuts) + { + string sc = buildShortcutString(item->key()); + a->setShortcut(QString(sc.c_str())); + if (sc.size() == 1 + && QString("") == a->shortcut().toString()) + { + // + // setShortcut takes a QKeySequence, and when + // we make one out of a single key in a + // Qstring, it doesn't work for some keys (like + // "`", so we give it the key instead. This + // seems to work for all ascii keys. + // + a->setShortcut(sc[0]); + } + } + + // rt.go(); + connect(a, SIGNAL(triggered()), this, SLOT(menuActivated())); + // rt.stop(); + a->setMenuRole(QAction::NoRole); + qmenu->addAction(a); + } } } -} -void -RvDocument::disconnectActions(const QList &actions) -{ - for (int i = 0; i < actions.size(); ++i) + void RvDocument::disconnectActions(const QList& actions) { - QAction* a = actions[i]; - - if (QMenu *m = a->menu()) + for (int i = 0; i < actions.size(); ++i) { - disconnectActions(m->actions()); - m->disconnect(); + QAction* a = actions[i]; + + if (QMenu* m = a->menu()) + { + disconnectActions(m->actions()); + m->disconnect(); + } + else + a->disconnect(); } - else a->disconnect(); } -} -void -RvDocument::purgeMenus() -{ - // - // I could not find (in the git trail) any record of why we treat the mac differently - // here, but this difference results in what appears to be a memory leak on linux/windows, - // where the total number of QMenus and QActions increases without bound. The below change - // eliminates the leak and unifies the behavior on all platforms. - // - //#ifdef PLATFORM_DARWIN - // - - if (workAroundActionLeak) + void RvDocument::purgeMenus() { - QObjectList children = mb()->children(); // copy + // + // I could not find (in the git trail) any record of why we treat the + // mac differently here, but this difference results in what appears to + // be a memory leak on linux/windows, where the total number of QMenus + // and QActions increases without bound. The below change eliminates + // the leak and unifies the behavior on all platforms. + // + // #ifdef PLATFORM_DARWIN + // - for (int i=0; i < children.size(); i++) + if (workAroundActionLeak) { - // Skip this menu if it is the "RV" menu (mac or not) - // - if (QMenu* menu = dynamic_cast(children[i])) + QObjectList children = mb()->children(); // copy + + for (int i = 0; i < children.size(); i++) { + // Skip this menu if it is the "RV" menu (mac or not) + // + if (QMenu* menu = dynamic_cast(children[i])) + { #if defined(PLATFORM_DARWIN) - if (menu != RvApp()->macRVMenu() && menu != m_rvMenu) + if (menu != RvApp()->macRVMenu() && menu != m_rvMenu) #else - if (menu != m_rvMenu) + if (menu != m_rvMenu) #endif - { - delete menu; + { + delete menu; + } } } } - } -//#else - else - { - if (mb()->actions().size() > 0) + // #else + else { - QList actionsMinusFirstOne = mb()->actions().mid(1); - disconnectActions(actionsMinusFirstOne); + if (mb()->actions().size() > 0) + { + QList actionsMinusFirstOne = mb()->actions().mid(1); + disconnectActions(actionsMinusFirstOne); + } + + mb()->clear(); } + // #endif - mb()->clear(); + delete m_mainPopup; + m_mainPopup = 0; + m_lastPopupAction = 0; } -//#endif - delete m_mainPopup; - m_mainPopup = 0; - m_lastPopupAction = 0; -} + void RvDocument::setBuildMenu() { m_menuTimer->start(); } -void -RvDocument::setBuildMenu() -{ - m_menuTimer->start(); -} - -void -RvDocument::buildMenu() -{ - if (!m_menuExecuting && m_session) + void RvDocument::buildMenu() { - mergeMenu(m_session->menu()); - m_menuTimer->stop(); + if (!m_menuExecuting && m_session) + { + mergeMenu(m_session->menu()); + m_menuTimer->stop(); + } } -} -void -RvDocument::mergeMenu(const TwkApp::Menu* menu, bool shortcuts) -{ - purgeMenus(); - - if (!menu) + void RvDocument::mergeMenu(const TwkApp::Menu* menu, bool shortcuts) { - return; - } + purgeMenus(); - // - // This is the only way to overcome the accelerators on the Mac. You - // just can't have any shortcuts. Even if the menu is disabled the - // shortcuts still function. This was a problem with the pure - // Cocoa version as well. - // + if (!menu) + { + return; + } - if (m_menuBarDisable) shortcuts = false; + // + // This is the only way to overcome the accelerators on the Mac. You + // just can't have any shortcuts. Even if the menu is disabled the + // shortcuts still function. This was a problem with the pure + // Cocoa version as well. + // + if (m_menuBarDisable) + shortcuts = false; #if !defined(PLATFORM_DARWIN) - if (!m_rvMenu || !workAroundActionLeak) - { - m_rvMenu = mb()->addMenu(UI_APPLICATION_NAME); - m_rvMenu->addAction(RvApp()->aboutAction()); - m_rvMenu->addSeparator(); - m_rvMenu->addAction(RvApp()->prefAction()); - m_rvMenu->addSeparator(); - if (RvApp()->networkAction()) m_rvMenu->addAction(RvApp()->networkAction()); - m_rvMenu->addSeparator(); - m_rvMenu->addAction(RvApp()->quitAction()); - m_rvMenu->menuAction()->font().setBold(true); - m_rvMenu->setObjectName(UI_APPLICATION_NAME " Menu"); - } + if (!m_rvMenu || !workAroundActionLeak) + { + m_rvMenu = mb()->addMenu(UI_APPLICATION_NAME); + m_rvMenu->addAction(RvApp()->aboutAction()); + m_rvMenu->addSeparator(); + m_rvMenu->addAction(RvApp()->prefAction()); + m_rvMenu->addSeparator(); + if (RvApp()->networkAction()) + m_rvMenu->addAction(RvApp()->networkAction()); + m_rvMenu->addSeparator(); + m_rvMenu->addAction(RvApp()->quitAction()); + m_rvMenu->menuAction()->font().setBold(true); + m_rvMenu->setObjectName(UI_APPLICATION_NAME " Menu"); + } #endif + if (m_mainPopup) + m_mainPopup->clear(); + else + m_mainPopup = new QMenu(this); - if (m_mainPopup) m_mainPopup->clear(); - else m_mainPopup = new QMenu(this); - - m_mainPopup->setObjectName("Main Popup"); + m_mainPopup->setObjectName("Main Popup"); #ifdef PLATFORM_DARWIN - QFont f = m_mainPopup->font(); - f.setPointSize(12); - m_mainPopup->setFont(f); + QFont f = m_mainPopup->font(); + f.setPointSize(12); + m_mainPopup->setFont(f); #endif - // rt.init(); - for (int i=0; i < menu->items().size(); i++) - { - const TwkApp::Menu::Item* item = menu->items()[i]; - - if (item->subMenu()) + // rt.init(); + for (int i = 0; i < menu->items().size(); i++) { - QString title = utf8(item->title()); + const TwkApp::Menu::Item* item = menu->items()[i]; + + if (item->subMenu()) + { + QString title = utf8(item->title()); - QMenu* menu = mb()->addMenu(title); - // rt.go(); - connect(menu, SIGNAL(aboutToShow()), this, SLOT(aboutToShowMenu())); - // rt.stop(); - convert(menu, item->subMenu(), shortcuts); + QMenu* menu = mb()->addMenu(title); + // rt.go(); + connect(menu, SIGNAL(aboutToShow()), this, + SLOT(aboutToShowMenu())); + // rt.stop(); + convert(menu, item->subMenu(), shortcuts); - QMenu* pmenu = m_mainPopup->addMenu(title); + QMenu* pmenu = m_mainPopup->addMenu(title); #ifdef PLATFORM_DARWIN - pmenu->setFont(f); + pmenu->setFont(f); #endif - // rt.go(); - connect(pmenu, SIGNAL(aboutToShow()), this, SLOT(aboutToShowMenu())); - // rt.stop(); - convert(pmenu, item->subMenu(), shortcuts); + // rt.go(); + connect(pmenu, SIGNAL(aboutToShow()), this, + SLOT(aboutToShowMenu())); + // rt.stop(); + convert(pmenu, item->subMenu(), shortcuts); + } } + // cerr << " total connect calls: " << rt.total() << " seconds" << + // endl; } - // cerr << " total connect calls: " << rt.total() << " seconds" << endl; -} -void -RvDocument::popupMenu(TwkApp::Menu* menu, QPoint point, bool shortcuts) -{ - // - // This is the only way to overcome the accelerators on the Mac. You - // just can't have any shortcuts. Even if the menu is disabled the - // shortcuts still function. This was a problem with the pure - // Cocoa version as well. - // + void RvDocument::popupMenu(TwkApp::Menu* menu, QPoint point, bool shortcuts) + { + // + // This is the only way to overcome the accelerators on the Mac. You + // just can't have any shortcuts. Even if the menu is disabled the + // shortcuts still function. This was a problem with the pure + // Cocoa version as well. + // - if (m_menuBarDisable) shortcuts = false; + if (m_menuBarDisable) + shortcuts = false; - if (m_userMenu) delete m_userMenu; - m_userMenu = menu; + if (m_userMenu) + delete m_userMenu; + m_userMenu = menu; - if (m_userPopup) m_userPopup->clear(); - else m_userPopup = new QMenu(this); + if (m_userPopup) + m_userPopup->clear(); + else + m_userPopup = new QMenu(this); - m_userPopup->setObjectName("User Popup"); + m_userPopup->setObjectName("User Popup"); #ifdef PLATFORM_DARWIN - QFont f = m_userPopup->font(); - f.setPointSize(12); - m_userPopup->setFont(f); + QFont f = m_userPopup->font(); + f.setPointSize(12); + m_userPopup->setFont(f); #endif - convert(m_userPopup, menu, shortcuts); - connect(m_userPopup, SIGNAL(aboutToShow()), this, SLOT(aboutToShowMenu())); - m_userPopup->popup(point); -} + convert(m_userPopup, menu, shortcuts); + connect(m_userPopup, SIGNAL(aboutToShow()), this, + SLOT(aboutToShowMenu())); + m_userPopup->popup(point); + } -void -RvDocument::frameChanged() -{ - // - // We'll get here if the frame changed LAST render, so the - // currently visible frame is not the same as the previous. The - // reason this is in a timer is that we don't want to process - // this stuff until after the swapbuffers. Otherwise its a waste - // of time. - // + void RvDocument::frameChanged() + { + // + // We'll get here if the frame changed LAST render, so the + // currently visible frame is not the same as the previous. The + // reason this is in a timer is that we don't want to process + // this stuff until after the swapbuffers. Otherwise its a waste + // of time. + // - lazyDeleteGLView(); - if (m_session) m_session->userGenericEvent("frame-changed", ""); -} + lazyDeleteGLView(); + if (m_session) + m_session->userGenericEvent("frame-changed", ""); + } -void -RvDocument::viewSizeChanged(int w, int h) -{ - if (m_session) + void RvDocument::viewSizeChanged(int w, int h) { - m_session->userRenderEvent("view-size-changed", ""); - m_session->deviceSizeChanged(m_glView->videoDevice()); + if (m_session) + { + m_session->userRenderEvent("view-size-changed", ""); + m_session->deviceSizeChanged(m_glView->videoDevice()); + } } -} -static bool firstEvent = true; -static bool restrictActivation = false; + static bool firstEvent = true; + static bool restrictActivation = false; -bool -RvDocument::event (QEvent *e) -{ - if (firstEvent) + bool RvDocument::event(QEvent* e) { - if (! getenv("RV_DO_NOT_RESTRICT_ACTIVATION")) restrictActivation = true; - firstEvent = false; - } + if (firstEvent) + { + if (!getenv("RV_DO_NOT_RESTRICT_ACTIVATION")) + restrictActivation = true; + firstEvent = false; + } - if (e->type() == QEvent::WindowActivate) - { - DB ("event: WindowActivate " << m_session->name() << ", currently active " << Rv::Session::activeSession()->name()); - // - // We should only have to call makeActive() if we are not - // currently the active session, but in that case Qt seems - // to sometimes take away our keyboard focus (even when - // activeWindow() returns true). - // - if (m_session) //&& m_session != Rv::Session::activeSession()) + if (e->type() == QEvent::WindowActivate) { - m_session->makeActive(); + DB("event: WindowActivate " + << m_session->name() << ", currently active " + << Rv::Session::activeSession()->name()); + // + // We should only have to call makeActive() if we are not + // currently the active session, but in that case Qt seems + // to sometimes take away our keyboard focus (even when + // activeWindow() returns true). + // + if (m_session) //&& m_session != Rv::Session::activeSession()) + { + m_session->makeActive(); + } + if (!restrictActivation) + activateWindow(); + DB("event: WindowActivate isActiveWindow " << isActiveWindow()); } - if (! restrictActivation) activateWindow(); - DB ("event: WindowActivate isActiveWindow " << isActiveWindow()); - } - bool result = QMainWindow::event(e); - return result; -} + bool result = QMainWindow::event(e); + return result; + } -static bool waitingForFirstPaint = true; + static bool waitingForFirstPaint = true; -void -RvDocument::changeEvent(QEvent* event) -{ + void RvDocument::changeEvent(QEvent* event) + { #if 0 DB ("changeEvent type " << event->type() << " active " << isActiveWindow() << " paint completed " << view()->firstPaintCompleted()); DB ("changeEvent current gl size w " << m_glView->width() << " h " << m_glView->height()); #endif - #if PLATFORM_LINUX +#if PLATFORM_LINUX // // For some reason KDE wants our main window to come up - // "lowered" ie beneath the other windows. This is the + // "lowered" ie beneath the other windows. This is the // only way I've found to counter that. if (waitingForFirstPaint && view() && view()->firstPaintCompleted()) { @@ -1872,145 +1967,145 @@ RvDocument::changeEvent(QEvent* event) raise(); waitingForFirstPaint = false; } - #endif -} - -void -RvDocument::closeEvent(QCloseEvent* event) -{ - // - // Unfortunately, I don't remember exactly why I added the m_closeEventReceived - // check below. It interferes with the new "before-session-deletion" check - // which allows Mu modes to setReturnContent("not ok") on the event to - // interupt the close process, so I'm taking it out for now. - // +#endif + } - // if (! m_closeEventReceived) + void RvDocument::closeEvent(QCloseEvent* event) { - string ok = m_session->userGenericEvent("before-session-deletion", ""); + // + // Unfortunately, I don't remember exactly why I added the + // m_closeEventReceived check below. It interferes with the new + // "before-session-deletion" check which allows Mu modes to + // setReturnContent("not ok") on the event to interupt the close + // process, so I'm taking it out for now. + // - if (ok == "") event->accept(); - else event->ignore(); + // if (! m_closeEventReceived) + { + string ok = + m_session->userGenericEvent("before-session-deletion", ""); + + if (ok == "") + event->accept(); + else + event->ignore(); - m_closeEventReceived = true; + m_closeEventReceived = true; + } } -} -void -RvDocument::moveEvent(QMoveEvent* event) -{ - if (m_session) - m_session->askForRedraw(); -} + void RvDocument::moveEvent(QMoveEvent* event) + { + if (m_session) + m_session->askForRedraw(); + } -void -RvDocument::addWatchFile(const string& path) -{ - if (!m_watcher) + void RvDocument::addWatchFile(const string& path) { - m_watcher = new QFileSystemWatcher(); + if (!m_watcher) + { + m_watcher = new QFileSystemWatcher(); - connect(m_watcher, SIGNAL(fileChanged(const QString&)), - this, SLOT(watchedFileChanged(const QString&))); + connect(m_watcher, SIGNAL(fileChanged(const QString&)), this, + SLOT(watchedFileChanged(const QString&))); - connect(m_watcher, SIGNAL(directoryChanged(const QString&)), - this, SLOT(watchedFileChanged(const QString&))); - } + connect(m_watcher, SIGNAL(directoryChanged(const QString&)), this, + SLOT(watchedFileChanged(const QString&))); + } - m_watcher->addPath(path.c_str()); -} + m_watcher->addPath(path.c_str()); + } -void -RvDocument::removeWatchFile(const string& path) -{ - if (m_watcher) + void RvDocument::removeWatchFile(const string& path) { - m_watcher->removePath(path.c_str()); + if (m_watcher) + { + m_watcher->removePath(path.c_str()); + } } -} - -void -RvDocument::watchedFileChanged(const QString& path) -{ - TwkApp::GenericStringEvent event("file-changed", - m_glView->videoDevice(), - path.toUtf8().data()); - //cout << m_watcher->files().size() << endl; - //cout << m_watcher->directories().size() << endl; - - //m_glView->frameBuffer()->sendEvent(event); - m_glView->videoDevice()->sendEvent(event); -} - -bool -RvDocument::queryDriverVSync() const -{ - return false; -} + void RvDocument::watchedFileChanged(const QString& path) + { + TwkApp::GenericStringEvent event( + "file-changed", m_glView->videoDevice(), path.toUtf8().data()); -void -RvDocument::checkDriverVSync() -{ - Rv::Options& opts = Options::sharedOptions(); + // cout << m_watcher->files().size() << endl; + // cout << m_watcher->directories().size() << endl; - if (queryDriverVSync() && opts.vsync > 0) - { - QMessageBox box(this); - box.setWindowTitle(tr(UI_APPLICATION_NAME ": VSync Conflict")); - QString baseText = tr("Both the graphics driver and RV v-sync are ON. " - UI_APPLICATION_NAME " vsync is being disabled."); - QString detailedText("RV's vsync is being disabled for this session because " - "the graphics driver's vsync is also ON. " - "You can change this in the nvidia-settings or " - "in " UI_APPLICATION_NAME "'s preferences. " - "Running " UI_APPLICATION_NAME " with both vsyncs enabled causes incorrect " - "playback. "); - box.setText(baseText + "\n\n" + detailedText); - box.setWindowModality(Qt::WindowModal); - QPushButton* b1 = box.addButton(tr("Ok"), QMessageBox::AcceptRole); - box.setIconPixmap(QPixmap(qApp->applicationDirPath() + QString(RV_ICON_PATH_SUFFIX)).scaledToHeight(64)); - box.exec(); - opts.vsync = 0; - m_vsyncDisabled = true; + // m_glView->frameBuffer()->sendEvent(event); + m_glView->videoDevice()->sendEvent(event); } -} -void -RvDocument::warnOnDriverVSync() -{ - Rv::Options& opts = Options::sharedOptions(); + bool RvDocument::queryDriverVSync() const { return false; } - if (queryDriverVSync()) + void RvDocument::checkDriverVSync() { - QMessageBox box(this); - box.setWindowTitle(tr(UI_APPLICATION_NAME ": Driver VSync Conflict")); - QString baseText = tr("The graphics driver v-sync is ON. " - "This can result in bad playback performance in presentation mode."); - QString detailedText("The graphics driver's vsync is ON. " - "You can change this in the nvidia-settings OpenGL section. " - "Running " UI_APPLICATION_NAME " in presentation mode with the driver " - "vsync enabled will cause incorrect " - "playback. "); - box.setWindowModality(Qt::WindowModal); - QPushButton* b1 = box.addButton(tr("Ok"), QMessageBox::AcceptRole); - box.setIconPixmap(QPixmap(qApp->applicationDirPath() + QString(RV_ICON_PATH_SUFFIX)).scaledToHeight(64)); - box.exec(); + Rv::Options& opts = Options::sharedOptions(); + + if (queryDriverVSync() && opts.vsync > 0) + { + QMessageBox box(this); + box.setWindowTitle(tr(UI_APPLICATION_NAME ": VSync Conflict")); + QString baseText = + tr("Both the graphics driver and RV v-sync are " + "ON. " UI_APPLICATION_NAME " vsync is being disabled."); + QString detailedText( + "RV's vsync is being disabled for this session because " + "the graphics driver's vsync is also ON. " + "You can change this in the nvidia-settings or " + "in " UI_APPLICATION_NAME "'s preferences. " + "Running " UI_APPLICATION_NAME + " with both vsyncs enabled causes incorrect " + "playback. "); + box.setText(baseText + "\n\n" + detailedText); + box.setWindowModality(Qt::WindowModal); + QPushButton* b1 = box.addButton(tr("Ok"), QMessageBox::AcceptRole); + box.setIconPixmap(QPixmap(qApp->applicationDirPath() + + QString(RV_ICON_PATH_SUFFIX)) + .scaledToHeight(64)); + box.exec(); + opts.vsync = 0; + m_vsyncDisabled = true; + } } -} -void -RvDocument::editSourceNode(const string& nodeName) -{ - if (!m_sourceEditor) + void RvDocument::warnOnDriverVSync() { - m_sourceEditor = new RvSourceEditor(session()); - } + Rv::Options& opts = Options::sharedOptions(); - m_sourceEditor->editNode(nodeName); - m_sourceEditor->show(); -} + if (queryDriverVSync()) + { + QMessageBox box(this); + box.setWindowTitle( + tr(UI_APPLICATION_NAME ": Driver VSync Conflict")); + QString baseText = tr("The graphics driver v-sync is ON. " + "This can result in bad playback performance " + "in presentation mode."); + QString detailedText( + "The graphics driver's vsync is ON. " + "You can change this in the nvidia-settings OpenGL section. " + "Running " UI_APPLICATION_NAME + " in presentation mode with the driver " + "vsync enabled will cause incorrect " + "playback. "); + box.setWindowModality(Qt::WindowModal); + QPushButton* b1 = box.addButton(tr("Ok"), QMessageBox::AcceptRole); + box.setIconPixmap(QPixmap(qApp->applicationDirPath() + + QString(RV_ICON_PATH_SUFFIX)) + .scaledToHeight(64)); + box.exec(); + } + } -} // Rv + void RvDocument::editSourceNode(const string& nodeName) + { + if (!m_sourceEditor) + { + m_sourceEditor = new RvSourceEditor(session()); + } + m_sourceEditor->editNode(nodeName); + m_sourceEditor->show(); + } +} // namespace Rv diff --git a/src/lib/app/RvCommon/RvFileDialog.cpp b/src/lib/app/RvCommon/RvFileDialog.cpp index cd93b838d..faf8198ae 100644 --- a/src/lib/app/RvCommon/RvFileDialog.cpp +++ b/src/lib/app/RvCommon/RvFileDialog.cpp @@ -1,13 +1,10 @@ // -// Copyright (c) 2008 Tweak Software. +// Copyright (c) 2008 Tweak Software. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// // - - - +// #ifdef PLATFORM_WINDOWS #ifndef WIN32_LEAN_AND_MEAN @@ -31,478 +28,491 @@ #include #include +namespace Rv +{ + using namespace std; + using namespace TwkUtil; -namespace Rv { -using namespace std; -using namespace TwkUtil; - -class + class -QMap RvFileDialog::m_iconMap; -QStringList RvFileDialog::m_visited; + QMap + RvFileDialog::m_iconMap; + QStringList RvFileDialog::m_visited; #if 0 -#define DB_ICON 0x01 -#define DB_ALL 0xff +#define DB_ICON 0x01 +#define DB_ALL 0xff -#define DB_LEVEL (DB_ALL & (~ DB_ICON)) +#define DB_LEVEL (DB_ALL & (~DB_ICON)) //#define DB_LEVEL DB_ALL -#define DB(x) cerr << x << endl; -#define DBL(level, x) if (level & DB_LEVEL) cerr << x << endl; +#define DB(x) cerr << x << endl; +#define DBL(level, x) \ + if (level & DB_LEVEL) \ + cerr << x << endl; #else -#define DB(x) +#define DB(x) #define DBL(level, x) #endif -//---------------------------------------------------------------------- - -//---------------------------------------------------------------------- - -RvFileDialog::RvFileDialog(QWidget* parent, - FileTypeTraits* traits, - Role role, - Qt::WindowFlags flags, - QString settingsGroup) - : QDialog(parent, flags), - m_building(false), - m_fileMode(OneExistingFile), - m_viewMode(NoViewMode), - m_role(OpenFileRole), - m_filters(QDir::NoDotAndDotDot | QDir::AllEntries), - m_sidePanelAccept(false), - m_detailFileModel(0), - m_detailMediaModel(0), - m_columnModel(0), - m_fileTraits(0), - m_settingsGroup(settingsGroup), - m_viewModeLocked(false), - m_watcher(0) -{ - DB ("RvFileDialog Constructor"); + //---------------------------------------------------------------------- + + //---------------------------------------------------------------------- + + RvFileDialog::RvFileDialog(QWidget* parent, FileTypeTraits* traits, + Role role, Qt::WindowFlags flags, + QString settingsGroup) + : QDialog(parent, flags) + , m_building(false) + , m_fileMode(OneExistingFile) + , m_viewMode(NoViewMode) + , m_role(OpenFileRole) + , m_filters(QDir::NoDotAndDotDot | QDir::AllEntries) + , m_sidePanelAccept(false) + , m_detailFileModel(0) + , m_detailMediaModel(0) + , m_columnModel(0) + , m_fileTraits(0) + , m_settingsGroup(settingsGroup) + , m_viewModeLocked(false) + , m_watcher(0) + { + DB("RvFileDialog Constructor"); + + m_ui.setupUi(this); + m_ui.searchButton->setVisible(false); + m_ui.contentFrame->setMaximumHeight(0); - m_ui.setupUi(this); - m_ui.searchButton->setVisible(false); - m_ui.contentFrame->setMaximumHeight(0); + // + // XXX hide the new folder button for now, since it's always + // disabled. + m_ui.newFolderButton->hide(); + if (!traits) + traits = new FileTypeTraits(); - // - // XXX hide the new folder button for now, since it's always - // disabled. - m_ui.newFolderButton->hide(); - if (!traits) traits = new FileTypeTraits(); - - RV_QSETTINGS; - settings.beginGroup(m_settingsGroup); - if (settings.contains("dialogGeometry")) - { - setGeometry(settings.value("dialogGeometry").toRect()); - } - centerOverApp(); + RV_QSETTINGS; + settings.beginGroup(m_settingsGroup); + if (settings.contains("dialogGeometry")) + { + setGeometry(settings.value("dialogGeometry").toRect()); + } + centerOverApp(); - #ifdef PLATFORM_WINDOWS - int iconMode = settings.value("iconMode", FileTypeTraits::NoIcons).toInt(); - #else - int iconMode = settings.value("iconMode", FileTypeTraits::SystemIcons).toInt(); - #endif +#ifdef PLATFORM_WINDOWS + int iconMode = + settings.value("iconMode", FileTypeTraits::NoIcons).toInt(); +#else + int iconMode = + settings.value("iconMode", FileTypeTraits::SystemIcons).toInt(); +#endif - switch (iconMode) - { - default: - case 0: - traits->setIconMode(FileTypeTraits::SystemIcons); - break; - case 1: - traits->setIconMode(FileTypeTraits::GenericIcons); - break; - case 2: - traits->setIconMode(FileTypeTraits::NoIcons); - break; - } - setFileTypeTraits(traits); + switch (iconMode) + { + default: + case 0: + traits->setIconMode(FileTypeTraits::SystemIcons); + break; + case 1: + traits->setIconMode(FileTypeTraits::GenericIcons); + break; + case 2: + traits->setIconMode(FileTypeTraits::NoIcons); + break; + } + setFileTypeTraits(traits); - if (m_visited.empty()) - { - m_visited = settings.value("visited", QStringList()).toStringList(); - } + if (m_visited.empty()) + { + m_visited = settings.value("visited", QStringList()).toStringList(); + } - int vmode = settings.value("viewModeNew", -1).toInt(); - int smode = settings.value("sortMethod", -1).toInt(); - bool showHiddenFiles = settings.value("showHiddenFiles", false).toBool(); - - m_allowAutoRefresh = settings.value("allowAutoRefresh", false).toBool(); - m_ui.autoRefreshCheckbox->setCheckState ((m_allowAutoRefresh) ? Qt::Checked : Qt::Unchecked); - - setWindowTitle("Select Files/Directories"); - setSizeGripEnabled(true); - m_reloadTimer = new QTimer(this); - m_sidePanelTimer = new QTimer(this); - m_columnViewTimer = new QTimer(this); - m_reloadTimer->setSingleShot(true); - m_sidePanelTimer->setSingleShot(true); - m_columnViewTimer->setSingleShot(true); - m_columnViewTimer->start(100); - m_ui.buttonBox->setStandardButtons(m_role == OpenFileRole ? - (QDialogButtonBox::Open | QDialogButtonBox::Cancel) : - (QDialogButtonBox::Save | QDialogButtonBox::Cancel)); - - m_ui.sidePanelList->setSelectionMode(QAbstractItemView::SingleSelection); - loadSidePanel(); - - while (QWidget* w = m_ui.viewStack->currentWidget()) delete w; - - m_sidePanelPopup = new QMenu(this); - QAction* spGo = m_sidePanelPopup->addAction("Go to Location"); - QAction* spUse = m_sidePanelPopup->addAction("Use Selection"); - m_sidePanelPopup->addSeparator(); - QAction* spRemove = m_sidePanelPopup->addAction("Remove Item from Panel"); - - m_configPopup = new QMenu(this); - m_cpSystem = m_configPopup->addAction("System Icons"); - m_cpGeneric = m_configPopup->addAction("Generic Icons"); - m_cpNone = m_configPopup->addAction("No Icons"); - m_configPopup->addSeparator(); - m_cpHidden = m_configPopup->addAction("Show Hidden Files"); - m_cpSystem->setCheckable(true); - m_cpGeneric->setCheckable(true); - m_cpNone->setCheckable(true); - m_cpHidden->setCheckable(true); - m_cpHidden->setChecked(showHiddenFiles); - QActionGroup* cpGroup = new QActionGroup(this); - cpGroup->addAction(m_cpSystem); - cpGroup->addAction(m_cpGeneric); - cpGroup->addAction(m_cpNone); - m_ui.configButton->setMenu(m_configPopup); - - QIcon backIcon = colorAdjustedIcon(":images/back_32x32.png"); - QIcon forwardIcon = colorAdjustedIcon(":images/forwd_32x32.png"); - QIcon configIcon = colorAdjustedIcon(":images/confg_32x32.png"); - - m_ui.previousButton->setDefaultAction(new QAction(backIcon, "<", this)); - m_ui.nextButton->setDefaultAction(new QAction(forwardIcon, ">", this)); - m_ui.configButton->setIcon(configIcon); - - switch (iconMode) - { - default: - case 0: - m_cpSystem->setChecked(true); - break; - case 1: - m_cpGeneric->setChecked(true); - break; - case 2: - m_cpNone->setChecked(true); - break; - } + int vmode = settings.value("viewModeNew", -1).toInt(); + int smode = settings.value("sortMethod", -1).toInt(); + bool showHiddenFiles = + settings.value("showHiddenFiles", false).toBool(); + + m_allowAutoRefresh = settings.value("allowAutoRefresh", false).toBool(); + m_ui.autoRefreshCheckbox->setCheckState( + (m_allowAutoRefresh) ? Qt::Checked : Qt::Unchecked); + + setWindowTitle("Select Files/Directories"); + setSizeGripEnabled(true); + m_reloadTimer = new QTimer(this); + m_sidePanelTimer = new QTimer(this); + m_columnViewTimer = new QTimer(this); + m_reloadTimer->setSingleShot(true); + m_sidePanelTimer->setSingleShot(true); + m_columnViewTimer->setSingleShot(true); + m_columnViewTimer->start(100); + m_ui.buttonBox->setStandardButtons( + m_role == OpenFileRole + ? (QDialogButtonBox::Open | QDialogButtonBox::Cancel) + : (QDialogButtonBox::Save | QDialogButtonBox::Cancel)); + + m_ui.sidePanelList->setSelectionMode( + QAbstractItemView::SingleSelection); + loadSidePanel(); + + while (QWidget* w = m_ui.viewStack->currentWidget()) + delete w; + + m_sidePanelPopup = new QMenu(this); + QAction* spGo = m_sidePanelPopup->addAction("Go to Location"); + QAction* spUse = m_sidePanelPopup->addAction("Use Selection"); + m_sidePanelPopup->addSeparator(); + QAction* spRemove = + m_sidePanelPopup->addAction("Remove Item from Panel"); + + m_configPopup = new QMenu(this); + m_cpSystem = m_configPopup->addAction("System Icons"); + m_cpGeneric = m_configPopup->addAction("Generic Icons"); + m_cpNone = m_configPopup->addAction("No Icons"); + m_configPopup->addSeparator(); + m_cpHidden = m_configPopup->addAction("Show Hidden Files"); + m_cpSystem->setCheckable(true); + m_cpGeneric->setCheckable(true); + m_cpNone->setCheckable(true); + m_cpHidden->setCheckable(true); + m_cpHidden->setChecked(showHiddenFiles); + QActionGroup* cpGroup = new QActionGroup(this); + cpGroup->addAction(m_cpSystem); + cpGroup->addAction(m_cpGeneric); + cpGroup->addAction(m_cpNone); + m_ui.configButton->setMenu(m_configPopup); + + QIcon backIcon = colorAdjustedIcon(":images/back_32x32.png"); + QIcon forwardIcon = colorAdjustedIcon(":images/forwd_32x32.png"); + QIcon configIcon = colorAdjustedIcon(":images/confg_32x32.png"); + + m_ui.previousButton->setDefaultAction(new QAction(backIcon, "<", this)); + m_ui.nextButton->setDefaultAction(new QAction(forwardIcon, ">", this)); + m_ui.configButton->setIcon(configIcon); + + switch (iconMode) + { + default: + case 0: + m_cpSystem->setChecked(true); + break; + case 1: + m_cpGeneric->setChecked(true); + break; + case 2: + m_cpNone->setChecked(true); + break; + } - m_columnView = new QColumnView(this); - QWidget* preview = new QWidget(); - m_columnPreview = new QTextEdit(); - QLayout* layout = new QVBoxLayout(); - layout->addWidget(m_columnPreview); - preview->setLayout(layout); - m_columnPreview->setReadOnly(true); - QSizePolicy p(QSizePolicy::Ignored, QSizePolicy::Preferred); - p.setHeightForWidth(true); - m_columnPreview->setSizePolicy(p); - preview->setSizePolicy(p); - m_columnView->setPreviewWidget(preview); + m_columnView = new QColumnView(this); + QWidget* preview = new QWidget(); + m_columnPreview = new QTextEdit(); + QLayout* layout = new QVBoxLayout(); + layout->addWidget(m_columnPreview); + preview->setLayout(layout); + m_columnPreview->setReadOnly(true); + QSizePolicy p(QSizePolicy::Ignored, QSizePolicy::Preferred); + p.setHeightForWidth(true); + m_columnPreview->setSizePolicy(p); + preview->setSizePolicy(p); + m_columnView->setPreviewWidget(preview); - m_detailTree = new QTreeView(this); - m_detailTree->setExpandsOnDoubleClick(false); - m_detailTree->setAlternatingRowColors(true); + m_detailTree = new QTreeView(this); + m_detailTree->setExpandsOnDoubleClick(false); + m_detailTree->setAlternatingRowColors(true); - m_detailTree->setDragEnabled(true); - m_columnView->setDragEnabled(true); + m_detailTree->setDragEnabled(true); + m_columnView->setDragEnabled(true); - QList widths; - for (int i=0; i < 25; i++) widths << 175; - m_columnView->setColumnWidths(widths); + QList widths; + for (int i = 0; i < 25; i++) + widths << 175; + m_columnView->setColumnWidths(widths); - m_columnModel = new MediaDirModel(m_fileTraits->copyTraits()); - m_columnView->setModel(m_columnModel); - m_columnView->setSelectionBehavior(QAbstractItemView::SelectItems); + m_columnModel = new MediaDirModel(m_fileTraits->copyTraits()); + m_columnView->setModel(m_columnModel); + m_columnView->setSelectionBehavior(QAbstractItemView::SelectItems); - setFileMode(m_fileMode); + setFileMode(m_fileMode); - m_detailMediaModel = new MediaDirModel(m_fileTraits->copyTraits()); - m_detailFileModel = new MediaDirModel(m_fileTraits->copyTraits()); - m_detailTree->setModel(m_detailFileModel); + m_detailMediaModel = new MediaDirModel(m_fileTraits->copyTraits()); + m_detailFileModel = new MediaDirModel(m_fileTraits->copyTraits()); + m_detailTree->setModel(m_detailFileModel); - m_detailMediaModel->setShowHiddenFiles(showHiddenFiles); - m_detailFileModel->setShowHiddenFiles(showHiddenFiles); - m_columnModel->setShowHiddenFiles(showHiddenFiles); + m_detailMediaModel->setShowHiddenFiles(showHiddenFiles); + m_detailFileModel->setShowHiddenFiles(showHiddenFiles); + m_columnModel->setShowHiddenFiles(showHiddenFiles); - m_ui.viewStack->addWidget(m_columnView); - m_ui.viewStack->addWidget(m_detailTree); - m_ui.viewStack->setCurrentIndex(0); - m_ui.currentPath->installEventFilter(this); + m_ui.viewStack->addWidget(m_columnView); + m_ui.viewStack->addWidget(m_detailTree); + m_ui.viewStack->setCurrentIndex(0); + m_ui.currentPath->installEventFilter(this); -//#ifdef PLATFORM_DARWIN - // this is nice, but it makes a mess out of the slider if one becomes visible - //m_ui.sidePanelList->setStyleSheet(QString::fromUtf8("background: rgb(235, 240, 248)")); -//#endif - m_ui.sidePanelList->installEventFilter(this); + // #ifdef PLATFORM_DARWIN + // this is nice, but it makes a mess out of the slider if one becomes + // visible + // m_ui.sidePanelList->setStyleSheet(QString::fromUtf8("background: + // rgb(235, 240, 248)")); + // #endif + m_ui.sidePanelList->installEventFilter(this); - connect(spGo, SIGNAL(triggered(bool)), this, SLOT(sidePanelGo(bool))); - connect(spRemove, SIGNAL(triggered(bool)), this, SLOT(sidePanelRemove(bool))); - connect(spUse, SIGNAL(triggered(bool)), this, SLOT(sidePanelAccept(bool))); + connect(spGo, SIGNAL(triggered(bool)), this, SLOT(sidePanelGo(bool))); + connect(spRemove, SIGNAL(triggered(bool)), this, + SLOT(sidePanelRemove(bool))); + connect(spUse, SIGNAL(triggered(bool)), this, + SLOT(sidePanelAccept(bool))); - connect(cpGroup, SIGNAL(triggered(QAction*)), this, SLOT(iconViewChanged(QAction*))); - connect(m_cpHidden, SIGNAL(triggered(bool)), this, SLOT(hiddenViewChanged(bool))); + connect(cpGroup, SIGNAL(triggered(QAction*)), this, + SLOT(iconViewChanged(QAction*))); + connect(m_cpHidden, SIGNAL(triggered(bool)), this, + SLOT(hiddenViewChanged(bool))); - connect(m_ui.previousButton, SIGNAL(triggered(QAction*)), - this, SLOT(prevButtonTrigger(QAction*))); + connect(m_ui.previousButton, SIGNAL(triggered(QAction*)), this, + SLOT(prevButtonTrigger(QAction*))); - connect(m_ui.nextButton, SIGNAL(triggered(QAction*)), - this, SLOT(nextButtonTrigger(QAction*))); + connect(m_ui.nextButton, SIGNAL(triggered(QAction*)), this, + SLOT(nextButtonTrigger(QAction*))); - connect(m_ui.sidePanelList->model(), - SIGNAL(rowsInserted(const QModelIndex&,int,int)), - this, SLOT(sidePanelInserted(const QModelIndex&,int,int))); + connect(m_ui.sidePanelList->model(), + SIGNAL(rowsInserted(const QModelIndex&, int, int)), this, + SLOT(sidePanelInserted(const QModelIndex&, int, int))); - connect(m_ui.sidePanelList, - SIGNAL(itemClicked(QListWidgetItem*)), - this, SLOT(sidePanelClick(QListWidgetItem*))); + connect(m_ui.sidePanelList, SIGNAL(itemClicked(QListWidgetItem*)), this, + SLOT(sidePanelClick(QListWidgetItem*))); - connect(m_ui.sidePanelList, - SIGNAL(itemDoubleClicked(QListWidgetItem*)), - this, SLOT(sidePanelDoubleClick(QListWidgetItem*))); + connect(m_ui.sidePanelList, SIGNAL(itemDoubleClicked(QListWidgetItem*)), + this, SLOT(sidePanelDoubleClick(QListWidgetItem*))); - connect(m_ui.sidePanelList, - SIGNAL(customContextMenuRequested(const QPoint&)), - this, SLOT(sidePanelPopup(const QPoint&))); + connect(m_ui.sidePanelList, + SIGNAL(customContextMenuRequested(const QPoint&)), this, + SLOT(sidePanelPopup(const QPoint&))); - connect(m_reloadTimer, SIGNAL(timeout()), this, SLOT(reloadTimeout())); + connect(m_reloadTimer, SIGNAL(timeout()), this, SLOT(reloadTimeout())); - connect(m_sidePanelTimer, SIGNAL(timeout()), this, SLOT(sidePanelTimeout())); + connect(m_sidePanelTimer, SIGNAL(timeout()), this, + SLOT(sidePanelTimeout())); - connect(m_columnViewTimer, SIGNAL(timeout()), this, SLOT(columnViewTimeout())); + connect(m_columnViewTimer, SIGNAL(timeout()), this, + SLOT(columnViewTimeout())); - connect(m_ui.sortCombo, SIGNAL(currentIndexChanged(int)), - this, SLOT(sortComboChanged(int))); + connect(m_ui.sortCombo, SIGNAL(currentIndexChanged(int)), this, + SLOT(sortComboChanged(int))); - connect(m_ui.viewCombo, SIGNAL(currentIndexChanged(int)), - this, SLOT(viewComboChanged(int))); + connect(m_ui.viewCombo, SIGNAL(currentIndexChanged(int)), this, + SLOT(viewComboChanged(int))); - connect(m_ui.pathCombo, SIGNAL(currentIndexChanged(int)), - this, SLOT(pathComboChanged(int))); + connect(m_ui.pathCombo, SIGNAL(currentIndexChanged(int)), this, + SLOT(pathComboChanged(int))); - connect(m_ui.currentPath, SIGNAL(returnPressed()), - this, SLOT(inputPathEntry())); + connect(m_ui.currentPath, SIGNAL(returnPressed()), this, + SLOT(inputPathEntry())); - connect(m_detailTree, SIGNAL(doubleClicked(const QModelIndex&)), - this, SLOT(doubleClickAccept(const QModelIndex&))); + connect(m_detailTree, SIGNAL(doubleClicked(const QModelIndex&)), this, + SLOT(doubleClickAccept(const QModelIndex&))); - connect(m_detailTree, SIGNAL(collapsed(const QModelIndex&)), - this, SLOT(resizeColumns(const QModelIndex&))); + connect(m_detailTree, SIGNAL(collapsed(const QModelIndex&)), this, + SLOT(resizeColumns(const QModelIndex&))); - connect(m_detailTree, SIGNAL(expanded(const QModelIndex&)), - this, SLOT(resizeColumns(const QModelIndex&))); + connect(m_detailTree, SIGNAL(expanded(const QModelIndex&)), this, + SLOT(resizeColumns(const QModelIndex&))); - connect(m_columnView, SIGNAL(doubleClicked(const QModelIndex&)), - this, SLOT(doubleClickAccept(const QModelIndex&))); + connect(m_columnView, SIGNAL(doubleClicked(const QModelIndex&)), this, + SLOT(doubleClickAccept(const QModelIndex&))); - connect(m_columnView->selectionModel(), - SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)), - this, - SLOT(columnSelectionChanged(const QItemSelection&, const QItemSelection&))); + connect(m_columnView->selectionModel(), + SIGNAL(selectionChanged(const QItemSelection&, + const QItemSelection&)), + this, + SLOT(columnSelectionChanged(const QItemSelection&, + const QItemSelection&))); - connect(m_detailTree->selectionModel(), - SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)), - this, - SLOT(treeSelectionChanged(const QItemSelection&, const QItemSelection&))); + connect(m_detailTree->selectionModel(), + SIGNAL(selectionChanged(const QItemSelection&, + const QItemSelection&)), + this, + SLOT(treeSelectionChanged(const QItemSelection&, + const QItemSelection&))); - connect(m_columnView, SIGNAL(updatePreviewWidget(const QModelIndex&)), - this, SLOT(columnUpdatePreview(const QModelIndex&))); + connect(m_columnView, SIGNAL(updatePreviewWidget(const QModelIndex&)), + this, SLOT(columnUpdatePreview(const QModelIndex&))); - connect(m_ui.reloadButton, SIGNAL(clicked(bool)), - this, SLOT(reload(bool))); + connect(m_ui.reloadButton, SIGNAL(clicked(bool)), this, + SLOT(reload(bool))); - connect(m_ui.autoRefreshCheckbox, SIGNAL(stateChanged(int)), - this, SLOT(autoRefreshChanged(int))); + connect(m_ui.autoRefreshCheckbox, SIGNAL(stateChanged(int)), this, + SLOT(autoRefreshChanged(int))); - connect(m_ui.fileTypeCombo, SIGNAL(currentIndexChanged(int)), - this, SLOT(fileTypeChanged(int))); + connect(m_ui.fileTypeCombo, SIGNAL(currentIndexChanged(int)), this, + SLOT(fileTypeChanged(int))); - QCompleter *completer = new QCompleter(this); - completer->setModel(new QDirModel(completer)); - completer->setCompletionMode(QCompleter::InlineCompletion); - m_ui.currentPath->setCompleter(completer); - m_ui.currentPath->setText(""); + QCompleter* completer = new QCompleter(this); + completer->setModel(new QDirModel(completer)); + completer->setCompletionMode(QCompleter::InlineCompletion); + m_ui.currentPath->setCompleter(completer); + m_ui.currentPath->setText(""); - if (vmode != -1) - { - m_ui.viewCombo->setCurrentIndex(vmode); - - // - // Need this because the combo will default to index 0 and thus - // provide no signal. The signal is required to intialize the - // column view. - // + if (vmode != -1) + { + m_ui.viewCombo->setCurrentIndex(vmode); + + // + // Need this because the combo will default to index 0 and thus + // provide no signal. The signal is required to intialize the + // column view. + // - if (vmode == ColumnView) + if (vmode == ColumnView) + { + setViewMode(ColumnView); + } + } + else { - setViewMode(ColumnView); + setViewMode(DetailedFileView); } + + if (smode != -1) + m_ui.sortCombo->setCurrentIndex(smode); } - else + + RvFileDialog::~RvFileDialog() { delete m_fileTraits; } + + void RvFileDialog::setFileTypeTraits(FileTypeTraits* traits) { - setViewMode(DetailedFileView); - } + const bool sameAsCurrent = m_fileTraits && m_fileTraits->sameAs(traits); - if (smode != -1) m_ui.sortCombo->setCurrentIndex(smode); -} + delete m_fileTraits; + m_fileTraits = traits; -RvFileDialog::~RvFileDialog() -{ - delete m_fileTraits; -} + // Nothing to do if the traits are the same as the current ones + if (sameAsCurrent) + return; -void -RvFileDialog::setFileTypeTraits(FileTypeTraits* traits) -{ - const bool sameAsCurrent = m_fileTraits && m_fileTraits->sameAs(traits); + m_ui.fileTypeCombo->clear(); - delete m_fileTraits; - m_fileTraits = traits; + QStringList list = m_fileTraits->typeDescriptions(); - // Nothing to do if the traits are the same as the current ones - if ( sameAsCurrent ) return; + for (size_t i = 0; i < list.size(); i++) + { + m_ui.fileTypeCombo->addItem(list[i]); + } - m_ui.fileTypeCombo->clear(); + if (m_columnModel) + { + m_columnModel->setFileTraits(traits->copyTraits()); + m_detailFileModel->setFileTraits(traits->copyTraits()); + m_detailMediaModel->setFileTraits(traits->copyTraits()); + } - QStringList list = m_fileTraits->typeDescriptions(); + setFileTypeIndex(0); + } - for (size_t i=0; i < list.size(); i++) + void RvFileDialog::setFileTypeIndex(size_t index) { - m_ui.fileTypeCombo->addItem(list[i]); + m_ui.fileTypeCombo->setCurrentIndex(index); } - if (m_columnModel) + void RvFileDialog::setFileMode(FileMode m) { - m_columnModel->setFileTraits(traits->copyTraits()); - m_detailFileModel->setFileTraits(traits->copyTraits()); - m_detailMediaModel->setFileTraits(traits->copyTraits()); - } + DB("setFileMode " << m); + m_fileMode = m; - setFileTypeIndex(0); -} + if (m_fileMode == ManyExistingFiles + || m_fileMode == ManyExistingFilesAndDirectories) + { + m_detailTree->setSelectionMode( + QAbstractItemView::ExtendedSelection); + } + else + { + m_detailTree->setSelectionMode(QAbstractItemView::SingleSelection); + } -void -RvFileDialog::setFileTypeIndex(size_t index) -{ - m_ui.fileTypeCombo->setCurrentIndex(index); -} + // + // We can't get columnView to behave properly with + // Multi/Extended selection, so we limit it to single + // selection for now. + // + m_columnView->setSelectionMode(QAbstractItemView::SingleSelection); + } -void -RvFileDialog::setFileMode(FileMode m) -{ - DB ("setFileMode " << m); - m_fileMode = m; + void RvFileDialog::setFilter(QDir::Filters filters) { m_filters = filters; } - if (m_fileMode == ManyExistingFiles || - m_fileMode == ManyExistingFilesAndDirectories) + void RvFileDialog::setViewMode(ViewMode v) { - m_detailTree->setSelectionMode(QAbstractItemView::ExtendedSelection); + m_ui.viewCombo->setCurrentIndex(v); + m_viewMode = NoViewMode; + viewComboChanged((int)v); } - else + + void RvFileDialog::setRole(Role r) { - m_detailTree->setSelectionMode(QAbstractItemView::SingleSelection); + m_role = r; + // XXX this is hidden for now + // m_ui.newFolderButton->setDisabled(m_role == OpenFileRole); + m_ui.buttonBox->setStandardButtons( + m_role == OpenFileRole + ? (QDialogButtonBox::Open | QDialogButtonBox::Cancel) + : (QDialogButtonBox::Save | QDialogButtonBox::Cancel)); } - // - // We can't get columnView to behave properly with - // Multi/Extended selection, so we limit it to single - // selection for now. - // - m_columnView->setSelectionMode(QAbstractItemView::SingleSelection); -} - -void -RvFileDialog::setFilter(QDir::Filters filters) -{ - m_filters = filters; -} - -void -RvFileDialog::setViewMode(ViewMode v) -{ - m_ui.viewCombo->setCurrentIndex(v); - m_viewMode = NoViewMode; - viewComboChanged((int)v); -} - -void -RvFileDialog::setRole(Role r) -{ - m_role = r; - // XXX this is hidden for now - // m_ui.newFolderButton->setDisabled(m_role == OpenFileRole); - m_ui.buttonBox->setStandardButtons(m_role == OpenFileRole ? - (QDialogButtonBox::Open | QDialogButtonBox::Cancel) : - (QDialogButtonBox::Save | QDialogButtonBox::Cancel)); -} - -void -RvFileDialog::setTitleLabel(const QString& text) -{ - m_ui.titleLabel->setText(text); -} + void RvFileDialog::setTitleLabel(const QString& text) + { + m_ui.titleLabel->setText(text); + } -QFileInfoList -RvFileDialog::findMountPoints() -{ - QFileInfoList list; + QFileInfoList RvFileDialog::findMountPoints() + { + QFileInfoList list; - list.push_back(QDir::home().path()); + list.push_back(QDir::home().path()); #if defined(PLATFORM_LINUX) || defined(PLATFORM_DARWIN) - list.push_back(QString("/")); - m_drives.insert ("/"); + list.push_back(QString("/")); + m_drives.insert("/"); #endif #if defined(PLATFORM_LINUX) - QStringList dirs; - dirs << "/Volumes"; - dirs << "/Network"; - dirs << "/media"; - dirs << "/mnt"; - - for (size_t i=0; i < dirs.size(); i++) - { - QDir dir(dirs[i]); + QStringList dirs; + dirs << "/Volumes"; + dirs << "/Network"; + dirs << "/media"; + dirs << "/mnt"; - if (dir.exists()) + for (size_t i = 0; i < dirs.size(); i++) { - // - // On linux, check and see if there's actually anything in - // there - // + QDir dir(dirs[i]); - QFileInfoList mpoints = dir.entryInfoList(); - - // skip the . and .. entries - for (int q=2; q < mpoints.size(); q++) + if (dir.exists()) { - if (dirs[i] == "/media") + // + // On linux, check and see if there's actually anything in + // there + // + + QFileInfoList mpoints = dir.entryInfoList(); + + // skip the . and .. entries + for (int q = 2; q < mpoints.size(); q++) { - if (mpoints[q].isDir()) + if (dirs[i] == "/media") { - QString aPath = mpoints[q].absoluteFilePath(); - QDir d(aPath); - if (d.count() <= 2) continue; - else m_drives.insert (aPath); + if (mpoints[q].isDir()) + { + QString aPath = mpoints[q].absoluteFilePath(); + QDir d(aPath); + if (d.count() <= 2) + continue; + else + m_drives.insert(aPath); + } + else + { + continue; + } } - else - { - continue; - } - } - list.push_back(mpoints[q]); + list.push_back(mpoints[q]); + } } } - } #if 0 // @@ -538,425 +548,427 @@ RvFileDialog::findMountPoints() #elif defined(PLATFORM_WINDOWS) - // - // Windows, get the drives - // - - QFileInfoList drives = QDir::drives(); - - for (int i=0; i < drives.size(); i++) - { - QString aPath = drives[i].absoluteFilePath(); - DB ("DRIVES[" << i << "]: '" << aPath.toUtf8().data() << "'"); - m_drives.insert (aPath); - list.push_back(drives[i]); - } -#endif + // + // Windows, get the drives + // - return list; -} + QFileInfoList drives = QDir::drives(); -void -RvFileDialog::loadSidePanel() -{ - DB ("loadSidePanel()"); - RV_QSETTINGS; - QListWidget* l = m_ui.sidePanelList; - l->clear(); + for (int i = 0; i < drives.size(); i++) + { + QString aPath = drives[i].absoluteFilePath(); + DB("DRIVES[" << i << "]: '" << aPath.toUtf8().data() << "'"); + m_drives.insert(aPath); + list.push_back(drives[i]); + } +#endif - settings.beginGroup("RvFileDialog"); - QStringList paths = settings.value("sidePanelPaths", QStringList()).toStringList(); - DB (" settings value, " << paths.size() << "items"); - settings.endGroup(); + return list; + } - // Add current working directory to head of list - // - QListWidgetItem* item = newItemForFile(QFileInfo(QDir::current().path())); - item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); - item->setText("Current Directory"); - l->addItem(item); + void RvFileDialog::loadSidePanel() + { + DB("loadSidePanel()"); + RV_QSETTINGS; + QListWidget* l = m_ui.sidePanelList; + l->clear(); - QFileInfoList mounts = findMountPoints(); + settings.beginGroup("RvFileDialog"); + QStringList paths = + settings.value("sidePanelPaths", QStringList()).toStringList(); + DB(" settings value, " << paths.size() << "items"); + settings.endGroup(); - for (int i=0; i < mounts.size(); i++) - { - QListWidgetItem* item = newItemForFile(mounts[i]); + // Add current working directory to head of list + // + QListWidgetItem* item = + newItemForFile(QFileInfo(QDir::current().path())); item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); + item->setText("Current Directory"); l->addItem(item); + + QFileInfoList mounts = findMountPoints(); + + for (int i = 0; i < mounts.size(); i++) + { + QListWidgetItem* item = newItemForFile(mounts[i]); + item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); + l->addItem(item); + } + + for (int i = 0; i < paths.size(); i++) + { + QFileInfo info(paths[i]); + l->addItem(newItemForFile(info)); + } + DB("loadSidePanel() done"); } - for (int i=0; i < paths.size(); i++) + void RvFileDialog::watchedDirChanged(const QString& dir) { - QFileInfo info(paths[i]); - l->addItem(newItemForFile(info)); + if (!m_reloadTimer->isActive()) + m_reloadTimer->start(1000); } - DB ("loadSidePanel() done"); -} - -void -RvFileDialog::watchedDirChanged(const QString& dir) -{ - if (!m_reloadTimer->isActive()) m_reloadTimer->start(1000); -} -void -RvFileDialog::setDirectory(const QString& inpath, bool force) -{ - if (m_building) return; + void RvFileDialog::setDirectory(const QString& inpath, bool force) + { + if (m_building) + return; - QString path = inpath; - QString cpath = m_ui.currentPath->text(); + QString path = inpath; + QString cpath = m_ui.currentPath->text(); - DB ("setDirectory " << - path.toUtf8().data() << " " << m_ui.currentPath->text().toUtf8().data()); + DB("setDirectory " << path.toUtf8().data() << " " + << m_ui.currentPath->text().toUtf8().data()); - QFileInfo pathInfo(path); + QFileInfo pathInfo(path); - if (path == "") - { - RV_QSETTINGS; - settings.beginGroup (m_settingsGroup); - path = settings.value ("lastDir", inpath).toString(); - settings.endGroup(); - pathInfo = QFileInfo(path); - if (!pathInfo.isDir()) + if (path == "") { - path = QDir::currentPath(); + RV_QSETTINGS; + settings.beginGroup(m_settingsGroup); + path = settings.value("lastDir", inpath).toString(); + settings.endGroup(); pathInfo = QFileInfo(path); + if (!pathInfo.isDir()) + { + path = QDir::currentPath(); + pathInfo = QFileInfo(path); + } + DB(" INITIALIZING with " << path.toUtf8().data()); } - DB (" INITIALIZING with " << path.toUtf8().data()); - } - - /* - * Well, who knows. For a while, I thought the below was - * really helping, preventing us from doing things twice. - * Now it seems to be necessary that we do those things twice - * (or more). So I'm leaving it in case we need it later, - * but be aware that uncommenting the below triggers bad - * behavior in the columnview: mouse down on a file, and all - * files above it in the list will be highlighted untill you - * mouse up. - * - if (!m_dirPrev.empty()) - { - QString prev = m_dirPrev.back(); - DB (" m_dirPrev.back() " << prev.toUtf8().data()); - if (!force && !m_dirPrev.empty() && (path == prev || - (prev.startsWith(path) && - prev.endsWith("/") && - prev.length() == path.length()+1))) + /* + * Well, who knows. For a while, I thought the below was + * really helping, preventing us from doing things twice. + * Now it seems to be necessary that we do those things twice + * (or more). So I'm leaving it in case we need it later, + * but be aware that uncommenting the below triggers bad + * behavior in the columnview: mouse down on a file, and all + * files above it in the list will be highlighted untill you + * mouse up. + * + if (!m_dirPrev.empty()) { - DB (" returning from setDirectory"); - return; + QString prev = m_dirPrev.back(); + + DB (" m_dirPrev.back() " << prev.toUtf8().data()); + if (!force && !m_dirPrev.empty() && (path == prev || + (prev.startsWith(path) && + prev.endsWith("/") && + prev.length() == path.length()+1))) + { + DB (" returning from setDirectory"); + return; + } } - } - NOTE: (from jim) this is actually a Qt bug that I think the above - code is just exacerbating - */ + NOTE: (from jim) this is actually a Qt bug that I think the above + code is just exacerbating + */ - m_building = true; + m_building = true; - QDir dir(path, - "", - QDir::Name | QDir::IgnoreCase, - m_filters); + QDir dir(path, "", QDir::Name | QDir::IgnoreCase, m_filters); - dir.makeAbsolute(); - QString absoluteDirPath = dir.absolutePath(); + dir.makeAbsolute(); + QString absoluteDirPath = dir.absolutePath(); - if (m_allowAutoRefresh) - { - if (!m_watcher) + if (m_allowAutoRefresh) { - m_watcher = new QFileSystemWatcher(this); - connect(m_watcher, SIGNAL(directoryChanged(const QString&)), - this, SLOT(watchedDirChanged(const QString&))); - } + if (!m_watcher) + { + m_watcher = new QFileSystemWatcher(this); + connect(m_watcher, SIGNAL(directoryChanged(const QString&)), + this, SLOT(watchedDirChanged(const QString&))); + } - if (!m_watcher->directories().empty()) - m_watcher->removePaths(m_watcher->directories()); + if (!m_watcher->directories().empty()) + m_watcher->removePaths(m_watcher->directories()); - m_watcher->addPath(absoluteDirPath); - } + m_watcher->addPath(absoluteDirPath); + } - if (pathInfo.isDir()) - { - if (!absoluteDirPath.endsWith("/")) absoluteDirPath += "/"; - if (m_dirPrev.empty() || absoluteDirPath != m_dirPrev.back()) + if (pathInfo.isDir()) { - m_dirPrev.push_back(absoluteDirPath); + if (!absoluteDirPath.endsWith("/")) + absoluteDirPath += "/"; + if (m_dirPrev.empty() || absoluteDirPath != m_dirPrev.back()) + { + m_dirPrev.push_back(absoluteDirPath); + } } - } - else - { - dir = QDir (pathInfo.absolutePath(), - "", - QDir::Name | QDir::IgnoreCase, - m_filters); - } - DB (" setting currentPath " << absoluteDirPath.toUtf8().data()); - m_ui.currentPath->setText(absoluteDirPath); - m_ui.currentPath->end(false); - m_currentFile = ""; - - if (m_viewMode == DetailedFileView || m_viewMode == DetailedMediaView) - { - MediaDirModel* model = dynamic_cast(m_detailTree->model()); - model->setDirectory(dir, m_viewMode == DetailedFileView - ? MediaDirModel::BasicFileDetails - : MediaDirModel::MediaDetails); - - for (int i=0; i < 8; i++) m_detailTree->resizeColumnToContents(i); - } - else if (m_viewMode == ColumnView) - { - QModelIndex i = m_columnModel->indexOfPath(absoluteDirPath); + else + { + dir = QDir(pathInfo.absolutePath(), "", + QDir::Name | QDir::IgnoreCase, m_filters); + } + DB(" setting currentPath " << absoluteDirPath.toUtf8().data()); + m_ui.currentPath->setText(absoluteDirPath); + m_ui.currentPath->end(false); + m_currentFile = ""; - if (!i.isValid()) + if (m_viewMode == DetailedFileView || m_viewMode == DetailedMediaView) + { + MediaDirModel* model = + dynamic_cast(m_detailTree->model()); + model->setDirectory(dir, m_viewMode == DetailedFileView + ? MediaDirModel::BasicFileDetails + : MediaDirModel::MediaDetails); + + for (int i = 0; i < 8; i++) + m_detailTree->resizeColumnToContents(i); + } + else if (m_viewMode == ColumnView) { + QModelIndex i = m_columnModel->indexOfPath(absoluteDirPath); + + if (!i.isValid()) + { + // + // On windows, we need to setdir to the root of the + // current file system. For example, C:/ or Y:/ not just + // "/" or some directory. + // + + QDir fd = dir; + while (fd.cdUp()) + ; + m_columnModel->setDirectory(fd, MediaDirModel::NoDetails); + } + // - // On windows, we need to setdir to the root of the - // current file system. For example, C:/ or Y:/ not just - // "/" or some directory. + // This is a hack to get around a Qt bug in the column view (or + // maybe its the scrolled area). The column view will get + // scrolled too far by setCurrentIndex() if its called before + // the dialog box is fully formed. // + DB(" m_columnViewTimer active " + << m_columnViewTimer->isActive()); - QDir fd = dir; - while (fd.cdUp()); - m_columnModel->setDirectory(fd, MediaDirModel::NoDetails); + if (i != m_columnView->currentIndex()) + { + if (m_columnViewTimer->isActive()) + { + m_columnViewFile = absoluteDirPath; + } + else if (i.isValid()) + { + DB(" setCurrentIndex on " + << absoluteDirPath.toUtf8().data()); + m_columnView->setCurrentIndex(i); + } + } } - // - // This is a hack to get around a Qt bug in the column view (or - // maybe its the scrolled area). The column view will get - // scrolled too far by setCurrentIndex() if its called before - // the dialog box is fully formed. - // - DB (" m_columnViewTimer active " << m_columnViewTimer->isActive()); + DB(" rebuilding path combo"); + m_ui.pathCombo->clear(); - if (i != m_columnView->currentIndex()) + for (bool done = false; !done;) { - if (m_columnViewTimer->isActive()) + QString aPath = dir.absolutePath(); + QString dName = dir.dirName(); + DB(" calling cdUp()"); + if (!dir.cdUp()) + // + // it's a root path + // { - m_columnViewFile = absoluteDirPath; + QString aPathNoSlash = aPath; + DB(" up to root: '" << aPath.toUtf8().data() << "'"); +#ifdef WIN32 + if (aPathNoSlash.endsWith("/")) + aPathNoSlash.chop(1); +#endif + m_ui.pathCombo->addItem(iconForFile(aPath), aPathNoSlash, + aPath); + + done = true; } - else if (i.isValid()) + else { - DB (" setCurrentIndex on " << - absoluteDirPath.toUtf8().data()); - m_columnView->setCurrentIndex(i); + DB(" not at root: '" << aPath.toUtf8().data() << "'"); + m_ui.pathCombo->addItem(iconForFile(aPath), dName, aPath); } } - } + DB(" adding Recent items"); - DB (" rebuilding path combo"); - m_ui.pathCombo->clear(); + m_ui.pathCombo->insertSeparator(m_ui.pathCombo->count()); + m_ui.pathCombo->addItem(" Recent"); + m_ui.pathCombo->insertSeparator(m_ui.pathCombo->count()); - for (bool done = false; !done; ) - { - QString aPath = dir.absolutePath(); - QString dName = dir.dirName(); - DB (" calling cdUp()"); - if (!dir.cdUp()) - // - // it's a root path - // + if (m_visited.contains(absoluteDirPath)) { - QString aPathNoSlash = aPath; - DB (" up to root: '" << aPath.toUtf8().data() << "'"); -#ifdef WIN32 - if (aPathNoSlash.endsWith("/")) aPathNoSlash.chop(1); -#endif - m_ui.pathCombo->addItem(iconForFile(aPath), - aPathNoSlash, - aPath); - - done = true; + m_visited.move(m_visited.indexOf(absoluteDirPath), 0); } else { - DB (" not at root: '" << aPath.toUtf8().data() << "'"); - m_ui.pathCombo->addItem(iconForFile(aPath), - dName, - aPath); + DB("adding to visited list: " << absoluteDirPath.toUtf8().data()); + m_visited.push_front(absoluteDirPath); + if (m_visited.size() > 20) + m_visited.pop_back(); } - } - - DB (" adding Recent items"); - - m_ui.pathCombo->insertSeparator(m_ui.pathCombo->count()); - m_ui.pathCombo->addItem(" Recent"); - m_ui.pathCombo->insertSeparator(m_ui.pathCombo->count()); - - if (m_visited.contains(absoluteDirPath)) - { - m_visited.move(m_visited.indexOf(absoluteDirPath), 0); - } - else - { - DB ("adding to visited list: " << absoluteDirPath.toUtf8().data()); - m_visited.push_front(absoluteDirPath); - if (m_visited.size() > 20) m_visited.pop_back(); - } - QStringList newVisited; + QStringList newVisited; - for (QStringList::const_iterator i = m_visited.begin(); - i != m_visited.end(); - ++i) - { - QString name = *i; - QFileInfo info(*i); - QString aPath = info.absoluteFilePath(); - // - // Deciding if "drives" exist can take a while. (We know - // they did when we added them to the list, Let's just assume - // they still do. - // - // Actually this can take a long time whether it's a drive - // or not, cause it could be a network path pointing to a - // wedged mount, etc. So don't check here and put it in - // the list, we'll find out if it doesn't exist when the - // user clicks on it. (see pathComboChanged()) - // - // if (m_drives.contains (aPath) || info.exists()) + for (QStringList::const_iterator i = m_visited.begin(); + i != m_visited.end(); ++i) { - m_ui.pathCombo->addItem (iconForFile(info), name, aPath); - newVisited.append (name); + QString name = *i; + QFileInfo info(*i); + QString aPath = info.absoluteFilePath(); + // + // Deciding if "drives" exist can take a while. (We know + // they did when we added them to the list, Let's just assume + // they still do. + // + // Actually this can take a long time whether it's a drive + // or not, cause it could be a network path pointing to a + // wedged mount, etc. So don't check here and put it in + // the list, we'll find out if it doesn't exist when the + // user clicks on it. (see pathComboChanged()) + // + // if (m_drives.contains (aPath) || info.exists()) + { + m_ui.pathCombo->addItem(iconForFile(info), name, aPath); + newVisited.append(name); + } } - } - - // - // This new list has only "drives" and existing directories. - // - m_visited = newVisited; - - m_ui.pathCombo->setCurrentIndex(0); - DB (" rebuilding path combo done"); - m_ui.previousButton->defaultAction()->setEnabled(m_dirPrev.size() > 1); - m_ui.nextButton->defaultAction()->setEnabled(m_dirNext.size() > 0); - - m_building = false; - DB ("setDirectory done"); -} + // + // This new list has only "drives" and existing directories. + // + m_visited = newVisited; -void -RvFileDialog::setCurrentFile(const QString& infileRef) -{ - QString infile = infileRef; - infile.replace("\\", "/"); - DB ("setCurrentFile() infile " << infile.toUtf8().data()); + m_ui.pathCombo->setCurrentIndex(0); + DB(" rebuilding path combo done"); - QFileInfo info(infile); + m_ui.previousButton->defaultAction()->setEnabled(m_dirPrev.size() > 1); + m_ui.nextButton->defaultAction()->setEnabled(m_dirNext.size() > 0); - if (info.isDir()) setDirectory(info.absoluteFilePath()); - else setDirectory(info.absolutePath()); + m_building = false; + DB("setDirectory done"); + } - // - // Just return if we're not changing anything. - // - if (m_currentFile == infile) + void RvFileDialog::setCurrentFile(const QString& infileRef) { - DB (" returning from setCurrentFile"); - return; - } + QString infile = infileRef; + infile.replace("\\", "/"); + DB("setCurrentFile() infile " << infile.toUtf8().data()); - m_building = true; - m_currentFile = infile; - m_ui.currentPath->setText(infile); - m_ui.currentPath->end(false); + QFileInfo info(infile); - // - // Get appropriate Data Model and View - // - MediaDirModel *mdm(0); - QAbstractItemView *view(0); - if (m_viewMode == ColumnView) - { - mdm = m_columnModel; - view = m_columnView; - } - else if (m_viewMode == DetailedFileView) - { - mdm = m_detailFileModel; - view = m_detailTree; - } - else if (m_viewMode == DetailedMediaView) - { - mdm = m_detailMediaModel; - view = m_detailTree; - } + if (info.isDir()) + setDirectory(info.absoluteFilePath()); + else + setDirectory(info.absolutePath()); - // - // Ensure that this item is selected and current and visible, if it's in - // the list. - // - if (!mdm || !view) - { - DB ("ERROR: RvFileDialog::" << __FUNCTION__ << " Can't find Data Model or View"); - } - else - { - DB (" calling mdm->indexOfPath()"); - QModelIndex i = mdm->indexOfPath (info); - if (i.isValid() && view->currentIndex() != i) - { - DB (" selecting "); - view->setCurrentIndex (i); - // view->selectionModel()->select (i, QItemSelectionModel::ClearAndSelect); - // view->selectionModel()->setCurrentIndex (i, QItemSelectionModel::ClearAndSelect); - DB (" selecting complete"); - if (QTreeView *tv = dynamic_cast (view)) - { - tv->scrollTo (i, QAbstractItemView::PositionAtCenter); - } - } - /* - * At some point I thought we needed the below to deselect a - * file when we've switch to selecting the directory that - * contains the file. But it seems to work without if now, - * so I'm taking it out in the interests of simplicity, but - * leaving it in the file, in case we think we need it in - * the future. - * - else + // + // Just return if we're not changing anything. + // + if (m_currentFile == infile) { - if (QTreeView *tv = dynamic_cast (view)) - { - view->setCurrentIndex (QModelIndex()); - // view->selectionModel()->select (QModelIndex(), QItemSelectionModel::Clear); - } + DB(" returning from setCurrentFile"); + return; } - */ - } - m_building = false; - DB ("setCurrentFile() done "); -} + m_building = true; + m_currentFile = infile; + m_ui.currentPath->setText(infile); + m_ui.currentPath->end(false); -void -RvFileDialog::accept() -{ - switch (m_fileMode) - { - case OneExistingFile: - case OneDirectory: + // + // Get appropriate Data Model and View + // + MediaDirModel* mdm(0); + QAbstractItemView* view(0); + if (m_viewMode == ColumnView) { - if ( TwkUtil::pathIsURL( m_currentFile.toStdString() ) ) - { - QDialog::accept(); - } + mdm = m_columnModel; + view = m_columnView; + } + else if (m_viewMode == DetailedFileView) + { + mdm = m_detailFileModel; + view = m_detailTree; + } + else if (m_viewMode == DetailedMediaView) + { + mdm = m_detailMediaModel; + view = m_detailTree; + } + + // + // Ensure that this item is selected and current and visible, if it's + // in the list. + // + if (!mdm || !view) + { + DB("ERROR: RvFileDialog::" << __FUNCTION__ + << " Can't find Data Model or View"); + } + else + { + DB(" calling mdm->indexOfPath()"); + QModelIndex i = mdm->indexOfPath(info); + if (i.isValid() && view->currentIndex() != i) + { + DB(" selecting "); + view->setCurrentIndex(i); + // view->selectionModel()->select (i, + // QItemSelectionModel::ClearAndSelect); + // view->selectionModel()->setCurrentIndex (i, + // QItemSelectionModel::ClearAndSelect); + DB(" selecting complete"); + if (QTreeView* tv = dynamic_cast(view)) + { + tv->scrollTo(i, QAbstractItemView::PositionAtCenter); + } + } + /* + * At some point I thought we needed the below to deselect a + * file when we've switch to selecting the directory that + * contains the file. But it seems to work without if now, + * so I'm taking it out in the interests of simplicity, but + * leaving it in the file, in case we think we need it in + * the future. + * else - { + { + if (QTreeView *tv = dynamic_cast (view)) + { + view->setCurrentIndex (QModelIndex()); + // view->selectionModel()->select (QModelIndex(), + QItemSelectionModel::Clear); + } + } + */ + } + + m_building = false; + DB("setCurrentFile() done "); + } + + void RvFileDialog::accept() + { + switch (m_fileMode) + { + case OneExistingFile: + case OneDirectory: + { + if (TwkUtil::pathIsURL(m_currentFile.toStdString())) + { + QDialog::accept(); + } + else + { QFileInfo info(m_currentFile); if (info.exists()) { - if ((m_fileMode == OneExistingFile && !info.isDir()) || - (m_fileMode == OneDirectory && info.isDir())) + if ((m_fileMode == OneExistingFile && !info.isDir()) + || (m_fileMode == OneDirectory && info.isDir())) { QDialog::accept(); } @@ -964,51 +976,58 @@ RvFileDialog::accept() } } } - - case ManyExistingFilesAndDirectories: - case ManyExistingFiles: - { - QStringList files = selectedFiles(); - if (files.empty()) break; - bool ok = true; - bool hasdir = false; - - for (int i=0; i < files.size(); i++) - { - if ( TwkUtil::pathIsURL( files[i].toStdString() ) ) continue; - - QFileInfo info(files[i]); - - if (!info.exists()) - { - QString test = firstFileInPattern(files[i].toUtf8().data()).c_str(); - QFileInfo testinfo(test); - if (!testinfo.exists()) ok = false; - } - - if (info.isDir()) hasdir = true; - } - - if (ok) - { - if (m_fileMode == ManyExistingFiles) - { - if (!hasdir) QDialog::accept(); - else if (1 == files.size()) setDirectory (files[0]); - } - else - { - QDialog::accept(); - } - } - - break; - } - - case OneFileName: - case OneDirectoryName: - { - if ( TwkUtil::pathIsURL( m_currentFile.toStdString() ) ) + + case ManyExistingFilesAndDirectories: + case ManyExistingFiles: + { + QStringList files = selectedFiles(); + if (files.empty()) + break; + bool ok = true; + bool hasdir = false; + + for (int i = 0; i < files.size(); i++) + { + if (TwkUtil::pathIsURL(files[i].toStdString())) + continue; + + QFileInfo info(files[i]); + + if (!info.exists()) + { + QString test = + firstFileInPattern(files[i].toUtf8().data()).c_str(); + QFileInfo testinfo(test); + if (!testinfo.exists()) + ok = false; + } + + if (info.isDir()) + hasdir = true; + } + + if (ok) + { + if (m_fileMode == ManyExistingFiles) + { + if (!hasdir) + QDialog::accept(); + else if (1 == files.size()) + setDirectory(files[0]); + } + else + { + QDialog::accept(); + } + } + + break; + } + + case OneFileName: + case OneDirectoryName: + { + if (TwkUtil::pathIsURL(m_currentFile.toStdString())) { QDialog::accept(); } @@ -1016,10 +1035,11 @@ RvFileDialog::accept() { QFileInfo info(m_currentFile); - if (!info.exists() || - (info.exists() && - ( (m_fileMode == OneFileName && !info.isDir()) || - (m_fileMode == OneDirectoryName && info.isDir()) ))) + if (!info.exists() + || (info.exists() + && ((m_fileMode == OneFileName && !info.isDir()) + || (m_fileMode == OneDirectoryName + && info.isDir())))) { QDialog::accept(); } @@ -1027,921 +1047,936 @@ RvFileDialog::accept() break; } - } + } - if (m_watcher) - { - delete m_watcher; - m_watcher = 0; + if (m_watcher) + { + delete m_watcher; + m_watcher = 0; + } } -} -void -RvFileDialog::reject() -{ - if (m_watcher) + void RvFileDialog::reject() { - delete m_watcher; - m_watcher = 0; - } - - QDialog::reject(); -} - -void -RvFileDialog::reloadTimeout() -{ - if (!m_building) reload(true); -} - -void -RvFileDialog::reload(bool) -{ - if (m_viewMode == ColumnView) m_columnModel->reload(); - QString current = m_ui.currentPath->text(); - setDirectory(current); -} - -void -RvFileDialog::autoRefreshChanged(int state) -{ - m_allowAutoRefresh = (state != 0); - - RV_QSETTINGS; - settings.beginGroup (m_settingsGroup); - settings.setValue("allowAutoRefresh", m_allowAutoRefresh); - settings.endGroup(); - - if (m_allowAutoRefresh) reload(true); -} - -void -RvFileDialog::columnSelectionChanged(const QItemSelection& selected, - const QItemSelection& deselected) -{ - DB ("columnSelectionChanged() m_building " << m_building << - " sel " << selected.indexes().size() << - " desel " << deselected.indexes().size()); + if (m_watcher) + { + delete m_watcher; + m_watcher = 0; + } - if (selected.empty()) return; + QDialog::reject(); + } - if (m_building) + void RvFileDialog::reloadTimeout() { - DB (" returning from columnSelectionChanged"); - return; + if (!m_building) + reload(true); } - const QModelIndex& i = m_columnView->selectionModel()->currentIndex(); - if (i.isValid()) + void RvFileDialog::reload(bool) { - QString path = m_columnModel->absoluteFilePath (i); - DB (" path: '" << path.toUtf8().data() << "'"); - setCurrentFile(path); + if (m_viewMode == ColumnView) + m_columnModel->reload(); + QString current = m_ui.currentPath->text(); + setDirectory(current); } -} -void -RvFileDialog::treeSelectionChanged(const QItemSelection& selected, - const QItemSelection& deselected) -{ - DB ("treeSelectionChanged() m_building " << m_building << - " sel " << selected.indexes().size() << - " desel " << deselected.indexes().size()); - - - if (m_building) + void RvFileDialog::autoRefreshChanged(int state) { - DB (" returning from treeSelectionChanged"); - return; - } + m_allowAutoRefresh = (state != 0); - if (selected.empty()) return; + RV_QSETTINGS; + settings.beginGroup(m_settingsGroup); + settings.setValue("allowAutoRefresh", m_allowAutoRefresh); + settings.endGroup(); - QModelIndexList selection = m_detailTree->selectionModel()->selectedIndexes(); - DB (" selection size " << selection.size()); - int reallyHowManySelected = 0; - for (int i = 0; i < selection.size(); i++) - { - const QModelIndex& index = selection[i]; - - if (index.isValid() && index.column() == 0) ++reallyHowManySelected; + if (m_allowAutoRefresh) + reload(true); } - DB (" real selection size " << reallyHowManySelected); - if (reallyHowManySelected == 1) + void RvFileDialog::columnSelectionChanged(const QItemSelection& selected, + const QItemSelection& deselected) { - MediaDirModel* model = 0; + DB("columnSelectionChanged() m_building " + << m_building << " sel " << selected.indexes().size() << " desel " + << deselected.indexes().size()); - if (m_viewMode == DetailedFileView) model = m_detailFileModel; - if (m_viewMode == DetailedMediaView) model = m_detailMediaModel; + if (selected.empty()) + return; - const QModelIndex& i = m_detailTree->selectionModel()->currentIndex(); - const QModelIndex& s = i.sibling(i.row(), 0); // Read path from first col - QString path = ""; - if (s.isValid()) + if (m_building) { - path = model->absoluteFilePath(s); + DB(" returning from columnSelectionChanged"); + return; } - else if (!m_dirPrev.empty()) + + const QModelIndex& i = m_columnView->selectionModel()->currentIndex(); + if (i.isValid()) { - path = m_dirPrev.back(); + QString path = m_columnModel->absoluteFilePath(i); + DB(" path: '" << path.toUtf8().data() << "'"); + setCurrentFile(path); } - - m_ui.currentPath->setText (path); - m_ui.currentPath->end (false); - m_currentFile = ""; } - else + + void RvFileDialog::treeSelectionChanged(const QItemSelection& selected, + const QItemSelection& deselected) { - if (!m_dirPrev.empty()) + DB("treeSelectionChanged() m_building " + << m_building << " sel " << selected.indexes().size() << " desel " + << deselected.indexes().size()); + + if (m_building) { - m_ui.currentPath->setText (m_dirPrev.back()); - m_ui.currentPath->end (false); - m_currentFile = ""; + DB(" returning from treeSelectionChanged"); + return; } - } -} + if (selected.empty()) + return; -void -RvFileDialog::pathComboChanged(int index) -{ - DB ("pathComboChanged() m_building " << m_building); - if (!m_building) - { - QString t = m_ui.pathCombo->itemData(index).toString(); + QModelIndexList selection = + m_detailTree->selectionModel()->selectedIndexes(); + DB(" selection size " << selection.size()); + int reallyHowManySelected = 0; + for (int i = 0; i < selection.size(); i++) + { + const QModelIndex& index = selection[i]; + + if (index.isValid() && index.column() == 0) + ++reallyHowManySelected; + } + DB(" real selection size " << reallyHowManySelected); - QFileInfo pathInfo(t); - if (!pathInfo.exists()) + if (reallyHowManySelected == 1) { - if (m_visited.removeOne(t)) + MediaDirModel* model = 0; + + if (m_viewMode == DetailedFileView) + model = m_detailFileModel; + if (m_viewMode == DetailedMediaView) + model = m_detailMediaModel; + + const QModelIndex& i = + m_detailTree->selectionModel()->currentIndex(); + const QModelIndex& s = + i.sibling(i.row(), 0); // Read path from first col + QString path = ""; + if (s.isValid()) { - cerr << "WARNING: " << t.toUtf8().data() << - " does not exist, removing from list." << endl; + path = model->absoluteFilePath(s); + } + else if (!m_dirPrev.empty()) + { + path = m_dirPrev.back(); + } + + m_ui.currentPath->setText(path); + m_ui.currentPath->end(false); + m_currentFile = ""; + } + else + { + if (!m_dirPrev.empty()) + { + m_ui.currentPath->setText(m_dirPrev.back()); + m_ui.currentPath->end(false); + m_currentFile = ""; } - m_ui.pathCombo->setCurrentIndex(0); } - else setDirectory(t); } -} -void -RvFileDialog::inputPathEntry() -{ - DB ("inputPathEntry() m_building " << m_building); - if (!m_building) + void RvFileDialog::pathComboChanged(int index) { - string p = varTildExp(m_ui.currentPath->text().toUtf8().data()); - setCurrentFile(p.c_str()); + DB("pathComboChanged() m_building " << m_building); + if (!m_building) + { + QString t = m_ui.pathCombo->itemData(index).toString(); + + QFileInfo pathInfo(t); + if (!pathInfo.exists()) + { + if (m_visited.removeOne(t)) + { + cerr << "WARNING: " << t.toUtf8().data() + << " does not exist, removing from list." << endl; + } + m_ui.pathCombo->setCurrentIndex(0); + } + else + setDirectory(t); + } } -} -void -RvFileDialog::done(int r) -{ + void RvFileDialog::inputPathEntry() { - RV_QSETTINGS; - settings.beginGroup(m_settingsGroup); - if (m_visited.empty()) settings.remove("visited"); - else settings.setValue("visited", m_visited); - settings.setValue("viewModeNew", m_ui.viewCombo->currentIndex()); - QFileInfo info(m_ui.currentPath->text()); - DB ("lastDir = " << info.absolutePath().toUtf8().data()); - settings.setValue("lastDir", info.absolutePath()); - int iconMode = 0; - if (m_cpGeneric->isChecked()) iconMode = 1; - else if (m_cpNone->isChecked()) iconMode = 2; - settings.setValue("iconMode", iconMode); - settings.setValue("showHiddenFiles", m_cpHidden->isChecked()); - settings.setValue("dialogGeometry", geometry()); - settings.endGroup(); + DB("inputPathEntry() m_building " << m_building); + if (!m_building) + { + string p = varTildExp(m_ui.currentPath->text().toUtf8().data()); + setCurrentFile(p.c_str()); + } } - saveSidePanel(); - QDialog::done(r); -} - -void -RvFileDialog::columnViewTimeout() -{ - DB ("columnViewTimeout file " << m_columnViewFile.toUtf8().data()); - QModelIndex i = m_columnModel->indexOfPath(m_columnViewFile); - if (i.isValid()) m_columnView->setCurrentIndex(i); -} - -void -RvFileDialog::sidePanelTimeout() -{ - // - // Delete any older duplicates - // + void RvFileDialog::done(int r) + { + { + RV_QSETTINGS; + settings.beginGroup(m_settingsGroup); + if (m_visited.empty()) + settings.remove("visited"); + else + settings.setValue("visited", m_visited); + settings.setValue("viewModeNew", m_ui.viewCombo->currentIndex()); + QFileInfo info(m_ui.currentPath->text()); + DB("lastDir = " << info.absolutePath().toUtf8().data()); + settings.setValue("lastDir", info.absolutePath()); + int iconMode = 0; + if (m_cpGeneric->isChecked()) + iconMode = 1; + else if (m_cpNone->isChecked()) + iconMode = 2; + settings.setValue("iconMode", iconMode); + settings.setValue("showHiddenFiles", m_cpHidden->isChecked()); + settings.setValue("dialogGeometry", geometry()); + settings.endGroup(); + } - QListWidget* l = m_ui.sidePanelList; - QStringList dropped; + saveSidePanel(); + QDialog::done(r); + } - for (int i=m_sideInsertStart; i <= m_sideInsertEnd; i++) + void RvFileDialog::columnViewTimeout() { - QListWidgetItem* item = l->item(i); - dropped.push_back(item->data(Qt::UserRole).toString()); + DB("columnViewTimeout file " << m_columnViewFile.toUtf8().data()); + QModelIndex i = m_columnModel->indexOfPath(m_columnViewFile); + if (i.isValid()) + m_columnView->setCurrentIndex(i); } - QList tbd; - - for (int i=0; i < l->count(); i++) + void RvFileDialog::sidePanelTimeout() { - if (i < m_sideInsertStart || i > m_sideInsertEnd) + // + // Delete any older duplicates + // + + QListWidget* l = m_ui.sidePanelList; + QStringList dropped; + + for (int i = m_sideInsertStart; i <= m_sideInsertEnd; i++) { QListWidgetItem* item = l->item(i); + dropped.push_back(item->data(Qt::UserRole).toString()); + } + + QList tbd; - if (dropped.contains(item->data(Qt::UserRole).toString())) + for (int i = 0; i < l->count(); i++) + { + if (i < m_sideInsertStart || i > m_sideInsertEnd) { - tbd.push_back(item); + QListWidgetItem* item = l->item(i); + + if (dropped.contains(item->data(Qt::UserRole).toString())) + { + tbd.push_back(item); + } } } - } - - for (int i=0; i < tbd.size(); i++) delete tbd[i]; - - saveSidePanel(); -} + for (int i = 0; i < tbd.size(); i++) + delete tbd[i]; -void -RvFileDialog::saveSidePanel() -{ - DB ("saveSidePanel()"); - QListWidget* l = m_ui.sidePanelList; - RV_QSETTINGS; - QStringList paths; + saveSidePanel(); + } - for (int i=0; i< l->count(); i++) + void RvFileDialog::saveSidePanel() { - QListWidgetItem* item = l->item(i); + DB("saveSidePanel()"); + QListWidget* l = m_ui.sidePanelList; + RV_QSETTINGS; + QStringList paths; - if (item->flags() & Qt::ItemIsDragEnabled) + for (int i = 0; i < l->count(); i++) { - QVariant v = item->data(Qt::UserRole); + QListWidgetItem* item = l->item(i); - if (v.canConvert(QVariant::String)) - // - // Sometimes we end up here with QVariant::Invalid - // data, so check and skip any such. - // + if (item->flags() & Qt::ItemIsDragEnabled) { - QString p = v.toString(); + QVariant v = item->data(Qt::UserRole); - if (!p.trimmed().isEmpty()) + if (v.canConvert(QVariant::String)) // - // Don't know how, but sometimes we get empty strings in - // the list. We don't want to save them. + // Sometimes we end up here with QVariant::Invalid + // data, so check and skip any such. // { - DB (" " << p.toUtf8().data()); - paths.push_back (p); + QString p = v.toString(); + + if (!p.trimmed().isEmpty()) + // + // Don't know how, but sometimes we get empty strings in + // the list. We don't want to save them. + // + { + DB(" " << p.toUtf8().data()); + paths.push_back(p); + } } } } + settings.beginGroup("RvFileDialog"); + // + // This is super annoying. If paths is empty, Qt writes + // garbage into the settings file ("@Invalid()"). So we check + // and remove this key from the settings if paths is empty. + // + DB(" settings setValue, " << paths.size() << "items"); + if (paths.empty()) + settings.remove("sidePanelPaths"); + else + settings.setValue("sidePanelPaths", paths); + settings.endGroup(); } - settings.beginGroup("RvFileDialog"); - // - // This is super annoying. If paths is empty, Qt writes - // garbage into the settings file ("@Invalid()"). So we check - // and remove this key from the settings if paths is empty. - // - DB (" settings setValue, " << paths.size() << "items"); - if (paths.empty()) settings.remove("sidePanelPaths"); - else settings.setValue("sidePanelPaths", paths); - settings.endGroup(); -} - -void -RvFileDialog::sidePanelInserted(const QModelIndex& parent, int first, int last) -{ - // - // For some reason, we can't get ahold of the side panel's new - // items in this function (eventhough it supposedly already - // finished inserting them). Perhaps Qt is trying to prevent us - // from accidently getting into an infinite loop. Anyway, its - // safer to edit the list in a new stack frame. - // - - m_sideInsertStart = first; - m_sideInsertEnd = last; - m_sidePanelTimer->start(); -} -void -RvFileDialog::sidePanelPopup(const QPoint& pos) -{ - m_sidePanelPopup->popup(m_ui.sidePanelList->mapToGlobal(pos)); -} + void RvFileDialog::sidePanelInserted(const QModelIndex& parent, int first, + int last) + { + // + // For some reason, we can't get ahold of the side panel's new + // items in this function (eventhough it supposedly already + // finished inserting them). Perhaps Qt is trying to prevent us + // from accidently getting into an infinite loop. Anyway, its + // safer to edit the list in a new stack frame. + // -void -RvFileDialog::sidePanelClick(QListWidgetItem* item) -{ - QString path = item->data(Qt::UserRole).toString(); - DB ("RvFileDialog::sidePanelClick path " << path.toUtf8().data()); - sidePanelGo(true); -} + m_sideInsertStart = first; + m_sideInsertEnd = last; + m_sidePanelTimer->start(); + } -void -RvFileDialog::sidePanelDoubleClick(QListWidgetItem* item) -{ - sidePanelGo(true); - m_sidePanelAccept = true; - accept(); -} + void RvFileDialog::sidePanelPopup(const QPoint& pos) + { + m_sidePanelPopup->popup(m_ui.sidePanelList->mapToGlobal(pos)); + } -void -RvFileDialog::sidePanelGo(bool) -{ - if (QListWidgetItem* item = m_ui.sidePanelList->currentItem()) + void RvFileDialog::sidePanelClick(QListWidgetItem* item) { QString path = item->data(Qt::UserRole).toString(); - QFileInfo info(path); - - setCurrentFile(path); + DB("RvFileDialog::sidePanelClick path " << path.toUtf8().data()); + sidePanelGo(true); } -} - -void -RvFileDialog::sidePanelAccept(bool) -{ - m_sidePanelAccept = true; - accept(); -} -void -RvFileDialog::sidePanelRemove(bool) -{ - QList selection = m_ui.sidePanelList->selectedItems(); - - for (int i=0; i< selection.size(); i++) + void RvFileDialog::sidePanelDoubleClick(QListWidgetItem* item) { - delete selection[i]; + sidePanelGo(true); + m_sidePanelAccept = true; + accept(); } - - saveSidePanel(); -} - -void -RvFileDialog::hiddenViewChanged(bool b) -{ - DB ("hiddenViewChanged() b " << b << " m_building " << m_building); - m_columnModel->setShowHiddenFiles(b); - m_detailFileModel->setShowHiddenFiles(b); - m_detailMediaModel->setShowHiddenFiles(b); - - ViewMode v = m_viewMode; - setViewMode(NoViewMode); - setViewMode(v); - QFileInfo currentInfo (m_ui.currentPath->text()); - setDirectory (currentInfo.absoluteDir().absolutePath(), true); -} - -void -RvFileDialog::iconViewChanged(QAction* action) -{ - FileTypeTraits::IconMode m; - - if (action == m_cpSystem) + void RvFileDialog::sidePanelGo(bool) { - m = FileTypeTraits::SystemIcons; + if (QListWidgetItem* item = m_ui.sidePanelList->currentItem()) + { + QString path = item->data(Qt::UserRole).toString(); + QFileInfo info(path); + + setCurrentFile(path); + } } - else if (action == m_cpGeneric) + + void RvFileDialog::sidePanelAccept(bool) { - m = FileTypeTraits::GenericIcons; + m_sidePanelAccept = true; + accept(); } - else if (action == m_cpNone) + + void RvFileDialog::sidePanelRemove(bool) { - m = FileTypeTraits::NoIcons; - } + QList selection = m_ui.sidePanelList->selectedItems(); - m_fileTraits->setIconMode(m); - m_columnModel->fileTraits()->setIconMode(m); - m_detailMediaModel->fileTraits()->setIconMode(m); - m_detailFileModel->fileTraits()->setIconMode(m); - m_iconMap.clear(); + for (int i = 0; i < selection.size(); i++) + { + delete selection[i]; + } - m_ui.sidePanelList->clear(); - loadSidePanel(); + saveSidePanel(); + } + void RvFileDialog::hiddenViewChanged(bool b) + { + DB("hiddenViewChanged() b " << b << " m_building " << m_building); + m_columnModel->setShowHiddenFiles(b); + m_detailFileModel->setShowHiddenFiles(b); + m_detailMediaModel->setShowHiddenFiles(b); - ViewMode v = m_viewMode; - setViewMode(NoViewMode); - setViewMode(v); - QFileInfo currentInfo (m_ui.currentPath->text()); - setDirectory (currentInfo.absoluteDir().absolutePath(), true); -} + ViewMode v = m_viewMode; + setViewMode(NoViewMode); + setViewMode(v); + QFileInfo currentInfo(m_ui.currentPath->text()); + setDirectory(currentInfo.absoluteDir().absolutePath(), true); + } -bool -RvFileDialog::event(QEvent* event) -{ - if (event->type() == QEvent::KeyPress) + void RvFileDialog::iconViewChanged(QAction* action) { - QKeyEvent *keyEvent = static_cast(event); + FileTypeTraits::IconMode m; - if (keyEvent->modifiers() == Qt::ControlModifier && - keyEvent->key() == Qt::Key_D) + if (action == m_cpSystem) { - // - // Go to ~/Desktop - // - - setDirectory(QDir::home().absoluteFilePath("Desktop")); - return true; + m = FileTypeTraits::SystemIcons; } - else if (keyEvent->modifiers() == (Qt::ControlModifier | Qt::ShiftModifier) && - keyEvent->key() == Qt::Key_H) + else if (action == m_cpGeneric) { - // - // Go to ~ - // - - setDirectory(QDir::home().path()); - return true; + m = FileTypeTraits::GenericIcons; + } + else if (action == m_cpNone) + { + m = FileTypeTraits::NoIcons; } - } - return QDialog::event(event); -} + m_fileTraits->setIconMode(m); + m_columnModel->fileTraits()->setIconMode(m); + m_detailMediaModel->fileTraits()->setIconMode(m); + m_detailFileModel->fileTraits()->setIconMode(m); + m_iconMap.clear(); -bool -RvFileDialog::eventFilter(QObject *object, QEvent *event) -{ - if (object == m_ui.sidePanelList) + m_ui.sidePanelList->clear(); + loadSidePanel(); + + ViewMode v = m_viewMode; + setViewMode(NoViewMode); + setViewMode(v); + QFileInfo currentInfo(m_ui.currentPath->text()); + setDirectory(currentInfo.absoluteDir().absolutePath(), true); + } + + bool RvFileDialog::event(QEvent* event) { - if (event->type() == QEvent::DragEnter) + if (event->type() == QEvent::KeyPress) { - QDropEvent* devent = static_cast(event); + QKeyEvent* keyEvent = static_cast(event); + + if (keyEvent->modifiers() == Qt::ControlModifier + && keyEvent->key() == Qt::Key_D) + { + // + // Go to ~/Desktop + // + + setDirectory(QDir::home().absoluteFilePath("Desktop")); + return true; + } + else if (keyEvent->modifiers() + == (Qt::ControlModifier | Qt::ShiftModifier) + && keyEvent->key() == Qt::Key_H) + { + // + // Go to ~ + // + + setDirectory(QDir::home().path()); + return true; + } } - - return false; + + return QDialog::event(event); } - else if (object == m_ui.currentPath) + + bool RvFileDialog::eventFilter(QObject* object, QEvent* event) { - if (event->type() == QEvent::KeyPress) + if (object == m_ui.sidePanelList) { - QKeyEvent *keyEvent = static_cast(event); - string utf8string = keyEvent->text().toUtf8().data(); - bool tab = keyEvent->key() == Qt::Key_Tab; + if (event->type() == QEvent::DragEnter) + { + QDropEvent* devent = static_cast(event); + } - if ((tab || utf8string == "/" || utf8string == "\\") && - m_ui.currentPath->selectionStart() != 0) + return false; + } + else if (object == m_ui.currentPath) + { + if (event->type() == QEvent::KeyPress) { - m_ui.currentPath->end(true); + QKeyEvent* keyEvent = static_cast(event); + string utf8string = keyEvent->text().toUtf8().data(); + bool tab = keyEvent->key() == Qt::Key_Tab; + + if ((tab || utf8string == "/" || utf8string == "\\") + && m_ui.currentPath->selectionStart() != 0) + { + m_ui.currentPath->end(true); #ifdef WIN32 - return false; + return false; #else - string p = varTildExp(m_ui.currentPath->text().toUtf8().data()); + string p = + varTildExp(m_ui.currentPath->text().toUtf8().data()); - if (utf8string == "/") - { - if (p.empty() || p[p.size()-1] != '/') p += "/"; - } + if (utf8string == "/") + { + if (p.empty() || p[p.size() - 1] != '/') + p += "/"; + } - DB ("eventFilter setting currentPath " << p); - m_ui.currentPath->setText(p.c_str()); - return true; + DB("eventFilter setting currentPath " << p); + m_ui.currentPath->setText(p.c_str()); + return true; #endif - } - else if (utf8string.size() == 1) - { - switch (utf8string[0]) + } + else if (utf8string.size() == 1) { - case 1 + ('a' - 'a'): // control-a - m_ui.currentPath->home(false); - return true; - case 1 + ('e' - 'a'): // control-e - m_ui.currentPath->end(false); - return true; - case 1 + ('k' - 'a'): // control-k - m_ui.currentPath->setText(""); - return true; - case 1 + ('w' - 'a'): // control-w - m_ui.currentPath->cut(); - return true; - case 1 + ('y' - 'a'): // control-y - m_ui.currentPath->paste(); - return true; + switch (utf8string[0]) + { + case 1 + ('a' - 'a'): // control-a + m_ui.currentPath->home(false); + return true; + case 1 + ('e' - 'a'): // control-e + m_ui.currentPath->end(false); + return true; + case 1 + ('k' - 'a'): // control-k + m_ui.currentPath->setText(""); + return true; + case 1 + ('w' - 'a'): // control-w + m_ui.currentPath->cut(); + return true; + case 1 + ('y' - 'a'): // control-y + m_ui.currentPath->paste(); + return true; + } } } + return m_ui.currentPath->eventFilter(object, event); } - return m_ui.currentPath->eventFilter(object, event); - } - - return false; -} - -QStringList -RvFileDialog::selectedFiles() const -{ - MediaDirModel* model = 0; - QAbstractItemView* view = 0; - switch (m_viewMode) - { - case DetailedFileView: - model = m_detailFileModel; - view = m_detailTree; - break; - case DetailedMediaView: - model = m_detailMediaModel; - view = m_detailTree; - break; - case ColumnView: - model = m_columnModel; - view = m_columnView; - break; - default: - break; + return false; } - QItemSelectionModel* selectionModel = view->selectionModel(); - QModelIndexList selection = selectionModel->selectedIndexes(); - - int reallyHowManySelected = 0; - for (int i = 0; i < selection.size(); i++) + QStringList RvFileDialog::selectedFiles() const { - const QModelIndex& index = selection[i]; - - if (index.isValid() && index.column() == 0) ++reallyHowManySelected; - } - DB ("RvFileDialog::selectedFiles() selection size " << selection.size() << - " really " << reallyHowManySelected); - - QStringList files; - // - // We want to allow a "partial selection specification" like - // "blah.1-3#.exr" that does not appear in the list, and hence - // cannot be selected. In this case the full selection spec - // will be in the list but may or may not be selected. - // - // In all other cases when there is only one element in the - // selection, it should be the same as the text in currentPath. - // + MediaDirModel* model = 0; + QAbstractItemView* view = 0; - if (reallyHowManySelected < 2) - { - // windows weirdness fix - if (m_ui.currentPath) + switch (m_viewMode) { - QString text = m_ui.currentPath->text(); - files.push_back (text); + case DetailedFileView: + model = m_detailFileModel; + view = m_detailTree; + break; + case DetailedMediaView: + model = m_detailMediaModel; + view = m_detailTree; + break; + case ColumnView: + model = m_columnModel; + view = m_columnView; + break; + default: + break; } - } - else - { - for (int i=0; i < selection.size(); i++) + + QItemSelectionModel* selectionModel = view->selectionModel(); + QModelIndexList selection = selectionModel->selectedIndexes(); + + int reallyHowManySelected = 0; + for (int i = 0; i < selection.size(); i++) { const QModelIndex& index = selection[i]; - + if (index.isValid() && index.column() == 0) - { - QString file = model->absoluteFilePath(index); - files.push_back(file); - DB (" file " << file.toUtf8().data()); - } + ++reallyHowManySelected; } - } - return files; -} + DB("RvFileDialog::selectedFiles() selection size " + << selection.size() << " really " << reallyHowManySelected); + QStringList files; + // + // We want to allow a "partial selection specification" like + // "blah.1-3#.exr" that does not appear in the list, and hence + // cannot be selected. In this case the full selection spec + // will be in the list but may or may not be selected. + // + // In all other cases when there is only one element in the + // selection, it should be the same as the text in currentPath. + // -QListWidgetItem* -RvFileDialog::newItemForFile(const QFileInfo& info) -{ - DB ("newItemForFile()"); - QString n = info.fileName(); - QString aPath; - DB (" fileName '" << n.toUtf8().data() << "'"); + if (reallyHowManySelected < 2) + { + // windows weirdness fix + if (m_ui.currentPath) + { + QString text = m_ui.currentPath->text(); + files.push_back(text); + } + } + else + { + for (int i = 0; i < selection.size(); i++) + { + const QModelIndex& index = selection[i]; - aPath = info.absoluteFilePath(); - if (n.isEmpty()) - { - n = aPath; - #ifdef PLATFORM_WINDOWS - if (n.endsWith("/")) n.chop(1); - #endif + if (index.isValid() && index.column() == 0) + { + QString file = model->absoluteFilePath(index); + files.push_back(file); + DB(" file " << file.toUtf8().data()); + } + } + } + return files; } - DB (" aPath " << aPath.toUtf8().data()); + QListWidgetItem* RvFileDialog::newItemForFile(const QFileInfo& info) + { + DB("newItemForFile()"); + QString n = info.fileName(); + QString aPath; + DB(" fileName '" << n.toUtf8().data() << "'"); - DB (" finding icon (icon size" << sizeof(QIcon) << ")"); - QIcon icon = iconForFile(info); - DB (" making QListWidgetItem"); - QListWidgetItem* item = new QListWidgetItem (icon, n); - DB (" calling item->setData()"); - item->setData(Qt::UserRole, QVariant(aPath)); - DB ("newItemForFile() done"); - return item; -} - -QIcon -RvFileDialog::iconForFile(const QFileInfo& ininfo) -{ - DBL (DB_ICON, "iconForFile()"); - QFileInfo info = ininfo; - QString file = info.absoluteFilePath(); - DBL (DB_ICON, " abs name " << file.toUtf8().data()); + aPath = info.absoluteFilePath(); + if (n.isEmpty()) + { + n = aPath; +#ifdef PLATFORM_WINDOWS + if (n.endsWith("/")) + n.chop(1); +#endif + } + DB(" aPath " << aPath.toUtf8().data()); - if (m_iconMap.contains(file)) - { - DBL (DB_ICON, " found icon in map"); - return m_iconMap[file]; + DB(" finding icon (icon size" << sizeof(QIcon) << ")"); + QIcon icon = iconForFile(info); + DB(" making QListWidgetItem"); + QListWidgetItem* item = new QListWidgetItem(icon, n); + DB(" calling item->setData()"); + item->setData(Qt::UserRole, QVariant(aPath)); + DB("newItemForFile() done"); + return item; } - else + + QIcon RvFileDialog::iconForFile(const QFileInfo& ininfo) { - QIcon icon; + DBL(DB_ICON, "iconForFile()"); + QFileInfo info = ininfo; + QString file = info.absoluteFilePath(); + DBL(DB_ICON, " abs name " << file.toUtf8().data()); - // - // First check to see if we already know it's a "Drive". - // - if (m_drives.contains (file)) + if (m_iconMap.contains(file)) { - icon = m_fileTraits->fileInfoIcon (info, QFileIconProvider::Drive); + DBL(DB_ICON, " found icon in map"); + return m_iconMap[file]; } - #ifdef PLATFORM_WINDOWS - // - // Windows special case. We don't want to stat network - // drives unless we really have to, so if it starts with - // "//" let's just say it's a network path and move on. - // - // Maybe we could check for "/Network" on mac ... - // - else if (file.startsWith("//")) - { - DBL (DB_ICON, " calling m_fileTraits->fileInfoIcon() 1"); - icon = m_fileTraits->fileInfoIcon (info, QFileIconProvider::Network); - } - #endif - else + else { - DBL (DB_ICON, " calling exists()"); - if (!info.exists()) + QIcon icon; + + // + // First check to see if we already know it's a "Drive". + // + if (m_drives.contains(file)) + { + icon = + m_fileTraits->fileInfoIcon(info, QFileIconProvider::Drive); + } +#ifdef PLATFORM_WINDOWS + // + // Windows special case. We don't want to stat network + // drives unless we really have to, so if it starts with + // "//" let's just say it's a network path and move on. + // + // Maybe we could check for "/Network" on mac ... + // + else if (file.startsWith("//")) { - DBL (DB_ICON, " checking non-existant file"); - QString name = firstFileInPattern(file.toUtf8().data()).c_str(); - info = QFileInfo(info.absoluteDir().absoluteFilePath(name)); + DBL(DB_ICON, " calling m_fileTraits->fileInfoIcon() 1"); + icon = m_fileTraits->fileInfoIcon(info, + QFileIconProvider::Network); + } +#endif + else + { + DBL(DB_ICON, " calling exists()"); + if (!info.exists()) + { + DBL(DB_ICON, " checking non-existant file"); + QString name = + firstFileInPattern(file.toUtf8().data()).c_str(); + info = QFileInfo(info.absoluteDir().absoluteFilePath(name)); + } + DBL(DB_ICON, " calling m_fileTraits->fileInfoIcon() 2"); + icon = m_fileTraits->fileInfoIcon(info); } - DBL (DB_ICON, " calling m_fileTraits->fileInfoIcon() 2"); - icon = m_fileTraits->fileInfoIcon(info); + m_iconMap[file] = icon; + return icon; } - m_iconMap[file] = icon; - return icon; } -} -void -RvFileDialog::resizeColumns(const QModelIndex&) -{ - for (int i=0; i < 8; i++) m_detailTree->resizeColumnToContents(i); -} - -void -RvFileDialog::doubleClickAccept(const QModelIndex& index) -{ - if (!index.isValid()) return; - - if (const MediaDirModel* model = dynamic_cast(index.model())) + void RvFileDialog::resizeColumns(const QModelIndex&) { - if (model->flags(index) == Qt::NoItemFlags) return; + for (int i = 0; i < 8; i++) + m_detailTree->resizeColumnToContents(i); + } - MediaDirModel* m = const_cast(model); - QString path = model->absoluteFilePath(index); - QFileInfo info(path); + void RvFileDialog::doubleClickAccept(const QModelIndex& index) + { + if (!index.isValid()) + return; - if (info.isDir()) + if (const MediaDirModel* model = + dynamic_cast(index.model())) { - if (model == m_detailMediaModel || model == m_detailFileModel) + if (model->flags(index) == Qt::NoItemFlags) + return; + + MediaDirModel* m = const_cast(model); + QString path = model->absoluteFilePath(index); + QFileInfo info(path); + + if (info.isDir()) { - setDirectory(path); + if (model == m_detailMediaModel || model == m_detailFileModel) + { + setDirectory(path); + } + else + { + // nothing + } } - else + else { - // nothing + accept(); } } - else + } + + void RvFileDialog::prevButtonTrigger(QAction*) + { + if (m_dirPrev.size() > 1) { - accept(); + m_dirNext.push_back(m_dirPrev.back()); + m_dirPrev.pop_back(); + QString d = m_dirPrev.back(); + m_dirPrev.pop_back(); + setDirectory(d); // m_dirPrev will have d pushed onto it } } -} -void -RvFileDialog::prevButtonTrigger(QAction*) -{ - if (m_dirPrev.size() > 1) + void RvFileDialog::nextButtonTrigger(QAction*) { - m_dirNext.push_back(m_dirPrev.back()); - m_dirPrev.pop_back(); - QString d = m_dirPrev.back(); - m_dirPrev.pop_back(); - setDirectory(d); // m_dirPrev will have d pushed onto it + if (m_dirNext.size() > 0) + { + QString d = m_dirNext.back(); + m_dirNext.pop_back(); + setDirectory(d); + } } -} -void -RvFileDialog::nextButtonTrigger(QAction*) -{ - if (m_dirNext.size() > 0) + void RvFileDialog::sortComboChanged(int index) { - QString d = m_dirNext.back(); - m_dirNext.pop_back(); - setDirectory(d); - } -} + QDir::SortFlags f = 0; -void -RvFileDialog::sortComboChanged(int index) -{ - QDir::SortFlags f = 0; + switch (index) + { + case 0: + f = QDir::Name; + break; + case 1: + f = QDir::Time; + break; + case 2: + f = QDir::Size; + break; + case 3: + f = QDir::Type; + break; + } - switch (index) - { - case 0: f = QDir::Name; break; - case 1: f = QDir::Time; break; - case 2: f = QDir::Size; break; - case 3: f = QDir::Type; break; - } + if (m_viewMode == ColumnView) + { + m_columnModel->setSortFlags(f); + QFileInfo info(m_ui.currentPath->text()); + QModelIndex i = m_columnModel->indexOfPath(info); + if (i.isValid() && !m_columnViewTimer->isActive()) + m_columnView->setCurrentIndex(i); + } + else if (m_viewMode == DetailedMediaView) + { + m_detailMediaModel->setSortFlags(f); + } + else if (m_viewMode == DetailedFileView) + { + m_detailFileModel->setSortFlags(f); + } - if (m_viewMode == ColumnView) - { - m_columnModel->setSortFlags(f); - QFileInfo info(m_ui.currentPath->text()); - QModelIndex i = m_columnModel->indexOfPath(info); - if (i.isValid() && !m_columnViewTimer->isActive()) m_columnView->setCurrentIndex(i); - } - else if (m_viewMode == DetailedMediaView) - { - m_detailMediaModel->setSortFlags(f); - } - else if (m_viewMode == DetailedFileView) - { - m_detailFileModel->setSortFlags(f); + RV_QSETTINGS; + settings.beginGroup(m_settingsGroup); + settings.setValue("sortMethod", index); + settings.endGroup(); } - RV_QSETTINGS; - settings.beginGroup(m_settingsGroup); - settings.setValue("sortMethod", index); - settings.endGroup(); -} - -void -RvFileDialog::viewComboChanged(int index) -{ - DB ("viewComboChanged() index " << index); - switch (index) + void RvFileDialog::viewComboChanged(int index) { - case 0: - if (m_viewMode != ColumnView) + DB("viewComboChanged() index " << index); + switch (index) { - DB (" switching to ColumnView"); - m_viewMode = ColumnView; - m_ui.viewStack->setCurrentIndex(0); - m_columnModel->setDirectory(QDir::root(), MediaDirModel::NoDetails); + case 0: + if (m_viewMode != ColumnView) + { + DB(" switching to ColumnView"); + m_viewMode = ColumnView; + m_ui.viewStack->setCurrentIndex(0); + m_columnModel->setDirectory(QDir::root(), + MediaDirModel::NoDetails); + + if (!m_dirPrev.empty()) + setDirectory(m_dirPrev.back(), true); + else + setDirectory("", true); + + /* + QFileInfo info(m_ui.currentPath->text()); + QModelIndex i = + m_columnModel->indexOfPath(info.absoluteFilePath()); + // + // This is a hack to get around a Qt bug in the column view + (or + // maybe its the scrolled area). The column view will get + // scrolled too far by setCurrentIndex() if its called before + // the dialog box is fully formed. + // + if (i != m_columnView->currentIndex()) + { + if (m_columnViewTimer->isActive()) + { + m_columnViewFile = m_ui.currentPath->text(); + } + else if (i.isValid()) + { + m_columnView->setCurrentIndex(i); + } + } + */ + } + break; - if (!m_dirPrev.empty()) setDirectory (m_dirPrev.back(), true); - else setDirectory ("", true); + case 1: + if (m_viewMode != DetailedFileView) + { + m_viewMode = DetailedFileView; + m_ui.viewStack->setCurrentIndex(1); + m_detailTree->setModel(m_detailFileModel); + connect(m_detailTree->selectionModel(), + SIGNAL(selectionChanged(const QItemSelection&, + const QItemSelection&)), + this, + SLOT(treeSelectionChanged(const QItemSelection&, + const QItemSelection&))); + if (!m_dirPrev.empty()) + setDirectory(m_dirPrev.back(), true); + else + setDirectory("", true); + sortComboChanged(m_ui.sortCombo->currentIndex()); + } + break; - /* - QFileInfo info(m_ui.currentPath->text()); - QModelIndex i = m_columnModel->indexOfPath(info.absoluteFilePath()); - // - // This is a hack to get around a Qt bug in the column view (or - // maybe its the scrolled area). The column view will get - // scrolled too far by setCurrentIndex() if its called before - // the dialog box is fully formed. - // - if (i != m_columnView->currentIndex()) - { - if (m_columnViewTimer->isActive()) - { - m_columnViewFile = m_ui.currentPath->text(); - } - else if (i.isValid()) - { - m_columnView->setCurrentIndex(i); - } + case 2: + if (m_viewMode != DetailedMediaView) + { + m_viewMode = DetailedMediaView; + m_ui.viewStack->setCurrentIndex(1); + m_detailTree->setModel(m_detailMediaModel); + connect(m_detailTree->selectionModel(), + SIGNAL(selectionChanged(const QItemSelection&, + const QItemSelection&)), + this, + SLOT(treeSelectionChanged(const QItemSelection&, + const QItemSelection&))); + if (!m_dirPrev.empty()) + setDirectory(m_dirPrev.back(), true); + else + setDirectory("", true); + sortComboChanged(m_ui.sortCombo->currentIndex()); } - */ + break; } - break; + DB("viewComboChanged() done"); + } - case 1: - if (m_viewMode != DetailedFileView) + void RvFileDialog::columnUpdatePreview(const QModelIndex& index) + { + DB("columnUpdatePreview()"); + QString file = m_columnModel->absoluteFilePath(index); + m_columnPreview->clear(); + QStringList attrs = m_fileTraits->fileAttributes(file); + + DB(" traits has image: " << m_fileTraits->hasImage(file)); + if (m_fileTraits->hasImage(file)) { - m_viewMode = DetailedFileView; - m_ui.viewStack->setCurrentIndex(1); - m_detailTree->setModel(m_detailFileModel); - connect(m_detailTree->selectionModel(), - SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)), - this, - SLOT(treeSelectionChanged(const QItemSelection&, const QItemSelection&))); - if (!m_dirPrev.empty()) setDirectory (m_dirPrev.back(), true); - else setDirectory ("", true); - sortComboChanged(m_ui.sortCombo->currentIndex()); + QImage image = m_fileTraits->fileImage(file); + m_columnPreview->document()->addResource( + QTextDocument::ImageResource, QUrl("icon://file.raw"), image); } - break; + else + { + QPixmap pixmap = + m_fileTraits->fileIcon(file).pixmap(QSize(128, 128)); + m_columnPreview->document()->addResource( + QTextDocument::ImageResource, QUrl("icon://file.raw"), pixmap); + } + + ostringstream str; + str << "" + << "
" + << "
" << QFileInfo(file).fileName().toUtf8().data() + << "
" + << ""; - case 2: - if (m_viewMode != DetailedMediaView) + DB(" attrs size: " << attrs.size()); + for (size_t i = 0; i < attrs.size(); i += 2) { - m_viewMode = DetailedMediaView; - m_ui.viewStack->setCurrentIndex(1); - m_detailTree->setModel(m_detailMediaModel); - connect(m_detailTree->selectionModel(), - SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)), - this, - SLOT(treeSelectionChanged(const QItemSelection&, const QItemSelection&))); - if (!m_dirPrev.empty()) setDirectory (m_dirPrev.back(), true); - else setDirectory ("", true); - sortComboChanged(m_ui.sortCombo->currentIndex()); + str << "" + << "" + << "" + << "" + << ""; } - break; - } - DB ("viewComboChanged() done"); -} -void -RvFileDialog::columnUpdatePreview(const QModelIndex& index) -{ - DB ("columnUpdatePreview()"); - QString file = m_columnModel->absoluteFilePath(index); - m_columnPreview->clear(); - QStringList attrs = m_fileTraits->fileAttributes(file); + str << "
" << attrs[i].toUtf8().data() + << "" << attrs[i + 1].toUtf8().data() << "
" + << "
" + << ""; - DB (" traits has image: " << m_fileTraits->hasImage(file)); - if (m_fileTraits->hasImage(file)) - { - QImage image = m_fileTraits->fileImage(file); - m_columnPreview->document()->addResource(QTextDocument::ImageResource, - QUrl("icon://file.raw"), - image); + m_columnPreview->setHtml(str.str().c_str()); } - else + + void RvFileDialog::lockViewMode(bool lock) { - QPixmap pixmap = m_fileTraits->fileIcon(file).pixmap(QSize(128,128)); - m_columnPreview->document()->addResource(QTextDocument::ImageResource, - QUrl("icon://file.raw"), - pixmap); + if (lock) + m_ui.viewCombo->hide(); + else + m_ui.viewCombo->show(); } - ostringstream str; - str << "" - << "
" - << "
" << QFileInfo(file).fileName().toUtf8().data() << "
" - << ""; - - DB (" attrs size: " << attrs.size()); - for (size_t i=0; i < attrs.size(); i+= 2) + void RvFileDialog::fileTypeChanged(int index) { - str << "" - << "" - << "" - << "" - << ""; + m_detailFileModel->setFileTraitsIndex(index); + m_detailMediaModel->setFileTraitsIndex(index); + m_columnModel->setFileTraitsIndex(index); } - str << "
" << attrs[i].toUtf8().data() << "" << attrs[i+1].toUtf8().data() << "
" - << "
" - << ""; - - m_columnPreview->setHtml(str.str().c_str()); -} - -void -RvFileDialog::lockViewMode(bool lock) -{ - if (lock) m_ui.viewCombo->hide(); - else m_ui.viewCombo->show(); -} - -void -RvFileDialog::fileTypeChanged(int index) -{ - m_detailFileModel->setFileTraitsIndex(index); - m_detailMediaModel->setFileTraitsIndex(index); - m_columnModel->setFileTraitsIndex(index); -} - -void -RvFileDialog::centerOverApp() -{ - if (QWidget* app = QApplication::activeWindow()) + void RvFileDialog::centerOverApp() { - QRect appGeom = app->geometry(); - int appX = appGeom.left() + int(appGeom.width()/2); - int appY = appGeom.top() + int(appGeom.height()/2); - - int x = appX - int(width()/2); - int y = appY - int(height()/2); - DB ("appX: " << appX << " appY: " << appY << " x: " << x << " y: " << y); - move (x, y); + if (QWidget* app = QApplication::activeWindow()) + { + QRect appGeom = app->geometry(); + int appX = appGeom.left() + int(appGeom.width() / 2); + int appY = appGeom.top() + int(appGeom.height() / 2); + + int x = appX - int(width() / 2); + int y = appY - int(height() / 2); + DB("appX: " << appX << " appY: " << appY << " x: " << x + << " y: " << y); + move(x, y); + } } -} -} // Rv - +} // namespace Rv diff --git a/src/lib/app/RvCommon/RvJavaScriptObject.cpp b/src/lib/app/RvCommon/RvJavaScriptObject.cpp index d4bd50374..01b3a4d9b 100644 --- a/src/lib/app/RvCommon/RvJavaScriptObject.cpp +++ b/src/lib/app/RvCommon/RvJavaScriptObject.cpp @@ -1,9 +1,9 @@ // -// Copyright (c) 2009 Tweak Software. +// Copyright (c) 2009 Tweak Software. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// // #include #include @@ -14,205 +14,214 @@ #include #include -namespace Rv { -using namespace std; -using namespace TwkApp; -using namespace TwkQtCoreUtil; - -RvJavaScriptObject::RvJavaScriptObject(RvDocument* doc, QWebEnginePage* page) - : QObject(doc), - EventNode("jsobject"), - m_frame(page), - m_doc(doc) +namespace Rv { - QFile webChannelJsFile(":/qtwebchannel/qwebchannel.js"); - - if(!webChannelJsFile.open(QIODevice::ReadOnly) ) + using namespace std; + using namespace TwkApp; + using namespace TwkQtCoreUtil; + + RvJavaScriptObject::RvJavaScriptObject(RvDocument* doc, + QWebEnginePage* page) + : QObject(doc) + , EventNode("jsobject") + , m_frame(page) + , m_doc(doc) { - QString msg = QString("Couldn't open qwebchannel.js file: %1").arg(webChannelJsFile.errorString()); - string err = msg.toStdString(); - cout << "ERROR: " << err << endl; - TWK_THROW_EXC_STREAM(err); + QFile webChannelJsFile(":/qtwebchannel/qwebchannel.js"); + + if (!webChannelJsFile.open(QIODevice::ReadOnly)) + { + QString msg = QString("Couldn't open qwebchannel.js file: %1") + .arg(webChannelJsFile.errorString()); + string err = msg.toStdString(); + cout << "ERROR: " << err << endl; + TWK_THROW_EXC_STREAM(err); + } + else + { + QByteArray webChannelJs = webChannelJsFile.readAll(); + webChannelJs.append( + "\nnew QWebChannel(window.qt.webChannelTransport, " + "function(channel) {window.rvsession = " + "channel.objects.rvsession;});"); + QWebEngineScript script; + script.setSourceCode(webChannelJs); + script.setName("qwebchannel.js"); + script.setWorldId(QWebEngineScript::MainWorld); + script.setInjectionPoint(QWebEngineScript::DocumentCreation); + script.setRunsOnSubFrames(false); + m_frame->scripts().insert(script); + } + + if (m_frame->webChannel()) + { + m_channel = m_frame->webChannel(); + } + else + { + m_channel = new QWebChannel(m_frame); + } + + m_channel->registerObject(QStringLiteral("rvsession"), this); + m_frame->setWebChannel(m_channel); + connect(m_frame, SIGNAL(loadFinished(bool)), this, SLOT(emitReady())); + + listenTo(m_doc->session()); } - else + + RvJavaScriptObject::~RvJavaScriptObject() {} + + void RvJavaScriptObject::emitReady() { - QByteArray webChannelJs = webChannelJsFile.readAll(); - webChannelJs.append("\nnew QWebChannel(window.qt.webChannelTransport, function(channel) {window.rvsession = channel.objects.rvsession;});"); - QWebEngineScript script; - script.setSourceCode(webChannelJs); - script.setName("qwebchannel.js"); - script.setWorldId(QWebEngineScript::MainWorld); - script.setInjectionPoint(QWebEngineScript::DocumentCreation); - script.setRunsOnSubFrames(false); - m_frame->scripts().insert(script); + m_frame->runJavaScript( + "var event = new CustomEvent(\"rvsession-ready\",{}); " + "document.dispatchEvent(event);"); } - if (m_frame->webChannel()) + QString RvJavaScriptObject::evaluate(const QString& code) { - m_channel = m_frame->webChannel(); + string rval = m_doc->session()->userGenericEvent( + "remote-eval", UTF8::qconvert(code), + UTF8::qconvert(m_frame->url().toString())); + return UTF8::qconvert(rval.c_str()); } - else + + QString RvJavaScriptObject::pyevaluate(const QString& code) { - m_channel = new QWebChannel(m_frame); + string rval = m_doc->session()->userGenericEvent( + "remote-pyeval", UTF8::qconvert(code), + UTF8::qconvert(m_frame->url().toString())); + return UTF8::qconvert(rval.c_str()); } - m_channel->registerObject(QStringLiteral("rvsession"), this); - m_frame->setWebChannel(m_channel); - connect(m_frame, SIGNAL(loadFinished(bool)), this, SLOT(emitReady())); - - listenTo(m_doc->session()); -} - -RvJavaScriptObject::~RvJavaScriptObject() {} - -void -RvJavaScriptObject::emitReady() -{ - m_frame->runJavaScript("var event = new CustomEvent(\"rvsession-ready\",{}); document.dispatchEvent(event);"); -} - -QString -RvJavaScriptObject::evaluate(const QString& code) -{ - string rval = - m_doc->session()->userGenericEvent("remote-eval", - UTF8::qconvert(code), - UTF8::qconvert(m_frame->url().toString())); - return UTF8::qconvert(rval.c_str()); -} - -QString -RvJavaScriptObject::pyevaluate(const QString& code) -{ - string rval = - m_doc->session()->userGenericEvent("remote-pyeval", - UTF8::qconvert(code), - UTF8::qconvert(m_frame->url().toString())); - return UTF8::qconvert(rval.c_str()); -} - -void -RvJavaScriptObject::pyexec(const QString& code) -{ - (void) m_doc->session()->userGenericEvent("remote-pyexec", - UTF8::qconvert(code), - UTF8::qconvert(m_frame->url().toString())); -} - -QString -RvJavaScriptObject::sendInternalEvent(const QString& eventName, - const QString& contents, - const QString& sender) -{ - QString s = (sender == "") ? m_frame->url().toString() : sender; + void RvJavaScriptObject::pyexec(const QString& code) + { + (void)m_doc->session()->userGenericEvent( + "remote-pyexec", UTF8::qconvert(code), + UTF8::qconvert(m_frame->url().toString())); + } - string rval = - m_doc->session()->userGenericEvent(UTF8::qconvert(eventName), - UTF8::qconvert(contents), - UTF8::qconvert(s)); - return UTF8::qconvert(rval.c_str()); -} + QString RvJavaScriptObject::sendInternalEvent(const QString& eventName, + const QString& contents, + const QString& sender) + { + QString s = (sender == "") ? m_frame->url().toString() : sender; -void -RvJavaScriptObject::bindToRegex(const QString& name) -{ - QRegExp re(name); - if (!m_eventNames.contains(re)) m_eventNames.push_back(re); -} + string rval = m_doc->session()->userGenericEvent( + UTF8::qconvert(eventName), UTF8::qconvert(contents), + UTF8::qconvert(s)); + return UTF8::qconvert(rval.c_str()); + } -void -RvJavaScriptObject::unbindRegex(const QString& name) -{ - m_eventNames.removeOne(QRegExp(name)); -} + void RvJavaScriptObject::bindToRegex(const QString& name) + { + QRegExp re(name); + if (!m_eventNames.contains(re)) + m_eventNames.push_back(re); + } -bool -RvJavaScriptObject::hasBinding(const QString& name) -{ - return m_eventNames.contains(QRegExp(name)); -} + void RvJavaScriptObject::unbindRegex(const QString& name) + { + m_eventNames.removeOne(QRegExp(name)); + } -EventNode::Result -RvJavaScriptObject::receiveEvent(const TwkApp::Event& event) -{ - QString name = event.name().c_str(); + bool RvJavaScriptObject::hasBinding(const QString& name) + { + return m_eventNames.contains(QRegExp(name)); + } - for (size_t i = 0; i < m_eventNames.size(); i++) + EventNode::Result + RvJavaScriptObject::receiveEvent(const TwkApp::Event& event) { - if (m_eventNames[i].indexIn(name) != -1) + QString name = event.name().c_str(); + + for (size_t i = 0; i < m_eventNames.size(); i++) { - if (const GenericStringEvent* ge = - dynamic_cast(&event)) - { - emit eventString(ge->name().c_str(), - ge->stringContent().c_str(), - ge->senderName().c_str()); - } - else if (const KeyEvent* ke = - dynamic_cast(&event)) - { - emit eventKey(ke->name().c_str(), - ke->key(), - ke->modifiers()); - } - else if (const PointerEvent* pe = - dynamic_cast(&event)) + if (m_eventNames[i].indexIn(name) != -1) { - float atime = 0.0; - - if (const PointerButtonPressEvent* bp = - dynamic_cast(pe)) + if (const GenericStringEvent* ge = + dynamic_cast(&event)) { - atime = bp->activationTime(); + emit eventString(ge->name().c_str(), + ge->stringContent().c_str(), + ge->senderName().c_str()); } - - if (const DragDropEvent* dd = - dynamic_cast(pe)) + else if (const KeyEvent* ke = + dynamic_cast(&event)) + { + emit eventKey(ke->name().c_str(), ke->key(), + ke->modifiers()); + } + else if (const PointerEvent* pe = + dynamic_cast(&event)) { - QString t, ct; + float atime = 0.0; - switch (dd->type()) + if (const PointerButtonPressEvent* bp = + dynamic_cast(pe)) { - case DragDropEvent::Enter: t = "enter"; break; - case DragDropEvent::Leave: t = "leave"; break; - case DragDropEvent::Move: t = "move"; break; - case DragDropEvent::Release: t = "release"; break; + atime = bp->activationTime(); } - switch (dd->contentType()) + if (const DragDropEvent* dd = + dynamic_cast(pe)) { - case DragDropEvent::File: ct = "file"; break; - case DragDropEvent::URL: ct = "url"; break; - case DragDropEvent::Text: ct = "text"; break; + QString t, ct; + + switch (dd->type()) + { + case DragDropEvent::Enter: + t = "enter"; + break; + case DragDropEvent::Leave: + t = "leave"; + break; + case DragDropEvent::Move: + t = "move"; + break; + case DragDropEvent::Release: + t = "release"; + break; + } + + switch (dd->contentType()) + { + case DragDropEvent::File: + ct = "file"; + break; + case DragDropEvent::URL: + ct = "url"; + break; + case DragDropEvent::Text: + ct = "text"; + break; + } + + emit eventDragDrop(pe->name().c_str(), pe->x(), pe->y(), + pe->w(), pe->h(), pe->startX(), + pe->startY(), + (int)pe->buttonStates(), t, ct, + dd->stringContent().c_str()); + } + else + { + emit eventPointer(pe->name().c_str(), pe->x(), pe->y(), + pe->w(), pe->h(), pe->startX(), + pe->startY(), pe->buttonStates(), + atime); } - - emit eventDragDrop(pe->name().c_str(), - pe->x(), pe->y(), pe->w(), pe->h(), - pe->startX(), pe->startY(), - (int)pe->buttonStates(), - t, ct, dd->stringContent().c_str()); - } - else - { - emit eventPointer(pe->name().c_str(), - pe->x(), pe->y(), pe->w(), pe->h(), - pe->startX(), pe->startY(), - pe->buttonStates(), - atime); } - } - break; + break; + } } - } - - // - // Don't EventNode::Accept here -- if you do then other webkit - // panes won't get the event. - // - return EventNode::EventIgnored; -} + // + // Don't EventNode::Accept here -- if you do then other webkit + // panes won't get the event. + // + return EventNode::EventIgnored; + } -} // Rv +} // namespace Rv diff --git a/src/lib/app/RvCommon/RvNetworkDialog.cpp b/src/lib/app/RvCommon/RvNetworkDialog.cpp index fdd7c6c05..b6153330d 100644 --- a/src/lib/app/RvCommon/RvNetworkDialog.cpp +++ b/src/lib/app/RvCommon/RvNetworkDialog.cpp @@ -1,13 +1,10 @@ // -// Copyright (c) 2008 Tweak Software. +// Copyright (c) 2008 Tweak Software. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// // - - - +// #include #include @@ -23,1268 +20,1303 @@ #include #include #ifdef PLATFORM_WINDOWS - #include +#include #endif #if 0 -#define DB_ICON 0x01 -#define DB_ALL 0xff +#define DB_ICON 0x01 +#define DB_ALL 0xff // #define DB_LEVEL (DB_ALL & (~ DB_ICON)) -#define DB_LEVEL DB_ALL +#define DB_LEVEL DB_ALL #ifdef PLATFORM_WINDOWS - #define GPID _getpid +#define GPID _getpid #else - #define GPID getpid +#define GPID getpid #endif -#define DB(x) cerr << "NetworkDialog " << GPID() << ": " << x << endl -#define DBL(level, x) if (level & DB_LEVEL) cerr << "NetworkDialog " GPID() << ": " << x << endl +#define DB(x) cerr << "NetworkDialog " << GPID() << ": " << x << endl +#define DBL(level, x) \ + if (level & DB_LEVEL) \ + cerr << "NetworkDialog " GPID() << ": " << x << endl #else #define DB(x) #define DBL(level, x) #endif -namespace Rv { -using namespace IPCore; -using namespace std; -using namespace TwkQtChat; -using namespace TwkQtCoreUtil; - -RvNetworkDialog::RvNetworkDialog(QWidget* parent) - : QWidget(parent), - m_client(0), - m_contactsModel(0), - m_connectDialog(this) -{ - DB(""); - setWindowFlags(Qt::Window); - setWindowModality(Qt::NonModal); - setWindowIcon(QIcon(qApp->applicationDirPath() + QString(RV_ICON_PATH_SUFFIX))); - m_ui.setupUi(this); - - m_connectUI.setupUi(&m_connectDialog); - m_connectUI.buttonBox->button(QDialogButtonBox::Ok)->setText("Connect"); - - m_contactPopup = new QMenu("Selection", 0); - QAction* mtitle = m_contactPopup->addAction(""); - QAction* msep = m_contactPopup->addSeparator(); - QAction* mconnect = m_contactPopup->addAction("Connect..."); - QAction* mdisconnect = m_contactPopup->addAction("Disconnect..."); - QAction* mdelete = m_contactPopup->addAction("Delete"); - - m_ui.statusLabel->setText("Not Running"); - m_contactsModel = new QStandardItemModel(); - m_ui.contactTreeView->setModel(m_contactsModel); - m_ui.contactTreeView->setItemDelegate(new PermDelegate()); - - connect(m_ui.startButton, SIGNAL(clicked()), this, SLOT(toggleServer())); - connect(m_ui.connectButton, SIGNAL(clicked()), this, SLOT(startConnect())); - connect(mconnect, SIGNAL(triggered(bool)), this, SLOT(popupConnect(bool))); - connect(mdisconnect, SIGNAL(triggered(bool)), this, SLOT(popupDisconnect(bool))); - connect(mdelete, SIGNAL(triggered(bool)), this, SLOT(popupDelete(bool))); - connect(m_ui.resetConfigButton, SIGNAL(clicked()), this, SLOT(resetConfig())); - - connect(m_ui.contactTreeView, - SIGNAL(customContextMenuRequested(const QPoint&)), - this, SLOT(popup(const QPoint&))); - - connect(m_ui.contactTreeView, SIGNAL(doubleClicked(const QModelIndex&)), - this, SLOT(doubleClickContact(const QModelIndex&))); - - - loadSettings(); -} - -RvNetworkDialog::~RvNetworkDialog() +namespace Rv { - DB ("RvNetworkDialog::~RvNetworkDialog"); - if (m_client) toggleServer(); -} + using namespace IPCore; + using namespace std; + using namespace TwkQtChat; + using namespace TwkQtCoreUtil; + + RvNetworkDialog::RvNetworkDialog(QWidget* parent) + : QWidget(parent) + , m_client(0) + , m_contactsModel(0) + , m_connectDialog(this) + { + DB(""); + setWindowFlags(Qt::Window); + setWindowModality(Qt::NonModal); + setWindowIcon( + QIcon(qApp->applicationDirPath() + QString(RV_ICON_PATH_SUFFIX))); + m_ui.setupUi(this); + + m_connectUI.setupUi(&m_connectDialog); + m_connectUI.buttonBox->button(QDialogButtonBox::Ok)->setText("Connect"); + + m_contactPopup = new QMenu("Selection", 0); + QAction* mtitle = m_contactPopup->addAction(""); + QAction* msep = m_contactPopup->addSeparator(); + QAction* mconnect = m_contactPopup->addAction("Connect..."); + QAction* mdisconnect = m_contactPopup->addAction("Disconnect..."); + QAction* mdelete = m_contactPopup->addAction("Delete"); + + m_ui.statusLabel->setText("Not Running"); + m_contactsModel = new QStandardItemModel(); + m_ui.contactTreeView->setModel(m_contactsModel); + m_ui.contactTreeView->setItemDelegate(new PermDelegate()); + + connect(m_ui.startButton, SIGNAL(clicked()), this, + SLOT(toggleServer())); + connect(m_ui.connectButton, SIGNAL(clicked()), this, + SLOT(startConnect())); + connect(mconnect, SIGNAL(triggered(bool)), this, + SLOT(popupConnect(bool))); + connect(mdisconnect, SIGNAL(triggered(bool)), this, + SLOT(popupDisconnect(bool))); + connect(mdelete, SIGNAL(triggered(bool)), this, + SLOT(popupDelete(bool))); + connect(m_ui.resetConfigButton, SIGNAL(clicked()), this, + SLOT(resetConfig())); + + connect(m_ui.contactTreeView, + SIGNAL(customContextMenuRequested(const QPoint&)), this, + SLOT(popup(const QPoint&))); + + connect(m_ui.contactTreeView, SIGNAL(doubleClicked(const QModelIndex&)), + this, SLOT(doubleClickContact(const QModelIndex&))); + + loadSettings(); + } -void -RvNetworkDialog::loadSettings() -{ - RV_QSETTINGS; - settings.beginGroup("Network"); - - const Rv::Options& opts = Rv::Options::sharedOptions(); + RvNetworkDialog::~RvNetworkDialog() + { + DB("RvNetworkDialog::~RvNetworkDialog"); + if (m_client) + toggleServer(); + } - int permPrefs[3] = {opts.networkPerm, settings.value("defaultPermission").toInt(), AskConnect}; - for (int permIndex = 0; permIndex < 3; permIndex++) + void RvNetworkDialog::loadSettings() { - int permCheck = permPrefs[permIndex]; - if (permCheck == AskConnect || permCheck == AllowConnect || permCheck == DenyConnect) + RV_QSETTINGS; + settings.beginGroup("Network"); + + const Rv::Options& opts = Rv::Options::sharedOptions(); + + int permPrefs[3] = {opts.networkPerm, + settings.value("defaultPermission").toInt(), + AskConnect}; + for (int permIndex = 0; permIndex < 3; permIndex++) { - m_ui.permissionCombo->setCurrentIndex(permCheck); - break; + int permCheck = permPrefs[permIndex]; + if (permCheck == AskConnect || permCheck == AllowConnect + || permCheck == DenyConnect) + { + m_ui.permissionCombo->setCurrentIndex(permCheck); + break; + } } - } - - // - // Create default contact information for this end. This will - // probably be replaced by the client app later. - // - QStringList envVariables; - envVariables << "USERNAME.*" << "USER.*" << "USERDOMAIN.*" - << "HOSTNAME.*" << "DOMAINNAME.*"; + // + // Create default contact information for this end. This will + // probably be replaced by the client app later. + // - QStringList environment = QProcess::systemEnvironment(); + QStringList envVariables; + envVariables << "USERNAME.*" << "USER.*" << "USERDOMAIN.*" + << "HOSTNAME.*" << "DOMAINNAME.*"; - QString defaultName; + QStringList environment = QProcess::systemEnvironment(); - foreach (QString string, envVariables) - { - int index = environment.indexOf(QRegExp(string)); + QString defaultName; - if (index != -1) + foreach (QString string, envVariables) { - QStringList stringList = environment.at(index).split("="); + int index = environment.indexOf(QRegExp(string)); - if (stringList.size() == 2) + if (index != -1) { - defaultName = stringList.at(1).toUtf8(); - break; + QStringList stringList = environment.at(index).split("="); + + if (stringList.size() == 2) + { + defaultName = stringList.at(1).toUtf8(); + break; + } } } - } - QString name; - if (opts.networkUser) - { - name = opts.networkUser; - } - else - { - name = settings.value("name", defaultName).toString(); - } - m_ui.nameLineEdit->setText(name); - - QString port = QString("%1").arg(settings.value("primaryPort", 45124).toInt()); - if (opts.networkPort) port = QString(QString("%1").arg(opts.networkPort)); - m_ui.portLineEdit->setText(port); - - ContactMap contacts = settings.value("contacts").toMap(); - - QList keys = contacts.keys(); - m_contactsModel->clear(); - QStringList headers; - headers.push_back("Connected"); - headers.push_back("Name "); - headers.push_back("Machine"); - headers.push_back("Permission"); - headers.push_back("App "); - headers.push_back("Session"); - m_contactsModel->setHorizontalHeaderLabels(headers); - - for (int i=0; i < keys.size(); i++) - { - QStringList parts = keys[i].split("@"); - unsigned int p = contacts[keys[i]].toUInt(); - addContact(parts[0], parts[1], 0, p, "", false); - } + QString name; + if (opts.networkUser) + { + name = opts.networkUser; + } + else + { + name = settings.value("name", defaultName).toString(); + } + m_ui.nameLineEdit->setText(name); + + QString port = + QString("%1").arg(settings.value("primaryPort", 45124).toInt()); + if (opts.networkPort) + port = QString(QString("%1").arg(opts.networkPort)); + m_ui.portLineEdit->setText(port); + + ContactMap contacts = settings.value("contacts").toMap(); + + QList keys = contacts.keys(); + m_contactsModel->clear(); + QStringList headers; + headers.push_back("Connected"); + headers.push_back("Name "); + headers.push_back("Machine"); + headers.push_back("Permission"); + headers.push_back("App "); + headers.push_back("Session"); + m_contactsModel->setHorizontalHeaderLabels(headers); + + for (int i = 0; i < keys.size(); i++) + { + QStringList parts = keys[i].split("@"); + unsigned int p = contacts[keys[i]].toUInt(); + addContact(parts[0], parts[1], 0, p, "", false); + } - for (int i=0; i < 4; i++) m_ui.contactTreeView->resizeColumnToContents(i); + for (int i = 0; i < 4; i++) + m_ui.contactTreeView->resizeColumnToContents(i); - settings.endGroup(); -} + settings.endGroup(); + } -bool -RvNetworkDialog::confirmDisconnect(const QString& contact) -{ - QMessageBox box(QMessageBox::Warning, - "Disconnect", - QString("Disconnect from %1?").arg(contact), - QMessageBox::NoButton, this, Qt::Sheet); - - QPushButton* q1 = box.addButton("Disconnect", QMessageBox::AcceptRole); - QPushButton* q2 = box.addButton("Cancel", QMessageBox::RejectRole); - box.setIcon(QMessageBox::Question); - box.exec(); - return box.clickedButton() == q1; -} - -void -RvNetworkDialog::resetConfig() -{ - QMessageBox box(QMessageBox::Warning, "Reset Network Configuration", - "Reset Network Configuration Settings?", - QMessageBox::NoButton, this, Qt::Sheet); + bool RvNetworkDialog::confirmDisconnect(const QString& contact) + { + QMessageBox box(QMessageBox::Warning, "Disconnect", + QString("Disconnect from %1?").arg(contact), + QMessageBox::NoButton, this, Qt::Sheet); - QPushButton* q1 = box.addButton("Reset", QMessageBox::AcceptRole); - QPushButton* q2 = box.addButton("Cancel", QMessageBox::RejectRole); - box.setIcon(QMessageBox::Warning); - box.exec(); + QPushButton* q1 = box.addButton("Disconnect", QMessageBox::AcceptRole); + QPushButton* q2 = box.addButton("Cancel", QMessageBox::RejectRole); + box.setIcon(QMessageBox::Question); + box.exec(); + return box.clickedButton() == q1; + } - if (box.clickedButton() == q1) + void RvNetworkDialog::resetConfig() { - m_ui.portLineEdit->setText("45124"); - } -} + QMessageBox box(QMessageBox::Warning, "Reset Network Configuration", + "Reset Network Configuration Settings?", + QMessageBox::NoButton, this, Qt::Sheet); -int -RvNetworkDialog::findContact(const QString& cname, - const QString& chost) -{ - int n = m_contactsModel->rowCount(); + QPushButton* q1 = box.addButton("Reset", QMessageBox::AcceptRole); + QPushButton* q2 = box.addButton("Cancel", QMessageBox::RejectRole); + box.setIcon(QMessageBox::Warning); + box.exec(); - for (int i=0; i < n; i++) - { - if (m_contactsModel->item(i, 1)->text() == cname && - m_contactsModel->item(i, 2)->text() == chost) + if (box.clickedButton() == q1) { - return i; + m_ui.portLineEdit->setText("45124"); } } - return -1; -} - -void -RvNetworkDialog::addContact(const QString& cname, - const QString& chost, - TwkQtChat::Connection* connection, - unsigned int cperms, - const QString& capp, - bool checkForExisting) -{ - unsigned int tperms = cperms; - if (tperms == CurrentConnect) tperms = m_ui.permissionCombo->currentIndex(); - - QString permText = ""; - if (tperms == AskConnect) permText = "Ask"; - else if (tperms == AllowConnect) permText = "Allow"; - else if (tperms == DenyConnect) permText = "Deny"; - else + int RvNetworkDialog::findContact(const QString& cname, const QString& chost) { - cerr << "ERROR: Unable to determine default contact permission: " << tperms; - return; - } + int n = m_contactsModel->rowCount(); - string sender = string(cname.toUtf8().constData()) + "@" + chost.toUtf8().constData(); - QString csess(m_sessionMap[sender].c_str()); - DB ("RvNetworkDialog::addContact cname " << cname.toUtf8().data() << - " chost " << chost.toUtf8().data() << - " connection " << connection << - " capp " << capp.toUtf8().data() << - " session " << csess.toUtf8().data()); + for (int i = 0; i < n; i++) + { + if (m_contactsModel->item(i, 1)->text() == cname + && m_contactsModel->item(i, 2)->text() == chost) + { + return i; + } + } - if (checkForExisting) - { - int i = findContact(cname, chost); + return -1; + } - if (i != -1) + void RvNetworkDialog::addContact(const QString& cname, const QString& chost, + TwkQtChat::Connection* connection, + unsigned int cperms, const QString& capp, + bool checkForExisting) + { + unsigned int tperms = cperms; + if (tperms == CurrentConnect) + tperms = m_ui.permissionCombo->currentIndex(); + + QString permText = ""; + if (tperms == AskConnect) + permText = "Ask"; + else if (tperms == AllowConnect) + permText = "Allow"; + else if (tperms == DenyConnect) + permText = "Deny"; + else { - if (cperms != CurrentConnect) - m_contactsModel->item(i, 3)->setText(permText); - m_contactsModel->item(i, 0)->setCheckState(connection ? Qt::Checked : Qt::Unchecked); - m_contactsModel->item(i, 4)->setText(capp); - m_contactsModel->item(i, 5)->setText(csess); - + cerr << "ERROR: Unable to determine default contact permission: " + << tperms; return; } - } - QStandardItem* conn = new QStandardItem(); - QStandardItem* name = new QStandardItem(cname); - QStandardItem* host = new QStandardItem(chost); - QStandardItem* perm = new QStandardItem(); - QStandardItem* appl = new QStandardItem(capp); - QStandardItem* sess = new QStandardItem(csess); - - conn->setCheckState(connection ? Qt::Checked : Qt::Unchecked); - conn->setEditable(false); - name->setEditable(false); - host->setEditable(false); - perm->setEditable(true); - perm->setText(permText); - appl->setEditable(false); - sess->setEditable(false); - - QList row; - row.push_back(conn); - row.push_back(name); - row.push_back(host); - row.push_back(perm); - row.push_back(appl); - row.push_back(sess); - - m_contactsModel->appendRow(row); - - // - // If this is a local connection, hide this row in the contact list, since - // we always allow them anyway, and display drivers, etc can clutter the - // contact list with lots of connections. - // - if (connection && connection->isLocal()) - { - m_ui.contactTreeView->setRowHidden(m_contactsModel->rowCount() - 1, QModelIndex(), true); - } -} + string sender = string(cname.toUtf8().constData()) + "@" + + chost.toUtf8().constData(); + QString csess(m_sessionMap[sender].c_str()); + DB("RvNetworkDialog::addContact cname " + << cname.toUtf8().data() << " chost " << chost.toUtf8().data() + << " connection " << connection << " capp " << capp.toUtf8().data() + << " session " << csess.toUtf8().data()); -void -RvNetworkDialog::saveSettings() -{ - RV_QSETTINGS; - settings.beginGroup("Network"); - settings.setValue("name", m_ui.nameLineEdit->text()); - settings.setValue("primaryPort", m_ui.portLineEdit->text().toInt()); + if (checkForExisting) + { + int i = findContact(cname, chost); - ContactMap contacts; - int n = m_contactsModel->rowCount(); + if (i != -1) + { + if (cperms != CurrentConnect) + m_contactsModel->item(i, 3)->setText(permText); + m_contactsModel->item(i, 0)->setCheckState( + connection ? Qt::Checked : Qt::Unchecked); + m_contactsModel->item(i, 4)->setText(capp); + m_contactsModel->item(i, 5)->setText(csess); + + return; + } + } + + QStandardItem* conn = new QStandardItem(); + QStandardItem* name = new QStandardItem(cname); + QStandardItem* host = new QStandardItem(chost); + QStandardItem* perm = new QStandardItem(); + QStandardItem* appl = new QStandardItem(capp); + QStandardItem* sess = new QStandardItem(csess); + + conn->setCheckState(connection ? Qt::Checked : Qt::Unchecked); + conn->setEditable(false); + name->setEditable(false); + host->setEditable(false); + perm->setEditable(true); + perm->setText(permText); + appl->setEditable(false); + sess->setEditable(false); + + QList row; + row.push_back(conn); + row.push_back(name); + row.push_back(host); + row.push_back(perm); + row.push_back(appl); + row.push_back(sess); + + m_contactsModel->appendRow(row); - for (int i=0; i < n; i++) - { // - // Only store in prefs if not hidden. Hidden rows hold contact info - // for local connections, which we don't need to store (since we always - // allow them). + // If this is a local connection, hide this row in the contact list, + // since we always allow them anyway, and display drivers, etc can + // clutter the contact list with lots of connections. // - if (! m_ui.contactTreeView->isRowHidden(i, QModelIndex())) + if (connection && connection->isLocal()) { - QString name = m_contactsModel->item(i, 1)->text(); - QString mach = m_contactsModel->item(i, 2)->text(); - QString pname = m_contactsModel->item(i, 3)->text(); - - unsigned int p = 0; - if (pname == "Allow") p = 1; - else if (pname == "Deny") p = 2; - - contacts[name + "@" + mach] = p; + m_ui.contactTreeView->setRowHidden(m_contactsModel->rowCount() - 1, + QModelIndex(), true); } } - settings.setValue("contacts", contacts); - settings.setValue("defaultPermission", m_ui.permissionCombo->currentIndex()); - settings.endGroup(); -} - -void -RvNetworkDialog::shutdownServer() -{ - DB ("RvNetworkDialog::shutdownServer m_client " << m_client); - if (m_client) + void RvNetworkDialog::saveSettings() { - std::vector cs = connections(); - for (int i=0; i < cs.size(); i++) + RV_QSETTINGS; + settings.beginGroup("Network"); + settings.setValue("name", m_ui.nameLineEdit->text()); + settings.setValue("primaryPort", m_ui.portLineEdit->text().toInt()); + + ContactMap contacts; + int n = m_contactsModel->rowCount(); + + for (int i = 0; i < n; i++) { - DB (" signOff " << cs[i]); - m_client->signOff(cs[i].c_str()); - } - saveSettings(); - delete m_client; - m_client = 0; - m_ui.participantList->clear(); - m_sessionMap.clear(); - sendSessionEvent("remote-network-stop", "", ""); + // + // Only store in prefs if not hidden. Hidden rows hold contact info + // for local connections, which we don't need to store (since we + // always allow them). + // + if (!m_ui.contactTreeView->isRowHidden(i, QModelIndex())) + { + QString name = m_contactsModel->item(i, 1)->text(); + QString mach = m_contactsModel->item(i, 2)->text(); + QString pname = m_contactsModel->item(i, 3)->text(); - deletePortNumberFile(); - } -} + unsigned int p = 0; + if (pname == "Allow") + p = 1; + else if (pname == "Deny") + p = 2; -void -RvNetworkDialog::savePortNumber() -{ - DB ("savePortNumber"); + contacts[name + "@" + mach] = p; + } + } - // System temp dir - QDir tmp = QDir::temp(); + settings.setValue("contacts", contacts); + settings.setValue("defaultPermission", + m_ui.permissionCombo->currentIndex()); + settings.endGroup(); + } - if (! tmp.exists ("tweak_rv_proc")) + void RvNetworkDialog::shutdownServer() { - DB (" dir doesn't exist"); - tmp.mkdir ("tweak_rv_proc"); - tmp.cd ("tweak_rv_proc"); - QFile::setPermissions (tmp.absolutePath(), - QFile::ReadOwner | QFile::ReadUser | QFile::ReadGroup | QFile::ReadOther | - QFile::WriteOwner | QFile::WriteUser | QFile::WriteGroup | QFile::WriteOther | - QFile::ExeOwner | QFile::ExeUser | QFile::ExeGroup | QFile::ExeOther); - } - else tmp.cd("tweak_rv_proc"); - - QString pid; - #ifdef PLATFORM_WINDOWS - pid.setNum (_getpid()); - #else - pid.setNum (getpid()); - #endif - - // - // Write port number to file named: /tweak_rv_proc/_ - // - - QString tagString("_"); - const Rv::Options& opts = Rv::Options::sharedOptions(); - if (opts.networkTag) tagString += opts.networkTag; - - QFile portFile(tmp.absolutePath() + "/" + pid + tagString); - - DB (" opening portfile '" << portFile.fileName().toUtf8().constData() << "'"); - portFile.open (QIODevice::WriteOnly | QIODevice::Truncate); - portFile.setPermissions ( - QFile::ReadOwner | QFile::ReadUser | QFile::ReadGroup | QFile::ReadOther | - QFile::WriteOwner | QFile::WriteUser | QFile::WriteGroup | QFile::WriteOther); - - QString portNum; - portNum.setNum(myPort()); - portNum += "\n"; - portFile.write (portNum.toUtf8()); - portFile.close(); - - m_portFile = portFile.fileName(); -} - -void -RvNetworkDialog::deletePortNumberFile() -{ - if (!m_portFile.isEmpty()) QFile::remove(m_portFile); -} + DB("RvNetworkDialog::shutdownServer m_client " << m_client); + if (m_client) + { + std::vector cs = connections(); + for (int i = 0; i < cs.size(); i++) + { + DB(" signOff " << cs[i]); + m_client->signOff(cs[i].c_str()); + } + saveSettings(); + delete m_client; + m_client = 0; + m_ui.participantList->clear(); + m_sessionMap.clear(); + sendSessionEvent("remote-network-stop", "", ""); -void -RvNetworkDialog::closeEvent(QCloseEvent *event) -{ - saveSettings(); - QWidget::closeEvent(event); -} + deletePortNumberFile(); + } + } -void -RvNetworkDialog::toggleServer() -{ - DB ("RvNetworkDialog::toggleServer m_client " << m_client); - if (m_client) + void RvNetworkDialog::savePortNumber() { - int n = m_ui.participantList->count(); - const TwkApp::Application::Documents& docs = IPCore::App()->documents(); + DB("savePortNumber"); - if (n > 0 && docs.size()) + // System temp dir + QDir tmp = QDir::temp(); + + if (!tmp.exists("tweak_rv_proc")) { - QMessageBox box(QMessageBox::Warning, "Stop Network", - QString("%1 connection%2 %3 still active") - .arg(n).arg(n==1 ? "" : "s").arg(n==1 ? "is" : "are"), - QMessageBox::NoButton, this, Qt::Sheet); - - QPushButton* q1 = box.addButton("Stop Network", QMessageBox::AcceptRole); - QPushButton* q2 = box.addButton("Cancel", QMessageBox::RejectRole); - box.setIcon(QMessageBox::Warning); - box.exec(); - if (box.clickedButton() == q2) return; + DB(" dir doesn't exist"); + tmp.mkdir("tweak_rv_proc"); + tmp.cd("tweak_rv_proc"); + QFile::setPermissions( + tmp.absolutePath(), + QFile::ReadOwner | QFile::ReadUser | QFile::ReadGroup + | QFile::ReadOther | QFile::WriteOwner | QFile::WriteUser + | QFile::WriteGroup | QFile::WriteOther | QFile::ExeOwner + | QFile::ExeUser | QFile::ExeGroup | QFile::ExeOther); } + else + tmp.cd("tweak_rv_proc"); - saveSettings(); + QString pid; +#ifdef PLATFORM_WINDOWS + pid.setNum(_getpid()); +#else + pid.setNum(getpid()); +#endif - std::vector cs = connections(); - for (int i=0; i < cs.size(); i++) - { - DB (" signOff " << cs[i]); - m_client->signOff(cs[i].c_str()); - } + // + // Write port number to file named: + // /tweak_rv_proc/_ + // + + QString tagString("_"); + const Rv::Options& opts = Rv::Options::sharedOptions(); + if (opts.networkTag) + tagString += opts.networkTag; + + QFile portFile(tmp.absolutePath() + "/" + pid + tagString); - delete m_client; - m_client = 0; - m_ui.participantList->clear(); - m_sessionMap.clear(); - - sendSessionEvent("remote-network-stop", "", ""); + DB(" opening portfile '" << portFile.fileName().toUtf8().constData() + << "'"); + portFile.open(QIODevice::WriteOnly | QIODevice::Truncate); + portFile.setPermissions(QFile::ReadOwner | QFile::ReadUser + | QFile::ReadGroup | QFile::ReadOther + | QFile::WriteOwner | QFile::WriteUser + | QFile::WriteGroup | QFile::WriteOther); - deletePortNumberFile(); + QString portNum; + portNum.setNum(myPort()); + portNum += "\n"; + portFile.write(portNum.toUtf8()); + portFile.close(); + + m_portFile = portFile.fileName(); } - else - { - int port = m_ui.portLineEdit->text().toInt(); - m_client = new Client(m_ui.nameLineEdit->text(), "rv", port, true, StreamConnection::connectionFactory); - if (m_client->online()) - { - fprintf (stderr, "INFO: listening on port %d\n", m_client->serverPort()); - QString portStr = QString(QString("%1").arg(m_client->serverPort())); - m_ui.portLineEdit->setText(portStr); + void RvNetworkDialog::deletePortNumberFile() + { + if (!m_portFile.isEmpty()) + QFile::remove(m_portFile); + } - connect(m_client, SIGNAL(newData(const QString&, - const QString&, - const QByteArray&)), - this, SLOT(newData(const QString&, - const QString&, - const QByteArray&))); + void RvNetworkDialog::closeEvent(QCloseEvent* event) + { + saveSettings(); + QWidget::closeEvent(event); + } - connect(m_client, SIGNAL(newContact(const QString &)), - this, SLOT(newRemoteContact(const QString &))); + void RvNetworkDialog::toggleServer() + { + DB("RvNetworkDialog::toggleServer m_client " << m_client); + if (m_client) + { + int n = m_ui.participantList->count(); + const TwkApp::Application::Documents& docs = + IPCore::App()->documents(); - connect(m_client, SIGNAL(newMessage(const QString &, const QString &)), - this, SLOT(newMessage(const QString &, const QString &))); + if (n > 0 && docs.size()) + { + QMessageBox box(QMessageBox::Warning, "Stop Network", + QString("%1 connection%2 %3 still active") + .arg(n) + .arg(n == 1 ? "" : "s") + .arg(n == 1 ? "is" : "are"), + QMessageBox::NoButton, this, Qt::Sheet); + + QPushButton* q1 = + box.addButton("Stop Network", QMessageBox::AcceptRole); + QPushButton* q2 = + box.addButton("Cancel", QMessageBox::RejectRole); + box.setIcon(QMessageBox::Warning); + box.exec(); + if (box.clickedButton() == q2) + return; + } - connect(m_client, SIGNAL(contactLeft(const QString &)), - this, SLOT(remoteContactLeft(const QString &))); + saveSettings(); - connect(m_client, SIGNAL(requestConnection(TwkQtChat::Connection*)), - this, SLOT(requestConnection(TwkQtChat::Connection*))); + std::vector cs = connections(); + for (int i = 0; i < cs.size(); i++) + { + DB(" signOff " << cs[i]); + m_client->signOff(cs[i].c_str()); + } - connect(m_client, SIGNAL(contactError(const QString&, const QString&, const QString&)), - this, SLOT(contactError(const QString&, const QString&, const QString&))); + delete m_client; + m_client = 0; + m_ui.participantList->clear(); + m_sessionMap.clear(); - sendSessionEvent("remote-network-start", "", ""); + sendSessionEvent("remote-network-stop", "", ""); - savePortNumber(); + deletePortNumberFile(); } else { - delete m_client; - m_client = 0; + int port = m_ui.portLineEdit->text().toInt(); + m_client = new Client(m_ui.nameLineEdit->text(), "rv", port, true, + StreamConnection::connectionFactory); + + if (m_client->online()) + { + fprintf(stderr, "INFO: listening on port %d\n", + m_client->serverPort()); + QString portStr = + QString(QString("%1").arg(m_client->serverPort())); + m_ui.portLineEdit->setText(portStr); + + connect(m_client, + SIGNAL(newData(const QString&, const QString&, + const QByteArray&)), + this, + SLOT(newData(const QString&, const QString&, + const QByteArray&))); + + connect(m_client, SIGNAL(newContact(const QString&)), this, + SLOT(newRemoteContact(const QString&))); + + connect(m_client, + SIGNAL(newMessage(const QString&, const QString&)), + this, SLOT(newMessage(const QString&, const QString&))); + + connect(m_client, SIGNAL(contactLeft(const QString&)), this, + SLOT(remoteContactLeft(const QString&))); + + connect(m_client, + SIGNAL(requestConnection(TwkQtChat::Connection*)), this, + SLOT(requestConnection(TwkQtChat::Connection*))); + + connect(m_client, + SIGNAL(contactError(const QString&, const QString&, + const QString&)), + this, + SLOT(contactError(const QString&, const QString&, + const QString&))); + + sendSessionEvent("remote-network-start", "", ""); + + savePortNumber(); + } + else + { + delete m_client; + m_client = 0; + } } + updateStatus(); } - updateStatus(); -} - -IPCore::Session* -RvNetworkDialog::targetSession (QString sender, bool doDisconnect) -{ - DB ("targetSession sender " << sender.toUtf8().constData() << - " doDis " << doDisconnect); - Session* s = RvApp()->session(m_sessionMap[sender.toUtf8().constData()]); - if (!s && doDisconnect) + IPCore::Session* RvNetworkDialog::targetSession(QString sender, + bool doDisconnect) { - cerr << "ERROR: Session associated with sender '" - << sender.toUtf8().constData() - << "' does not exist, disconnecting" - << endl; - - QList items = - m_ui.participantList->findItems(sender, Qt::MatchExactly); - for (int i=0; i < items.size(); i++) delete items[i]; - - m_sessionMap.erase(sender.toUtf8().constData()); - m_client->signOff(sender); - m_client->disconnectFrom(sender); + DB("targetSession sender " << sender.toUtf8().constData() << " doDis " + << doDisconnect); + Session* s = + RvApp()->session(m_sessionMap[sender.toUtf8().constData()]); + if (!s && doDisconnect) + { + cerr << "ERROR: Session associated with sender '" + << sender.toUtf8().constData() + << "' does not exist, disconnecting" << endl; + + QList items = + m_ui.participantList->findItems(sender, Qt::MatchExactly); + for (int i = 0; i < items.size(); i++) + delete items[i]; + + m_sessionMap.erase(sender.toUtf8().constData()); + m_client->signOff(sender); + m_client->disconnectFrom(sender); + } + return s; } - return s; -} - -void -RvNetworkDialog::newRemoteContact(const QString& name) -{ - DB ("newRemoteContact '" << UTF8::qconvert(name) << "'"); - Session* s = targetSession(name); - if (!s) return; - m_ui.participantList->addItem(name); - updateStatus(); + void RvNetworkDialog::newRemoteContact(const QString& name) + { + DB("newRemoteContact '" << UTF8::qconvert(name) << "'"); + Session* s = targetSession(name); + if (!s) + return; - s->userGenericEvent("remote-connection-start", name.toUtf8().constData(), ""); -} + m_ui.participantList->addItem(name); + updateStatus(); -RvNetworkDialog::ConnectPermission -RvNetworkDialog::contactPermission(const QStringList& parts) -{ - int n = m_contactsModel->rowCount(); + s->userGenericEvent("remote-connection-start", + name.toUtf8().constData(), ""); + } - for (int i=0; i < n; i++) + RvNetworkDialog::ConnectPermission + RvNetworkDialog::contactPermission(const QStringList& parts) { - QStandardItem* item1 = m_contactsModel->item(i, 1); + int n = m_contactsModel->rowCount(); - if (item1->text() == parts[0]) + for (int i = 0; i < n; i++) { - QStandardItem* item2 = m_contactsModel->item(i, 2); + QStandardItem* item1 = m_contactsModel->item(i, 1); - if (item2->text() == parts[1]) + if (item1->text() == parts[0]) { - QStandardItem* item3 = m_contactsModel->item(i, 3); - QString perms = item3->text(); - if (perms == "Ask") return AskConnect; - if (perms == "Allow") return AllowConnect; - if (perms == "Deny") return DenyConnect; + QStandardItem* item2 = m_contactsModel->item(i, 2); + + if (item2->text() == parts[1]) + { + QStandardItem* item3 = m_contactsModel->item(i, 3); + QString perms = item3->text(); + if (perms == "Ask") + return AskConnect; + if (perms == "Allow") + return AllowConnect; + if (perms == "Deny") + return DenyConnect; + } } } - } - - int index = m_ui.permissionCombo->currentIndex(); - if (index == 1) return AllowConnect; - if (index == 2) return DenyConnect; - return AskConnect; -} + int index = m_ui.permissionCombo->currentIndex(); + if (index == 1) + return AllowConnect; + if (index == 2) + return DenyConnect; + return AskConnect; + } -void -RvNetworkDialog::requestConnection(TwkQtChat::Connection* c) -{ - DB ("RvNetworkDialog::requestConnection " << - c->remoteContactName().toUtf8().constData()); - // - // This may add the contact - // - - DB (" checking for StreamConnection"); - const char* streamDir = getenv ("RV_NETWORK_STREAM_STORAGE_DIR"); - if (streamDir) + void RvNetworkDialog::requestConnection(TwkQtChat::Connection* c) { - if (StreamConnection *strCon = dynamic_cast (c)) + DB("RvNetworkDialog::requestConnection " + << c->remoteContactName().toUtf8().constData()); + // + // This may add the contact + // + + DB(" checking for StreamConnection"); + const char* streamDir = getenv("RV_NETWORK_STREAM_STORAGE_DIR"); + if (streamDir) { - if (strCon->streamState() == StreamConnection::NormalState) + if (StreamConnection* strCon = dynamic_cast(c)) { - DB (" calling storeStream() dir '" << streamDir << "'"); - strCon->storeStream(streamDir); + if (strCon->streamState() == StreamConnection::NormalState) + { + DB(" calling storeStream() dir '" << streamDir << "'"); + strCon->storeStream(streamDir); + } } } - } - QString name = c->remoteContactName(); - QStringList parts = name.split("@"); + QString name = c->remoteContactName(); + QStringList parts = name.split("@"); - // - // XXX Prob we neeed to pop a dialog here to ask the user - // which session they'd like to connect to. - // - Session* session = Session::activeSession(); - QString csess; - if (!session) - { - cerr << "ERROR: RvNetwork: no session for incoming connection" << endl; - m_client->rejectConnection(c); - return; - } - string sender = name.toUtf8().constData(); - if (m_sessionMap[sender].size()) - { - cerr << "ERROR: RvNetwork: '" << sender << "' is already connected." << endl; - c->setDuplicate(true); - m_client->rejectConnection(c); - return; - } - m_sessionMap[sender] = session->name(); - DB (" new sessionMap val '" << m_sessionMap[sender] << "'"); - csess = session->name().c_str(); + // + // XXX Prob we neeed to pop a dialog here to ask the user + // which session they'd like to connect to. + // + Session* session = Session::activeSession(); + QString csess; + if (!session) + { + cerr << "ERROR: RvNetwork: no session for incoming connection" + << endl; + m_client->rejectConnection(c); + return; + } + string sender = name.toUtf8().constData(); + if (m_sessionMap[sender].size()) + { + cerr << "ERROR: RvNetwork: '" << sender << "' is already connected." + << endl; + c->setDuplicate(true); + m_client->rejectConnection(c); + return; + } + m_sessionMap[sender] = session->name(); + DB(" new sessionMap val '" << m_sessionMap[sender] << "'"); + csess = session->name().c_str(); - if (c->isLocal()) - { - addContact(parts[0], parts[1], c, CurrentConnect, c->remoteApp()); - return; - } + if (c->isLocal()) + { + addContact(parts[0], parts[1], c, CurrentConnect, c->remoteApp()); + return; + } - // - // Find out the existing policy regarding the contact that's - // trying to make the connection. - // + // + // Find out the existing policy regarding the contact that's + // trying to make the connection. + // - ConnectPermission perm = contactPermission(parts); + ConnectPermission perm = contactPermission(parts); - if (perm == AskConnect) - { - QMessageBox box(QMessageBox::Warning, "Connection Request", - QString("%1 wants to connect\n ").arg(name), - QMessageBox::NoButton, this, Qt::Dialog); + if (perm == AskConnect) + { + QMessageBox box(QMessageBox::Warning, "Connection Request", + QString("%1 wants to connect\n ").arg(name), + QMessageBox::NoButton, this, Qt::Dialog); + + QPushButton* q3 = + box.addButton("Always Allow", QMessageBox::AcceptRole); + QPushButton* q1 = + box.addButton("Allow Once", QMessageBox::ApplyRole); + QPushButton* q2 = box.addButton("Deny", QMessageBox::RejectRole); + box.exec(); - QPushButton* q3 = box.addButton("Always Allow", QMessageBox::AcceptRole); - QPushButton* q1 = box.addButton("Allow Once", QMessageBox::ApplyRole); - QPushButton* q2 = box.addButton("Deny", QMessageBox::RejectRole); - box.exec(); + if (box.clickedButton() == q2) + { + // Deny + m_client->rejectConnection(c); + addContact(parts[0], parts[1], 0, CurrentConnect, ""); + } + else if (box.clickedButton() == q1) + { + // allow + addContact(parts[0], parts[1], c, CurrentConnect, + c->remoteApp()); + } + else if (box.clickedButton() == q3) + { + // allow and record it for future - if (box.clickedButton() == q2) + addContact(parts[0], parts[1], c, AllowConnect, c->remoteApp()); + } + } + else if (perm == DenyConnect) { - // Deny m_client->rejectConnection(c); - addContact(parts[0], parts[1], 0, CurrentConnect, ""); + addContact(parts[0], parts[1], 0, CurrentConnect, c->remoteApp()); } - else if (box.clickedButton() == q1) + else { - // allow + // just allow connect addContact(parts[0], parts[1], c, CurrentConnect, c->remoteApp()); } - else if (box.clickedButton() == q3) - { - // allow and record it for future - - addContact(parts[0], parts[1], c, AllowConnect, c->remoteApp()); - } - } - else if (perm == DenyConnect) - { - m_client->rejectConnection(c); - addContact(parts[0], parts[1], 0, CurrentConnect, c->remoteApp()); - } - else - { - // just allow connect - addContact(parts[0], parts[1], c, CurrentConnect, c->remoteApp()); } -} -void -RvNetworkDialog::remoteContactLeft(const QString& name) -{ - DB ("RvNetworkDialog::remoteContactLeft name " << name.toUtf8().constData()); - const TwkApp::Application::Documents& docs = App()->documents(); - if (!docs.size()) + void RvNetworkDialog::remoteContactLeft(const QString& name) { - DB ("exiting ?"); - // we're probably exiting - return; - } - - QList items = - m_ui.participantList->findItems(name, Qt::MatchExactly); + DB("RvNetworkDialog::remoteContactLeft name " + << name.toUtf8().constData()); + const TwkApp::Application::Documents& docs = App()->documents(); + if (!docs.size()) + { + DB("exiting ?"); + // we're probably exiting + return; + } - for (int i=0; i < items.size(); i++) delete items[i]; - QStringList parts = name.split("@"); + QList items = + m_ui.participantList->findItems(name, Qt::MatchExactly); - if (parts.size() == 2) - { - int row = findContact(parts[0], parts[1]); + for (int i = 0; i < items.size(); i++) + delete items[i]; + QStringList parts = name.split("@"); - if (row != -1) + if (parts.size() == 2) { - m_contactsModel->item(row, 0)->setCheckState(Qt::Unchecked); - m_contactsModel->item(row, 5)->setText(""); - } - } + int row = findContact(parts[0], parts[1]); - updateStatus(); - Session* s = targetSession(name, false); - m_sessionMap.erase(name.toUtf8().constData()); + if (row != -1) + { + m_contactsModel->item(row, 0)->setCheckState(Qt::Unchecked); + m_contactsModel->item(row, 5)->setText(""); + } + } - if (!s) return; + updateStatus(); + Session* s = targetSession(name, false); + m_sessionMap.erase(name.toUtf8().constData()); - s->userGenericEvent("remote-connection-stop", name.toUtf8().constData(), ""); -} + if (!s) + return; -void -RvNetworkDialog::updateStatus() -{ - if (m_client) - { - int n = m_ui.participantList->count(); - QString t = QString("Running
%1 Connection%2").arg(n).arg(n==1?"":"s"); - m_ui.statusLabel->setText(t); - m_ui.startButton->setText("Stop Network"); - m_ui.nameLineEdit->setDisabled(true); - m_ui.portLineEdit->setDisabled(true); - m_ui.resetConfigButton->setDisabled(true); + s->userGenericEvent("remote-connection-stop", name.toUtf8().constData(), + ""); } - else - { - m_ui.statusLabel->setText("Not Running"); - m_ui.startButton->setText("Start Network"); - m_ui.nameLineEdit->setDisabled(false); - m_ui.portLineEdit->setDisabled(false); - m_ui.resetConfigButton->setDisabled(false); - int n = m_contactsModel->rowCount(); - for (int i=0; i < n; i++) + void RvNetworkDialog::updateStatus() + { + if (m_client) + { + int n = m_ui.participantList->count(); + QString t = QString("Running
%1 Connection%2") + .arg(n) + .arg(n == 1 ? "" : "s"); + m_ui.statusLabel->setText(t); + m_ui.startButton->setText("Stop Network"); + m_ui.nameLineEdit->setDisabled(true); + m_ui.portLineEdit->setDisabled(true); + m_ui.resetConfigButton->setDisabled(true); + } + else { - m_contactsModel->item(i, 0)->setCheckState(Qt::Unchecked); + m_ui.statusLabel->setText("Not Running"); + m_ui.startButton->setText("Start Network"); + m_ui.nameLineEdit->setDisabled(false); + m_ui.portLineEdit->setDisabled(false); + m_ui.resetConfigButton->setDisabled(false); + + int n = m_contactsModel->rowCount(); + for (int i = 0; i < n; i++) + { + m_contactsModel->item(i, 0)->setCheckState(Qt::Unchecked); + } } } -} - -void -RvNetworkDialog::newData(const QString& sender, - const QString& interp, - const QByteArray& data) -{ - DB ("newData from " << UTF8::qconvert(sender) << " interp '" << UTF8::qconvert(interp) << "' " << data.size() << " bytes"); - Session* s = targetSession(sender); - if (!s) return; - if (interp.startsWith("PIXELTILE")) - { - s->pixelBlockEvent("pixel-block", - interp.toUtf8().constData(), - data.constData(), - data.size()); - } - else - if (interp.startsWith("DATAEVENT")) + void RvNetworkDialog::newData(const QString& sender, const QString& interp, + const QByteArray& data) { - vector tokens; - stl_ext::tokenize(tokens, interp.toUtf8().constData(), "(),"); + DB("newData from " << UTF8::qconvert(sender) << " interp '" + << UTF8::qconvert(interp) << "' " << data.size() + << " bytes"); + Session* s = targetSession(sender); + if (!s) + return; - if (tokens.size() < 4) + if (interp.startsWith("PIXELTILE")) { - cerr << "ERROR: mal-formed DATAEVENT: " - << interp.toUtf8().constData() - << endl; + s->pixelBlockEvent("pixel-block", interp.toUtf8().constData(), + data.constData(), data.size()); } - string ename = tokens[1]; - string etarget = tokens[2]; - string dinterp = tokens[3]; - string senderName = sender.toUtf8().data(); + else if (interp.startsWith("DATAEVENT")) + { + vector tokens; + stl_ext::tokenize(tokens, interp.toUtf8().constData(), "(),"); - const TwkApp::Application::Documents& docs = App()->documents(); - if (docs.size()) + if (tokens.size() < 4) + { + cerr << "ERROR: mal-formed DATAEVENT: " + << interp.toUtf8().constData() << endl; + } + string ename = tokens[1]; + string etarget = tokens[2]; + string dinterp = tokens[3]; + string senderName = sender.toUtf8().data(); + + const TwkApp::Application::Documents& docs = App()->documents(); + if (docs.size()) + { + string r = s->userRawDataEvent(ename, dinterp, data.constData(), + data.size(), 0, senderName); + // XXX no replies from data events. + } + } + else { - string r = s->userRawDataEvent (ename, dinterp, - data.constData(), data.size(), 0, senderName); - // XXX no replies from data events. + cerr << "ERROR: Unknown Data message: " + << interp.toUtf8().constData() << endl; } } - else - { - cerr << "ERROR: Unknown Data message: " << - interp.toUtf8().constData() << endl; - } -} - -void -RvNetworkDialog::newMessage(const QString& sender, - const QString& inmessage) -{ - DB ("newMessage from " << UTF8::qconvert(sender) << " '" << UTF8::qconvert(inmessage) << "'"); - Session* s = targetSession(sender); - if (!s) return; - string senderName = sender.toUtf8().data(); - bool isReturnEvent = (inmessage.startsWith("RETURNEVENT ")); - - if (isReturnEvent || inmessage.startsWith("EVENT ")) + void RvNetworkDialog::newMessage(const QString& sender, + const QString& inmessage) { - QString message = inmessage; - const TwkApp::Application::Documents& docs = App()->documents(); - QString eventName = message.section(" ", 1, 1); - QString eventTarget = message.section(" ", 2, 2); - int typeSize = (isReturnEvent) ? 13 : 7; - message.remove(0, typeSize + eventName.size() + 1 + eventTarget.size()); + DB("newMessage from " << UTF8::qconvert(sender) << " '" + << UTF8::qconvert(inmessage) << "'"); + Session* s = targetSession(sender); + if (!s) + return; - string ename = eventName.toUtf8().data(); - string contents = message.toUtf8().data(); + string senderName = sender.toUtf8().data(); + bool isReturnEvent = (inmessage.startsWith("RETURNEVENT ")); - string r = s->userGenericEvent(ename, contents, senderName); - if (isReturnEvent) + if (isReturnEvent || inmessage.startsWith("EVENT ")) { - m_client->sendMessage(sender, QString("RETURN %1").arg(r.c_str())); + QString message = inmessage; + const TwkApp::Application::Documents& docs = App()->documents(); + QString eventName = message.section(" ", 1, 1); + QString eventTarget = message.section(" ", 2, 2); + int typeSize = (isReturnEvent) ? 13 : 7; + message.remove(0, typeSize + eventName.size() + 1 + + eventTarget.size()); + + string ename = eventName.toUtf8().data(); + string contents = message.toUtf8().data(); + + string r = s->userGenericEvent(ename, contents, senderName); + if (isReturnEvent) + { + m_client->sendMessage(sender, + QString("RETURN %1").arg(r.c_str())); + } + } + else if (inmessage.startsWith("DISCONNECT")) + { + DB("DISCONNECT from " << senderName); + m_client->disconnectFrom(sender); + s->userGenericEvent("remote-connection-stop", senderName, ""); } } - else if (inmessage.startsWith("DISCONNECT")) - { - DB ("DISCONNECT from " << senderName); - m_client->disconnectFrom(sender); - s->userGenericEvent("remote-connection-stop", senderName, ""); - } -} - -void -RvNetworkDialog::startConnect() -{ - startConnectDialog(""); -} -void -RvNetworkDialog::connectByName(string host, int port) -{ - QString qhost(host.c_str()); - QHostInfo info = QHostInfo::fromName(qhost); - if (!m_client) toggleServer(); + void RvNetworkDialog::startConnect() { startConnectDialog(""); } - if (info.error() == QHostInfo::NoError && info.addresses().size()) + void RvNetworkDialog::connectByName(string host, int port) { - m_client->connectTo("unknown", info.addresses()[0], port); - } - else - { - QHostAddress addr(qhost); - if (addr.protocol() != QAbstractSocket::UnknownNetworkLayerProtocol) + QString qhost(host.c_str()); + QHostInfo info = QHostInfo::fromName(qhost); + if (!m_client) + toggleServer(); + + if (info.error() == QHostInfo::NoError && info.addresses().size()) { - m_client->connectTo("unknown", addr, port); + m_client->connectTo("unknown", info.addresses()[0], port); } else { - QMessageBox::critical(this, "Unknown Host Name", - QString("Could not resolve host name %1").arg(qhost)); + QHostAddress addr(qhost); + if (addr.protocol() != QAbstractSocket::UnknownNetworkLayerProtocol) + { + m_client->connectTo("unknown", addr, port); + } + else + { + QMessageBox::critical( + this, "Unknown Host Name", + QString("Could not resolve host name %1").arg(qhost)); + } } } -} - -void -RvNetworkDialog::startConnectDialog(const QString& name) -{ - // - // If name is empty, just hide the fields for it - // - if (name != "") + void RvNetworkDialog::startConnectDialog(const QString& name) { - m_connectUI.nameLineEdit->show(); - m_connectUI.nameLabel->show(); - m_connectUI.nameLineEdit->setText(name); - } - else - { - m_connectUI.nameLineEdit->hide(); - m_connectUI.nameLabel->hide(); - } - - m_connectDialog.setWindowFlags(Qt::Sheet); - m_connectDialog.setModal(true); - m_connectDialog.setWindowModality(Qt::WindowModal); + // + // If name is empty, just hide the fields for it + // - if (m_connectDialog.exec() == QDialog::Accepted) - { - if (!m_client) toggleServer(); - QString hname = m_connectUI.hostnameLineEdit->text(); - QHostInfo info = QHostInfo::fromName(hname); - int port = m_connectUI.portLineEdit->text().toInt(); - - if (info.error() == QHostInfo::NoError && info.addresses().size()) + if (name != "") { - m_client->connectTo(name, info.addresses()[0], port); + m_connectUI.nameLineEdit->show(); + m_connectUI.nameLabel->show(); + m_connectUI.nameLineEdit->setText(name); } else { - QHostAddress addr(hname); + m_connectUI.nameLineEdit->hide(); + m_connectUI.nameLabel->hide(); + } - if (addr.protocol() != QAbstractSocket::UnknownNetworkLayerProtocol) + m_connectDialog.setWindowFlags(Qt::Sheet); + m_connectDialog.setModal(true); + m_connectDialog.setWindowModality(Qt::WindowModal); + + if (m_connectDialog.exec() == QDialog::Accepted) + { + if (!m_client) + toggleServer(); + QString hname = m_connectUI.hostnameLineEdit->text(); + QHostInfo info = QHostInfo::fromName(hname); + int port = m_connectUI.portLineEdit->text().toInt(); + + if (info.error() == QHostInfo::NoError && info.addresses().size()) { - m_client->connectTo(name, addr, port); + m_client->connectTo(name, info.addresses()[0], port); } else { - QMessageBox::critical(this, "Unknown Host Name", - QString("Could not resolve host name %1").arg(hname)); + QHostAddress addr(hname); + + if (addr.protocol() + != QAbstractSocket::UnknownNetworkLayerProtocol) + { + m_client->connectTo(name, addr, port); + } + else + { + QMessageBox::critical( + this, "Unknown Host Name", + QString("Could not resolve host name %1").arg(hname)); + } } } } -} -set -RvNetworkDialog::selectedContacts() -{ - QModelIndexList selection = - m_ui.contactTreeView->selectionModel()->selectedIndexes(); + set RvNetworkDialog::selectedContacts() + { + QModelIndexList selection = + m_ui.contactTreeView->selectionModel()->selectedIndexes(); - set rows; + set rows; - for (int i=0; i < selection.size(); i++) - { - const QModelIndex& index = selection[i]; - rows.insert(index.row()); + for (int i = 0; i < selection.size(); i++) + { + const QModelIndex& index = selection[i]; + rows.insert(index.row()); + } + + return rows; } - return rows; -} + void RvNetworkDialog::popup(const QPoint& pos) + { + set rows = selectedContacts(); -void -RvNetworkDialog::popup(const QPoint& pos) -{ - set rows = selectedContacts(); + if (!rows.empty()) + { + int row = *rows.begin(); + + QStandardItem* check = m_contactsModel->item(row, 0); + QStandardItem* name = m_contactsModel->item(row, 1); + QStandardItem* host = m_contactsModel->item(row, 2); + bool connected = check->checkState() == Qt::Checked; + QString contact = + QString("%1@%2").arg(name->text()).arg(host->text()); + QList actions = m_contactPopup->actions(); + + m_contactPopup->setTitle(contact); + actions[0]->setText(contact); // popup "title" + actions[0]->setEnabled(false); + + actions[2]->setEnabled(!connected); // connect + actions[3]->setEnabled(connected); // disconnect + } - if (!rows.empty()) - { - int row = *rows.begin(); + QWidget* w = (QWidget*)sender(); + m_contactPopup->popup(w->mapToGlobal(pos)); + } - QStandardItem* check = m_contactsModel->item(row, 0); - QStandardItem* name = m_contactsModel->item(row, 1); - QStandardItem* host = m_contactsModel->item(row, 2); - bool connected = check->checkState() == Qt::Checked; - QString contact = QString("%1@%2").arg(name->text()).arg(host->text()); - QList actions = m_contactPopup->actions(); + void RvNetworkDialog::popupDisconnect(bool) + { + set rows = selectedContacts(); - m_contactPopup->setTitle(contact); - actions[0]->setText(contact); // popup "title" - actions[0]->setEnabled(false); + if (!rows.empty()) + { + int row = *rows.begin(); - actions[2]->setEnabled(!connected); // connect - actions[3]->setEnabled(connected); // disconnect - } + QStandardItem* name = m_contactsModel->item(row, 1); + QStandardItem* host = m_contactsModel->item(row, 2); + m_connectUI.hostnameLineEdit->setText(host->text()); - QWidget* w = (QWidget*)sender(); - m_contactPopup->popup(w->mapToGlobal(pos)); -} + QString contact = + QString("%1@%2").arg(name->text()).arg(host->text()); -void -RvNetworkDialog::popupDisconnect(bool) -{ - set rows = selectedContacts(); + if (confirmDisconnect(contact)) + { + m_client->signOff(contact); + m_client->disconnectFrom(contact); + } + } + } - if (!rows.empty()) + void RvNetworkDialog::popupConnect(bool) { - int row = *rows.begin(); + set rows = selectedContacts(); - QStandardItem* name = m_contactsModel->item(row, 1); - QStandardItem* host = m_contactsModel->item(row, 2); - m_connectUI.hostnameLineEdit->setText(host->text()); + if (!rows.empty()) + { + int row = *rows.begin(); - QString contact = QString("%1@%2").arg(name->text()).arg(host->text()); + QStandardItem* name = m_contactsModel->item(row, 1); + QStandardItem* host = m_contactsModel->item(row, 2); + m_connectUI.hostnameLineEdit->setText(host->text()); - if (confirmDisconnect(contact)) - { - m_client->signOff(contact); - m_client->disconnectFrom(contact); + startConnectDialog(name->text()); } } -} - -void -RvNetworkDialog::popupConnect(bool) -{ - set rows = selectedContacts(); - if (!rows.empty()) + void RvNetworkDialog::popupDelete(bool) { - int row = *rows.begin(); + // + // Delete all the selected rows + // - QStandardItem* name = m_contactsModel->item(row, 1); - QStandardItem* host = m_contactsModel->item(row, 2); - m_connectUI.hostnameLineEdit->setText(host->text()); + QModelIndexList selection = + m_ui.contactTreeView->selectionModel()->selectedIndexes(); - startConnectDialog(name->text()); - } -} + set rows; -void -RvNetworkDialog::popupDelete(bool) -{ - // - // Delete all the selected rows - // + for (int i = 0; i < selection.size(); i++) + { + const QModelIndex& index = selection[i]; + rows.insert(index.row()); + } - QModelIndexList selection = - m_ui.contactTreeView->selectionModel()->selectedIndexes(); + // + // Delete the rows in reverse order (since the other selected row + // numbers will not change). + // - set rows; + for (set::reverse_iterator i = rows.rbegin(); i != rows.rend(); + ++i) + { + m_contactsModel->removeRow(*i); + } - for (int i=0; i < selection.size(); i++) - { - const QModelIndex& index = selection[i]; - rows.insert(index.row()); + saveSettings(); } - // - // Delete the rows in reverse order (since the other selected row - // numbers will not change). - // - - for (set::reverse_iterator i = rows.rbegin(); - i != rows.rend(); - ++i) + void RvNetworkDialog::doubleClickContact(const QModelIndex& index) { - m_contactsModel->removeRow(*i); - } - - saveSettings(); -} - -void -RvNetworkDialog::doubleClickContact(const QModelIndex& index) -{ - // - // Don't respond if its double click on permissions (that causes - // editing). - // + // + // Don't respond if its double click on permissions (that causes + // editing). + // - if (index.column() == 3 || !index.isValid()) return; + if (index.column() == 3 || !index.isValid()) + return; - // - // Update the connect dialogs fields from the double clicked on - // item and start it up. - // + // + // Update the connect dialogs fields from the double clicked on + // item and start it up. + // - QStandardItem* check = m_contactsModel->item(index.row(), 0); - QStandardItem* name = m_contactsModel->item(index.row(), 1); - QStandardItem* host = m_contactsModel->item(index.row(), 2); + QStandardItem* check = m_contactsModel->item(index.row(), 0); + QStandardItem* name = m_contactsModel->item(index.row(), 1); + QStandardItem* host = m_contactsModel->item(index.row(), 2); - // - // If we're connected ask about disconnecting. Otherwise, set up - // the connection dialog - // + // + // If we're connected ask about disconnecting. Otherwise, set up + // the connection dialog + // - if (check->checkState() == Qt::Checked) - { - QString contact = QString("%1@%2").arg(name->text()).arg(host->text()); + if (check->checkState() == Qt::Checked) + { + QString contact = + QString("%1@%2").arg(name->text()).arg(host->text()); - if (confirmDisconnect(contact)) + if (confirmDisconnect(contact)) + { + m_client->disconnectFrom(contact); + } + } + else { - m_client->disconnectFrom(contact); + m_connectUI.hostnameLineEdit->setText(host->text()); + startConnectDialog(name->text()); } } - else - { - m_connectUI.hostnameLineEdit->setText(host->text()); - startConnectDialog(name->text()); - } -} - -void -RvNetworkDialog::contactError(const QString& contact, - const QString& machine, - const QString& msg) -{ - Session* s = targetSession(contact, false /*doDisconnect*/); - bool showContactError = true; - if (s) + void RvNetworkDialog::contactError(const QString& contact, + const QString& machine, + const QString& msg) { - const string r = s->userGenericEvent("remote-contact-error-show", - contact.toUtf8().constData(), ""); - showContactError = r != "no"; - } - - if (showContactError) - { - if (contact == "" || contact[0] == '@') + Session* s = targetSession(contact, false /*doDisconnect*/); + + bool showContactError = true; + if (s) { - QMessageBox::critical(this, "Network Error", - QString("Connection to %1:\n%2") - .arg(machine) - .arg(msg)); + const string r = s->userGenericEvent( + "remote-contact-error-show", contact.toUtf8().constData(), ""); + showContactError = r != "no"; } - else + + if (showContactError) { - QMessageBox::critical(this, "Network Error", - QString("Connection to %1:\n%3") - .arg(contact) - .arg(msg)); + if (contact == "" || contact[0] == '@') + { + QMessageBox::critical( + this, "Network Error", + QString("Connection to %1:\n%2").arg(machine).arg(msg)); + } + else + { + QMessageBox::critical( + this, "Network Error", + QString("Connection to %1:\n%3").arg(contact).arg(msg)); + } } - } - - if (!s) return; - s->userGenericEvent("remote-contact-error", contact.toUtf8().constData(), ""); -} - -void -RvNetworkDialog::sendSessionEvent(const QString& event, - const QString& contents, - const QString& sender) -{ - RvApp()->userGenericEventOnAll(event.toUtf8().data(), - contents.toUtf8().data(), - sender.toUtf8().data()); -} + if (!s) + return; -vector -RvNetworkDialog::contacts() const -{ - vector c; - - int n = m_contactsModel->rowCount(); + s->userGenericEvent("remote-contact-error", + contact.toUtf8().constData(), ""); + } - for (int i=0; i < n; i++) + void RvNetworkDialog::sendSessionEvent(const QString& event, + const QString& contents, + const QString& sender) { - c.push_back(m_contactsModel->item(i, 1)->text().toUtf8().data()); + RvApp()->userGenericEventOnAll(event.toUtf8().data(), + contents.toUtf8().data(), + sender.toUtf8().data()); } - return c; -} + vector RvNetworkDialog::contacts() const + { + vector c; -vector -RvNetworkDialog::connections() const -{ - vector c; - - int n = m_contactsModel->rowCount(); + int n = m_contactsModel->rowCount(); - for (int i=0; i < n; i++) - { - if (m_contactsModel->item(i, 0)->checkState() == Qt::Checked) + for (int i = 0; i < n; i++) { - QString cname = m_contactsModel->item(i, 1)->text(); - cname += "@"; - cname += m_contactsModel->item(i, 2)->text(); - c.push_back(cname.toUtf8().data()); + c.push_back(m_contactsModel->item(i, 1)->text().toUtf8().data()); } + + return c; } - return c; -} + vector RvNetworkDialog::connections() const + { + vector c; -vector -RvNetworkDialog::sessions() -{ - vector c; - - int n = m_contactsModel->rowCount(); + int n = m_contactsModel->rowCount(); - for (int i=0; i < n; i++) - { - if (m_contactsModel->item(i, 0)->checkState() == Qt::Checked) + for (int i = 0; i < n; i++) { - QString cname = m_contactsModel->item(i, 1)->text(); - cname += "@"; - cname += m_contactsModel->item(i, 2)->text(); - c.push_back(m_sessionMap[cname.toUtf8().data()]); + if (m_contactsModel->item(i, 0)->checkState() == Qt::Checked) + { + QString cname = m_contactsModel->item(i, 1)->text(); + cname += "@"; + cname += m_contactsModel->item(i, 2)->text(); + c.push_back(cname.toUtf8().data()); + } } + + return c; } - return c; -} + vector RvNetworkDialog::sessions() + { + vector c; -vector -RvNetworkDialog::applications() const -{ - vector c; - - int n = m_contactsModel->rowCount(); + int n = m_contactsModel->rowCount(); - for (int i=0; i < n; i++) - { - if (m_contactsModel->item(i, 0)->checkState() == Qt::Checked) + for (int i = 0; i < n; i++) { - QString capp = m_contactsModel->item(i, 4)->text(); - c.push_back(capp.toUtf8().data()); + if (m_contactsModel->item(i, 0)->checkState() == Qt::Checked) + { + QString cname = m_contactsModel->item(i, 1)->text(); + cname += "@"; + cname += m_contactsModel->item(i, 2)->text(); + c.push_back(m_sessionMap[cname.toUtf8().data()]); + } } + + return c; } - return c; -} + vector RvNetworkDialog::applications() const + { + vector c; -int -RvNetworkDialog::myPort() -{ - return m_ui.portLineEdit->text().toInt(); -} + int n = m_contactsModel->rowCount(); -void -RvNetworkDialog::sessionDeleted(const char *sessionName) -{ - DB ("sessionDeleted " << sessionName); - string sstr(sessionName); - if (!sstr.size()) return; - vector contacts; + for (int i = 0; i < n; i++) + { + if (m_contactsModel->item(i, 0)->checkState() == Qt::Checked) + { + QString capp = m_contactsModel->item(i, 4)->text(); + c.push_back(capp.toUtf8().data()); + } + } - for (SessionMap::iterator i = m_sessionMap.begin(); i != m_sessionMap.end(); ++i) - { - if ((*i).second == sstr) contacts.push_back ((*i).first); + return c; } - for (int i = 0; i < contacts.size(); ++i) + int RvNetworkDialog::myPort() { return m_ui.portLineEdit->text().toInt(); } + + void RvNetworkDialog::sessionDeleted(const char* sessionName) { - DB ("disconnecting from " << contacts[i]); - QList items = - m_ui.participantList->findItems(contacts[i].c_str(), Qt::MatchExactly); - for (int j=0; j < items.size(); j++) delete items[i]; - - m_sessionMap.erase(contacts[i]); - if (m_client) - { - m_client->signOff(contacts[i].c_str()); - m_client->disconnectFrom(contacts[i].c_str()); - } - } -} + DB("sessionDeleted " << sessionName); + string sstr(sessionName); + if (!sstr.size()) + return; + vector contacts; -void -RvNetworkDialog::spoofConnectionStream(const QString& fileName, float timeScale, bool verbose) -{ - // XXX mem leak - StreamConnection* stream = new StreamConnection(this, true); + for (SessionMap::iterator i = m_sessionMap.begin(); + i != m_sessionMap.end(); ++i) + { + if ((*i).second == sstr) + contacts.push_back((*i).first); + } + + for (int i = 0; i < contacts.size(); ++i) + { + DB("disconnecting from " << contacts[i]); + QList items = m_ui.participantList->findItems( + contacts[i].c_str(), Qt::MatchExactly); + for (int j = 0; j < items.size(); j++) + delete items[i]; + + m_sessionMap.erase(contacts[i]); + if (m_client) + { + m_client->signOff(contacts[i].c_str()); + m_client->disconnectFrom(contacts[i].c_str()); + } + } + } - if (! stream->spoofStream(UTF8::qconvert(fileName), verbose)) return; + void RvNetworkDialog::spoofConnectionStream(const QString& fileName, + float timeScale, bool verbose) + { + // XXX mem leak + StreamConnection* stream = new StreamConnection(this, true); - requestConnection(stream); + if (!stream->spoofStream(UTF8::qconvert(fileName), verbose)) + return; - newRemoteContact(stream->remoteContactName()); + requestConnection(stream); - connect(stream, SIGNAL(newData(const QString&, - const QString&, - const QByteArray&)), - this, SLOT(newData(const QString&, - const QString&, - const QByteArray&))); + newRemoteContact(stream->remoteContactName()); - connect(stream, SIGNAL(newMessage(const QString &, const QString &)), - this, SLOT(newMessage(const QString &, const QString &))); + connect( + stream, + SIGNAL(newData(const QString&, const QString&, const QByteArray&)), + this, + SLOT(newData(const QString&, const QString&, const QByteArray&))); - stream->startSpoofing(timeScale); -} + connect(stream, SIGNAL(newMessage(const QString&, const QString&)), + this, SLOT(newMessage(const QString&, const QString&))); + stream->startSpoofing(timeScale); + } -} // Rv +} // namespace Rv diff --git a/src/lib/app/RvCommon/RvPreferences.cpp b/src/lib/app/RvCommon/RvPreferences.cpp index c637be685..c33164197 100644 --- a/src/lib/app/RvCommon/RvPreferences.cpp +++ b/src/lib/app/RvCommon/RvPreferences.cpp @@ -1,9 +1,9 @@ //****************************************************************************** -// Copyright (c) 2008 Tweak Inc. +// Copyright (c) 2008 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #ifdef PLATFORM_WINDOWS @@ -61,307 +61,316 @@ extern const char* rv_mac_dark; extern const char* rv_linux_dark; #endif -namespace Rv { -using namespace std; -using namespace TwkApp; -using namespace IPCore; -using namespace TwkQtCoreUtil; - -bool ScrollEventEater::eventFilter(QObject *obj, QEvent *event) -{ - if (event->type() == QEvent::Wheel) return true; - - return QObject::eventFilter(obj, event); -} - -static const char* CompositeRenderer = "Composite"; -static const char* DirectRenderer = "Direct"; -static const char* AppleRenderer = "Apple Composite"; -static const char* Area = "area"; -static const char* Cubic = "cubic"; -static const char* Linear = "linear"; -static const char* Nearest = "nearest"; -static const char* StereoAnaglyph = "anaglyph"; -static const char* StereoLumAnaglyph = "lumanaglyph"; -static const char* StereoPair = "pair"; -static const char* StereoMirror = "mirror"; -static const char* StereoLeft = "left"; -static const char* StereoRight = "right"; -static const char* StereoChecker = "checker"; -static const char* StereoScanline = "scanline"; -static const char* StereoHardware = "hardware"; -static const char* Solid0 = "black"; -static const char* Solid18 = "grey18"; -static const char* Solid50 = "grey50"; -static const char* Solid100 = "white"; -static const char* Checker = "checker"; -static const char* CrossHatch = "crosshatch"; -static const char* RGB8 = "RGB8"; -static const char* RGBA8 = "RGBA8"; -static const char* RGB8_PLANAR = "RGB8_PLANAR"; -static const char* RGB10_A2 = "RGB10_A2"; -static const char* A2_BGR10 = "A2_BGR10"; -static const char* RGB16 = "RGB16"; -static const char* RGBA16 = "RGBA16"; -static const char* RGB16_PLANAR = "RGB16_PLANAR"; - -RvPreferences::RvPreferences(QWidget* parent) - : QDialog(parent, Qt::Window), - PackageManager(), - m_showHiddenPackages(false), - m_updated(false), - m_currentVideoModule(-1), - m_currentVideoDevice(-1), - m_lockPresentCheck(false), - m_packageLocationDialog(0), - m_videoLatencyDialog(0) +namespace Rv { - // - // We don't want wheel events or other scrolling to affect the combo - // boxes, so filter them out. - // - ScrollEventEater *scrollEventEater = new ScrollEventEater(this); + using namespace std; + using namespace TwkApp; + using namespace IPCore; + using namespace TwkQtCoreUtil; + + bool ScrollEventEater::eventFilter(QObject* obj, QEvent* event) + { + if (event->type() == QEvent::Wheel) + return true; + + return QObject::eventFilter(obj, event); + } + + static const char* CompositeRenderer = "Composite"; + static const char* DirectRenderer = "Direct"; + static const char* AppleRenderer = "Apple Composite"; + static const char* Area = "area"; + static const char* Cubic = "cubic"; + static const char* Linear = "linear"; + static const char* Nearest = "nearest"; + static const char* StereoAnaglyph = "anaglyph"; + static const char* StereoLumAnaglyph = "lumanaglyph"; + static const char* StereoPair = "pair"; + static const char* StereoMirror = "mirror"; + static const char* StereoLeft = "left"; + static const char* StereoRight = "right"; + static const char* StereoChecker = "checker"; + static const char* StereoScanline = "scanline"; + static const char* StereoHardware = "hardware"; + static const char* Solid0 = "black"; + static const char* Solid18 = "grey18"; + static const char* Solid50 = "grey50"; + static const char* Solid100 = "white"; + static const char* Checker = "checker"; + static const char* CrossHatch = "crosshatch"; + static const char* RGB8 = "RGB8"; + static const char* RGBA8 = "RGBA8"; + static const char* RGB8_PLANAR = "RGB8_PLANAR"; + static const char* RGB10_A2 = "RGB10_A2"; + static const char* A2_BGR10 = "A2_BGR10"; + static const char* RGB16 = "RGB16"; + static const char* RGBA16 = "RGBA16"; + static const char* RGB16_PLANAR = "RGB16_PLANAR"; + + RvPreferences::RvPreferences(QWidget* parent) + : QDialog(parent, Qt::Window) + , PackageManager() + , m_showHiddenPackages(false) + , m_updated(false) + , m_currentVideoModule(-1) + , m_currentVideoDevice(-1) + , m_lockPresentCheck(false) + , m_packageLocationDialog(0) + , m_videoLatencyDialog(0) + { + // + // We don't want wheel events or other scrolling to affect the combo + // boxes, so filter them out. + // + ScrollEventEater* scrollEventEater = new ScrollEventEater(this); - m_ui.setupUi(this); - connect(m_ui.exrAutoThreadsToggle, SIGNAL(stateChanged(int)), - this, SLOT(exrAutoThreads(int))); - connect(m_ui.exrNumThreadsEdit, SIGNAL(textChanged(const QString&)), - this, SLOT(exrThreadNumChanged(const QString&))); - setWindowTitle(UI_APPLICATION_NAME " Preferences"); + m_ui.setupUi(this); + connect(m_ui.exrAutoThreadsToggle, SIGNAL(stateChanged(int)), this, + SLOT(exrAutoThreads(int))); + connect(m_ui.exrNumThreadsEdit, SIGNAL(textChanged(const QString&)), + this, SLOT(exrThreadNumChanged(const QString&))); + setWindowTitle(UI_APPLICATION_NAME " Preferences"); #ifndef PLATFORM_DARWIN - m_ui.appleClientStorageToggle->setEnabled(false); + m_ui.appleClientStorageToggle->setEnabled(false); #endif - m_packageModel = new QStandardItemModel(); - m_ui.extTreeView->setModel(m_packageModel); - m_ui.extTreeView->setAlternatingRowColors(true); - QItemSelectionModel* s = m_ui.extTreeView->selectionModel(); + m_packageModel = new QStandardItemModel(); + m_ui.extTreeView->setModel(m_packageModel); + m_ui.extTreeView->setAlternatingRowColors(true); + QItemSelectionModel* s = m_ui.extTreeView->selectionModel(); - connect(m_ui.stylusAsMouseToggle, SIGNAL(stateChanged(int)), - this, SLOT(stylusAsMouseChanged(int))); + connect(m_ui.stylusAsMouseToggle, SIGNAL(stateChanged(int)), this, + SLOT(stylusAsMouseChanged(int))); - connect(m_ui.startupResizeToggle, SIGNAL(stateChanged(int)), - this, SLOT(startupResizeChanged(int))); + connect(m_ui.startupResizeToggle, SIGNAL(stateChanged(int)), this, + SLOT(startupResizeChanged(int))); - connect(s, SIGNAL(selectionChanged(const QItemSelection&,const QItemSelection&)), - this, SLOT(packageSelection(const QItemSelection&, const QItemSelection&))); + connect(s, + SIGNAL(selectionChanged(const QItemSelection&, + const QItemSelection&)), + this, + SLOT(packageSelection(const QItemSelection&, + const QItemSelection&))); - connect(m_ui.extTreeView, SIGNAL(clicked(QModelIndex)), - this, SLOT(clickedPackage(QModelIndex))); + connect(m_ui.extTreeView, SIGNAL(clicked(QModelIndex)), this, + SLOT(clickedPackage(QModelIndex))); - connect(m_ui.extAddButton, SIGNAL(clicked(bool)), this, SLOT(addPackage(bool))); - connect(m_ui.extRemoveButton, SIGNAL(clicked(bool)), this, SLOT(removePackage(bool))); - connect(m_ui.extShowHiddenToggle, SIGNAL(clicked(bool)), this, SLOT(showHiddenPackages(bool))); + connect(m_ui.extAddButton, SIGNAL(clicked(bool)), this, + SLOT(addPackage(bool))); + connect(m_ui.extRemoveButton, SIGNAL(clicked(bool)), this, + SLOT(removePackage(bool))); + connect(m_ui.extShowHiddenToggle, SIGNAL(clicked(bool)), this, + SLOT(showHiddenPackages(bool))); - connect(m_ui.audioModuleCombo, SIGNAL(activated(int)), - this, SLOT(audioModuleChanged(int))); - m_ui.audioModuleCombo->installEventFilter(scrollEventEater); + connect(m_ui.audioModuleCombo, SIGNAL(activated(int)), this, + SLOT(audioModuleChanged(int))); + m_ui.audioModuleCombo->installEventFilter(scrollEventEater); - connect(m_ui.audioDeviceCombo, SIGNAL(activated(int)), - this, SLOT(audioDeviceChanged(int))); - m_ui.audioDeviceCombo->installEventFilter(scrollEventEater); + connect(m_ui.audioDeviceCombo, SIGNAL(activated(int)), this, + SLOT(audioDeviceChanged(int))); + m_ui.audioDeviceCombo->installEventFilter(scrollEventEater); - connect(m_ui.audioDeviceRateCombo, SIGNAL(activated(int)), - this, SLOT(audioRateChanged(int))); - m_ui.audioDeviceRateCombo->installEventFilter(scrollEventEater); + connect(m_ui.audioDeviceRateCombo, SIGNAL(activated(int)), this, + SLOT(audioRateChanged(int))); + m_ui.audioDeviceRateCombo->installEventFilter(scrollEventEater); - connect(m_ui.audioDeviceFormatCombo, SIGNAL(activated(int)), - this, SLOT(audioFormatChanged(int))); - m_ui.audioDeviceFormatCombo->installEventFilter(scrollEventEater); + connect(m_ui.audioDeviceFormatCombo, SIGNAL(activated(int)), this, + SLOT(audioFormatChanged(int))); + m_ui.audioDeviceFormatCombo->installEventFilter(scrollEventEater); - connect(m_ui.audioDeviceLayoutCombo, SIGNAL(activated(int)), - this, SLOT(audioChannelsChanged(int))); - m_ui.audioDeviceLayoutCombo->installEventFilter(scrollEventEater); + connect(m_ui.audioDeviceLayoutCombo, SIGNAL(activated(int)), this, + SLOT(audioChannelsChanged(int))); + m_ui.audioDeviceLayoutCombo->installEventFilter(scrollEventEater); - connect(m_ui.audioHoldOpenToggle, SIGNAL(stateChanged(int)), - this, SLOT(audioHoldOpenChanged(int))); + connect(m_ui.audioHoldOpenToggle, SIGNAL(stateChanged(int)), this, + SLOT(audioHoldOpenChanged(int))); - connect(m_ui.audioHardwareLockToggle, SIGNAL(stateChanged(int)), - this, SLOT(audioVideoSyncChanged(int))); + connect(m_ui.audioHardwareLockToggle, SIGNAL(stateChanged(int)), this, + SLOT(audioVideoSyncChanged(int))); - connect(m_ui.audioPreRollToggle, SIGNAL(stateChanged(int)), - this, SLOT(audioPreRollChanged(int))); + connect(m_ui.audioPreRollToggle, SIGNAL(stateChanged(int)), this, + SLOT(audioPreRollChanged(int))); - connect(m_ui.audioDevicePacketEdit, SIGNAL(editingFinished()), - this, SLOT(audioDevicePacketChanged())); + connect(m_ui.audioDevicePacketEdit, SIGNAL(editingFinished()), this, + SLOT(audioDevicePacketChanged())); - connect(m_ui.audioCachePacketEdit, SIGNAL(editingFinished()), - this, SLOT(audioCachePacketChanged())); + connect(m_ui.audioCachePacketEdit, SIGNAL(editingFinished()), this, + SLOT(audioCachePacketChanged())); - connect(m_ui.audioGlobalOffsetEdit, SIGNAL(editingFinished()), - this, SLOT(audioOffsetFinished())); + connect(m_ui.audioGlobalOffsetEdit, SIGNAL(editingFinished()), this, + SLOT(audioOffsetFinished())); - connect(m_ui.audioDeviceLatencyEdit, SIGNAL(editingFinished()), - this, SLOT(audioDeviceLatencyFinished())); + connect(m_ui.audioDeviceLatencyEdit, SIGNAL(editingFinished()), this, + SLOT(audioDeviceLatencyFinished())); +// Only connect the update slot to the architecture appropriate signal +#ifdef ARCH_IA32 + connect(m_ui.lookAheadCacheSize32Edit, SIGNAL(editingFinished()), this, + SLOT(lookaheadCacheSizeFinisihed())); - // Only connect the update slot to the architecture appropriate signal - #ifdef ARCH_IA32 - connect(m_ui.lookAheadCacheSize32Edit, SIGNAL(editingFinished()), - this, SLOT(lookaheadCacheSizeFinisihed())); - - connect(m_ui.regionCacheSize32Edit, SIGNAL(editingFinished()), - this, SLOT(regionCacheSizeFinisihed())); - #else - connect(m_ui.lookAheadCacheSize64Edit, SIGNAL(editingFinished()), - this, SLOT(lookaheadCacheSizeFinisihed())); + connect(m_ui.regionCacheSize32Edit, SIGNAL(editingFinished()), this, + SLOT(regionCacheSizeFinisihed())); +#else + connect(m_ui.lookAheadCacheSize64Edit, SIGNAL(editingFinished()), this, + SLOT(lookaheadCacheSizeFinisihed())); - connect(m_ui.regionCacheSize64Edit, SIGNAL(editingFinished()), - this, SLOT(regionCacheSizeFinisihed())); - #endif + connect(m_ui.regionCacheSize64Edit, SIGNAL(editingFinished()), this, + SLOT(regionCacheSizeFinisihed())); +#endif - connect(m_ui.bufferWaitEdit, SIGNAL(editingFinished()), - this, SLOT(bufferWaitFinished())); + connect(m_ui.bufferWaitEdit, SIGNAL(editingFinished()), this, + SLOT(bufferWaitFinished())); - connect(m_ui.lookBehindFracEdit, SIGNAL(editingFinished()), - this, SLOT(lookBehindFinished())); + connect(m_ui.lookBehindFracEdit, SIGNAL(editingFinished()), this, + SLOT(lookBehindFinished())); - connect(m_ui.cacheOutsideRegionToggle, SIGNAL(stateChanged(int)), - this, SLOT(cacheOutsideRegionChanged(int))); + connect(m_ui.cacheOutsideRegionToggle, SIGNAL(stateChanged(int)), this, + SLOT(cacheOutsideRegionChanged(int))); - connect(m_ui.rthreadEdit, SIGNAL(editingFinished()), - this, SLOT(rthreadFinished())); + connect(m_ui.rthreadEdit, SIGNAL(editingFinished()), this, + SLOT(rthreadFinished())); - connect(m_ui.bitDepthCombo, SIGNAL(activated(int)), - this, SLOT(bitDepthChanged(int))); - m_ui.bitDepthCombo->installEventFilter(scrollEventEater); + connect(m_ui.bitDepthCombo, SIGNAL(activated(int)), this, + SLOT(bitDepthChanged(int))); + m_ui.bitDepthCombo->installEventFilter(scrollEventEater); - connect(m_ui.allowFloatToggle, SIGNAL(stateChanged(int)), - this, SLOT(allowFloatChanged(int))); + connect(m_ui.allowFloatToggle, SIGNAL(stateChanged(int)), this, + SLOT(allowFloatChanged(int))); - connect(m_ui.newGLSLlutInterpToggle, SIGNAL(stateChanged(int)), - this, SLOT(newGLSLlutInterpChanged(int))); + connect(m_ui.newGLSLlutInterpToggle, SIGNAL(stateChanged(int)), this, + SLOT(newGLSLlutInterpChanged(int))); - connect(m_ui.swapScanlinesToggle, SIGNAL(stateChanged(int)), - this, SLOT(swapScanlinesChanged(int))); + connect(m_ui.swapScanlinesToggle, SIGNAL(stateChanged(int)), this, + SLOT(swapScanlinesChanged(int))); - connect(m_ui.prefetchToggle, SIGNAL(stateChanged(int)), - this, SLOT(prefetchChanged(int))); + connect(m_ui.prefetchToggle, SIGNAL(stateChanged(int)), this, + SLOT(prefetchChanged(int))); - connect(m_ui.appleClientStorageToggle, SIGNAL(stateChanged(int)), - this, SLOT(appleClientStorageChanged(int))); + connect(m_ui.appleClientStorageToggle, SIGNAL(stateChanged(int)), this, + SLOT(appleClientStorageChanged(int))); - connect(m_ui.useThreadedUploadToggle, SIGNAL(stateChanged(int)), - this, SLOT(useThreadedUploadChanged(int))); + connect(m_ui.useThreadedUploadToggle, SIGNAL(stateChanged(int)), this, + SLOT(useThreadedUploadChanged(int))); - connect(m_ui.displayVideoSyncButton, SIGNAL(stateChanged(int)), - this, SLOT(videoSyncChanged(int))); + connect(m_ui.displayVideoSyncButton, SIGNAL(stateChanged(int)), this, + SLOT(videoSyncChanged(int))); - connect(m_ui.configureVideoLatencyButton, SIGNAL(clicked()), - this, SLOT(configVideoLatency())); + connect(m_ui.configureVideoLatencyButton, SIGNAL(clicked()), this, + SLOT(configVideoLatency())); - connect(m_ui.exrRGBAToggle, SIGNAL(stateChanged(int)), - this, SLOT(exrRGBAChanged(int))); + connect(m_ui.exrRGBAToggle, SIGNAL(stateChanged(int)), this, + SLOT(exrRGBAChanged(int))); - connect(m_ui.exrInheritToggle, SIGNAL(stateChanged(int)), - this, SLOT(exrInheritChanged(int))); + connect(m_ui.exrInheritToggle, SIGNAL(stateChanged(int)), this, + SLOT(exrInheritChanged(int))); - connect(m_ui.exrPlanar3ChannelToggle, SIGNAL(stateChanged(int)), - this, SLOT(exrPlanar3ChannelChanged(int))); + connect(m_ui.exrPlanar3ChannelToggle, SIGNAL(stateChanged(int)), this, + SLOT(exrPlanar3ChannelChanged(int))); - connect(m_ui.exrNoOneChannelToggle, SIGNAL(stateChanged(int)), - this, SLOT(exrNoOneChannelChanged(int))); + connect(m_ui.exrNoOneChannelToggle, SIGNAL(stateChanged(int)), this, + SLOT(exrNoOneChannelChanged(int))); - connect(m_ui.exrReadWindowIsDisplayWindowToggle, SIGNAL(stateChanged(int)), - this, SLOT(exrReadWindowIsDisplayWindowChanged(int))); + connect(m_ui.exrReadWindowIsDisplayWindowToggle, + SIGNAL(stateChanged(int)), this, + SLOT(exrReadWindowIsDisplayWindowChanged(int))); - connect(m_ui.exrNumThreadsEdit, SIGNAL(editingFinished()), - this, SLOT(exrNumThreadsFinished())); + connect(m_ui.exrNumThreadsEdit, SIGNAL(editingFinished()), this, + SLOT(exrNumThreadsFinished())); - connect(m_ui.exrChunkSizeEdit, SIGNAL(editingFinished()), - this, SLOT(exrChunkSizeFinished())); + connect(m_ui.exrChunkSizeEdit, SIGNAL(editingFinished()), this, + SLOT(exrChunkSizeFinished())); - connect(m_ui.exrMaxInFlightEdit, SIGNAL(editingFinished()), - this, SLOT(exrMaxInFlightFinished())); + connect(m_ui.exrMaxInFlightEdit, SIGNAL(editingFinished()), this, + SLOT(exrMaxInFlightFinished())); - connect(m_ui.exrIOMethodCombo, SIGNAL(activated(int)), - this, SLOT(exrIOMethodChanged(int))); - m_ui.exrIOMethodCombo->installEventFilter(scrollEventEater); + connect(m_ui.exrIOMethodCombo, SIGNAL(activated(int)), this, + SLOT(exrIOMethodChanged(int))); + m_ui.exrIOMethodCombo->installEventFilter(scrollEventEater); - connect(m_ui.exrReadWindowCombo, SIGNAL(activated(int)), - this, SLOT(exrReadWindowChanged(int))); - m_ui.exrReadWindowCombo->installEventFilter(scrollEventEater); + connect(m_ui.exrReadWindowCombo, SIGNAL(activated(int)), this, + SLOT(exrReadWindowChanged(int))); + m_ui.exrReadWindowCombo->installEventFilter(scrollEventEater); - connect(m_ui.cinChunkSizeEdit, SIGNAL(editingFinished()), - this, SLOT(cinChunkSizeFinished())); + connect(m_ui.cinChunkSizeEdit, SIGNAL(editingFinished()), this, + SLOT(cinChunkSizeFinished())); - connect(m_ui.cinMaxInFlightEdit, SIGNAL(editingFinished()), - this, SLOT(cinMaxInFlightFinished())); + connect(m_ui.cinMaxInFlightEdit, SIGNAL(editingFinished()), this, + SLOT(cinMaxInFlightFinished())); - connect(m_ui.cinIOMethodCombo, SIGNAL(activated(int)), - this, SLOT(cinIOMethodChanged(int))); - m_ui.cinIOMethodCombo->installEventFilter(scrollEventEater); + connect(m_ui.cinIOMethodCombo, SIGNAL(activated(int)), this, + SLOT(cinIOMethodChanged(int))); + m_ui.cinIOMethodCombo->installEventFilter(scrollEventEater); - connect(m_ui.cinDisplayPixelCombo, SIGNAL(activated(int)), - this, SLOT(cinPixelsChanged(int))); - m_ui.cinDisplayPixelCombo->installEventFilter(scrollEventEater); + connect(m_ui.cinDisplayPixelCombo, SIGNAL(activated(int)), this, + SLOT(cinPixelsChanged(int))); + m_ui.cinDisplayPixelCombo->installEventFilter(scrollEventEater); - connect(m_ui.cinChromaToggle, SIGNAL(stateChanged(int)), - this, SLOT(cinChromaChanged(int))); + connect(m_ui.cinChromaToggle, SIGNAL(stateChanged(int)), this, + SLOT(cinChromaChanged(int))); - connect(m_ui.dpxChunkSizeEdit, SIGNAL(editingFinished()), - this, SLOT(dpxChunkSizeFinished())); + connect(m_ui.dpxChunkSizeEdit, SIGNAL(editingFinished()), this, + SLOT(dpxChunkSizeFinished())); - connect(m_ui.dpxMaxInFlightEdit, SIGNAL(editingFinished()), - this, SLOT(dpxMaxInFlightFinished())); + connect(m_ui.dpxMaxInFlightEdit, SIGNAL(editingFinished()), this, + SLOT(dpxMaxInFlightFinished())); - connect(m_ui.dpxIOMethodCombo, SIGNAL(activated(int)), - this, SLOT(dpxIOMethodChanged(int))); - m_ui.dpxIOMethodCombo->installEventFilter(scrollEventEater); + connect(m_ui.dpxIOMethodCombo, SIGNAL(activated(int)), this, + SLOT(dpxIOMethodChanged(int))); + m_ui.dpxIOMethodCombo->installEventFilter(scrollEventEater); - connect(m_ui.dpxDisplayPixelCombo, SIGNAL(activated(int)), - this, SLOT(dpxPixelsChanged(int))); - m_ui.dpxDisplayPixelCombo->installEventFilter(scrollEventEater); + connect(m_ui.dpxDisplayPixelCombo, SIGNAL(activated(int)), this, + SLOT(dpxPixelsChanged(int))); + m_ui.dpxDisplayPixelCombo->installEventFilter(scrollEventEater); - connect(m_ui.dpxChromaToggle, SIGNAL(stateChanged(int)), - this, SLOT(dpxChromaChanged(int))); + connect(m_ui.dpxChromaToggle, SIGNAL(stateChanged(int)), this, + SLOT(dpxChromaChanged(int))); - connect(m_ui.tgaChunkSizeEdit, SIGNAL(editingFinished()), - this, SLOT(tgaChunkSizeFinished())); + connect(m_ui.tgaChunkSizeEdit, SIGNAL(editingFinished()), this, + SLOT(tgaChunkSizeFinished())); - connect(m_ui.tgaMaxInFlightEdit, SIGNAL(editingFinished()), - this, SLOT(tgaMaxInFlightFinished())); + connect(m_ui.tgaMaxInFlightEdit, SIGNAL(editingFinished()), this, + SLOT(tgaMaxInFlightFinished())); - connect(m_ui.tgaIOMethodCombo, SIGNAL(activated(int)), - this, SLOT(tgaIOMethodChanged(int))); - m_ui.tgaIOMethodCombo->installEventFilter(scrollEventEater); + connect(m_ui.tgaIOMethodCombo, SIGNAL(activated(int)), this, + SLOT(tgaIOMethodChanged(int))); + m_ui.tgaIOMethodCombo->installEventFilter(scrollEventEater); - connect(m_ui.tifChunkSizeEdit, SIGNAL(editingFinished()), - this, SLOT(tiffChunkSizeFinished())); + connect(m_ui.tifChunkSizeEdit, SIGNAL(editingFinished()), this, + SLOT(tiffChunkSizeFinished())); - connect(m_ui.tifMaxInFlightEdit, SIGNAL(editingFinished()), - this, SLOT(tiffMaxInFlightFinished())); + connect(m_ui.tifMaxInFlightEdit, SIGNAL(editingFinished()), this, + SLOT(tiffMaxInFlightFinished())); - connect(m_ui.tifIOMethodCombo, SIGNAL(activated(int)), - this, SLOT(tiffIOMethodChanged(int))); - m_ui.tifIOMethodCombo->installEventFilter(scrollEventEater); + connect(m_ui.tifIOMethodCombo, SIGNAL(activated(int)), this, + SLOT(tiffIOMethodChanged(int))); + m_ui.tifIOMethodCombo->installEventFilter(scrollEventEater); - connect(m_ui.jpegChunkSizeEdit, SIGNAL(editingFinished()), - this, SLOT(jpegChunkSizeFinished())); + connect(m_ui.jpegChunkSizeEdit, SIGNAL(editingFinished()), this, + SLOT(jpegChunkSizeFinished())); - connect(m_ui.jpegMaxInFlightEdit, SIGNAL(editingFinished()), - this, SLOT(jpegMaxInFlightFinished())); + connect(m_ui.jpegMaxInFlightEdit, SIGNAL(editingFinished()), this, + SLOT(jpegMaxInFlightFinished())); - connect(m_ui.jpegIOMethodCombo, SIGNAL(activated(int)), - this, SLOT(jpegIOMethodChanged(int))); - m_ui.jpegIOMethodCombo->installEventFilter(scrollEventEater); + connect(m_ui.jpegIOMethodCombo, SIGNAL(activated(int)), this, + SLOT(jpegIOMethodChanged(int))); + m_ui.jpegIOMethodCombo->installEventFilter(scrollEventEater); - connect(m_ui.jpegRGBAToggle, SIGNAL(stateChanged(int)), - this, SLOT(jpegRGBAChanged(int))); + connect(m_ui.jpegRGBAToggle, SIGNAL(stateChanged(int)), this, + SLOT(jpegRGBAChanged(int))); - connect(m_ui.displayOutputCombo, SIGNAL(activated(int)), - this, SLOT(displayOutputChanged(int))); + connect(m_ui.displayOutputCombo, SIGNAL(activated(int)), this, + SLOT(displayOutputChanged(int))); - connect(m_ui.fontSizeSpinBox, SIGNAL(editingFinished()), - this, SLOT(fontChanged())); + connect(m_ui.fontSizeSpinBox, SIGNAL(editingFinished()), this, + SLOT(fontChanged())); - connect(m_ui.fontSize2SpinBox, SIGNAL(editingFinished()), - this, SLOT(fontChanged())); + connect(m_ui.fontSize2SpinBox, SIGNAL(editingFinished()), this, + SLOT(fontChanged())); - m_ui.displayOutputCombo->installEventFilter(scrollEventEater); + m_ui.displayOutputCombo->installEventFilter(scrollEventEater); - #ifdef PLATFORM_WINDOWS +#ifdef PLATFORM_WINDOWS m_ui.exrMaxInFlightEdit->setEnabled(false); m_ui.cinMaxInFlightEdit->setEnabled(false); m_ui.dpxMaxInFlightEdit->setEnabled(false); @@ -375,3665 +384,4245 @@ RvPreferences::RvPreferences(QWidget* parent) m_ui.tgaMaxInFlightLabel->setEnabled(false); m_ui.tifMaxInFlightLabel->setEnabled(false); m_ui.jpegMaxInFlightLabel->setEnabled(false); - #endif - - m_ui.extRemoveButton->setEnabled(false); - m_ui.extTextBrowser->zoomOut(); - - connect(m_ui.videoModuleCombo, SIGNAL(activated(int)), this, SLOT(videoModuleChanged(int))); - connect(m_ui.videoDeviceCombo, SIGNAL(activated(int)), this, SLOT(videoDeviceChanged(int))); - connect(m_ui.videoFormatCombo, SIGNAL(activated(int)), this, SLOT(videoFormatChanged(int))); - connect(m_ui.video4KTransportCombo, SIGNAL(activated(int)), this, SLOT(video4KTransportChanged(int))); - connect(m_ui.videoAudioFormatCombo, SIGNAL(activated(int)), this, SLOT(videoAudioFormatChanged(int))); - connect(m_ui.dataFormatCombo, SIGNAL(activated(int)), this, SLOT(videoDataFormatChanged(int))); - connect(m_ui.syncMethodCombo, SIGNAL(activated(int)), this, SLOT(syncMethodChanged(int))); - connect(m_ui.syncSourceCombo, SIGNAL(activated(int)), this, SLOT(syncSourceChanged(int))); - connect(m_ui.videoAudioDeviceCheckBox, SIGNAL(stateChanged(int)), this, SLOT(videoAudioCheckBoxChanged(int))); - connect(m_ui.videoSwapStereoEyesCheckBox, SIGNAL(stateChanged(int)), this, SLOT(videoSwapStereoEyesChanged(int))); - connect(m_ui.useVideoLatencyCheckBox, SIGNAL(stateChanged(int)), this, SLOT(videoUseLatencyCheckBoxChanged(int))); - connect(m_ui.presentationCheckBox, SIGNAL(stateChanged(int)), this, SLOT(presentationCheckBoxChanged(int))); - connect(m_ui.additionalOptionsEdit, SIGNAL(textChanged()), this, SLOT(videoAdditionalOptionsChanged())); - - connect(m_ui.moduleProfileCombo, SIGNAL(activated(int)), this, SLOT(modProfileChanged(int))); - connect(m_ui.deviceProfileCombo, SIGNAL(activated(int)), this, SLOT(devProfileChanged(int))); - connect(m_ui.formatProfileCombo, SIGNAL(activated(int)), this, SLOT(formatProfileChanged(int))); - - m_ui.videoModuleCombo->installEventFilter(scrollEventEater); - m_ui.videoDeviceCombo->installEventFilter(scrollEventEater); - m_ui.videoFormatCombo->installEventFilter(scrollEventEater); - m_ui.video4KTransportCombo->installEventFilter(scrollEventEater); - m_ui.videoAudioFormatCombo->installEventFilter(scrollEventEater); - m_ui.dataFormatCombo->installEventFilter(scrollEventEater); - m_ui.syncMethodCombo->installEventFilter(scrollEventEater); - m_ui.syncSourceCombo->installEventFilter(scrollEventEater); - - m_ui.playbackModeCombo->installEventFilter(scrollEventEater); - m_ui.startupScreenCombo->installEventFilter(scrollEventEater); - m_ui.stereoModeCombo->installEventFilter(scrollEventEater); - m_ui.cacheModeCombo->installEventFilter(scrollEventEater); - m_ui.resampleMethodCombo->installEventFilter(scrollEventEater); - m_ui.imageFilterCombo->installEventFilter(scrollEventEater); - m_ui.bgPatternCombo->installEventFilter(scrollEventEater); -} - -RvPreferences::~RvPreferences() -{ -} +#endif -void -RvPreferences::update() -{ - if (isVisible()) return; - Options opts; - loadSettingsIntoOptions(opts); - RV_QSETTINGS; - QString s; - float f; - int n = 0; + m_ui.extRemoveButton->setEnabled(false); + m_ui.extTextBrowser->zoomOut(); + + connect(m_ui.videoModuleCombo, SIGNAL(activated(int)), this, + SLOT(videoModuleChanged(int))); + connect(m_ui.videoDeviceCombo, SIGNAL(activated(int)), this, + SLOT(videoDeviceChanged(int))); + connect(m_ui.videoFormatCombo, SIGNAL(activated(int)), this, + SLOT(videoFormatChanged(int))); + connect(m_ui.video4KTransportCombo, SIGNAL(activated(int)), this, + SLOT(video4KTransportChanged(int))); + connect(m_ui.videoAudioFormatCombo, SIGNAL(activated(int)), this, + SLOT(videoAudioFormatChanged(int))); + connect(m_ui.dataFormatCombo, SIGNAL(activated(int)), this, + SLOT(videoDataFormatChanged(int))); + connect(m_ui.syncMethodCombo, SIGNAL(activated(int)), this, + SLOT(syncMethodChanged(int))); + connect(m_ui.syncSourceCombo, SIGNAL(activated(int)), this, + SLOT(syncSourceChanged(int))); + connect(m_ui.videoAudioDeviceCheckBox, SIGNAL(stateChanged(int)), this, + SLOT(videoAudioCheckBoxChanged(int))); + connect(m_ui.videoSwapStereoEyesCheckBox, SIGNAL(stateChanged(int)), + this, SLOT(videoSwapStereoEyesChanged(int))); + connect(m_ui.useVideoLatencyCheckBox, SIGNAL(stateChanged(int)), this, + SLOT(videoUseLatencyCheckBoxChanged(int))); + connect(m_ui.presentationCheckBox, SIGNAL(stateChanged(int)), this, + SLOT(presentationCheckBoxChanged(int))); + connect(m_ui.additionalOptionsEdit, SIGNAL(textChanged()), this, + SLOT(videoAdditionalOptionsChanged())); + + connect(m_ui.moduleProfileCombo, SIGNAL(activated(int)), this, + SLOT(modProfileChanged(int))); + connect(m_ui.deviceProfileCombo, SIGNAL(activated(int)), this, + SLOT(devProfileChanged(int))); + connect(m_ui.formatProfileCombo, SIGNAL(activated(int)), this, + SLOT(formatProfileChanged(int))); + + m_ui.videoModuleCombo->installEventFilter(scrollEventEater); + m_ui.videoDeviceCombo->installEventFilter(scrollEventEater); + m_ui.videoFormatCombo->installEventFilter(scrollEventEater); + m_ui.video4KTransportCombo->installEventFilter(scrollEventEater); + m_ui.videoAudioFormatCombo->installEventFilter(scrollEventEater); + m_ui.dataFormatCombo->installEventFilter(scrollEventEater); + m_ui.syncMethodCombo->installEventFilter(scrollEventEater); + m_ui.syncSourceCombo->installEventFilter(scrollEventEater); + + m_ui.playbackModeCombo->installEventFilter(scrollEventEater); + m_ui.startupScreenCombo->installEventFilter(scrollEventEater); + m_ui.stereoModeCombo->installEventFilter(scrollEventEater); + m_ui.cacheModeCombo->installEventFilter(scrollEventEater); + m_ui.resampleMethodCombo->installEventFilter(scrollEventEater); + m_ui.imageFilterCombo->installEventFilter(scrollEventEater); + m_ui.bgPatternCombo->installEventFilter(scrollEventEater); + } + + RvPreferences::~RvPreferences() {} + + void RvPreferences::update() + { + if (isVisible()) + return; + Options opts; + loadSettingsIntoOptions(opts); + RV_QSETTINGS; + QString s; + float f; + int n = 0; - loadPackages(); + loadPackages(); #ifdef PLATFORM_DARWIN - m_ui.noMenuBarToggle->setDisabled(true); + m_ui.noMenuBarToggle->setDisabled(true); #endif - //---------------------------------------------------------------------- - settings.beginGroup("Controls"); - - m_ui.clickToPlayEnableToggle->setCheckState(opts.clickToPlayEnable ? Qt::Checked : Qt::Unchecked); - m_ui.scrubEnableToggle->setCheckState(opts.scrubEnable ? Qt::Checked : Qt::Unchecked); + //---------------------------------------------------------------------- + settings.beginGroup("Controls"); - settings.endGroup(); + m_ui.clickToPlayEnableToggle->setCheckState( + opts.clickToPlayEnable ? Qt::Checked : Qt::Unchecked); + m_ui.scrubEnableToggle->setCheckState(opts.scrubEnable ? Qt::Checked + : Qt::Unchecked); - //---------------------------------------------------------------------- - settings.beginGroup("General"); - - m_ui.fontSizeSpinBox->setValue(opts.fontSize1); - m_ui.fontSize2SpinBox->setValue(opts.fontSize2); - - m_ui.playbackModeCombo->setCurrentIndex(opts.playMode); - m_ui.playOnStartupToggle->setCheckState(opts.play ? Qt::Checked : Qt::Unchecked); - m_ui.reuseSessionToggle->setCheckState(opts.urlsReuseSession ? Qt::Checked : Qt::Unchecked); - m_ui.networkToggle->setCheckState(opts.networkOnStartup ? Qt::Checked : Qt::Unchecked); - m_ui.stylusAsMouseToggle->setCheckState(opts.stylusAsMouse ? Qt::Checked : Qt::Unchecked); - m_ui.startupResizeToggle->setCheckState(opts.startupResize ? Qt::Checked : Qt::Unchecked); - m_ui.desktopAwareToggle->setCheckState(opts.qtdesktop ? Qt::Checked : Qt::Unchecked); - m_ui.noMenuBarToggle->setCheckState(opts.nomb ? Qt::Checked : Qt::Unchecked); - m_ui.fullscreenOnStartupToggle->setCheckState(opts.fullscreen ? Qt::Checked : Qt::Unchecked); - s.setNum(opts.defaultfps, 'g', 4); m_ui.fpsEdit->setText(s); - s.setNum(opts.readerThreads); m_ui.rthreadEdit->setText(s); - m_ui.networkHostEdit->setText(opts.networkHost ? opts.networkHost : ""); - m_ui.autoRetimeToggle->setCheckState(opts.autoRetime ? Qt::Checked : Qt::Unchecked); - m_ui.useCrashReporterToggle->setCheckState(Qt::Unchecked); - m_ui.useCrashReporterToggle->setDisabled(true); - - m_ui.startupScreenCombo->clear(); - m_ui.startupScreenCombo->addItem("Follow Pointer"); - for (int i = 0; i < QApplication::desktop()->screenCount(); ++i) - { - m_ui.startupScreenCombo->addItem(QString("Screen %1").arg((unsigned int)(i))); - } - m_ui.startupScreenCombo->setCurrentIndex ((opts.screen < m_ui.startupScreenCombo->count()-1) ? opts.screen+1 : 0); - - n = 0; - if (opts.stereoMode) - { - string s = opts.stereoMode; - if (s == StereoAnaglyph) n = 1; - else if (s == StereoPair) n = 2; - else if (s == StereoMirror) n = 3; - else if (s == StereoLeft) n = 4; - else if (s == StereoRight) n = 5; - else if (s == StereoChecker) n = 6; - else if (s == StereoScanline) n = 7; - else if (s == StereoHardware) n = 8; - else if ( s == StereoLumAnaglyph) n = 9; - } - - m_ui.stereoModeCombo->setCurrentIndex(n); - - settings.endGroup(); + settings.endGroup(); - //---------------------------------------------------------------------- - settings.beginGroup("Caching"); + //---------------------------------------------------------------------- + settings.beginGroup("General"); + + m_ui.fontSizeSpinBox->setValue(opts.fontSize1); + m_ui.fontSize2SpinBox->setValue(opts.fontSize2); + + m_ui.playbackModeCombo->setCurrentIndex(opts.playMode); + m_ui.playOnStartupToggle->setCheckState(opts.play ? Qt::Checked + : Qt::Unchecked); + m_ui.reuseSessionToggle->setCheckState( + opts.urlsReuseSession ? Qt::Checked : Qt::Unchecked); + m_ui.networkToggle->setCheckState( + opts.networkOnStartup ? Qt::Checked : Qt::Unchecked); + m_ui.stylusAsMouseToggle->setCheckState( + opts.stylusAsMouse ? Qt::Checked : Qt::Unchecked); + m_ui.startupResizeToggle->setCheckState( + opts.startupResize ? Qt::Checked : Qt::Unchecked); + m_ui.desktopAwareToggle->setCheckState(opts.qtdesktop ? Qt::Checked + : Qt::Unchecked); + m_ui.noMenuBarToggle->setCheckState(opts.nomb ? Qt::Checked + : Qt::Unchecked); + m_ui.fullscreenOnStartupToggle->setCheckState( + opts.fullscreen ? Qt::Checked : Qt::Unchecked); + s.setNum(opts.defaultfps, 'g', 4); + m_ui.fpsEdit->setText(s); + s.setNum(opts.readerThreads); + m_ui.rthreadEdit->setText(s); + m_ui.networkHostEdit->setText(opts.networkHost ? opts.networkHost : ""); + m_ui.autoRetimeToggle->setCheckState(opts.autoRetime ? Qt::Checked + : Qt::Unchecked); + m_ui.useCrashReporterToggle->setCheckState(Qt::Unchecked); + m_ui.useCrashReporterToggle->setDisabled(true); + + m_ui.startupScreenCombo->clear(); + m_ui.startupScreenCombo->addItem("Follow Pointer"); + for (int i = 0; i < QApplication::desktop()->screenCount(); ++i) + { + m_ui.startupScreenCombo->addItem( + QString("Screen %1").arg((unsigned int)(i))); + } + m_ui.startupScreenCombo->setCurrentIndex( + (opts.screen < m_ui.startupScreenCombo->count() - 1) + ? opts.screen + 1 + : 0); - n = 0; - if (opts.useCache) n = 1; - if (opts.useLCache) n = 2; + n = 0; + if (opts.stereoMode) + { + string s = opts.stereoMode; + if (s == StereoAnaglyph) + n = 1; + else if (s == StereoPair) + n = 2; + else if (s == StereoMirror) + n = 3; + else if (s == StereoLeft) + n = 4; + else if (s == StereoRight) + n = 5; + else if (s == StereoChecker) + n = 6; + else if (s == StereoScanline) + n = 7; + else if (s == StereoHardware) + n = 8; + else if (s == StereoLumAnaglyph) + n = 9; + } - m_ui.cacheModeCombo->setCurrentIndex(settings.value("cacheMode", n).toInt()); + m_ui.stereoModeCombo->setCurrentIndex(n); - // Pull the achitecture specific settings... - double max32lram = settings.value("lookAheadCacheSize32New", opts.maxlram).toDouble(); - double max64lram = settings.value("lookAheadCacheSize64New", opts.maxlram).toDouble(); - double max32cram = settings.value("regionCacheSize32New", opts.maxcram).toDouble(); - double max64cram = settings.value("regionCacheSize64New", opts.maxcram).toDouble(); + settings.endGroup(); - // ...and populate the preference fields - //s.setNum(max32lram, 'g', 3); m_ui.lookAheadCacheSize32Edit->setText(s); - s.setNum(max64lram, 'g', 3); m_ui.lookAheadCacheSize64Edit->setText(s); - //s.setNum(max32cram, 'g', 3); m_ui.regionCacheSize32Edit->setText(s); - s.setNum(max64cram, 'g', 3); m_ui.regionCacheSize64Edit->setText(s); + //---------------------------------------------------------------------- + settings.beginGroup("Caching"); + + n = 0; + if (opts.useCache) + n = 1; + if (opts.useLCache) + n = 2; + + m_ui.cacheModeCombo->setCurrentIndex( + settings.value("cacheMode", n).toInt()); + + // Pull the achitecture specific settings... + double max32lram = + settings.value("lookAheadCacheSize32New", opts.maxlram).toDouble(); + double max64lram = + settings.value("lookAheadCacheSize64New", opts.maxlram).toDouble(); + double max32cram = + settings.value("regionCacheSize32New", opts.maxcram).toDouble(); + double max64cram = + settings.value("regionCacheSize64New", opts.maxcram).toDouble(); + + // ...and populate the preference fields + // s.setNum(max32lram, 'g', 3); + // m_ui.lookAheadCacheSize32Edit->setText(s); + s.setNum(max64lram, 'g', 3); + m_ui.lookAheadCacheSize64Edit->setText(s); + // s.setNum(max32cram, 'g', 3); m_ui.regionCacheSize32Edit->setText(s); + s.setNum(max64cram, 'g', 3); + m_ui.regionCacheSize64Edit->setText(s); + + s.setNum(opts.maxbwait, 'g', 3); + m_ui.bufferWaitEdit->setText(s); + s.setNum(opts.lookback, 'g', 3); + m_ui.lookBehindFracEdit->setText(s); + + m_ui.cacheOutsideRegionToggle->setCheckState( + opts.cacheOutsideRegion ? Qt::Checked : Qt::Unchecked); - s.setNum(opts.maxbwait, 'g', 3); m_ui.bufferWaitEdit->setText(s); - s.setNum(opts.lookback, 'g', 3); m_ui.lookBehindFracEdit->setText(s); + settings.endGroup(); - m_ui.cacheOutsideRegionToggle->setCheckState(opts.cacheOutsideRegion ? Qt::Checked : Qt::Unchecked); + //---------------------------------------------------------------------- + settings.beginGroup("Rendering"); + + n = 0; + if (opts.maxbits == 16) + n = 1; + if (opts.maxbits == 8) + n = 2; + + m_ui.bitDepthCombo->setCurrentIndex(n); + m_ui.allowFloatToggle->setCheckState(opts.nofloat ? Qt::Unchecked + : Qt::Checked); + m_ui.swapScanlinesToggle->setCheckState( + opts.swapScanlines ? Qt::Checked : Qt::Unchecked); + m_ui.prefetchToggle->setCheckState(opts.prefetch ? Qt::Checked + : Qt::Unchecked); + m_ui.newGLSLlutInterpToggle->setCheckState( + opts.newGLSLlutInterp ? Qt::Checked : Qt::Unchecked); + + if (ImageRenderer::queryClientStorage()) + { + m_ui.appleClientStorageToggle->setCheckState( + opts.useAppleClientStorage ? Qt::Checked : Qt::Unchecked); + } + else + { + m_ui.appleClientStorageToggle->setEnabled(false); + } - settings.endGroup(); + if (ImageRenderer::queryThreadedUpload()) + { + m_ui.useThreadedUploadToggle->setCheckState( + opts.useThreadedUpload ? Qt::Checked : Qt::Unchecked); + } + else + { + m_ui.useThreadedUploadToggle->setEnabled(false); + } - //---------------------------------------------------------------------- - settings.beginGroup("Rendering"); + n = 0; + if (opts.resampleMethod) + { + // "area" is n=0. + if (!strcmp(opts.resampleMethod, "cubic")) + n = 1; + else if (!strcmp(opts.resampleMethod, "linear")) + n = 2; + else if (!strcmp(opts.resampleMethod, "nearest")) + n = 3; + } + m_ui.resampleMethodCombo->setCurrentIndex(n); - n = 0; - if (opts.maxbits == 16) n = 1; - if (opts.maxbits == 8) n = 2; + if (opts.imageFilter == GL_LINEAR) + m_ui.imageFilterCombo->setCurrentIndex(0); + if (opts.imageFilter == GL_NEAREST) + m_ui.imageFilterCombo->setCurrentIndex(1); - m_ui.bitDepthCombo->setCurrentIndex(n); - m_ui.allowFloatToggle->setCheckState(opts.nofloat ? Qt::Unchecked : Qt::Checked); - m_ui.swapScanlinesToggle->setCheckState(opts.swapScanlines ? Qt::Checked : Qt::Unchecked); - m_ui.prefetchToggle->setCheckState(opts.prefetch ? Qt::Checked : Qt::Unchecked); - m_ui.newGLSLlutInterpToggle->setCheckState(opts.newGLSLlutInterp ? Qt::Checked : Qt::Unchecked); + n = 0; + if (opts.bgpattern) + { + if (!strcmp(opts.bgpattern, "grey18")) + n = 1; + else if (!strcmp(opts.bgpattern, "grey50")) + n = 2; + else if (!strcmp(opts.bgpattern, "white")) + n = 3; + else if (!strcmp(opts.bgpattern, "checker")) + n = 4; + else if (!strcmp(opts.bgpattern, "crosshatch")) + n = 5; + } - if (ImageRenderer::queryClientStorage()) - { - m_ui.appleClientStorageToggle->setCheckState(opts.useAppleClientStorage ? Qt::Checked : Qt::Unchecked); - } - else - { - m_ui.appleClientStorageToggle->setEnabled(false); - } + m_ui.bgPatternCombo->setCurrentIndex(n); - if (ImageRenderer::queryThreadedUpload()) - { - m_ui.useThreadedUploadToggle->setCheckState(opts.useThreadedUpload ? Qt::Checked : Qt::Unchecked); - } - else - { - m_ui.useThreadedUploadToggle->setEnabled(false); - } + settings.endGroup(); - n = 0; - if (opts.resampleMethod) - { - // "area" is n=0. - if (!strcmp(opts.resampleMethod, "cubic")) n = 1; - else if (!strcmp(opts.resampleMethod, "linear")) n = 2; - else if (!strcmp(opts.resampleMethod, "nearest")) n = 3; - } - m_ui.resampleMethodCombo->setCurrentIndex(n); + //---------------------------------------------------------------------- + settings.beginGroup("Audio"); - if (opts.imageFilter == GL_LINEAR) m_ui.imageFilterCombo->setCurrentIndex(0); - if (opts.imageFilter == GL_NEAREST) m_ui.imageFilterCombo->setCurrentIndex(1); + if (AudioRenderer::audioDisabledAlways()) + { + m_ui.audioModuleCombo->clear(); + m_ui.audioDeviceCombo->clear(); + m_ui.audioDeviceLayoutCombo->clear(); + m_ui.audioDeviceFormatCombo->clear(); + m_ui.audioDeviceRateCombo->clear(); + m_ui.audioModuleCombo->addItem("Audio Disabled"); + m_ui.audioModuleCombo->setItemIcon( + 0, colorAdjustedIcon(":images/mute_32x32.png")); + m_ui.audioDeviceCombo->setEnabled(false); + m_ui.audioDeviceLayoutCombo->setEnabled(false); + m_ui.audioDeviceFormatCombo->setEnabled(false); + m_ui.audioDeviceRateCombo->setEnabled(false); + } + else if (!m_ui.audioModuleCombo->count()) + { + const AudioRenderer::ModuleVector& modules = + AudioRenderer::modules(); + size_t current = 0; - n = 0; - if (opts.bgpattern) - { - if (!strcmp(opts.bgpattern, "grey18")) n = 1; - else if (!strcmp(opts.bgpattern, "grey50")) n = 2; - else if (!strcmp(opts.bgpattern, "white")) n = 3; - else if (!strcmp(opts.bgpattern, "checker")) n = 4; - else if (!strcmp(opts.bgpattern, "crosshatch")) n = 5; - } + for (size_t i = 0; i < modules.size(); i++) + { + if (modules[i].internal) + break; + if (opts.audioModule && modules[i].name == opts.audioModule) + current = i; + m_ui.audioModuleCombo->addItem( + QString::fromUtf8(modules[i].name.c_str())); + } - m_ui.bgPatternCombo->setCurrentIndex(n); + m_ui.audioModuleCombo->setCurrentIndex(current); - settings.endGroup(); + // + // This will take care of the remaining related UI + // - //---------------------------------------------------------------------- - settings.beginGroup("Audio"); + audioModuleChanged(current); + } - if (AudioRenderer::audioDisabledAlways()) - { - m_ui.audioModuleCombo->clear(); - m_ui.audioDeviceCombo->clear(); - m_ui.audioDeviceLayoutCombo->clear(); - m_ui.audioDeviceFormatCombo->clear(); - m_ui.audioDeviceRateCombo->clear(); - m_ui.audioModuleCombo->addItem("Audio Disabled"); - m_ui.audioModuleCombo->setItemIcon(0, colorAdjustedIcon(":images/mute_32x32.png")); - m_ui.audioDeviceCombo->setEnabled(false); - m_ui.audioDeviceLayoutCombo->setEnabled(false); - m_ui.audioDeviceFormatCombo->setEnabled(false); - m_ui.audioDeviceRateCombo->setEnabled(false); - } - else if (!m_ui.audioModuleCombo->count()) - { - const AudioRenderer::ModuleVector& modules = AudioRenderer::modules(); - size_t current = 0; + m_ui.volumeSlider->setSliderPosition(int(opts.volume * 100.0)); + m_ui.audioHoldOpenToggle->setCheckState(opts.audioNice ? Qt::Unchecked + : Qt::Checked); + m_ui.audioHardwareLockToggle->setCheckState( + opts.audioNoLock ? Qt::Unchecked : Qt::Checked); + m_ui.audioScrubAtLaunchToggle->setCheckState( + opts.audioScrub ? Qt::Checked : Qt::Unchecked); + m_ui.audioPreRollToggle->setCheckState( + opts.audioPreRoll ? Qt::Checked : Qt::Unchecked); + + s.setNum(opts.aframesize); + m_ui.audioDevicePacketEdit->setText(s); + s.setNum(opts.acachesize); + m_ui.audioCachePacketEdit->setText(s); + s.setNum(opts.audioMinCache, 'g', 2); + m_ui.audioCacheMinEdit->setText(s); + s.setNum(opts.audioMaxCache, 'g', 2); + m_ui.audioCacheMaxEdit->setText(s); + s.setNum(opts.audioGlobalOffset, 'g', 4); + m_ui.audioGlobalOffsetEdit->setText(s); + s.setNum(opts.audioDeviceLatency, 'g', 4); + m_ui.audioDeviceLatencyEdit->setText(s); + // s.setNum(opts.audioRate, 'g', 10); + // m_ui.audioDeviceRateEdit->setText(s); - for (size_t i= 0; i < modules.size(); i++) + TwkAudio::Format currentFormat; + switch (opts.audioPrecision) { - if (modules[i].internal) break; - if (opts.audioModule && modules[i].name == opts.audioModule) current = i; - m_ui.audioModuleCombo->addItem(QString::fromUtf8(modules[i].name.c_str())); + default: + case 32: + currentFormat = TwkAudio::Float32Format; + break; + case 24: + currentFormat = TwkAudio::Int24Format; + break; + case 16: + currentFormat = TwkAudio::Int16Format; + break; + case 8: + currentFormat = TwkAudio::Int8Format; + ; + break; + case -32: + currentFormat = TwkAudio::Int32Format; + break; } - m_ui.audioModuleCombo->setCurrentIndex(current); + for (int index = 0; index < m_ui.audioDeviceFormatCombo->count(); + ++index) + { + if (m_ui.audioDeviceFormatCombo->itemData(index) == currentFormat) + { + m_ui.audioDeviceFormatCombo->setCurrentIndex(index); + break; + } + } - // - // This will take care of the remaining related UI - // + for (int index = 0; index < m_ui.audioDeviceLayoutCombo->count(); + ++index) + { + if (m_ui.audioDeviceLayoutCombo->itemData(index) + == opts.audioLayout) + { + m_ui.audioDeviceLayoutCombo->setCurrentIndex(index); + break; + } + } - audioModuleChanged(current); - } + settings.endGroup(); - m_ui.volumeSlider->setSliderPosition(int(opts.volume * 100.0)); - m_ui.audioHoldOpenToggle->setCheckState(opts.audioNice ? Qt::Unchecked : Qt::Checked); - m_ui.audioHardwareLockToggle->setCheckState(opts.audioNoLock ? Qt::Unchecked : Qt::Checked); - m_ui.audioScrubAtLaunchToggle->setCheckState(opts.audioScrub ? Qt::Checked : Qt::Unchecked); - m_ui.audioPreRollToggle->setCheckState(opts.audioPreRoll ? Qt::Checked : Qt::Unchecked); + //---------------------------------------------------------------------- + settings.beginGroup("Display"); - s.setNum(opts.aframesize); m_ui.audioDevicePacketEdit->setText(s); - s.setNum(opts.acachesize); m_ui.audioCachePacketEdit->setText(s); - s.setNum(opts.audioMinCache, 'g', 2); m_ui.audioCacheMinEdit->setText(s); - s.setNum(opts.audioMaxCache, 'g', 2); m_ui.audioCacheMaxEdit->setText(s); - s.setNum(opts.audioGlobalOffset, 'g', 4); m_ui.audioGlobalOffsetEdit->setText(s); - s.setNum(opts.audioDeviceLatency, 'g', 4); m_ui.audioDeviceLatencyEdit->setText(s); - //s.setNum(opts.audioRate, 'g', 10); m_ui.audioDeviceRateEdit->setText(s); + m_ui.displayVideoSyncButton->setCheckState(opts.vsync ? Qt::Checked + : Qt::Unchecked); - TwkAudio::Format currentFormat; - switch (opts.audioPrecision) - { - default: - case 32: currentFormat = TwkAudio::Float32Format; break; - case 24: currentFormat = TwkAudio::Int24Format; break; - case 16: currentFormat = TwkAudio::Int16Format; break; - case 8: currentFormat = TwkAudio::Int8Format;; break; - case -32: currentFormat = TwkAudio::Int32Format; break; - } + int dindex = 0; - for (int index=0; index < m_ui.audioDeviceFormatCombo->count(); ++index) - { - if (m_ui.audioDeviceFormatCombo->itemData(index) == currentFormat) + if (opts.dispRedBits == 8 && opts.dispGreenBits == 8 + && opts.dispBlueBits == 8 && opts.dispAlphaBits == 8) { - m_ui.audioDeviceFormatCombo->setCurrentIndex(index); - break; + dindex = 1; } - } - - for (int index=0; index < m_ui.audioDeviceLayoutCombo->count(); ++index) - { - if (m_ui.audioDeviceLayoutCombo->itemData(index) == opts.audioLayout) + else if (opts.dispRedBits == 10 && opts.dispGreenBits == 10 + && opts.dispBlueBits == 10 && opts.dispAlphaBits == 2) { - m_ui.audioDeviceLayoutCombo->setCurrentIndex(index); - break; + dindex = 2; + } + else + { + dindex = 0; } - } - - settings.endGroup(); - - //---------------------------------------------------------------------- - settings.beginGroup("Display"); - m_ui.displayVideoSyncButton->setCheckState(opts.vsync ? Qt::Checked : Qt::Unchecked); - - int dindex = 0; + m_ui.displayOutputCombo->setCurrentIndex(dindex); - if (opts.dispRedBits == 8 && - opts.dispGreenBits == 8 && - opts.dispBlueBits == 8 && - opts.dispAlphaBits == 8) - { - dindex = 1; - } - else if (opts.dispRedBits == 10 && - opts.dispGreenBits == 10 && - opts.dispBlueBits == 10 && - opts.dispAlphaBits == 2) - { - dindex = 2; - } - else - { - dindex = 0; - } + settings.endGroup(); - m_ui.displayOutputCombo->setCurrentIndex(dindex); + //---------------------------------------------------------------------- + settings.beginGroup("OpenEXR"); + m_ui.exrRGBAToggle->setCheckState(opts.exrRGBA ? Qt::Checked + : Qt::Unchecked); + m_ui.exrInheritToggle->setCheckState(opts.exrInherit ? Qt::Checked + : Qt::Unchecked); + m_ui.exrPlanar3ChannelToggle->setCheckState( + opts.exrPlanar3Chan ? Qt::Checked : Qt::Unchecked); + m_ui.exrNoOneChannelToggle->setCheckState( + opts.exrNoOneChannel ? Qt::Checked : Qt::Unchecked); + m_ui.exrReadWindowIsDisplayWindowToggle->setCheckState( + opts.exrReadWindowIsDisplayWindow ? Qt::Checked : Qt::Unchecked); + m_ui.exrAutoThreadsToggle->setCheckState( + opts.exrcpus == 0 ? Qt::Checked : Qt::Unchecked); + s.setNum(opts.exrcpus); + m_ui.exrNumThreadsEdit->setText(s); + m_ui.exrIOMethodCombo->setCurrentIndex(opts.exrIOMethod); + m_ui.exrReadWindowCombo->setCurrentIndex(opts.exrReadWindow); + m_ui.exrNumThreadsEdit->setEnabled(opts.exrcpus != 0); + m_ui.exrThreadsLabel->setEnabled(opts.exrcpus != 0); + s.setNum(opts.exrIOSize); + m_ui.exrChunkSizeEdit->setText(s); + s.setNum(opts.exrMaxAsync); + m_ui.exrMaxInFlightEdit->setText(s); + settings.endGroup(); - settings.endGroup(); + //---------------------------------------------------------------------- + settings.beginGroup("JPEG"); + m_ui.jpegRGBAToggle->setCheckState(opts.jpegRGBA ? Qt::Checked + : Qt::Unchecked); + m_ui.jpegIOMethodCombo->setCurrentIndex(opts.jpegIOMethod); + s.setNum(opts.jpegIOSize); + m_ui.jpegChunkSizeEdit->setText(s); + s.setNum(opts.jpegMaxAsync); + m_ui.jpegMaxInFlightEdit->setText(s); + settings.endGroup(); - //---------------------------------------------------------------------- - settings.beginGroup("OpenEXR"); - m_ui.exrRGBAToggle->setCheckState(opts.exrRGBA ? Qt::Checked : Qt::Unchecked); - m_ui.exrInheritToggle->setCheckState(opts.exrInherit ? Qt::Checked : Qt::Unchecked); - m_ui.exrPlanar3ChannelToggle->setCheckState(opts.exrPlanar3Chan ? Qt::Checked : Qt::Unchecked); - m_ui.exrNoOneChannelToggle->setCheckState(opts.exrNoOneChannel ? Qt::Checked : Qt::Unchecked); - m_ui.exrReadWindowIsDisplayWindowToggle->setCheckState(opts.exrReadWindowIsDisplayWindow ? Qt::Checked : Qt::Unchecked); - m_ui.exrAutoThreadsToggle->setCheckState(opts.exrcpus == 0 ? Qt::Checked : Qt::Unchecked); - s.setNum(opts.exrcpus); - m_ui.exrNumThreadsEdit->setText(s); - m_ui.exrIOMethodCombo->setCurrentIndex(opts.exrIOMethod); - m_ui.exrReadWindowCombo->setCurrentIndex(opts.exrReadWindow); - m_ui.exrNumThreadsEdit->setEnabled(opts.exrcpus != 0); - m_ui.exrThreadsLabel->setEnabled(opts.exrcpus != 0); - s.setNum(opts.exrIOSize); - m_ui.exrChunkSizeEdit->setText(s); - s.setNum(opts.exrMaxAsync); - m_ui.exrMaxInFlightEdit->setText(s); - settings.endGroup(); + //---------------------------------------------------------------------- + settings.beginGroup("Cineon"); + m_ui.cinIOMethodCombo->setCurrentIndex(opts.cinIOMethod); + s.setNum(opts.cinIOSize); + m_ui.cinChunkSizeEdit->setText(s); + s.setNum(opts.cinMaxAsync); + m_ui.cinMaxInFlightEdit->setText(s); + m_ui.cinChromaToggle->setCheckState(opts.cinchroma ? Qt::Checked + : Qt::Unchecked); + + n = 2; + s = opts.cinPixel; + if (s == RGB8) + n = 0; + else if (s == RGBA8) + n = 1; + else if (s == RGB8_PLANAR) + n = 2; + else if (s == RGB10_A2) + n = 3; + else if (s == A2_BGR10) + n = 4; + else if (s == RGB16) + n = 5; + else if (s == RGBA16) + n = 6; + else if (s == RGB16_PLANAR) + n = 7; + m_ui.cinDisplayPixelCombo->setCurrentIndex(n); - //---------------------------------------------------------------------- - settings.beginGroup("JPEG"); - m_ui.jpegRGBAToggle->setCheckState(opts.jpegRGBA ? Qt::Checked : Qt::Unchecked); - m_ui.jpegIOMethodCombo->setCurrentIndex(opts.jpegIOMethod); - s.setNum(opts.jpegIOSize); - m_ui.jpegChunkSizeEdit->setText(s); - s.setNum(opts.jpegMaxAsync); - m_ui.jpegMaxInFlightEdit->setText(s); - settings.endGroup(); + settings.endGroup(); - //---------------------------------------------------------------------- - settings.beginGroup("Cineon"); - m_ui.cinIOMethodCombo->setCurrentIndex(opts.cinIOMethod); - s.setNum(opts.cinIOSize); - m_ui.cinChunkSizeEdit->setText(s); - s.setNum(opts.cinMaxAsync); - m_ui.cinMaxInFlightEdit->setText(s); - m_ui.cinChromaToggle->setCheckState(opts.cinchroma ? Qt::Checked : Qt::Unchecked); - - n = 2; - s = opts.cinPixel; - if (s == RGB8) n = 0; - else if (s == RGBA8) n = 1; - else if (s == RGB8_PLANAR) n = 2; - else if (s == RGB10_A2) n = 3; - else if (s == A2_BGR10) n = 4; - else if (s == RGB16) n = 5; - else if (s == RGBA16) n = 6; - else if (s == RGB16_PLANAR) n = 7; - m_ui.cinDisplayPixelCombo->setCurrentIndex(n); - - settings.endGroup(); + //---------------------------------------------------------------------- + settings.beginGroup("DPX"); + m_ui.dpxIOMethodCombo->setCurrentIndex(opts.dpxIOMethod); + s.setNum(opts.dpxIOSize); + m_ui.dpxChunkSizeEdit->setText(s); + s.setNum(opts.dpxMaxAsync); + m_ui.dpxMaxInFlightEdit->setText(s); + m_ui.dpxChromaToggle->setCheckState(opts.dpxchroma ? Qt::Checked + : Qt::Unchecked); + + n = 2; + s = opts.dpxPixel; + if (s == RGB8) + n = 0; + else if (s == RGBA8) + n = 1; + else if (s == RGB8_PLANAR) + n = 2; + else if (s == RGB10_A2) + n = 3; + else if (s == A2_BGR10) + n = 4; + else if (s == RGB16) + n = 5; + else if (s == RGBA16) + n = 6; + else if (s == RGB16_PLANAR) + n = 7; + m_ui.dpxDisplayPixelCombo->setCurrentIndex(n); - //---------------------------------------------------------------------- - settings.beginGroup("DPX"); - m_ui.dpxIOMethodCombo->setCurrentIndex(opts.dpxIOMethod); - s.setNum(opts.dpxIOSize); - m_ui.dpxChunkSizeEdit->setText(s); - s.setNum(opts.dpxMaxAsync); - m_ui.dpxMaxInFlightEdit->setText(s); - m_ui.dpxChromaToggle->setCheckState(opts.dpxchroma ? Qt::Checked : Qt::Unchecked); - - n = 2; - s = opts.dpxPixel; - if (s == RGB8) n = 0; - else if (s == RGBA8) n = 1; - else if (s == RGB8_PLANAR) n = 2; - else if (s == RGB10_A2) n = 3; - else if (s == A2_BGR10) n = 4; - else if (s == RGB16) n = 5; - else if (s == RGBA16) n = 6; - else if (s == RGB16_PLANAR) n = 7; - m_ui.dpxDisplayPixelCombo->setCurrentIndex(n); - - settings.endGroup(); + settings.endGroup(); - //---------------------------------------------------------------------- - settings.beginGroup("TGA"); - m_ui.tgaIOMethodCombo->setCurrentIndex(opts.tgaIOMethod); - s.setNum(opts.tgaIOSize); - m_ui.tgaChunkSizeEdit->setText(s); - s.setNum(opts.tgaMaxAsync); - m_ui.tgaMaxInFlightEdit->setText(s); - settings.endGroup(); + //---------------------------------------------------------------------- + settings.beginGroup("TGA"); + m_ui.tgaIOMethodCombo->setCurrentIndex(opts.tgaIOMethod); + s.setNum(opts.tgaIOSize); + m_ui.tgaChunkSizeEdit->setText(s); + s.setNum(opts.tgaMaxAsync); + m_ui.tgaMaxInFlightEdit->setText(s); + settings.endGroup(); - //---------------------------------------------------------------------- - settings.beginGroup("TIFF"); - m_ui.tifIOMethodCombo->setCurrentIndex(opts.tiffIOMethod); - s.setNum(opts.tiffIOSize); - m_ui.tifChunkSizeEdit->setText(s); - s.setNum(opts.tiffMaxAsync); - m_ui.tifMaxInFlightEdit->setText(s); - settings.endGroup(); + //---------------------------------------------------------------------- + settings.beginGroup("TIFF"); + m_ui.tifIOMethodCombo->setCurrentIndex(opts.tiffIOMethod); + s.setNum(opts.tiffIOSize); + m_ui.tifChunkSizeEdit->setText(s); + s.setNum(opts.tiffMaxAsync); + m_ui.tifMaxInFlightEdit->setText(s); + settings.endGroup(); - //---------------------------------------------------------------------- - // VIDEO + //---------------------------------------------------------------------- + // VIDEO - updateVideo(); - m_updated = true; -} + updateVideo(); + m_updated = true; + } -void -RvPreferences::resetPreferencesFile() -{ + void RvPreferences::resetPreferencesFile() + { #ifdef PLATFORM_WINDOWS - QSettings::setDefaultFormat(QSettings::IniFormat); + QSettings::setDefaultFormat(QSettings::IniFormat); #endif - - QCoreApplication::setOrganizationName(INTERNAL_ORGANIZATION_NAME); - QCoreApplication::setOrganizationDomain(INTERNAL_ORGANIZATION_DOMAIN); - QCoreApplication::setApplicationName(INTERNAL_APPLICATION_NAME); - - QSettings user; - user.clear(); - user.sync(); -} - -void -RvPreferences::loadSettingsIntoOptions(Options& opts) -{ - RV_QSETTINGS; - - loadSettingsIntoOptions (settings, opts); -} -void -RvPreferences::loadSettingsIntoOptions(RvSettings& settings, Options& opts) -{ - QString s; - settings.beginGroup("Controls"); - - opts.clickToPlayEnable = int(!settings.value("disableClickToPlay", opts.clickToPlayEnable ? false : true).toBool()); - opts.scrubEnable = int(!settings.value("disableScrubInView", opts.scrubEnable ? false : true).toBool()); - - settings.endGroup(); - - settings.beginGroup("General"); - - opts.fontSize1 = settings.value("fontSize1", opts.fontSize1).toInt(); - opts.fontSize2 = settings.value("fontSize2", opts.fontSize2).toInt(); - - opts.playMode = settings.value("playMode", opts.playMode).toInt(); - opts.play = int(settings.value("playOnStartup", opts.play ? true : false).toBool()); - opts.networkOnStartup = int(settings.value("networkOnStartup", opts.networkOnStartup ? true : false).toBool()); - opts.stylusAsMouse = int(settings.value("stylusAsMouse", opts.stylusAsMouse ? true : false).toBool()); - opts.startupResize = int(settings.value("startupResize", opts.startupResize ? true : false).toBool()); - opts.qtdesktop = int(settings.value("desktopAware", opts.qtdesktop ? true : false).toBool()); - opts.urlsReuseSession = int(settings.value("urlsReuseSession", opts.urlsReuseSession ? true : false).toBool()); - opts.fullscreen = int(settings.value("fullscreenOnStartup", opts.fullscreen ? true : false).toBool()); - opts.screen = settings.value("startupScreenPolicy", opts.screen).toInt(); - opts.nomb = int(settings.value("noMenuBar", opts.nomb ? true : false).toBool()); - opts.defaultfps = settings.value("fps", opts.defaultfps).toDouble(); - opts.networkHostBuf = settings.value("networkHost", (opts.networkHost) ? opts.networkHost : "").toString().toUtf8().data(); - opts.networkHost = (char *) ((opts.networkHostBuf.empty()) ? 0 : opts.networkHostBuf.c_str()); - opts.readerThreads = settings.value("readerThreads", opts.readerThreads).toInt(); - opts.autoRetime = int(settings.value("autoRetime", opts.autoRetime ? true : false).toBool()); - opts.useCrashReporter = int(settings.value("useCrashReporter", opts.useCrashReporter ? true : false).toBool()); - - opts.stereoMode = 0; - s = settings.value("stereoMode", opts.stereoMode).toString(); - if (s == StereoAnaglyph) opts.stereoMode = (char*)StereoAnaglyph; - if (s == StereoLumAnaglyph) opts.stereoMode = (char*)StereoLumAnaglyph; - if (s == StereoPair) opts.stereoMode = (char*)StereoPair; - if (s == StereoMirror) opts.stereoMode = (char*)StereoMirror; - if (s == StereoChecker) opts.stereoMode = (char*)StereoChecker; - if (s == StereoScanline) opts.stereoMode = (char*)StereoScanline; - if (s == StereoHardware) opts.stereoMode = (char*)StereoHardware; - if (s == StereoLeft) opts.stereoMode = (char*)StereoLeft; - if (s == StereoRight) opts.stereoMode = (char*)StereoRight; - - settings.endGroup(); + QCoreApplication::setOrganizationName(INTERNAL_ORGANIZATION_NAME); + QCoreApplication::setOrganizationDomain(INTERNAL_ORGANIZATION_DOMAIN); + QCoreApplication::setApplicationName(INTERNAL_APPLICATION_NAME); - //---------------------------------------------------------------------- - settings.beginGroup("Caching"); - int cacheMode = settings.value("cacheMode", 2 /*Look-Ahead Cache*/).toInt(); - - opts.useCache = false; - opts.useLCache = false; - - switch (cacheMode) - { - default: - case 0: - break; - case 1: - opts.useCache = true; - break; - case 2: - opts.useLCache = true; - break; - } - - // Look for architecture specific preferences first, then fall back to non-specific - double tmplram = -1; - double tmpcram = -1; - - #ifdef ARCH_IA32 - tmplram = settings.value("lookAheadCacheSize32New", tmplram).toDouble(); - tmpcram = settings.value("regionCacheSize32New", tmpcram).toDouble(); - #else - tmplram = settings.value("lookAheadCacheSize64New", tmplram).toDouble(); - tmpcram = settings.value("regionCacheSize64New", tmpcram).toDouble(); - #endif + QSettings user; + user.clear(); + user.sync(); + } - if (tmplram == -1) opts.maxlram = settings.value("lookAheadCacheSizeNew", opts.maxlram).toDouble(); - else opts.maxlram = tmplram; - if (tmpcram == -1) opts.maxcram = settings.value("regionCacheSizeNew", opts.maxcram).toDouble(); - else opts.maxcram = tmpcram; + void RvPreferences::loadSettingsIntoOptions(Options& opts) + { + RV_QSETTINGS; - opts.maxbwait = settings.value("bufferWait", opts.maxbwait).toDouble(); - opts.lookback = settings.value("lookBehindFraction", opts.lookback).toDouble(); - opts.cacheOutsideRegion = settings.value("cacheOutsideRegion", opts.cacheOutsideRegion).toBool(); + loadSettingsIntoOptions(settings, opts); + } - settings.endGroup(); + void RvPreferences::loadSettingsIntoOptions(RvSettings& settings, + Options& opts) + { + QString s; + settings.beginGroup("Controls"); + + opts.clickToPlayEnable = + int(!settings + .value("disableClickToPlay", + opts.clickToPlayEnable ? false : true) + .toBool()); + opts.scrubEnable = int( + !settings + .value("disableScrubInView", opts.scrubEnable ? false : true) + .toBool()); - //---------------------------------------------------------------------- - settings.beginGroup("Rendering"); - opts.nofloat = settings.value("nofloat", opts.nofloat).toBool(); - opts.swapScanlines = settings.value("swapScanlines", opts.swapScanlines).toBool(); - opts.prefetch = settings.value("prefetch2", opts.prefetch).toBool(); - opts.useAppleClientStorage = settings.value("appleClientStorage", opts.useAppleClientStorage).toBool(); - opts.newGLSLlutInterp = settings.value("newGLSLlutInterp", opts.newGLSLlutInterp).toBool(); - - // Can't check ImageRenderer::queryThreadedUpload() here because this - // function is called very early (before video modules are created). If - // threaded uploads are not allowed, later code will ensure the checkbox - // is disabled, etc. But opts struct should represent state in settings - // file. - // - - opts.useThreadedUpload = settings.value("useThreadedUpload3", opts.useThreadedUpload).toBool(); - - opts.maxvram = settings.value("vram", opts.maxvram).toDouble(); - opts.maxbits = settings.value("maxBitDepth", opts.maxbits).toInt(); + settings.endGroup(); - s = settings.value("resampleMethod", opts.resampleMethod).toString(); + settings.beginGroup("General"); + + opts.fontSize1 = settings.value("fontSize1", opts.fontSize1).toInt(); + opts.fontSize2 = settings.value("fontSize2", opts.fontSize2).toInt(); + + opts.playMode = settings.value("playMode", opts.playMode).toInt(); + opts.play = int( + settings.value("playOnStartup", opts.play ? true : false).toBool()); + opts.networkOnStartup = int( + settings + .value("networkOnStartup", opts.networkOnStartup ? true : false) + .toBool()); + opts.stylusAsMouse = int( + settings.value("stylusAsMouse", opts.stylusAsMouse ? true : false) + .toBool()); + opts.startupResize = int( + settings.value("startupResize", opts.startupResize ? true : false) + .toBool()); + opts.qtdesktop = + int(settings.value("desktopAware", opts.qtdesktop ? true : false) + .toBool()); + opts.urlsReuseSession = int( + settings + .value("urlsReuseSession", opts.urlsReuseSession ? true : false) + .toBool()); + opts.fullscreen = int( + settings + .value("fullscreenOnStartup", opts.fullscreen ? true : false) + .toBool()); + opts.screen = + settings.value("startupScreenPolicy", opts.screen).toInt(); + opts.nomb = + int(settings.value("noMenuBar", opts.nomb ? true : false).toBool()); + opts.defaultfps = settings.value("fps", opts.defaultfps).toDouble(); + opts.networkHostBuf = + settings + .value("networkHost", + (opts.networkHost) ? opts.networkHost : "") + .toString() + .toUtf8() + .data(); + opts.networkHost = (char*)((opts.networkHostBuf.empty()) + ? 0 + : opts.networkHostBuf.c_str()); + opts.readerThreads = + settings.value("readerThreads", opts.readerThreads).toInt(); + opts.autoRetime = + int(settings.value("autoRetime", opts.autoRetime ? true : false) + .toBool()); + opts.useCrashReporter = int( + settings + .value("useCrashReporter", opts.useCrashReporter ? true : false) + .toBool()); + + opts.stereoMode = 0; + s = settings.value("stereoMode", opts.stereoMode).toString(); + if (s == StereoAnaglyph) + opts.stereoMode = (char*)StereoAnaglyph; + if (s == StereoLumAnaglyph) + opts.stereoMode = (char*)StereoLumAnaglyph; + if (s == StereoPair) + opts.stereoMode = (char*)StereoPair; + if (s == StereoMirror) + opts.stereoMode = (char*)StereoMirror; + if (s == StereoChecker) + opts.stereoMode = (char*)StereoChecker; + if (s == StereoScanline) + opts.stereoMode = (char*)StereoScanline; + if (s == StereoHardware) + opts.stereoMode = (char*)StereoHardware; + if (s == StereoLeft) + opts.stereoMode = (char*)StereoLeft; + if (s == StereoRight) + opts.stereoMode = (char*)StereoRight; - if (s == Area) opts.resampleMethod = (char*)Area; - else if (s == Linear) opts.resampleMethod = (char*)Linear; - else if (s == Cubic) opts.resampleMethod = (char*)Cubic; - else if (s == Nearest) opts.resampleMethod = (char*)Nearest; + settings.endGroup(); - s = settings.value("imageFilter", opts.imageFilter).toString(); + //---------------------------------------------------------------------- + settings.beginGroup("Caching"); + int cacheMode = + settings.value("cacheMode", 2 /*Look-Ahead Cache*/).toInt(); - if (s == Linear) opts.imageFilter = GL_LINEAR; - else if (s == Nearest) opts.imageFilter = GL_NEAREST; + opts.useCache = false; + opts.useLCache = false; - s = settings.value("backgroundPattern", - (opts.bgpattern ? opts.bgpattern : "black")).toString(); + switch (cacheMode) + { + default: + case 0: + break; + case 1: + opts.useCache = true; + break; + case 2: + opts.useLCache = true; + break; + } - if (s == "black") opts.bgpattern = (char*)Solid0; - else if (s == "white") opts.bgpattern = (char*)Solid100; - else if (s == "grey18") opts.bgpattern = (char*)Solid18; - else if (s == "grey50") opts.bgpattern = (char*)Solid50; - else if (s == "checker") opts.bgpattern = (char*)Checker; - else if (s == "crosshatch") opts.bgpattern = (char*)CrossHatch; + // Look for architecture specific preferences first, then fall back to + // non-specific + double tmplram = -1; + double tmpcram = -1; - settings.endGroup(); +#ifdef ARCH_IA32 + tmplram = settings.value("lookAheadCacheSize32New", tmplram).toDouble(); + tmpcram = settings.value("regionCacheSize32New", tmpcram).toDouble(); +#else + tmplram = settings.value("lookAheadCacheSize64New", tmplram).toDouble(); + tmpcram = settings.value("regionCacheSize64New", tmpcram).toDouble(); +#endif - //---------------------------------------------------------------------- - settings.beginGroup("Audio"); - opts.volume = settings.value("volume", opts.volume).toDouble(); - - string audioDevice = (opts.audioDevice) ? opts.audioDevice : ""; - audioDevice = UTF8::qconvert(settings.value("outputDevice", QVariant(UTF8::qconvert(audioDevice.c_str()))).toString()); - opts.audioDevice = strdup(audioDevice.c_str()); - - string audioModule = (opts.audioModule) ? opts.audioModule : ""; - audioModule = UTF8::qconvert(settings.value("outputModule", QVariant(UTF8::qconvert(audioModule.c_str()))).toString()); - opts.audioModule = strdup(audioModule.c_str()); - - opts.audioNice = int(!settings.value("holdDeviceOpen", !opts.audioNice).toBool()); - opts.aframesize = settings.value("devicePacketSize", opts.aframesize).toInt(); - opts.acachesize = settings.value("cachePacketSizeNew", opts.acachesize).toInt(); - opts.audioMinCache = settings.value("audioMinCache", opts.audioMinCache).toDouble(); - opts.audioMaxCache = settings.value("audioMaxCache", opts.audioMaxCache).toDouble(); - opts.audioNoLock = int(!settings.value("hardwareLock", !opts.audioNoLock).toBool()); - opts.audioPrecision = settings.value("outputPrecision", opts.audioPrecision).toInt(); - opts.audioLayout = settings.value("outputLayout", opts.audioLayout).toInt(); - opts.audioRate = settings.value("outputRate", opts.audioRate).toInt(); - opts.audioGlobalOffset = settings.value("globalOffset", opts.audioGlobalOffset).toDouble(); - opts.audioDeviceLatency = settings.value("audioDeviceLatency", opts.audioDeviceLatency).toDouble(); - opts.audioScrub = int(settings.value("audioScrub", opts.audioScrub).toBool()); - opts.audioPreRoll = int(settings.value("audioPreRoll", opts.audioPreRoll).toBool()); - settings.endGroup(); + if (tmplram == -1) + opts.maxlram = settings.value("lookAheadCacheSizeNew", opts.maxlram) + .toDouble(); + else + opts.maxlram = tmplram; + if (tmpcram == -1) + opts.maxcram = + settings.value("regionCacheSizeNew", opts.maxcram).toDouble(); + else + opts.maxcram = tmpcram; - //---------------------------------------------------------------------- - settings.beginGroup("Display"); - opts.gamma = settings.value("gamma", opts.gamma).toDouble(); - opts.brightness = settings.value("brightness", opts.brightness).toDouble(); - opts.vsync = settings.value("vsync", opts.vsync).toInt(); - opts.dispRedBits = settings.value("dispRedBits", opts.dispRedBits).toInt(); - opts.dispGreenBits = settings.value("dispBlueBits", opts.dispGreenBits).toInt(); - opts.dispBlueBits = settings.value("dispGreenBits", opts.dispBlueBits).toInt(); - opts.dispAlphaBits = settings.value("dispAlphaBits", opts.dispAlphaBits).toInt(); - settings.endGroup(); + opts.maxbwait = settings.value("bufferWait", opts.maxbwait).toDouble(); + opts.lookback = + settings.value("lookBehindFraction", opts.lookback).toDouble(); + opts.cacheOutsideRegion = + settings.value("cacheOutsideRegion", opts.cacheOutsideRegion) + .toBool(); - //---------------------------------------------------------------------- - settings.beginGroup("OpenEXR"); - opts.exrRGBA = settings.value("useRGBA", bool(opts.exrRGBA)).toBool(); - opts.exrInherit = settings.value("inheritChannels", bool(opts.exrInherit)).toBool(); - opts.exrPlanar3Chan = settings.value("planar3Channel", bool(opts.exrPlanar3Chan)).toBool(); - opts.exrNoOneChannel = settings.value("noOneChannel", bool(opts.exrNoOneChannel)).toBool(); - opts.exrcpus = settings.value("cpus", opts.exrcpus).toInt(); - opts.exrIOMethod = settings.value("IOmethod", opts.exrIOMethod).toInt(); - opts.exrIOSize = settings.value("IOsize", opts.exrIOSize).toInt(); - opts.exrMaxAsync = settings.value("MaxInFlight", opts.exrMaxAsync).toInt(); - opts.exrReadWindowIsDisplayWindow = settings.value("readWindowIsDisplayWindow", bool(opts.exrReadWindowIsDisplayWindow)).toBool(); - opts.exrReadWindow = settings.value("readWindow", opts.exrReadWindow).toInt(); - settings.endGroup(); + settings.endGroup(); - //---------------------------------------------------------------------- - settings.beginGroup("JPEG"); - opts.jpegRGBA = int(settings.value("RGBA", bool(opts.jpegRGBA)).toBool()); - opts.jpegIOMethod = settings.value("IOmethod", opts.jpegIOMethod).toInt(); - opts.jpegIOSize = settings.value("IOsize", opts.jpegIOSize).toInt(); - opts.jpegMaxAsync = settings.value("MaxInFlight", opts.jpegMaxAsync).toInt(); - settings.endGroup(); + //---------------------------------------------------------------------- + settings.beginGroup("Rendering"); + opts.nofloat = settings.value("nofloat", opts.nofloat).toBool(); + opts.swapScanlines = + settings.value("swapScanlines", opts.swapScanlines).toBool(); + opts.prefetch = settings.value("prefetch2", opts.prefetch).toBool(); + opts.useAppleClientStorage = + settings.value("appleClientStorage", opts.useAppleClientStorage) + .toBool(); + opts.newGLSLlutInterp = + settings.value("newGLSLlutInterp", opts.newGLSLlutInterp).toBool(); + + // Can't check ImageRenderer::queryThreadedUpload() here because this + // function is called very early (before video modules are created). If + // threaded uploads are not allowed, later code will ensure the + // checkbox is disabled, etc. But opts struct should represent state + // in settings file. + // - //---------------------------------------------------------------------- - settings.beginGroup("Cineon"); - opts.cinIOMethod = settings.value("IOmethod", opts.cinIOMethod).toInt(); - opts.cinIOSize = settings.value("IOsize", opts.cinIOSize).toInt(); - opts.cinMaxAsync = settings.value("MaxInFlight", opts.cinMaxAsync).toInt(); - opts.cinchroma = int(settings.value("usePrimaries", bool(opts.cinchroma)).toBool()); - - QString cinpf = settings.value("pixelFormatNew", opts.cinPixel).toString(); - - if (cinpf == RGB8) opts.cinPixel = (char*)RGB8; - else if (cinpf == RGBA8) opts.cinPixel = (char*)RGBA8; - else if (cinpf == RGB8_PLANAR) opts.cinPixel = (char*)RGB8_PLANAR; - else if (cinpf == RGB10_A2) opts.cinPixel = (char*)RGB10_A2; - else if (cinpf == A2_BGR10) opts.cinPixel = (char*)A2_BGR10; - else if (cinpf == RGB16) opts.cinPixel = (char*)RGB16; - else if (cinpf == RGBA16) opts.cinPixel = (char*)RGBA16; - else if (cinpf == RGB16_PLANAR) opts.cinPixel = (char*)RGB16_PLANAR; - - settings.endGroup(); + opts.useThreadedUpload = + settings.value("useThreadedUpload3", opts.useThreadedUpload) + .toBool(); + + opts.maxvram = settings.value("vram", opts.maxvram).toDouble(); + opts.maxbits = settings.value("maxBitDepth", opts.maxbits).toInt(); + + s = settings.value("resampleMethod", opts.resampleMethod).toString(); + + if (s == Area) + opts.resampleMethod = (char*)Area; + else if (s == Linear) + opts.resampleMethod = (char*)Linear; + else if (s == Cubic) + opts.resampleMethod = (char*)Cubic; + else if (s == Nearest) + opts.resampleMethod = (char*)Nearest; + + s = settings.value("imageFilter", opts.imageFilter).toString(); + + if (s == Linear) + opts.imageFilter = GL_LINEAR; + else if (s == Nearest) + opts.imageFilter = GL_NEAREST; + + s = settings + .value("backgroundPattern", + (opts.bgpattern ? opts.bgpattern : "black")) + .toString(); + + if (s == "black") + opts.bgpattern = (char*)Solid0; + else if (s == "white") + opts.bgpattern = (char*)Solid100; + else if (s == "grey18") + opts.bgpattern = (char*)Solid18; + else if (s == "grey50") + opts.bgpattern = (char*)Solid50; + else if (s == "checker") + opts.bgpattern = (char*)Checker; + else if (s == "crosshatch") + opts.bgpattern = (char*)CrossHatch; - //---------------------------------------------------------------------- - settings.beginGroup("DPX"); - opts.dpxIOMethod = settings.value("IOmethod", opts.dpxIOMethod).toInt(); - opts.dpxIOSize = settings.value("IOsize", opts.dpxIOSize).toInt(); - opts.dpxMaxAsync = settings.value("MaxInFlight", opts.dpxMaxAsync).toInt(); - opts.dpxchroma = int(settings.value("usePrimaries", bool(opts.dpxchroma)).toBool()); + settings.endGroup(); - QString dpxpf = settings.value("pixelFormatNew", opts.dpxPixel).toString(); + //---------------------------------------------------------------------- + settings.beginGroup("Audio"); + opts.volume = settings.value("volume", opts.volume).toDouble(); + + string audioDevice = (opts.audioDevice) ? opts.audioDevice : ""; + audioDevice = UTF8::qconvert( + settings + .value("outputDevice", + QVariant(UTF8::qconvert(audioDevice.c_str()))) + .toString()); + opts.audioDevice = strdup(audioDevice.c_str()); + + string audioModule = (opts.audioModule) ? opts.audioModule : ""; + audioModule = UTF8::qconvert( + settings + .value("outputModule", + QVariant(UTF8::qconvert(audioModule.c_str()))) + .toString()); + opts.audioModule = strdup(audioModule.c_str()); + + opts.audioNice = + int(!settings.value("holdDeviceOpen", !opts.audioNice).toBool()); + opts.aframesize = + settings.value("devicePacketSize", opts.aframesize).toInt(); + opts.acachesize = + settings.value("cachePacketSizeNew", opts.acachesize).toInt(); + opts.audioMinCache = + settings.value("audioMinCache", opts.audioMinCache).toDouble(); + opts.audioMaxCache = + settings.value("audioMaxCache", opts.audioMaxCache).toDouble(); + opts.audioNoLock = + int(!settings.value("hardwareLock", !opts.audioNoLock).toBool()); + opts.audioPrecision = + settings.value("outputPrecision", opts.audioPrecision).toInt(); + opts.audioLayout = + settings.value("outputLayout", opts.audioLayout).toInt(); + opts.audioRate = settings.value("outputRate", opts.audioRate).toInt(); + opts.audioGlobalOffset = + settings.value("globalOffset", opts.audioGlobalOffset).toDouble(); + opts.audioDeviceLatency = + settings.value("audioDeviceLatency", opts.audioDeviceLatency) + .toDouble(); + opts.audioScrub = + int(settings.value("audioScrub", opts.audioScrub).toBool()); + opts.audioPreRoll = + int(settings.value("audioPreRoll", opts.audioPreRoll).toBool()); + settings.endGroup(); - if (dpxpf == RGB8) opts.dpxPixel = (char*)RGB8; - else if (dpxpf == RGBA8) opts.dpxPixel = (char*)RGBA8; - else if (dpxpf == RGB8_PLANAR) opts.dpxPixel = (char*)RGB8_PLANAR; - else if (dpxpf == RGB10_A2) opts.dpxPixel = (char*)RGB10_A2; - else if (dpxpf == A2_BGR10) opts.dpxPixel = (char*)A2_BGR10; - else if (dpxpf == RGB16) opts.dpxPixel = (char*)RGB16; - else if (dpxpf == RGBA16) opts.dpxPixel = (char*)RGBA16; - else if (dpxpf == RGB16_PLANAR) opts.dpxPixel = (char*)RGB16_PLANAR; + //---------------------------------------------------------------------- + settings.beginGroup("Display"); + opts.gamma = settings.value("gamma", opts.gamma).toDouble(); + opts.brightness = + settings.value("brightness", opts.brightness).toDouble(); + opts.vsync = settings.value("vsync", opts.vsync).toInt(); + opts.dispRedBits = + settings.value("dispRedBits", opts.dispRedBits).toInt(); + opts.dispGreenBits = + settings.value("dispBlueBits", opts.dispGreenBits).toInt(); + opts.dispBlueBits = + settings.value("dispGreenBits", opts.dispBlueBits).toInt(); + opts.dispAlphaBits = + settings.value("dispAlphaBits", opts.dispAlphaBits).toInt(); + settings.endGroup(); - settings.endGroup(); + //---------------------------------------------------------------------- + settings.beginGroup("OpenEXR"); + opts.exrRGBA = settings.value("useRGBA", bool(opts.exrRGBA)).toBool(); + opts.exrInherit = + settings.value("inheritChannels", bool(opts.exrInherit)).toBool(); + opts.exrPlanar3Chan = + settings.value("planar3Channel", bool(opts.exrPlanar3Chan)) + .toBool(); + opts.exrNoOneChannel = + settings.value("noOneChannel", bool(opts.exrNoOneChannel)).toBool(); + opts.exrcpus = settings.value("cpus", opts.exrcpus).toInt(); + opts.exrIOMethod = settings.value("IOmethod", opts.exrIOMethod).toInt(); + opts.exrIOSize = settings.value("IOsize", opts.exrIOSize).toInt(); + opts.exrMaxAsync = + settings.value("MaxInFlight", opts.exrMaxAsync).toInt(); + opts.exrReadWindowIsDisplayWindow = + settings + .value("readWindowIsDisplayWindow", + bool(opts.exrReadWindowIsDisplayWindow)) + .toBool(); + opts.exrReadWindow = + settings.value("readWindow", opts.exrReadWindow).toInt(); + settings.endGroup(); + //---------------------------------------------------------------------- + settings.beginGroup("JPEG"); + opts.jpegRGBA = + int(settings.value("RGBA", bool(opts.jpegRGBA)).toBool()); + opts.jpegIOMethod = + settings.value("IOmethod", opts.jpegIOMethod).toInt(); + opts.jpegIOSize = settings.value("IOsize", opts.jpegIOSize).toInt(); + opts.jpegMaxAsync = + settings.value("MaxInFlight", opts.jpegMaxAsync).toInt(); + settings.endGroup(); - //---------------------------------------------------------------------- - settings.beginGroup("TGA"); - opts.tgaIOMethod = settings.value("IOmethod", opts.tgaIOMethod).toInt(); - opts.tgaIOSize = settings.value("IOsize", opts.tgaIOSize).toInt(); - opts.tgaMaxAsync = settings.value("MaxInFlight", opts.tgaMaxAsync).toInt(); - settings.endGroup(); + //---------------------------------------------------------------------- + settings.beginGroup("Cineon"); + opts.cinIOMethod = settings.value("IOmethod", opts.cinIOMethod).toInt(); + opts.cinIOSize = settings.value("IOsize", opts.cinIOSize).toInt(); + opts.cinMaxAsync = + settings.value("MaxInFlight", opts.cinMaxAsync).toInt(); + opts.cinchroma = + int(settings.value("usePrimaries", bool(opts.cinchroma)).toBool()); + + QString cinpf = + settings.value("pixelFormatNew", opts.cinPixel).toString(); + + if (cinpf == RGB8) + opts.cinPixel = (char*)RGB8; + else if (cinpf == RGBA8) + opts.cinPixel = (char*)RGBA8; + else if (cinpf == RGB8_PLANAR) + opts.cinPixel = (char*)RGB8_PLANAR; + else if (cinpf == RGB10_A2) + opts.cinPixel = (char*)RGB10_A2; + else if (cinpf == A2_BGR10) + opts.cinPixel = (char*)A2_BGR10; + else if (cinpf == RGB16) + opts.cinPixel = (char*)RGB16; + else if (cinpf == RGBA16) + opts.cinPixel = (char*)RGBA16; + else if (cinpf == RGB16_PLANAR) + opts.cinPixel = (char*)RGB16_PLANAR; - //---------------------------------------------------------------------- - settings.beginGroup("TIFF"); - opts.tiffIOMethod = settings.value("IOmethod", opts.tiffIOMethod).toInt(); - opts.tiffIOSize = settings.value("IOsize", opts.tiffIOSize).toInt(); - opts.tiffMaxAsync = settings.value("MaxInFlight", opts.tiffMaxAsync).toInt(); - settings.endGroup(); + settings.endGroup(); - opts.exportIOEnvVars(); + //---------------------------------------------------------------------- + settings.beginGroup("DPX"); + opts.dpxIOMethod = settings.value("IOmethod", opts.dpxIOMethod).toInt(); + opts.dpxIOSize = settings.value("IOsize", opts.dpxIOSize).toInt(); + opts.dpxMaxAsync = + settings.value("MaxInFlight", opts.dpxMaxAsync).toInt(); + opts.dpxchroma = + int(settings.value("usePrimaries", bool(opts.dpxchroma)).toBool()); + + QString dpxpf = + settings.value("pixelFormatNew", opts.dpxPixel).toString(); + + if (dpxpf == RGB8) + opts.dpxPixel = (char*)RGB8; + else if (dpxpf == RGBA8) + opts.dpxPixel = (char*)RGBA8; + else if (dpxpf == RGB8_PLANAR) + opts.dpxPixel = (char*)RGB8_PLANAR; + else if (dpxpf == RGB10_A2) + opts.dpxPixel = (char*)RGB10_A2; + else if (dpxpf == A2_BGR10) + opts.dpxPixel = (char*)A2_BGR10; + else if (dpxpf == RGB16) + opts.dpxPixel = (char*)RGB16; + else if (dpxpf == RGBA16) + opts.dpxPixel = (char*)RGBA16; + else if (dpxpf == RGB16_PLANAR) + opts.dpxPixel = (char*)RGB16_PLANAR; + settings.endGroup(); - //---------------------------------------------------------------------- - settings.beginGroup("Video"); - QString pdev = settings.value("presentationDevice", UTF8::qconvert(opts.presentDevice)).toString(); - settings.endGroup(); + //---------------------------------------------------------------------- + settings.beginGroup("TGA"); + opts.tgaIOMethod = settings.value("IOmethod", opts.tgaIOMethod).toInt(); + opts.tgaIOSize = settings.value("IOsize", opts.tgaIOSize).toInt(); + opts.tgaMaxAsync = + settings.value("MaxInFlight", opts.tgaMaxAsync).toInt(); + settings.endGroup(); - QStringList parts = pdev.split("/"); + //---------------------------------------------------------------------- + settings.beginGroup("TIFF"); + opts.tiffIOMethod = + settings.value("IOmethod", opts.tiffIOMethod).toInt(); + opts.tiffIOSize = settings.value("IOsize", opts.tiffIOSize).toInt(); + opts.tiffMaxAsync = + settings.value("MaxInFlight", opts.tiffMaxAsync).toInt(); + settings.endGroup(); - if (parts.size() == 2) - { - // ALLOWED LEAKING! WINDOWS BUG - //if (strcmp(opts.presentDevice, "")) free(opts.presentDevice); - opts.presentDevice = strdup(pdev.toUtf8().constData()); - } -} + opts.exportIOEnvVars(); -void -RvPreferences::closeEvent(QCloseEvent* event) -{ - QWidget::closeEvent(event); - // - // If we've never updated, the values in the dialog are wrong, - // so don't write, and don't tell mu clients to write. - // - if (m_updated) - { - write(); + //---------------------------------------------------------------------- + settings.beginGroup("Video"); + QString pdev = + settings + .value("presentationDevice", UTF8::qconvert(opts.presentDevice)) + .toString(); + settings.endGroup(); - const TwkApp::Application::Documents& docs = RvApp()->documents(); + QStringList parts = pdev.split("/"); - for (size_t i = 0; i < docs.size(); i++) + if (parts.size() == 2) { - Rv::Session* s = static_cast(docs[i]); - s->userGenericEvent("preferences-hide", ""); + // ALLOWED LEAKING! WINDOWS BUG + // if (strcmp(opts.presentDevice, "")) free(opts.presentDevice); + opts.presentDevice = strdup(pdev.toUtf8().constData()); } } -} - -void -RvPreferences::write() -{ - Options& opts = Options::sharedOptions(); - RV_QSETTINGS; - - settings.beginGroup("Controls"); - settings.setValue("disableClickToPlay", m_ui.clickToPlayEnableToggle->checkState() != Qt::Checked); - settings.setValue("disableScrubInView", m_ui.scrubEnableToggle->checkState() != Qt::Checked); - settings.endGroup(); - - settings.beginGroup("General"); - settings.setValue("playOnStartup", m_ui.playOnStartupToggle->checkState() == Qt::Checked); - settings.setValue("networkOnStartup", m_ui.networkToggle->checkState() == Qt::Checked); - settings.setValue("stylusAsMouse", m_ui.stylusAsMouseToggle->checkState() == Qt::Checked); - settings.setValue("startupResize", m_ui.startupResizeToggle->checkState() == Qt::Checked); - settings.setValue("desktopAware", m_ui.desktopAwareToggle->checkState() == Qt::Checked); - settings.setValue("urlsReuseSession", m_ui.reuseSessionToggle->checkState() == Qt::Checked); - settings.setValue("playMode", m_ui.playbackModeCombo->currentIndex()); - settings.setValue("noMenuBar", m_ui.noMenuBarToggle->checkState() == Qt::Checked); - settings.setValue("fullscreenOnStartup", m_ui.fullscreenOnStartupToggle->checkState() == Qt::Checked); - settings.setValue("startupScreenPolicy", m_ui.startupScreenCombo->currentIndex()-1); - settings.setValue("fps", m_ui.fpsEdit->text().toDouble()); - settings.setValue("networkHost", m_ui.networkHostEdit->text()); - settings.setValue("readerThreads", m_ui.rthreadEdit->text().toInt()); - settings.setValue("autoRetime", m_ui.autoRetimeToggle->checkState() == Qt::Checked); - settings.setValue("useCrashReporter", m_ui.useCrashReporterToggle->checkState() == Qt::Checked); - settings.setValue("fontSize1", m_ui.fontSizeSpinBox->value()); - settings.setValue("fontSize2", m_ui.fontSize2SpinBox->value()); - - char* stereo = 0; - switch (m_ui.stereoModeCombo->currentIndex()) - { - default: break; - case 1: stereo = (char*)StereoAnaglyph; break; - case 2: stereo = (char*)StereoPair; break; - case 3: stereo = (char*)StereoMirror; break; - case 4: stereo = (char*)StereoLeft; break; - case 5: stereo = (char*)StereoRight; break; - case 6: stereo = (char*)StereoChecker; break; - case 7: stereo = (char*)StereoScanline; break; - case 8: stereo = (char*)StereoHardware; break; - case 9: stereo = (char*)StereoLumAnaglyph; break; - } - - settings.setValue("stereoMode", UTF8::qconvert(stereo)); - - settings.endGroup(); - - //---------------------------------------------------------------------- - - settings.beginGroup("Caching"); - settings.setValue("cacheMode", m_ui.cacheModeCombo->currentIndex()); - - // Use the setting from the running architecture as the shared setting for - // backwards compatibility. - #ifdef ARCH_IA32 - settings.setValue("lookAheadCacheSizeNew", m_ui.lookAheadCacheSize32Edit->text().toDouble()); - settings.setValue("regionCacheSizeNew", m_ui.regionCacheSize32Edit->text().toDouble()); - #else - settings.setValue("lookAheadCacheSizeNew", m_ui.lookAheadCacheSize64Edit->text().toDouble()); - settings.setValue("regionCacheSizeNew", m_ui.regionCacheSize64Edit->text().toDouble()); - #endif - - // Set the architecture specific settings - //settings.setValue("lookAheadCacheSize32New", m_ui.lookAheadCacheSize32Edit->text().toDouble()); - settings.setValue("lookAheadCacheSize64New", m_ui.lookAheadCacheSize64Edit->text().toDouble()); - //settings.setValue("regionCacheSize32New", m_ui.regionCacheSize32Edit->text().toDouble()); - settings.setValue("regionCacheSize64New", m_ui.regionCacheSize64Edit->text().toDouble()); - - settings.setValue("bufferWait", m_ui.bufferWaitEdit->text().toDouble()); - settings.setValue("lookBehindFraction", m_ui.lookBehindFracEdit->text().toDouble()); - settings.setValue("cacheOutsideRegion", m_ui.cacheOutsideRegionToggle->checkState() == Qt::Checked); - settings.endGroup(); - - //---------------------------------------------------------------------- - settings.beginGroup("Rendering"); - - settings.setValue("nofloat", m_ui.allowFloatToggle->checkState() != Qt::Checked); - settings.setValue("swapScanlines", m_ui.swapScanlinesToggle->checkState() == Qt::Checked); - settings.setValue("prefetch2", m_ui.prefetchToggle->checkState() == Qt::Checked); - settings.setValue("appleClientStorage", m_ui.appleClientStorageToggle->checkState() == Qt::Checked); - settings.setValue("newGLSLlutInterp", m_ui.newGLSLlutInterpToggle->checkState() == Qt::Checked); - - // Don't write the value of the toggle as a setting unless the user was - // actually allowed to change it. - // - if (ImageRenderer::queryThreadedUpload()) - { - settings.setValue("useThreadedUpload3", m_ui.useThreadedUploadToggle->checkState() == Qt::Checked); - } - - int n = 32; - switch (m_ui.bitDepthCombo->currentIndex()) + void RvPreferences::closeEvent(QCloseEvent* event) { - default: - case 0: n = 32; break; - case 1: n = 16; break; - case 2: n = 8; break; - } + QWidget::closeEvent(event); + // + // If we've never updated, the values in the dialog are wrong, + // so don't write, and don't tell mu clients to write. + // + if (m_updated) + { + write(); - settings.setValue("maxBitDepth", n); + const TwkApp::Application::Documents& docs = RvApp()->documents(); - char* method = 0; + for (size_t i = 0; i < docs.size(); i++) + { + Rv::Session* s = static_cast(docs[i]); + s->userGenericEvent("preferences-hide", ""); + } + } + } - switch (m_ui.resampleMethodCombo->currentIndex()) + void RvPreferences::write() { - default: - case 0: method = (char*)Area; break; - case 1: method = (char*)Cubic; break; - case 2: method = (char*)Linear; break; - case 3: method = (char*)Nearest; break; - } + Options& opts = Options::sharedOptions(); + RV_QSETTINGS; - settings.setValue("resampleMethod", method); + settings.beginGroup("Controls"); + settings.setValue("disableClickToPlay", + m_ui.clickToPlayEnableToggle->checkState() + != Qt::Checked); + settings.setValue("disableScrubInView", + m_ui.scrubEnableToggle->checkState() != Qt::Checked); + settings.endGroup(); - switch (m_ui.imageFilterCombo->currentIndex()) - { - default: - case 0: method = (char*)Linear; break; - case 1: method = (char*)Nearest; break; - } + settings.beginGroup("General"); + settings.setValue("playOnStartup", + m_ui.playOnStartupToggle->checkState() + == Qt::Checked); + settings.setValue("networkOnStartup", + m_ui.networkToggle->checkState() == Qt::Checked); + settings.setValue("stylusAsMouse", + m_ui.stylusAsMouseToggle->checkState() + == Qt::Checked); + settings.setValue("startupResize", + m_ui.startupResizeToggle->checkState() + == Qt::Checked); + settings.setValue("desktopAware", + m_ui.desktopAwareToggle->checkState() == Qt::Checked); + settings.setValue("urlsReuseSession", + m_ui.reuseSessionToggle->checkState() == Qt::Checked); + settings.setValue("playMode", m_ui.playbackModeCombo->currentIndex()); + settings.setValue("noMenuBar", + m_ui.noMenuBarToggle->checkState() == Qt::Checked); + settings.setValue("fullscreenOnStartup", + m_ui.fullscreenOnStartupToggle->checkState() + == Qt::Checked); + settings.setValue("startupScreenPolicy", + m_ui.startupScreenCombo->currentIndex() - 1); + settings.setValue("fps", m_ui.fpsEdit->text().toDouble()); + settings.setValue("networkHost", m_ui.networkHostEdit->text()); + settings.setValue("readerThreads", m_ui.rthreadEdit->text().toInt()); + settings.setValue("autoRetime", + m_ui.autoRetimeToggle->checkState() == Qt::Checked); + settings.setValue("useCrashReporter", + m_ui.useCrashReporterToggle->checkState() + == Qt::Checked); + settings.setValue("fontSize1", m_ui.fontSizeSpinBox->value()); + settings.setValue("fontSize2", m_ui.fontSize2SpinBox->value()); + + char* stereo = 0; + switch (m_ui.stereoModeCombo->currentIndex()) + { + default: + break; + case 1: + stereo = (char*)StereoAnaglyph; + break; + case 2: + stereo = (char*)StereoPair; + break; + case 3: + stereo = (char*)StereoMirror; + break; + case 4: + stereo = (char*)StereoLeft; + break; + case 5: + stereo = (char*)StereoRight; + break; + case 6: + stereo = (char*)StereoChecker; + break; + case 7: + stereo = (char*)StereoScanline; + break; + case 8: + stereo = (char*)StereoHardware; + break; + case 9: + stereo = (char*)StereoLumAnaglyph; + break; + } - settings.setValue("imageFilter", method); + settings.setValue("stereoMode", UTF8::qconvert(stereo)); - switch (m_ui.bgPatternCombo->currentIndex()) - { - default: - case 0: method = (char*)Solid0; break; - case 1: method = (char*)Solid18; break; - case 2: method = (char*)Solid50; break; - case 3: method = (char*)Solid100; break; - case 4: method = (char*)Checker; break; - case 5: method = (char*)CrossHatch; break; - } + settings.endGroup(); - settings.setValue("backgroundPattern", method); + //---------------------------------------------------------------------- - settings.endGroup(); + settings.beginGroup("Caching"); + settings.setValue("cacheMode", m_ui.cacheModeCombo->currentIndex()); - //---------------------------------------------------------------------- +// Use the setting from the running architecture as the shared setting for +// backwards compatibility. +#ifdef ARCH_IA32 + settings.setValue("lookAheadCacheSizeNew", + m_ui.lookAheadCacheSize32Edit->text().toDouble()); + settings.setValue("regionCacheSizeNew", + m_ui.regionCacheSize32Edit->text().toDouble()); +#else + settings.setValue("lookAheadCacheSizeNew", + m_ui.lookAheadCacheSize64Edit->text().toDouble()); + settings.setValue("regionCacheSizeNew", + m_ui.regionCacheSize64Edit->text().toDouble()); +#endif - settings.beginGroup("Audio"); - settings.setValue("volume", m_ui.volumeSlider->sliderPosition() / 100.0); - settings.setValue("holdDeviceOpen", m_ui.audioHoldOpenToggle->checkState() == Qt::Checked); - settings.setValue("hardwareLock", m_ui.audioHardwareLockToggle->checkState() == Qt::Checked); - settings.setValue("audioScrub", m_ui.audioScrubAtLaunchToggle->checkState() == Qt::Checked); - settings.setValue("audioPreRoll", m_ui.audioPreRollToggle->checkState() == Qt::Checked); - settings.setValue("devicePacketSize", m_ui.audioDevicePacketEdit->text().toInt()); - settings.setValue("cachePacketSizeNew", m_ui.audioCachePacketEdit->text().toInt()); - settings.setValue("audioMinCache", m_ui.audioCacheMinEdit->text().toDouble()); - settings.setValue("audioMaxCache", m_ui.audioCacheMaxEdit->text().toDouble()); - settings.setValue("globalOffset", m_ui.audioGlobalOffsetEdit->text().toDouble()); - settings.setValue("audioDeviceLatency", m_ui.audioDeviceLatencyEdit->text().toDouble()); - - if (!AudioRenderer::audioDisabledAlways() && - m_ui.audioDeviceLayoutCombo->currentText() != "Unavailable" && - m_ui.audioDeviceLayoutCombo->currentText() != "") - { - settings.setValue("outputRate", m_ui.audioDeviceRateCombo->currentText().toDouble()); - settings.setValue("outputModule", m_ui.audioModuleCombo->currentText()); - settings.setValue("outputDevice", m_ui.audioDeviceCombo->currentText()); - - // Handle outputPrecision settings - int currentIndex = m_ui.audioDeviceFormatCombo->currentIndex(); - TwkAudio::Format currentFormat; + // Set the architecture specific settings + // settings.setValue("lookAheadCacheSize32New", + // m_ui.lookAheadCacheSize32Edit->text().toDouble()); + settings.setValue("lookAheadCacheSize64New", + m_ui.lookAheadCacheSize64Edit->text().toDouble()); + // settings.setValue("regionCacheSize32New", + // m_ui.regionCacheSize32Edit->text().toDouble()); + settings.setValue("regionCacheSize64New", + m_ui.regionCacheSize64Edit->text().toDouble()); + + settings.setValue("bufferWait", m_ui.bufferWaitEdit->text().toDouble()); + settings.setValue("lookBehindFraction", + m_ui.lookBehindFracEdit->text().toDouble()); + settings.setValue("cacheOutsideRegion", + m_ui.cacheOutsideRegionToggle->checkState() + == Qt::Checked); + settings.endGroup(); - if (currentIndex < m_ui.audioDeviceFormatCombo->count()) + //---------------------------------------------------------------------- + + settings.beginGroup("Rendering"); + + settings.setValue("nofloat", + m_ui.allowFloatToggle->checkState() != Qt::Checked); + settings.setValue("swapScanlines", + m_ui.swapScanlinesToggle->checkState() + == Qt::Checked); + settings.setValue("prefetch2", + m_ui.prefetchToggle->checkState() == Qt::Checked); + settings.setValue("appleClientStorage", + m_ui.appleClientStorageToggle->checkState() + == Qt::Checked); + settings.setValue("newGLSLlutInterp", + m_ui.newGLSLlutInterpToggle->checkState() + == Qt::Checked); + + // Don't write the value of the toggle as a setting unless the user was + // actually allowed to change it. + // + if (ImageRenderer::queryThreadedUpload()) { - currentFormat = (TwkAudio::Format) m_ui.audioDeviceFormatCombo->itemData(currentIndex).toInt(); + settings.setValue("useThreadedUpload3", + m_ui.useThreadedUploadToggle->checkState() + == Qt::Checked); } - int prec; - switch (currentFormat) + int n = 32; + switch (m_ui.bitDepthCombo->currentIndex()) { - default: - case TwkAudio::Float32Format: prec = 32; break; - case TwkAudio::Int24Format: prec = 24; break; - case TwkAudio::Int16Format: prec = 16; break; - case TwkAudio::Int8Format: prec = 8; break; - case TwkAudio::Int32Format: prec = -32 ; break; + default: + case 0: + n = 32; + break; + case 1: + n = 16; + break; + case 2: + n = 8; + break; } - settings.setValue("outputPrecision", prec); + settings.setValue("maxBitDepth", n); - // Handle outputLayout settings - currentIndex = m_ui.audioDeviceLayoutCombo->currentIndex(); - TwkAudio::Layout currentChannelLayout; + char* method = 0; - if (currentIndex < m_ui.audioDeviceLayoutCombo->count()) + switch (m_ui.resampleMethodCombo->currentIndex()) { - currentChannelLayout = (TwkAudio::Layout) m_ui.audioDeviceLayoutCombo->itemData(currentIndex).toInt(); + default: + case 0: + method = (char*)Area; + break; + case 1: + method = (char*)Cubic; + break; + case 2: + method = (char*)Linear; + break; + case 3: + method = (char*)Nearest; + break; } - settings.setValue("outputLayout", int(currentChannelLayout)); - } - settings.endGroup(); + settings.setValue("resampleMethod", method); - //---------------------------------------------------------------------- + switch (m_ui.imageFilterCombo->currentIndex()) + { + default: + case 0: + method = (char*)Linear; + break; + case 1: + method = (char*)Nearest; + break; + } - settings.beginGroup("Display"); - settings.setValue("vsync", m_ui.displayVideoSyncButton->checkState() == Qt::Checked ? 1 : 0); + settings.setValue("imageFilter", method); - int rbits = 0, gbits = 0, bbits = 0, abits = 0; + switch (m_ui.bgPatternCombo->currentIndex()) + { + default: + case 0: + method = (char*)Solid0; + break; + case 1: + method = (char*)Solid18; + break; + case 2: + method = (char*)Solid50; + break; + case 3: + method = (char*)Solid100; + break; + case 4: + method = (char*)Checker; + break; + case 5: + method = (char*)CrossHatch; + break; + } - switch (m_ui.displayOutputCombo->currentIndex()) - { - default: - case 0: abits = bbits = gbits = rbits = 0; break; - case 1: abits = bbits = gbits = rbits = 8; break; - case 2: bbits = gbits = rbits = 10; abits = 2; break; - break; - } - - settings.setValue("dispRedBits", rbits); - settings.setValue("dispGreenBits", gbits); - settings.setValue("dispBlueBits", bbits); - settings.setValue("dispAlphaBits", abits); - settings.endGroup(); + settings.setValue("backgroundPattern", method); - //---------------------------------------------------------------------- + settings.endGroup(); - settings.beginGroup("OpenEXR"); - settings.setValue("useRGBA", m_ui.exrRGBAToggle->checkState() == Qt::Checked); - settings.setValue("inheritChannels", m_ui.exrInheritToggle->checkState() == Qt::Checked); - settings.setValue("planar3Channel", m_ui.exrPlanar3ChannelToggle->checkState() == Qt::Checked); - settings.setValue("noOneChannel", m_ui.exrNoOneChannelToggle->checkState() == Qt::Checked); - settings.setValue("readWindowIsDisplayWindow", m_ui.exrReadWindowIsDisplayWindowToggle->checkState() == Qt::Checked); - settings.setValue("cpus", m_ui.exrNumThreadsEdit->text().toInt()); - settings.setValue("IOmethod", m_ui.exrIOMethodCombo->currentIndex()); - settings.setValue("readWindow", m_ui.exrReadWindowCombo->currentIndex()); - settings.setValue("IOsize", m_ui.exrChunkSizeEdit->text().toInt()); - settings.setValue("MaxInFlight", m_ui.exrMaxInFlightEdit->text().toInt()); - settings.endGroup(); + //---------------------------------------------------------------------- + + settings.beginGroup("Audio"); + settings.setValue("volume", + m_ui.volumeSlider->sliderPosition() / 100.0); + settings.setValue("holdDeviceOpen", + m_ui.audioHoldOpenToggle->checkState() + == Qt::Checked); + settings.setValue("hardwareLock", + m_ui.audioHardwareLockToggle->checkState() + == Qt::Checked); + settings.setValue("audioScrub", + m_ui.audioScrubAtLaunchToggle->checkState() + == Qt::Checked); + settings.setValue("audioPreRoll", + m_ui.audioPreRollToggle->checkState() == Qt::Checked); + settings.setValue("devicePacketSize", + m_ui.audioDevicePacketEdit->text().toInt()); + settings.setValue("cachePacketSizeNew", + m_ui.audioCachePacketEdit->text().toInt()); + settings.setValue("audioMinCache", + m_ui.audioCacheMinEdit->text().toDouble()); + settings.setValue("audioMaxCache", + m_ui.audioCacheMaxEdit->text().toDouble()); + settings.setValue("globalOffset", + m_ui.audioGlobalOffsetEdit->text().toDouble()); + settings.setValue("audioDeviceLatency", + m_ui.audioDeviceLatencyEdit->text().toDouble()); + + if (!AudioRenderer::audioDisabledAlways() + && m_ui.audioDeviceLayoutCombo->currentText() != "Unavailable" + && m_ui.audioDeviceLayoutCombo->currentText() != "") + { + settings.setValue( + "outputRate", + m_ui.audioDeviceRateCombo->currentText().toDouble()); + settings.setValue("outputModule", + m_ui.audioModuleCombo->currentText()); + settings.setValue("outputDevice", + m_ui.audioDeviceCombo->currentText()); + + // Handle outputPrecision settings + int currentIndex = m_ui.audioDeviceFormatCombo->currentIndex(); + TwkAudio::Format currentFormat; + + if (currentIndex < m_ui.audioDeviceFormatCombo->count()) + { + currentFormat = (TwkAudio::Format)m_ui.audioDeviceFormatCombo + ->itemData(currentIndex) + .toInt(); + } - //---------------------------------------------------------------------- + int prec; + switch (currentFormat) + { + default: + case TwkAudio::Float32Format: + prec = 32; + break; + case TwkAudio::Int24Format: + prec = 24; + break; + case TwkAudio::Int16Format: + prec = 16; + break; + case TwkAudio::Int8Format: + prec = 8; + break; + case TwkAudio::Int32Format: + prec = -32; + break; + } - settings.beginGroup("JPEG"); - settings.setValue("RGBA", m_ui.jpegRGBAToggle->checkState() == Qt::Checked); - settings.setValue("IOmethod", m_ui.jpegIOMethodCombo->currentIndex()); - settings.setValue("IOsize", m_ui.jpegChunkSizeEdit->text().toInt()); - settings.setValue("MaxInFlight", m_ui.jpegMaxInFlightEdit->text().toInt()); - settings.endGroup(); + settings.setValue("outputPrecision", prec); - //---------------------------------------------------------------------- + // Handle outputLayout settings + currentIndex = m_ui.audioDeviceLayoutCombo->currentIndex(); + TwkAudio::Layout currentChannelLayout; - settings.beginGroup("Cineon"); - settings.setValue("IOmethod", m_ui.cinIOMethodCombo->currentIndex()); - settings.setValue("IOsize", m_ui.cinChunkSizeEdit->text().toInt()); - settings.setValue("MaxInFlight", m_ui.cinMaxInFlightEdit->text().toInt()); - settings.setValue("usePrimaries", m_ui.cinChromaToggle->checkState() == Qt::Checked); + if (currentIndex < m_ui.audioDeviceLayoutCombo->count()) + { + currentChannelLayout = + (TwkAudio::Layout)m_ui.audioDeviceLayoutCombo + ->itemData(currentIndex) + .toInt(); + } + settings.setValue("outputLayout", int(currentChannelLayout)); + } - const char* cinfmt = opts.cinPixel; + settings.endGroup(); - switch (m_ui.cinDisplayPixelCombo->currentIndex()) - { - case 0: cinfmt = RGB8; break; - case 1: cinfmt = RGBA8; break; - case 2: cinfmt = RGB8_PLANAR; break; - case 3: cinfmt = RGB10_A2; break; - case 4: cinfmt = A2_BGR10; break; - case 5: cinfmt = RGB16; break; - case 6: cinfmt = RGBA16; break; - case 7: cinfmt = RGB16_PLANAR; break; - } + //---------------------------------------------------------------------- + + settings.beginGroup("Display"); + settings.setValue( + "vsync", + m_ui.displayVideoSyncButton->checkState() == Qt::Checked ? 1 : 0); + + int rbits = 0, gbits = 0, bbits = 0, abits = 0; + + switch (m_ui.displayOutputCombo->currentIndex()) + { + default: + case 0: + abits = bbits = gbits = rbits = 0; + break; + case 1: + abits = bbits = gbits = rbits = 8; + break; + case 2: + bbits = gbits = rbits = 10; + abits = 2; + break; + break; + } + + settings.setValue("dispRedBits", rbits); + settings.setValue("dispGreenBits", gbits); + settings.setValue("dispBlueBits", bbits); + settings.setValue("dispAlphaBits", abits); + settings.endGroup(); + + //---------------------------------------------------------------------- + + settings.beginGroup("OpenEXR"); + settings.setValue("useRGBA", + m_ui.exrRGBAToggle->checkState() == Qt::Checked); + settings.setValue("inheritChannels", + m_ui.exrInheritToggle->checkState() == Qt::Checked); + settings.setValue("planar3Channel", + m_ui.exrPlanar3ChannelToggle->checkState() + == Qt::Checked); + settings.setValue("noOneChannel", + m_ui.exrNoOneChannelToggle->checkState() + == Qt::Checked); + settings.setValue("readWindowIsDisplayWindow", + m_ui.exrReadWindowIsDisplayWindowToggle->checkState() + == Qt::Checked); + settings.setValue("cpus", m_ui.exrNumThreadsEdit->text().toInt()); + settings.setValue("IOmethod", m_ui.exrIOMethodCombo->currentIndex()); + settings.setValue("readWindow", + m_ui.exrReadWindowCombo->currentIndex()); + settings.setValue("IOsize", m_ui.exrChunkSizeEdit->text().toInt()); + settings.setValue("MaxInFlight", + m_ui.exrMaxInFlightEdit->text().toInt()); + settings.endGroup(); - settings.setValue("pixelFormatNew", UTF8::qconvert(cinfmt)); - settings.endGroup(); + //---------------------------------------------------------------------- + + settings.beginGroup("JPEG"); + settings.setValue("RGBA", + m_ui.jpegRGBAToggle->checkState() == Qt::Checked); + settings.setValue("IOmethod", m_ui.jpegIOMethodCombo->currentIndex()); + settings.setValue("IOsize", m_ui.jpegChunkSizeEdit->text().toInt()); + settings.setValue("MaxInFlight", + m_ui.jpegMaxInFlightEdit->text().toInt()); + settings.endGroup(); + + //---------------------------------------------------------------------- + + settings.beginGroup("Cineon"); + settings.setValue("IOmethod", m_ui.cinIOMethodCombo->currentIndex()); + settings.setValue("IOsize", m_ui.cinChunkSizeEdit->text().toInt()); + settings.setValue("MaxInFlight", + m_ui.cinMaxInFlightEdit->text().toInt()); + settings.setValue("usePrimaries", + m_ui.cinChromaToggle->checkState() == Qt::Checked); + + const char* cinfmt = opts.cinPixel; + + switch (m_ui.cinDisplayPixelCombo->currentIndex()) + { + case 0: + cinfmt = RGB8; + break; + case 1: + cinfmt = RGBA8; + break; + case 2: + cinfmt = RGB8_PLANAR; + break; + case 3: + cinfmt = RGB10_A2; + break; + case 4: + cinfmt = A2_BGR10; + break; + case 5: + cinfmt = RGB16; + break; + case 6: + cinfmt = RGBA16; + break; + case 7: + cinfmt = RGB16_PLANAR; + break; + } + + settings.setValue("pixelFormatNew", UTF8::qconvert(cinfmt)); + settings.endGroup(); + + //---------------------------------------------------------------------- + + settings.beginGroup("DPX"); + settings.setValue("IOmethod", m_ui.dpxIOMethodCombo->currentIndex()); + settings.setValue("IOsize", m_ui.dpxChunkSizeEdit->text().toInt()); + settings.setValue("MaxInFlight", + m_ui.dpxMaxInFlightEdit->text().toInt()); + settings.setValue("usePrimaries", + m_ui.dpxChromaToggle->checkState() == Qt::Checked); + + const char* dpxfmt = opts.dpxPixel; + + switch (m_ui.dpxDisplayPixelCombo->currentIndex()) + { + case 0: + dpxfmt = RGB8; + break; + case 1: + dpxfmt = RGBA8; + break; + case 2: + dpxfmt = RGB8_PLANAR; + break; + case 3: + dpxfmt = RGB10_A2; + break; + case 4: + dpxfmt = A2_BGR10; + break; + case 5: + dpxfmt = RGB16; + break; + case 6: + dpxfmt = RGBA16; + break; + case 7: + dpxfmt = RGB16_PLANAR; + break; + } + + settings.setValue("pixelFormatNew", UTF8::qconvert(dpxfmt)); + settings.endGroup(); + + //---------------------------------------------------------------------- + settings.beginGroup("TGA"); + settings.setValue("IOmethod", m_ui.tgaIOMethodCombo->currentIndex()); + settings.setValue("IOsize", m_ui.tgaChunkSizeEdit->text().toInt()); + settings.setValue("MaxInFlight", + m_ui.tgaMaxInFlightEdit->text().toInt()); + settings.endGroup(); + + settings.beginGroup("TIFF"); + settings.setValue("IOmethod", m_ui.tifIOMethodCombo->currentIndex()); + settings.setValue("IOsize", m_ui.tifChunkSizeEdit->text().toInt()); + settings.setValue("MaxInFlight", + m_ui.tifMaxInFlightEdit->text().toInt()); + settings.endGroup(); + + // + // Ensure that settings changes are written to disk. + // + settings.sync(); + + const TwkApp::Application::Documents& docs = RvApp()->documents(); + + for (size_t i = 0; i < docs.size(); i++) + { + Rv::Session* s = static_cast(docs[i]); + s->userGenericEvent("after-preferences-write", ""); + } + } //---------------------------------------------------------------------- + // + // General + // - settings.beginGroup("DPX"); - settings.setValue("IOmethod", m_ui.dpxIOMethodCombo->currentIndex()); - settings.setValue("IOsize", m_ui.dpxChunkSizeEdit->text().toInt()); - settings.setValue("MaxInFlight", m_ui.dpxMaxInFlightEdit->text().toInt()); - settings.setValue("usePrimaries", m_ui.dpxChromaToggle->checkState() == Qt::Checked); + void RvPreferences::updateStyleSheet() + { + Options& opts = Options::sharedOptions(); - const char* dpxfmt = opts.dpxPixel; + if (!opts.qtcss) + { +#ifdef PLATFORM_DARWIN + QString csstext = UTF8::qconvert(rv_mac_dark) + .arg(opts.fontSize1) + .arg(opts.fontSize2); +#else + QString csstext = UTF8::qconvert(rv_linux_dark) + .arg(opts.fontSize1) + .arg(opts.fontSize2) + .arg(opts.fontSize2 - 1); +#endif + qApp->setStyleSheet(csstext); + } + } - switch (m_ui.dpxDisplayPixelCombo->currentIndex()) + void RvPreferences::stylusAsMouseChanged(int state) { - case 0: dpxfmt = RGB8; break; - case 1: dpxfmt = RGBA8; break; - case 2: dpxfmt = RGB8_PLANAR; break; - case 3: dpxfmt = RGB10_A2; break; - case 4: dpxfmt = A2_BGR10; break; - case 5: dpxfmt = RGB16; break; - case 6: dpxfmt = RGBA16; break; - case 7: dpxfmt = RGB16_PLANAR; break; + Options::sharedOptions().stylusAsMouse = (state == 0) ? 0 : 1; } - settings.setValue("pixelFormatNew", UTF8::qconvert(dpxfmt)); - settings.endGroup(); + void RvPreferences::startupResizeChanged(int state) + { + Options::sharedOptions().startupResize = (state == 0) ? 0 : 1; + } //---------------------------------------------------------------------- - settings.beginGroup("TGA"); - settings.setValue("IOmethod", m_ui.tgaIOMethodCombo->currentIndex()); - settings.setValue("IOsize", m_ui.tgaChunkSizeEdit->text().toInt()); - settings.setValue("MaxInFlight", m_ui.tgaMaxInFlightEdit->text().toInt()); - settings.endGroup(); - - settings.beginGroup("TIFF"); - settings.setValue("IOmethod", m_ui.tifIOMethodCombo->currentIndex()); - settings.setValue("IOsize", m_ui.tifChunkSizeEdit->text().toInt()); - settings.setValue("MaxInFlight", m_ui.tifMaxInFlightEdit->text().toInt()); - settings.endGroup(); - // - // Ensure that settings changes are written to disk. + // Caching slots // - settings.sync(); - const TwkApp::Application::Documents& docs = RvApp()->documents(); - - for (size_t i = 0; i < docs.size(); i++) + static void newCacheSize(float gigs, IPGraph::CachingMode m) { - Rv::Session* s = static_cast(docs[i]); - s->userGenericEvent("after-preferences-write", ""); + const TwkApp::Application::Documents& docs = IPCore::App()->documents(); + + // + // Don't bother setting it to something impossible on a 32-bit + // build, and don't set it to 0.0, since something will surely + // break. + // + if (4 == sizeof(void*) && gigs > 3.5) + gigs = 3.5; + if (gigs < 0.01) + gigs = 0.01; + + size_t bytes = size_t(double(gigs) * 1024.0 * 1024.0 * 1024.0); + + if (m == IPGraph::BufferCache) + { + Options::sharedOptions().maxlram = gigs; + Session::setMaxBufferCacheSize(bytes); + } + else + { + Options::sharedOptions().maxcram = gigs; + Session::setMaxGreedyCacheSize(bytes); + } + + for (size_t i = 0; i < docs.size(); i++) + { + Session* s = static_cast(docs[i]); + s->graph().setCacheModeSize(m, bytes); + s->updateGraphInOut(); + } } -} -//---------------------------------------------------------------------- -// -// General -// + void RvPreferences::lookaheadCacheSizeFinisihed() + { + float gigs = + (dynamic_cast(QObject::sender()))->text().toFloat(); + newCacheSize(gigs, IPGraph::BufferCache); + } + void RvPreferences::regionCacheSizeFinisihed() + { + float gigs = + (dynamic_cast(QObject::sender()))->text().toFloat(); + newCacheSize(gigs, IPGraph::GreedyCache); + } -void -RvPreferences::updateStyleSheet() -{ - Options& opts = Options::sharedOptions(); + void RvPreferences::bufferWaitFinished() + { + float seconds = m_ui.bufferWaitEdit->text().toFloat(); + Session::setMaxBufferedWaitTime(seconds); + } - if (!opts.qtcss) + void RvPreferences::lookBehindFinished() { -#ifdef PLATFORM_DARWIN - QString csstext = UTF8::qconvert(rv_mac_dark).arg(opts.fontSize1).arg(opts.fontSize2); -#else - QString csstext = UTF8::qconvert(rv_linux_dark).arg(opts.fontSize1).arg(opts.fontSize2).arg(opts.fontSize2-1); -#endif - qApp->setStyleSheet(csstext); + float percent = m_ui.lookBehindFracEdit->text().toFloat(); + Options::sharedOptions().lookback = percent; + Session::setCacheLookBehindFraction(percent); + + const TwkApp::Application::Documents& docs = IPCore::App()->documents(); + + for (size_t i = 0; i < docs.size(); i++) + { + Session* s = static_cast(docs[i]); + s->graph().setLookBehindFraction(percent); + } } -} -void -RvPreferences::stylusAsMouseChanged(int state) -{ - Options::sharedOptions().stylusAsMouse = (state == 0) ? 0 : 1; -} + void RvPreferences::cacheOutsideRegionChanged(int state) + { + IPCore::FBCache::setCacheOutsideRegion(state != 0); -void -RvPreferences::startupResizeChanged(int state) -{ - Options::sharedOptions().startupResize = (state == 0) ? 0 : 1; -} + const TwkApp::Application::Documents& docs = IPCore::App()->documents(); -//---------------------------------------------------------------------- -// -// Caching slots -// + for (size_t i = 0; i < docs.size(); i++) + { + Session* s = static_cast(docs[i]); + s->updateGraphInOut(); + } + } -static void -newCacheSize(float gigs, IPGraph::CachingMode m) -{ - const TwkApp::Application::Documents& docs = IPCore::App()->documents(); + void RvPreferences::rthreadFinished() {} + //---------------------------------------------------------------------- // - // Don't bother setting it to something impossible on a 32-bit - // build, and don't set it to 0.0, since something will surely - // break. + // Rendering // - if (4 == sizeof(void *) && gigs > 3.5) gigs = 3.5; - if (gigs < 0.01) gigs = 0.01; - - size_t bytes = size_t(double(gigs) * 1024.0 * 1024.0 * 1024.0); - if (m == IPGraph::BufferCache) + void RvPreferences::bitDepthChanged(int index) { - Options::sharedOptions().maxlram = gigs; - Session::setMaxBufferCacheSize(bytes); + switch (index) + { + case 0: // 32 + FormatIPNode::defaultBitDepth = 32; + break; + case 1: // 16 + FormatIPNode::defaultBitDepth = 16; + break; + case 2: // 8 + FormatIPNode::defaultBitDepth = 8; + break; + } } - else + + void RvPreferences::allowFloatChanged(int state) { - Options::sharedOptions().maxcram = gigs; - Session::setMaxGreedyCacheSize(bytes); + FormatIPNode::defaultAllowFP = state != 0; } - for (size_t i = 0; i < docs.size(); i++) + void RvPreferences::newGLSLlutInterpChanged(int state) { - Session* s = static_cast(docs[i]); - s->graph().setCacheModeSize(m, bytes); - s->updateGraphInOut(); + LUTIPNode::newGLSLlutInterp = (state != 0); } -} -void -RvPreferences::lookaheadCacheSizeFinisihed() -{ - float gigs = (dynamic_cast (QObject::sender()))->text().toFloat(); - newCacheSize(gigs, IPGraph::BufferCache); -} + void RvPreferences::swapScanlinesChanged(int state) + { + DisplayStereoIPNode::setSwapScanlines((state == Qt::Checked)); + } -void -RvPreferences::regionCacheSizeFinisihed() -{ - float gigs = (dynamic_cast (QObject::sender()))->text().toFloat(); - newCacheSize(gigs, IPGraph::GreedyCache); -} + void RvPreferences::prefetchChanged(int state) + { + const TwkApp::Application::Documents& docs = IPCore::App()->documents(); -void -RvPreferences::bufferWaitFinished() -{ - float seconds = m_ui.bufferWaitEdit->text().toFloat(); - Session::setMaxBufferedWaitTime(seconds); -} + for (size_t i = 0; i < docs.size(); i++) + { + Session* s = static_cast(docs[i]); + s->setUsePreEval(state != 0); + } + } -void -RvPreferences::lookBehindFinished() -{ - float percent = m_ui.lookBehindFracEdit->text().toFloat(); - Options::sharedOptions().lookback = percent; - Session::setCacheLookBehindFraction(percent); + void RvPreferences::appleClientStorageChanged(int state) + { + ImageRenderer::setUseAppleClientStorage(state != 0); + const TwkApp::Application::Documents& docs = IPCore::App()->documents(); - const TwkApp::Application::Documents& docs = IPCore::App()->documents(); + for (size_t i = 0; i < docs.size(); i++) + { + Session* s = static_cast(docs[i]); + s->clearVideoDeviceCaches(); + } + } - for (size_t i = 0; i < docs.size(); i++) + void RvPreferences::useThreadedUploadChanged(int state) { - Session* s = static_cast(docs[i]); - s->graph().setLookBehindFraction (percent); + const TwkApp::Application::Documents& docs = IPCore::App()->documents(); + + for (size_t i = 0; i < docs.size(); i++) + { + Session* s = static_cast(docs[i]); + s->renderer()->setUseThreadedUpload(state != 0); + } } -} -void -RvPreferences::cacheOutsideRegionChanged(int state) -{ - IPCore::FBCache::setCacheOutsideRegion(state != 0); + void RvPreferences::videoSyncChanged(int state) + { + const TwkApp::Application::Documents& docs = IPCore::App()->documents(); - const TwkApp::Application::Documents& docs = IPCore::App()->documents(); + for (size_t i = 0; i < docs.size(); i++) + { + Session* s = static_cast(docs[i]); + if (RvDocument* rvdoc = + reinterpret_cast(s->opaquePointer())) + { + rvdoc->setVSync(state != 0); + } + } + } - for (size_t i = 0; i < docs.size(); i++) + void RvPreferences::displayOutputChanged(int state) { - Session* s = static_cast(docs[i]); - s->updateGraphInOut(); + const TwkApp::Application::Documents& docs = IPCore::App()->documents(); + + for (size_t i = 0; i < docs.size(); i++) + { + Session* s = static_cast(docs[i]); + if (RvDocument* rvdoc = + reinterpret_cast(s->opaquePointer())) + { + RvDocument::DisplayOutputType t; + + switch (state) + { + default: + case 0: + t = RvDocument::OpenGL8888; + break; + case 1: + t = RvDocument::OpenGL8888; + break; + case 2: + t = RvDocument::OpenGL1010102; + break; + } + + rvdoc->setDisplayOutput(t); + } + } } -} -void -RvPreferences::rthreadFinished() -{ -} + //---------------------------------------------------------------------- + // + // Helper func to find plugin + // -//---------------------------------------------------------------------- -// -// Rendering -// + typedef TwkFB::GenericIO::Plugins FBPlugins; + typedef TwkFB::IOexr IOexr; + typedef TwkFB::IOjpeg IOjpeg; + typedef TwkFB::IOcin IOcin; + typedef TwkFB::IOdpx IOdpx; + typedef TwkFB::IOtarga IOtarga; + typedef TwkFB::IOtiff IOtiff; + using namespace TwkFB; -void -RvPreferences::bitDepthChanged(int index) -{ - switch (index) - { - case 0: // 32 - FormatIPNode::defaultBitDepth = 32; - break; - case 1: // 16 - FormatIPNode::defaultBitDepth = 16; - break; - case 2: // 8 - FormatIPNode::defaultBitDepth = 8; - break; - } -} - -void -RvPreferences::allowFloatChanged(int state) -{ - FormatIPNode::defaultAllowFP = state != 0; -} + static StreamingFrameBufferIO* findPlugin(const string& name) + { + const FBPlugins& plugs = TwkFB::GenericIO::allPlugins(); -void -RvPreferences::newGLSLlutInterpChanged(int state) -{ - LUTIPNode::newGLSLlutInterp = (state != 0); -} + for (FBPlugins::const_iterator i = plugs.begin(); i != plugs.end(); ++i) + { + if (StreamingFrameBufferIO* sio = + dynamic_cast(*i)) + { + if (sio->identifier() == name) + return sio; + } + } -void -RvPreferences::swapScanlinesChanged(int state) -{ - DisplayStereoIPNode::setSwapScanlines((state == Qt::Checked)); -} + return 0; + } -void -RvPreferences::prefetchChanged(int state) -{ - const TwkApp::Application::Documents& docs = IPCore::App()->documents(); + //---------------------------------------------------------------------- + // + // EXR slots + // - for (size_t i = 0; i < docs.size(); i++) + void RvPreferences::exrRGBAChanged(int state) { - Session* s = static_cast(docs[i]); - s->setUsePreEval(state != 0); + if (StreamingFrameBufferIO* exr = findPlugin("IOexr")) + exr->setBoolAttribute("rgbaOnly", state != 0); } -} - -void -RvPreferences::appleClientStorageChanged(int state) -{ - ImageRenderer::setUseAppleClientStorage(state != 0); - const TwkApp::Application::Documents& docs = IPCore::App()->documents(); - for (size_t i = 0; i < docs.size(); i++) + void RvPreferences::exrInheritChanged(int state) { - Session* s = static_cast(docs[i]); - s->clearVideoDeviceCaches(); + if (StreamingFrameBufferIO* exr = findPlugin("IOexr")) + exr->setBoolAttribute("inheritChannels", state != 0); } -} -void -RvPreferences::useThreadedUploadChanged(int state) -{ - const TwkApp::Application::Documents& docs = IPCore::App()->documents(); + void RvPreferences::exrPlanar3ChannelChanged(int state) + { + if (StreamingFrameBufferIO* exr = findPlugin("IOexr")) + exr->setBoolAttribute("planar3Channel", state != 0); + } - for (size_t i = 0; i < docs.size(); i++) + void RvPreferences::exrNoOneChannelChanged(int state) { - Session* s = static_cast(docs[i]); - s->renderer()->setUseThreadedUpload(state != 0); + if (StreamingFrameBufferIO* exr = findPlugin("IOexr")) + exr->setBoolAttribute("noOneChannelPlanes", state != 0); } -} -void -RvPreferences::videoSyncChanged(int state) -{ - const TwkApp::Application::Documents& docs = IPCore::App()->documents(); + void RvPreferences::exrReadWindowIsDisplayWindowChanged(int state) + { + if (StreamingFrameBufferIO* exr = findPlugin("IOexr")) + exr->setBoolAttribute("readWindowIsDisplayWindow", state != 0); + } - for (size_t i = 0; i < docs.size(); i++) + void RvPreferences::exrNumThreadsFinished() { - Session* s = static_cast(docs[i]); - if (RvDocument* rvdoc = reinterpret_cast(s->opaquePointer())) + if (m_ui.exrNumThreadsEdit->text() == "0") + { + Imf::setGlobalThreadCount(TwkUtil::SystemInfo::numCPUs() > 1 + ? (TwkUtil::SystemInfo::numCPUs() - 1) + : 1); + } + else { - rvdoc->setVSync(state != 0); + Imf::setGlobalThreadCount(m_ui.exrNumThreadsEdit->text().toInt()); } } -} -void -RvPreferences::displayOutputChanged(int state) -{ - const TwkApp::Application::Documents& docs = IPCore::App()->documents(); + void RvPreferences::exrAutoThreads(int state) + { + if (state == Qt::Checked) + { + m_ui.exrNumThreadsEdit->setText("0"); + m_ui.exrNumThreadsEdit->setEnabled(false); + m_ui.exrThreadsLabel->setEnabled(false); + Imf::setGlobalThreadCount(TwkUtil::SystemInfo::numCPUs() > 1 + ? (TwkUtil::SystemInfo::numCPUs() - 1) + : 1); + } + else + { + m_ui.exrNumThreadsEdit->setEnabled(true); + m_ui.exrThreadsLabel->setEnabled(true); + QString s; + s.setNum(Imf::globalThreadCount()); + m_ui.exrNumThreadsEdit->setText(s); + } + } - for (size_t i = 0; i < docs.size(); i++) + void RvPreferences::exrThreadNumChanged(const QString& text) { - Session* s = static_cast(docs[i]); - if (RvDocument* rvdoc = reinterpret_cast(s->opaquePointer())) + if (text == "0") { - RvDocument::DisplayOutputType t; + m_ui.exrAutoThreadsToggle->setCheckState(Qt::Checked); + } + else + { + m_ui.exrAutoThreadsToggle->setCheckState(Qt::Unchecked); + } + } - switch (state) - { - default: - case 0: t = RvDocument::OpenGL8888; break; - case 1: t = RvDocument::OpenGL8888; break; - case 2: t = RvDocument::OpenGL1010102; break; - } + void RvPreferences::exrChunkSizeFinished() + { + if (StreamingFrameBufferIO* exr = findPlugin("IOexr")) + exr->setIntAttribute("iosize", + m_ui.exrChunkSizeEdit->text().toInt()); + } - rvdoc->setDisplayOutput(t); - } + void RvPreferences::exrMaxInFlightFinished() + { + if (StreamingFrameBufferIO* exr = findPlugin("IOexr")) + exr->setIntAttribute("iomaxAsync", + m_ui.exrMaxInFlightEdit->text().toInt()); } -} + void RvPreferences::exrIOMethodChanged(int state) + { + if (StreamingFrameBufferIO* exr = findPlugin("IOexr")) + exr->setIntAttribute("iotype", + (TwkFB::StreamingFrameBufferIO::IOType) + m_ui.exrIOMethodCombo->currentIndex()); + } -//---------------------------------------------------------------------- -// -// Helper func to find plugin -// + void RvPreferences::exrReadWindowChanged(int state) + { + if (StreamingFrameBufferIO* exr = findPlugin("IOexr")) + exr->setIntAttribute("readWindow", + (TwkFB::IOexr::ReadWindow) + m_ui.exrReadWindowCombo->currentIndex()); + } -typedef TwkFB::GenericIO::Plugins FBPlugins; -typedef TwkFB::IOexr IOexr; -typedef TwkFB::IOjpeg IOjpeg; -typedef TwkFB::IOcin IOcin; -typedef TwkFB::IOdpx IOdpx; -typedef TwkFB::IOtarga IOtarga; -typedef TwkFB::IOtiff IOtiff; -using namespace TwkFB; - -static -StreamingFrameBufferIO* findPlugin (const string& name) -{ - const FBPlugins& plugs = TwkFB::GenericIO::allPlugins(); + //---------------------------------------------------------------------- + // + // Cineon + // - for (FBPlugins::const_iterator i = plugs.begin(); - i != plugs.end(); - ++i) + void RvPreferences::cinChunkSizeFinished() { - if (StreamingFrameBufferIO* sio = dynamic_cast(*i)) + if (StreamingFrameBufferIO* exr = findPlugin("IOexr")) + exr->setIntAttribute("iosize", + m_ui.exrChunkSizeEdit->text().toInt()); + } + + void RvPreferences::cinMaxInFlightFinished() + { + if (StreamingFrameBufferIO* cin = findPlugin("IOcin")) + cin->setIntAttribute("iomaxAsync", + m_ui.cinMaxInFlightEdit->text().toInt()); + } + + void RvPreferences::cinIOMethodChanged(int state) + { + if (StreamingFrameBufferIO* cin = findPlugin("IOcin")) + cin->setIntAttribute("iotype", + (TwkFB::StreamingFrameBufferIO::IOType) + m_ui.cinIOMethodCombo->currentIndex()); + } + + void RvPreferences::cinChromaChanged(int state) + { + if (StreamingFrameBufferIO* cin = findPlugin("IOcin")) + cin->setBoolAttribute("useChromaticities", state != 0); + } + + void RvPreferences::cinPixelsChanged(int index) + { + if (StreamingFrameBufferIO* cin = findPlugin("IOcin")) { - if (sio->identifier() == name) return sio; + switch (index) + { + case 0: + cin->setIntAttribute("format", IOcin::RGB8); + break; + case 1: + cin->setIntAttribute("format", IOcin::RGBA8); + break; + case 2: + cin->setIntAttribute("format", IOcin::RGB8_PLANAR); + break; + case 3: + cin->setIntAttribute("format", IOcin::RGB10_A2); + break; + case 4: + cin->setIntAttribute("format", IOcin::A2_BGR10); + break; + case 5: + cin->setIntAttribute("format", IOcin::RGB16); + break; + case 6: + cin->setIntAttribute("format", IOcin::RGBA16); + break; + case 7: + cin->setIntAttribute("format", IOcin::RGB16_PLANAR); + break; + } } } - return 0; -} + //---------------------------------------------------------------------- + // + // DPX + // -//---------------------------------------------------------------------- -// -// EXR slots -// + void RvPreferences::dpxChunkSizeFinished() + { + if (StreamingFrameBufferIO* dpx = findPlugin("IOdpx")) + dpx->setIntAttribute("iosize", + m_ui.dpxChunkSizeEdit->text().toInt()); + } + void RvPreferences::dpxMaxInFlightFinished() + { + if (StreamingFrameBufferIO* dpx = findPlugin("IOdpx")) + dpx->setIntAttribute("iomaxAsync", + m_ui.dpxMaxInFlightEdit->text().toInt()); + } -void RvPreferences::exrRGBAChanged(int state) -{ - if (StreamingFrameBufferIO* exr = findPlugin("IOexr")) - exr->setBoolAttribute("rgbaOnly", state != 0); -} + void RvPreferences::dpxIOMethodChanged(int state) + { + if (StreamingFrameBufferIO* dpx = findPlugin("IOdpx")) + dpx->setIntAttribute("iotype", + (TwkFB::StreamingFrameBufferIO::IOType) + m_ui.dpxIOMethodCombo->currentIndex()); + } -void RvPreferences::exrInheritChanged(int state) -{ - if (StreamingFrameBufferIO* exr = findPlugin("IOexr")) - exr->setBoolAttribute("inheritChannels", state != 0); -} + void RvPreferences::dpxChromaChanged(int state) + { + if (StreamingFrameBufferIO* dpx = findPlugin("IOdpx")) + dpx->setBoolAttribute("useChromaticities", state != 0); + } -void RvPreferences::exrPlanar3ChannelChanged(int state) -{ - if (StreamingFrameBufferIO* exr = findPlugin("IOexr")) - exr->setBoolAttribute("planar3Channel", state != 0); -} + void RvPreferences::dpxPixelsChanged(int index) + { + if (StreamingFrameBufferIO* dpx = findPlugin("IOdpx")) + { + switch (index) + { + case 0: + dpx->setIntAttribute("format", IOdpx::RGB8); + break; + case 1: + dpx->setIntAttribute("format", IOdpx::RGBA8); + break; + case 2: + dpx->setIntAttribute("format", IOdpx::RGB8_PLANAR); + break; + case 3: + dpx->setIntAttribute("format", IOdpx::RGB10_A2); + break; + case 4: + dpx->setIntAttribute("format", IOdpx::A2_BGR10); + break; + case 5: + dpx->setIntAttribute("format", IOdpx::RGB16); + break; + case 6: + dpx->setIntAttribute("format", IOdpx::RGBA16); + break; + case 7: + dpx->setIntAttribute("format", IOdpx::RGB16_PLANAR); + break; + } + } + } -void RvPreferences::exrNoOneChannelChanged(int state) -{ - if (StreamingFrameBufferIO* exr = findPlugin("IOexr")) - exr->setBoolAttribute("noOneChannelPlanes", state != 0); -} + //---------------------------------------------------------------------- + // + // TGA + // -void RvPreferences::exrReadWindowIsDisplayWindowChanged(int state) -{ - if (StreamingFrameBufferIO* exr = findPlugin("IOexr")) - exr->setBoolAttribute("readWindowIsDisplayWindow", state != 0); -} + void RvPreferences::tgaChunkSizeFinished() + { + if (StreamingFrameBufferIO* tga = findPlugin("IOtga")) + tga->setIntAttribute("iosize", + m_ui.tgaChunkSizeEdit->text().toInt()); + } -void RvPreferences::exrNumThreadsFinished() -{ - if (m_ui.exrNumThreadsEdit->text() == "0") + void RvPreferences::tgaMaxInFlightFinished() { - Imf::setGlobalThreadCount(TwkUtil::SystemInfo::numCPUs() > 1 - ? (TwkUtil::SystemInfo::numCPUs()-1) - : 1); + if (StreamingFrameBufferIO* tga = findPlugin("IOtga")) + tga->setIntAttribute("iomaxAsync", + m_ui.tgaMaxInFlightEdit->text().toInt()); } - else + + void RvPreferences::tgaIOMethodChanged(int state) { - Imf::setGlobalThreadCount(m_ui.exrNumThreadsEdit->text().toInt()); + if (StreamingFrameBufferIO* tga = findPlugin("IOtga")) + tga->setIntAttribute("iotype", + (TwkFB::StreamingFrameBufferIO::IOType) + m_ui.tgaIOMethodCombo->currentIndex()); } -} -void -RvPreferences::exrAutoThreads(int state) -{ - if (state == Qt::Checked) + //---------------------------------------------------------------------- + // + // TIFF + // + + void RvPreferences::tiffChunkSizeFinished() { - m_ui.exrNumThreadsEdit->setText("0"); - m_ui.exrNumThreadsEdit->setEnabled(false); - m_ui.exrThreadsLabel->setEnabled(false); - Imf::setGlobalThreadCount(TwkUtil::SystemInfo::numCPUs() > 1 - ? (TwkUtil::SystemInfo::numCPUs()-1) - : 1); + if (StreamingFrameBufferIO* tif = findPlugin("IOtif")) + tif->setIntAttribute("iosize", + m_ui.tifChunkSizeEdit->text().toInt()); } - else + + void RvPreferences::tiffMaxInFlightFinished() { - m_ui.exrNumThreadsEdit->setEnabled(true); - m_ui.exrThreadsLabel->setEnabled(true); - QString s; - s.setNum(Imf::globalThreadCount()); - m_ui.exrNumThreadsEdit->setText(s); + if (StreamingFrameBufferIO* tif = findPlugin("IOtif")) + tif->setIntAttribute("iomaxAsync", + m_ui.tifMaxInFlightEdit->text().toInt()); } -} -void -RvPreferences::exrThreadNumChanged(const QString& text) -{ - if (text == "0") + void RvPreferences::tiffIOMethodChanged(int state) { - m_ui.exrAutoThreadsToggle->setCheckState(Qt::Checked); + if (StreamingFrameBufferIO* tif = findPlugin("IOtif")) + tif->setIntAttribute("iotype", + (TwkFB::StreamingFrameBufferIO::IOType) + m_ui.tifIOMethodCombo->currentIndex()); } - else + + //---------------------------------------------------------------------- + // + // JPEG + // + + void RvPreferences::jpegChunkSizeFinished() { - m_ui.exrAutoThreadsToggle->setCheckState(Qt::Unchecked); + if (StreamingFrameBufferIO* jpeg = findPlugin("IOjpeg")) + jpeg->setIntAttribute("iosize", + m_ui.jpegChunkSizeEdit->text().toInt()); } -} + void RvPreferences::jpegMaxInFlightFinished() + { + if (StreamingFrameBufferIO* jpeg = findPlugin("IOjpeg")) + jpeg->setIntAttribute("iomaxAsync", + m_ui.jpegMaxInFlightEdit->text().toInt()); + } -void -RvPreferences::exrChunkSizeFinished() -{ - if (StreamingFrameBufferIO* exr = findPlugin("IOexr")) - exr->setIntAttribute("iosize", m_ui.exrChunkSizeEdit->text().toInt()); -} + void RvPreferences::jpegIOMethodChanged(int state) + { + if (StreamingFrameBufferIO* jpeg = findPlugin("IOjpeg")) + jpeg->setIntAttribute("iotype", + (TwkFB::StreamingFrameBufferIO::IOType) + m_ui.jpegIOMethodCombo->currentIndex()); + } -void -RvPreferences::exrMaxInFlightFinished() -{ - if (StreamingFrameBufferIO* exr = findPlugin("IOexr")) - exr->setIntAttribute("iomaxAsync", m_ui.exrMaxInFlightEdit->text().toInt()); -} + void RvPreferences::jpegRGBAChanged(int state) + { + // if (StreamingFrameBufferIO* jpeg = findPlugin("IOjpeg")) + // if (IOjpeg* jpeg = findPlugin()) + //{ + // jpeg->format(state != 0 ? IOjpeg::RGBA : IOjpeg::YUV); + //} + } -void -RvPreferences::exrIOMethodChanged(int state) -{ - if (StreamingFrameBufferIO* exr = findPlugin("IOexr")) - exr->setIntAttribute("iotype", (TwkFB::StreamingFrameBufferIO::IOType) - m_ui.exrIOMethodCombo->currentIndex()); -} + //---------------------------------------------------------------------- + // + // Display Output + // -void -RvPreferences::exrReadWindowChanged(int state) -{ - if (StreamingFrameBufferIO* exr = findPlugin("IOexr")) - exr->setIntAttribute("readWindow", (TwkFB::IOexr::ReadWindow) - m_ui.exrReadWindowCombo->currentIndex()); -} + //---------------------------------------------------------------------- + // + // Audio slots + // -//---------------------------------------------------------------------- -// -// Cineon -// + bool RvPreferences::initAudioDeviceMenu( + AudioRenderer::RendererParameters& params, + const AudioRenderer::DeviceVector& devices, + const string& currentDeviceName) + { + m_ui.audioDeviceCombo->clear(); -void -RvPreferences::cinChunkSizeFinished() -{ - if (StreamingFrameBufferIO* exr = findPlugin("IOexr")) - exr->setIntAttribute("iosize", m_ui.exrChunkSizeEdit->text().toInt()); -} + if (devices.empty()) + { + m_ui.audioDeviceCombo->addItem("Unavailable"); + m_ui.audioDeviceCombo->setItemIcon( + 0, colorAdjustedIcon(":images/mute_32x32.png")); + m_ui.audioDeviceCombo->setCurrentIndex(0); + m_ui.audioDeviceCombo->setEnabled(false); + return false; + } + else + { + int current = 0; + for (size_t i = 0; i < devices.size(); i++) + { + m_ui.audioDeviceCombo->addItem( + QString::fromUtf8(devices[i].name.c_str())); + if (devices[i].name == currentDeviceName) + current = i; + } -void -RvPreferences::cinMaxInFlightFinished() -{ - if (StreamingFrameBufferIO* cin = findPlugin("IOcin")) - cin->setIntAttribute("iomaxAsync", m_ui.cinMaxInFlightEdit->text().toInt()); -} + m_ui.audioDeviceCombo->setCurrentIndex(current); + m_ui.audioDeviceCombo->setEnabled(true); -void -RvPreferences::cinIOMethodChanged(int state) -{ - if (StreamingFrameBufferIO* cin = findPlugin("IOcin")) - cin->setIntAttribute("iotype", (TwkFB::StreamingFrameBufferIO::IOType) - m_ui.cinIOMethodCombo->currentIndex()); -} + params.device = devices[current].name; + } -void -RvPreferences::cinChromaChanged(int state) -{ - if (StreamingFrameBufferIO* cin = findPlugin("IOcin")) - cin->setBoolAttribute("useChromaticities", state != 0); -} + return true; + } -void -RvPreferences::cinPixelsChanged(int index) -{ - if (StreamingFrameBufferIO* cin = findPlugin("IOcin")) + bool RvPreferences::initAudioLayoutMenu( + AudioRenderer::RendererParameters& params, + const AudioRenderer::LayoutsVector& layouts, + const AudioRenderer::Layout& currentLayout) { - switch (index) + m_ui.audioDeviceLayoutCombo->clear(); + + if (layouts.empty()) { - case 0: cin->setIntAttribute("format", IOcin::RGB8); break; - case 1: cin->setIntAttribute("format", IOcin::RGBA8); break; - case 2: cin->setIntAttribute("format", IOcin::RGB8_PLANAR); break; - case 3: cin->setIntAttribute("format", IOcin::RGB10_A2); break; - case 4: cin->setIntAttribute("format", IOcin::A2_BGR10); break; - case 5: cin->setIntAttribute("format", IOcin::RGB16); break; - case 6: cin->setIntAttribute("format", IOcin::RGBA16); break; - case 7: cin->setIntAttribute("format", IOcin::RGB16_PLANAR); break; + m_ui.audioDeviceLayoutCombo->addItem("Unavailable"); + m_ui.audioDeviceLayoutCombo->setItemIcon( + 0, colorAdjustedIcon(":images/mute_32x32.png")); + m_ui.audioDeviceLayoutCombo->setCurrentIndex(0); + m_ui.audioDeviceLayoutCombo->setEnabled(false); + return false; } - } -} + else + { + int current = 0; + for (size_t i = 0; i < layouts.size(); i++) + { + m_ui.audioDeviceLayoutCombo->addItem( + QString::fromUtf8( + TwkAudio::layoutString(layouts[i]).c_str()), + layouts[i]); + if (layouts[i] == currentLayout) + current = i; + } -//---------------------------------------------------------------------- -// -// DPX -// + m_ui.audioDeviceLayoutCombo->setEnabled(true); + m_ui.audioDeviceLayoutCombo->setCurrentIndex(current); + params.layout = layouts[current]; + } -void -RvPreferences::dpxChunkSizeFinished() -{ - if (StreamingFrameBufferIO* dpx = findPlugin("IOdpx")) - dpx->setIntAttribute("iosize", m_ui.dpxChunkSizeEdit->text().toInt()); -} + return true; + } -void -RvPreferences::dpxMaxInFlightFinished() -{ - if (StreamingFrameBufferIO* dpx = findPlugin("IOdpx")) - dpx->setIntAttribute("iomaxAsync", m_ui.dpxMaxInFlightEdit->text().toInt()); -} + bool RvPreferences::initAudioFormatMenu( + AudioRenderer::RendererParameters& params, + const AudioRenderer::FormatVector& formats, + const AudioRenderer::Format& currentFormat) + { + m_ui.audioDeviceFormatCombo->clear(); -void -RvPreferences::dpxIOMethodChanged(int state) -{ - if (StreamingFrameBufferIO* dpx = findPlugin("IOdpx")) - dpx->setIntAttribute("iotype", (TwkFB::StreamingFrameBufferIO::IOType) - m_ui.dpxIOMethodCombo->currentIndex()); -} + if (formats.empty()) + { + m_ui.audioDeviceFormatCombo->addItem("Unavailable"); + m_ui.audioDeviceFormatCombo->setItemIcon( + 0, colorAdjustedIcon(":images/mute_32x32.png")); + m_ui.audioDeviceFormatCombo->setCurrentIndex(0); + m_ui.audioDeviceFormatCombo->setEnabled(false); + return false; + } + else + { + int current = 0; + for (size_t i = 0; i < formats.size(); i++) + { + m_ui.audioDeviceFormatCombo->addItem( + QString::fromUtf8( + TwkAudio::formatString(formats[i]).c_str()), + formats[i]); + if (formats[i] == currentFormat) + current = i; + } -void -RvPreferences::dpxChromaChanged(int state) -{ - if (StreamingFrameBufferIO* dpx = findPlugin("IOdpx")) - dpx->setBoolAttribute("useChromaticities", state != 0); -} + m_ui.audioDeviceFormatCombo->setEnabled(true); + m_ui.audioDeviceFormatCombo->setCurrentIndex(current); + params.format = formats[current]; + } -void -RvPreferences::dpxPixelsChanged(int index) -{ - if (StreamingFrameBufferIO* dpx = findPlugin("IOdpx")) + return true; + } + + bool + RvPreferences::initAudioRatesMenu(AudioRenderer::RendererParameters& params, + const AudioRenderer::RateVector& rates, + const size_t& currentRate) { - switch (index) + m_ui.audioDeviceRateCombo->clear(); + + if (rates.empty()) { - case 0: dpx->setIntAttribute("format", IOdpx::RGB8); break; - case 1: dpx->setIntAttribute("format", IOdpx::RGBA8); break; - case 2: dpx->setIntAttribute("format", IOdpx::RGB8_PLANAR); break; - case 3: dpx->setIntAttribute("format", IOdpx::RGB10_A2); break; - case 4: dpx->setIntAttribute("format", IOdpx::A2_BGR10); break; - case 5: dpx->setIntAttribute("format", IOdpx::RGB16); break; - case 6: dpx->setIntAttribute("format", IOdpx::RGBA16); break; - case 7: dpx->setIntAttribute("format", IOdpx::RGB16_PLANAR); break; + m_ui.audioDeviceRateCombo->clear(); + m_ui.audioDeviceRateCombo->addItem("Unavailable"); + m_ui.audioDeviceRateCombo->setItemIcon( + 0, colorAdjustedIcon(":images/mute_32x32.png")); + m_ui.audioDeviceRateCombo->setCurrentIndex(0); + m_ui.audioDeviceRateCombo->setEnabled(false); + return false; } + else + { + int current = 0; + for (size_t i = 0; i < rates.size(); i++) + { + QString s = QString("%1").arg((unsigned int)(rates[i])); + m_ui.audioDeviceRateCombo->addItem(s, (unsigned int)rates[i]); + + if (rates[i] == currentRate) + current = i; + } + + m_ui.audioDeviceRateCombo->setEnabled(true); + m_ui.audioDeviceRateCombo->setCurrentIndex(current); + params.rate = rates[current]; + } + + return true; } -} -//---------------------------------------------------------------------- -// -// TGA -// + void RvPreferences::audioModuleChanged(int index) + { + if (AudioRenderer::audioDisabledAlways()) + return; -void -RvPreferences::tgaChunkSizeFinished() -{ - if (StreamingFrameBufferIO* tga = findPlugin("IOtga")) - tga->setIntAttribute("iosize", m_ui.tgaChunkSizeEdit->text().toInt()); -} + if (index != -1) + { + try + { + string moduleChoice = + m_ui.audioModuleCombo->currentText().toUtf8().constData(); + if (moduleChoice != AudioRenderer::currentModule() + || m_ui.audioDeviceCombo->count() == 0) + { + // If we really have switched module then we must + // force the device choice to "Default" since this is + // the only choice that is common across all the audio + // module choices. + AudioRenderer::RendererParameters params = + AudioRenderer::defaultParameters(); + params.device = "Default"; + AudioRenderer::setDefaultParameters(params); + AudioRenderer::setModule(moduleChoice); + AudioRenderer::setDefaultParameters( + params); // Re-set cause the setModule() can change + // params values. when switching modules. + } + } + catch (...) + { + /* + cerr << "got exception from audiorenderer::setModule() " << + m_ui.audioModuleCombo->currentText().toUtf8().constData() + << endl; + */ + } + } -void -RvPreferences::tgaMaxInFlightFinished() -{ - if (StreamingFrameBufferIO* tga = findPlugin("IOtga")) - tga->setIntAttribute("iomaxAsync", m_ui.tgaMaxInFlightEdit->text().toInt()); -} + AudioRenderer* renderer = 0; + try + { + renderer = AudioRenderer::renderer(); + } + catch (...) + { /* cerr << "renderer() threw" << endl; */ + } -void -RvPreferences::tgaIOMethodChanged(int state) -{ - if (StreamingFrameBufferIO* tga = findPlugin("IOtga")) - tga->setIntAttribute("iotype", (TwkFB::StreamingFrameBufferIO::IOType) - m_ui.tgaIOMethodCombo->currentIndex()); -} + if (!renderer) + return; -//---------------------------------------------------------------------- -// -// TIFF -// + AudioRenderer::RendererParameters params = + AudioRenderer::defaultParameters(); -void -RvPreferences::tiffChunkSizeFinished() -{ - if (StreamingFrameBufferIO* tif = findPlugin("IOtif")) - tif->setIntAttribute("iosize", m_ui.tifChunkSizeEdit->text().toInt()); -} + // If we've initialized a device, try to reuse it. + // + string deviceName = params.device; -void -RvPreferences::tiffMaxInFlightFinished() -{ - if (StreamingFrameBufferIO* tif = findPlugin("IOtif")) - tif->setIntAttribute("iomaxAsync", m_ui.tifMaxInFlightEdit->text().toInt()); -} + // + // If we haven't initialized a device, use the one from the + // settings file + // + Options& opts = Options::sharedOptions(); + if ((deviceName == "" || deviceName == "Default") && opts.audioDevice) + deviceName = opts.audioDevice; + int deviceIndex = renderer->findDeviceByName(deviceName); -void -RvPreferences::tiffIOMethodChanged(int state) -{ - if (StreamingFrameBufferIO* tif = findPlugin("IOtif")) - tif->setIntAttribute("iotype", (TwkFB::StreamingFrameBufferIO::IOType) - m_ui.tifIOMethodCombo->currentIndex()); -} + // Audio Device List setup + // + // If we can't find a device by that name, use the default + // device + // + if (deviceIndex == -1) + deviceIndex = renderer->findDefaultDevice(); + AudioRenderer::Device d = renderer->outputDevices()[deviceIndex]; -//---------------------------------------------------------------------- -// -// JPEG -// + // + // Create Device choice List + // + const AudioRenderer::DeviceVector& devices = renderer->outputDevices(); + bool initMenusOK = initAudioDeviceMenu(params, devices, d.name); -void -RvPreferences::jpegChunkSizeFinished() -{ - if (StreamingFrameBufferIO* jpeg = findPlugin("IOjpeg")) - jpeg->setIntAttribute("iosize", m_ui.jpegChunkSizeEdit->text().toInt()); -} + AudioRenderer::Format currentFormat = + AudioRenderer::defaultParameters().format; + AudioRenderer::Layout currentLayout = + AudioRenderer::defaultParameters().layout; + size_t currentRate = size_t(AudioRenderer::defaultParameters().rate); -void -RvPreferences::jpegMaxInFlightFinished() -{ - if (StreamingFrameBufferIO* jpeg = findPlugin("IOjpeg")) - jpeg->setIntAttribute("iomaxAsync", m_ui.jpegMaxInFlightEdit->text().toInt()); -} + AudioRenderer::LayoutsVector layouts; + AudioRenderer::FormatVector formats; + AudioRenderer::RateVector rates; -void -RvPreferences::jpegIOMethodChanged(int state) -{ - if (StreamingFrameBufferIO* jpeg = findPlugin("IOjpeg")) - jpeg->setIntAttribute("iotype", (TwkFB::StreamingFrameBufferIO::IOType) - m_ui.jpegIOMethodCombo->currentIndex()); -} + IPCore::App()->stopAll(); + renderer->shutdown(); + renderer->availableLayouts(d, layouts); + + bool hasStereoLayout = false; + for (int i = 0; i < layouts.size();) + { + if (layouts[i] == currentLayout) + break; + if (layouts[i] == TwkAudio::Stereo_2) + hasStereoLayout = true; + ++i; + if (i == layouts.size()) + { + // Implies currentLayout isnt a valid choice + // for this device so use Stereo_2 if its an option + // otherwise pick the first choice in the list. + currentLayout = + (hasStereoLayout ? TwkAudio::Stereo_2 : layouts.front()); + } + } + d.layout = currentLayout; + + renderer->availableFormats(d, formats); + + if (!formats.empty()) + { + for (int i = 0; i < formats.size();) + { + if (formats[i] == currentFormat) + break; + ++i; + if (i == formats.size()) + { + // Implies currentFormat isnt a valid choice + // for this device. + currentFormat = formats.front(); + } + } + renderer->availableRates(d, currentFormat, rates); + } + IPCore::App()->resumeAll(); + + // Create the channel layout choice list + initMenusOK = + initMenusOK && initAudioLayoutMenu(params, layouts, currentLayout); + + // Create format choice list + initMenusOK = + initMenusOK && initAudioFormatMenu(params, formats, currentFormat); + + // Create rates choice list + initMenusOK = + initMenusOK && initAudioRatesMenu(params, rates, currentRate); + + if (initMenusOK) + { + AudioRenderer::setDefaultParameters(params); + AudioRenderer::reset(); + } + } + + void RvPreferences::audioDeviceChanged(int index) + { + if (AudioRenderer::audioDisabledAlways()) + return; + + bool hasChanged = true; + if (index != -1) + { + AudioRenderer::RendererParameters params = + AudioRenderer::defaultParameters(); + string deviceChoice = + m_ui.audioDeviceCombo->currentText().toUtf8().constData(); + + if (deviceChoice != params.device) + { + params.device = deviceChoice; + AudioRenderer::setDefaultParameters(params); + } + else + { + hasChanged = false; + } + } + + // cerr << "audioDeviceChanged index=" << index << " hasChanged=" << + // (int) hasChanged << endl; + + AudioRenderer* renderer = 0; + try + { + renderer = AudioRenderer::renderer(); + } + catch (...) + { /* cerr << "renderer() threw" << endl; */ + } + + if (!renderer || !hasChanged) + return; + + AudioRenderer::RendererParameters params = + AudioRenderer::defaultParameters(); + + string deviceName = params.device; + int deviceIndex = renderer->findDeviceByName(deviceName); + if (deviceIndex == -1) + { + cerr << "cant find device " << deviceName << endl; + deviceIndex = renderer->findDefaultDevice(); + } + AudioRenderer::Device d = renderer->outputDevices()[deviceIndex]; + AudioRenderer::Format currentFormat = + AudioRenderer::defaultParameters().format; + AudioRenderer::Layout currentLayout = + AudioRenderer::defaultParameters().layout; + size_t currentRate = size_t(AudioRenderer::defaultParameters().rate); + + AudioRenderer::LayoutsVector layouts; + AudioRenderer::FormatVector formats; + AudioRenderer::RateVector rates; + + IPCore::App()->stopAll(); + renderer->shutdown(); + renderer->availableLayouts(d, layouts); + + bool hasStereoLayout = false; + for (int i = 0; i < layouts.size();) + { + if (layouts[i] == currentLayout) + break; + if (layouts[i] == TwkAudio::Stereo_2) + hasStereoLayout = true; + ++i; + if (i == layouts.size()) + { + // Implies currentLayout isnt a valid choice + // for this device so use Stereo_2 if its an option + // otherwise pick the first choice in the list. + currentLayout = + (hasStereoLayout ? TwkAudio::Stereo_2 : layouts.front()); + } + } + d.layout = currentLayout; + + renderer->availableFormats(d, formats); + if (!formats.empty()) + { + for (int i = 0; i < formats.size();) + { + if (formats[i] == currentFormat) + break; + ++i; + if (i == formats.size()) + { + // Implies currentFormat isnt a valid choice + // for this device. + currentFormat = formats.front(); + } + } + renderer->availableRates(d, currentFormat, rates); + } + IPCore::App()->resumeAll(); -void -RvPreferences::jpegRGBAChanged(int state) -{ - //if (StreamingFrameBufferIO* jpeg = findPlugin("IOjpeg")) - //if (IOjpeg* jpeg = findPlugin()) - //{ - //jpeg->format(state != 0 ? IOjpeg::RGBA : IOjpeg::YUV); - //} -} - -//---------------------------------------------------------------------- -// -// Display Output -// + // Create the channel layout choice list + bool initMenusOK = initAudioLayoutMenu(params, layouts, currentLayout); -//---------------------------------------------------------------------- -// -// Audio slots -// + // Create format choice list + initMenusOK = + initMenusOK && initAudioFormatMenu(params, formats, currentFormat); -bool -RvPreferences::initAudioDeviceMenu(AudioRenderer::RendererParameters ¶ms, - const AudioRenderer::DeviceVector &devices, - const string ¤tDeviceName) -{ - m_ui.audioDeviceCombo->clear(); + // Create rates choice list + initMenusOK = + initMenusOK && initAudioRatesMenu(params, rates, currentRate); - if (devices.empty()) - { - m_ui.audioDeviceCombo->addItem("Unavailable"); - m_ui.audioDeviceCombo->setItemIcon(0, colorAdjustedIcon(":images/mute_32x32.png")); - m_ui.audioDeviceCombo->setCurrentIndex(0); - m_ui.audioDeviceCombo->setEnabled(false); - return false; - } - else - { - int current = 0; - for (size_t i = 0; i < devices.size(); i++) + if (initMenusOK) { - m_ui.audioDeviceCombo->addItem(QString::fromUtf8(devices[i].name.c_str())); - if (devices[i].name == currentDeviceName) current = i; + AudioRenderer::setDefaultParameters(params); + AudioRenderer::reset(); } + } - m_ui.audioDeviceCombo->setCurrentIndex(current); - m_ui.audioDeviceCombo->setEnabled(true); + void RvPreferences::audioChannelsChanged(int index) + { + if (AudioRenderer::audioDisabledAlways()) + return; - params.device = devices[current].name; - } + bool hasChanged = true; - return true; -} + if ((index != -1) && (index < m_ui.audioDeviceLayoutCombo->count())) + { + AudioRenderer::RendererParameters params = + AudioRenderer::defaultParameters(); + TwkAudio::Layout layoutChoice = + (TwkAudio::Layout)m_ui.audioDeviceLayoutCombo->itemData(index) + .toInt(); -bool -RvPreferences::initAudioLayoutMenu(AudioRenderer::RendererParameters ¶ms, - const AudioRenderer::LayoutsVector &layouts, - const AudioRenderer::Layout ¤tLayout) -{ - m_ui.audioDeviceLayoutCombo->clear(); + if (layoutChoice != params.layout) + { + params.layout = layoutChoice; + AudioRenderer::setDefaultParameters(params); + } + else + { + hasChanged = false; + } + } - if (layouts.empty()) - { - m_ui.audioDeviceLayoutCombo->addItem("Unavailable"); - m_ui.audioDeviceLayoutCombo->setItemIcon(0, colorAdjustedIcon(":images/mute_32x32.png")); - m_ui.audioDeviceLayoutCombo->setCurrentIndex(0); - m_ui.audioDeviceLayoutCombo->setEnabled(false); - return false; - } - else - { - int current = 0; - for (size_t i = 0; i < layouts.size(); i++) + AudioRenderer* renderer = 0; + try { - m_ui.audioDeviceLayoutCombo->addItem(QString::fromUtf8(TwkAudio::layoutString(layouts[i]).c_str()), - layouts[i]); - if (layouts[i] == currentLayout) current = i; + renderer = AudioRenderer::renderer(); + } + catch (...) + { /* cerr << "renderer() threw" << endl; */ } - m_ui.audioDeviceLayoutCombo->setEnabled(true); - m_ui.audioDeviceLayoutCombo->setCurrentIndex(current); - params.layout = layouts[current]; - } + if (!renderer || !hasChanged) + return; - return true; -} + AudioRenderer::RendererParameters params = + AudioRenderer::defaultParameters(); + string deviceName = params.device; + int deviceIndex = renderer->findDeviceByName(deviceName); + if (deviceIndex == -1) + deviceIndex = renderer->findDefaultDevice(); + const AudioRenderer::Device& d = renderer->outputDevices()[deviceIndex]; -bool -RvPreferences::initAudioFormatMenu(AudioRenderer::RendererParameters ¶ms, - const AudioRenderer::FormatVector &formats, - const AudioRenderer::Format ¤tFormat) -{ - m_ui.audioDeviceFormatCombo->clear(); + AudioRenderer::Format currentFormat = + AudioRenderer::defaultParameters().format; + size_t currentRate = size_t(AudioRenderer::defaultParameters().rate); - if (formats.empty()) - { - m_ui.audioDeviceFormatCombo->addItem("Unavailable"); - m_ui.audioDeviceFormatCombo->setItemIcon(0, colorAdjustedIcon(":images/mute_32x32.png")); - m_ui.audioDeviceFormatCombo->setCurrentIndex(0); - m_ui.audioDeviceFormatCombo->setEnabled(false); - return false; - } - else - { - int current = 0; - for (size_t i = 0; i < formats.size(); i++) + AudioRenderer::FormatVector formats; + AudioRenderer::RateVector rates; + + IPCore::App()->stopAll(); + renderer->shutdown(); + renderer->availableFormats(d, formats); + if (!formats.empty()) { - m_ui.audioDeviceFormatCombo->addItem(QString::fromUtf8(TwkAudio::formatString(formats[i]).c_str()), - formats[i]); - if (formats[i] == currentFormat) current = i; + for (int i = 0; i < formats.size();) + { + if (formats[i] == currentFormat) + break; + ++i; + if (i == formats.size()) + { + // Implies currentFormat isnt a valid choice + // for this device. + currentFormat = formats.front(); + } + } + renderer->availableRates(d, currentFormat, rates); } + IPCore::App()->resumeAll(); - m_ui.audioDeviceFormatCombo->setEnabled(true); - m_ui.audioDeviceFormatCombo->setCurrentIndex(current); - params.format = formats[current]; - } - - return true; -} + // Create format choice list + bool initMenusOK = initAudioFormatMenu(params, formats, currentFormat); -bool -RvPreferences::initAudioRatesMenu(AudioRenderer::RendererParameters ¶ms, - const AudioRenderer::RateVector &rates, - const size_t ¤tRate) -{ - m_ui.audioDeviceRateCombo->clear(); + // Create rates choice list + initMenusOK = + initMenusOK && initAudioRatesMenu(params, rates, currentRate); - if (rates.empty()) - { - m_ui.audioDeviceRateCombo->clear(); - m_ui.audioDeviceRateCombo->addItem("Unavailable"); - m_ui.audioDeviceRateCombo->setItemIcon(0, colorAdjustedIcon(":images/mute_32x32.png")); - m_ui.audioDeviceRateCombo->setCurrentIndex(0); - m_ui.audioDeviceRateCombo->setEnabled(false); - return false; - } - else - { - int current = 0; - for (size_t i = 0; i < rates.size(); i++) + if (initMenusOK) { - QString s = QString("%1").arg((unsigned int)(rates[i])); - m_ui.audioDeviceRateCombo->addItem(s, (unsigned int)rates[i]); - - if (rates[i] == currentRate) current = i; + AudioRenderer::setDefaultParameters(params); + AudioRenderer::reset(); } - - m_ui.audioDeviceRateCombo->setEnabled(true); - m_ui.audioDeviceRateCombo->setCurrentIndex(current); - params.rate = rates[current]; } - return true; -} - + void RvPreferences::audioFormatChanged(int index) + { + if (AudioRenderer::audioDisabledAlways()) + return; -void -RvPreferences::audioModuleChanged(int index) -{ - if (AudioRenderer::audioDisabledAlways()) return; + bool hasChanged = true; - if (index != -1) - { - try + if ((index != -1) && (index < m_ui.audioDeviceFormatCombo->count())) { - string moduleChoice = m_ui.audioModuleCombo->currentText().toUtf8().constData(); - if (moduleChoice != AudioRenderer::currentModule() || m_ui.audioDeviceCombo->count() == 0) + AudioRenderer::RendererParameters params = + AudioRenderer::defaultParameters(); + + TwkAudio::Format formatChoice = + (TwkAudio::Format)m_ui.audioDeviceFormatCombo->itemData(index) + .toInt(); + + if (formatChoice != params.format) { - // If we really have switched module then we must - // force the device choice to "Default" since this is - // the only choice that is common across all the audio module - // choices. - AudioRenderer::RendererParameters params = AudioRenderer::defaultParameters(); - params.device = "Default"; + params.format = formatChoice; AudioRenderer::setDefaultParameters(params); - AudioRenderer::setModule(moduleChoice); - AudioRenderer::setDefaultParameters(params); // Re-set cause the setModule() can change params values. - // when switching modules. + } + else + { + hasChanged = false; } } - catch (...) + + AudioRenderer* renderer = 0; + try { - /* - cerr << "got exception from audiorenderer::setModule() " << - m_ui.audioModuleCombo->currentText().toUtf8().constData() << endl; - */ + renderer = AudioRenderer::renderer(); + } + catch (...) + { /* cerr << "renderer() threw" << endl; */ } - } - - AudioRenderer* renderer = 0; - try { renderer = AudioRenderer::renderer(); } - catch(...) { /* cerr << "renderer() threw" << endl; */ } - - if (!renderer) return; - - AudioRenderer::RendererParameters params = AudioRenderer::defaultParameters(); - - // If we've initialized a device, try to reuse it. - // - string deviceName = params.device; - // - // If we haven't initialized a device, use the one from the - // settings file - // - Options& opts = Options::sharedOptions(); - if ((deviceName == "" || deviceName == "Default") && opts.audioDevice) deviceName = opts.audioDevice; - int deviceIndex = renderer->findDeviceByName(deviceName); + if (!renderer || !hasChanged) + return; + AudioRenderer::RendererParameters params = + AudioRenderer::defaultParameters(); - // Audio Device List setup - // - // If we can't find a device by that name, use the default - // device - // - if (deviceIndex == -1) deviceIndex = renderer->findDefaultDevice(); - AudioRenderer::Device d = renderer->outputDevices()[deviceIndex]; + string deviceName = params.device; + int deviceIndex = renderer->findDeviceByName(deviceName); + if (deviceIndex == -1) + deviceIndex = renderer->findDefaultDevice(); + const AudioRenderer::Device& d = renderer->outputDevices()[deviceIndex]; - // - // Create Device choice List - // - const AudioRenderer::DeviceVector& devices = renderer->outputDevices(); - bool initMenusOK = initAudioDeviceMenu(params, devices, d.name); + AudioRenderer::Format currentFormat = + AudioRenderer::defaultParameters().format; + size_t currentRate = size_t(AudioRenderer::defaultParameters().rate); - AudioRenderer::Format currentFormat = AudioRenderer::defaultParameters().format; - AudioRenderer::Layout currentLayout = AudioRenderer::defaultParameters().layout; - size_t currentRate = size_t(AudioRenderer::defaultParameters().rate); + AudioRenderer::RateVector rates; - AudioRenderer::LayoutsVector layouts; - AudioRenderer::FormatVector formats; - AudioRenderer::RateVector rates; + IPCore::App()->stopAll(); + renderer->shutdown(); + renderer->availableRates(d, currentFormat, rates); + IPCore::App()->resumeAll(); - IPCore::App()->stopAll(); - renderer->shutdown(); - renderer->availableLayouts(d, layouts); + // Create rates choice list + bool initMenusOK = initAudioRatesMenu(params, rates, currentRate); - bool hasStereoLayout = false; - for (int i=0; i < layouts.size(); ) - { - if (layouts[i] == currentLayout) break; - if (layouts[i] == TwkAudio::Stereo_2) hasStereoLayout = true; - ++i; - if (i == layouts.size()) + if (initMenusOK) { - // Implies currentLayout isnt a valid choice - // for this device so use Stereo_2 if its an option - // otherwise pick the first choice in the list. - currentLayout = (hasStereoLayout?TwkAudio::Stereo_2:layouts.front()); + AudioRenderer::setDefaultParameters(params); + AudioRenderer::reset(); } } - d.layout = currentLayout; - renderer->availableFormats(d, formats); - - if (!formats.empty()) + void RvPreferences::audioRateChanged(int index) { - for (int i=0; i < formats.size(); ) - { - if (formats[i] == currentFormat) break; - ++i; - if (i == formats.size()) - { - // Implies currentFormat isnt a valid choice - // for this device. - currentFormat = formats.front(); - } - } - renderer->availableRates(d, currentFormat, rates); + if (AudioRenderer::audioDisabledAlways()) + return; + size_t rate = m_ui.audioDeviceRateCombo->currentText().toInt(); + + AudioRenderer::RendererParameters params = + AudioRenderer::defaultParameters(); + params.rate = rate; + AudioRenderer::setDefaultParameters(params); + AudioRenderer::reset(); } - IPCore::App()->resumeAll(); - // Create the channel layout choice list - initMenusOK = initMenusOK && initAudioLayoutMenu(params, layouts, currentLayout); + void RvPreferences::audioHoldOpenChanged(int state) + { + AudioRenderer::RendererParameters params = + AudioRenderer::defaultParameters(); + params.holdOpen = state == Qt::Checked; + AudioRenderer::setDefaultParameters(params); + AudioRenderer::reset(); + } - // Create format choice list - initMenusOK = initMenusOK && initAudioFormatMenu(params, formats, currentFormat); + void RvPreferences::audioVideoSyncChanged(int state) + { + AudioRenderer::RendererParameters params = + AudioRenderer::defaultParameters(); + params.hardwareLock = state == Qt::Checked; + AudioRenderer::setDefaultParameters(params); + AudioRenderer::reset(); + } - // Create rates choice list - initMenusOK = initMenusOK && initAudioRatesMenu(params, rates, currentRate); + void RvPreferences::audioPreRollChanged(int state) + { + AudioRenderer::RendererParameters params = + AudioRenderer::defaultParameters(); + params.preRoll = state == Qt::Checked; + AudioRenderer::setDefaultParameters(params); + AudioRenderer::reset(); + } - if (initMenusOK) + void RvPreferences::audioDevicePacketChanged() { + AudioRenderer::RendererParameters params = + AudioRenderer::defaultParameters(); + params.framesPerBuffer = m_ui.audioDevicePacketEdit->text().toInt(); AudioRenderer::setDefaultParameters(params); AudioRenderer::reset(); } -} -void -RvPreferences::audioDeviceChanged(int index) -{ - if (AudioRenderer::audioDisabledAlways()) return; + void RvPreferences::audioCachePacketChanged() {} - bool hasChanged = true; + //---------------------------------------------------------------------- + // + // PACKAGE management + // - if (index != -1) + void RvPreferences::clickedPackage(QModelIndex index) { - AudioRenderer::RendererParameters params = AudioRenderer::defaultParameters(); - string deviceChoice = m_ui.audioDeviceCombo->currentText().toUtf8().constData(); - - if (deviceChoice != params.device) - { - params.device = deviceChoice; - AudioRenderer::setDefaultParameters(params); - } - else + if (index.column() == 0) { - hasChanged = false; - } - } + QStandardItem* pitem = m_packageModel->itemFromIndex(index); + Package& package = m_packages[pitem->data().toInt()]; - // cerr << "audioDeviceChanged index=" << index << " hasChanged=" << (int) hasChanged << endl; + if (!pitem->isEnabled()) + return; - AudioRenderer* renderer = 0; - try { renderer = AudioRenderer::renderer(); } - catch(...) { /* cerr << "renderer() threw" << endl; */ } + if (package.compatible) + { + if (package.installed) + { + uninstallPackage(package); + } + else + { + installPackage(package); + } - if (!renderer || !hasChanged) return; + for (int i = 0; i < m_packages.size(); i++) + { + const Package& p = m_packages[i]; + if (p.row >= 0) + { + QStandardItem* iitem = m_packageModel->item(p.row, 0); + QStandardItem* litem = m_packageModel->item(p.row, 1); + + if (p.compatible) + { + iitem->setCheckState(p.installed ? Qt::Checked + : Qt::Unchecked); + litem->setCheckState(p.installed && p.loadable + ? Qt::Checked + : Qt::Unchecked); + } + } + } - AudioRenderer::RendererParameters params = AudioRenderer::defaultParameters(); + m_ui.extRemoveButton->setEnabled( + !package.installed + && (package.fileWritable && package.dirWritable)); + } + } + else if (index.column() == 1) + { + QStandardItem* pitem = m_packageModel->itemFromIndex(index); + Package& package = m_packages[pitem->data().toInt()]; - string deviceName = params.device; - int deviceIndex = renderer->findDeviceByName(deviceName); - if (deviceIndex == -1) - { - cerr << "cant find device " << deviceName << endl; - deviceIndex = renderer->findDefaultDevice(); - } - AudioRenderer::Device d = renderer->outputDevices()[deviceIndex]; - AudioRenderer::Format currentFormat = AudioRenderer::defaultParameters().format; - AudioRenderer::Layout currentLayout = AudioRenderer::defaultParameters().layout; - size_t currentRate = size_t(AudioRenderer::defaultParameters().rate); + if (package.installed) + { + allowLoading(package, pitem->checkState() != Qt::Checked, 0); - AudioRenderer::LayoutsVector layouts; - AudioRenderer::FormatVector formats; - AudioRenderer::RateVector rates; + size_t n = m_packageModel->rowCount(); - IPCore::App()->stopAll(); - renderer->shutdown(); - renderer->availableLayouts(d, layouts); + for (size_t q = 0; q < n; q++) + { + QStandardItem* item = m_packageModel->item(q, 1); + Package& package = m_packages[item->data().toInt()]; - bool hasStereoLayout = false; - for (int i=0; i < layouts.size(); ) - { - if (layouts[i] == currentLayout) break; - if (layouts[i] == TwkAudio::Stereo_2) hasStereoLayout = true; - ++i; - if (i == layouts.size()) - { - // Implies currentLayout isnt a valid choice - // for this device so use Stereo_2 if its an option - // otherwise pick the first choice in the list. - currentLayout = (hasStereoLayout?TwkAudio::Stereo_2:layouts.front()); + if (package.installed && package.compatible) + { + item->setCheckState(package.loadable ? Qt::Checked + : Qt::Unchecked); + } + } + } } } - d.layout = currentLayout; - renderer->availableFormats(d, formats); - if (!formats.empty()) + void RvPreferences::addPackageItem(const Package& p, size_t index) { - for (int i=0; i < formats.size(); ) + QFileInfo finfo(p.file); + + QStandardItem* installed = new QStandardItem(); + QStandardItem* loaded = new QStandardItem(); + QStandardItem* name = new QStandardItem(p.name); + QStandardItem* file = new QStandardItem(finfo.fileName()); + QStandardItem* version = new QStandardItem(p.version); + QStandardItem* author = new QStandardItem(p.author); + QStandardItem* organization = new QStandardItem(p.organization); + + if (p.compatible) { - if (formats[i] == currentFormat) break; - ++i; - if (i == formats.size()) - { - // Implies currentFormat isnt a valid choice - // for this device. - currentFormat = formats.front(); - } + loaded->setCheckState(p.loadable && p.installed ? Qt::Checked + : Qt::Unchecked); + installed->setCheckState(p.installed ? Qt::Checked : Qt::Unchecked); + } + else + { + QBrush b = name->foreground(); + QColor c = b.color(); + c.setAlpha(128); + QBrush f = QBrush(c); + + name->setForeground(f); + file->setForeground(f); + version->setForeground(f); + author->setForeground(f); + organization->setForeground(f); } - renderer->availableRates(d, currentFormat, rates); - } - IPCore::App()->resumeAll(); - - // Create the channel layout choice list - bool initMenusOK = initAudioLayoutMenu(params, layouts, currentLayout); - // Create format choice list - initMenusOK = initMenusOK && initAudioFormatMenu(params, formats, currentFormat); + installed->setData(QVariant(int(index))); + loaded->setData(QVariant(int(index))); - // Create rates choice list - initMenusOK = initMenusOK && initAudioRatesMenu(params, rates, currentRate); + installed->setEditable(false); + loaded->setEditable(false); + name->setEditable(false); + file->setEditable(false); + version->setEditable(false); + author->setEditable(false); + organization->setEditable(false); - if (initMenusOK) - { - AudioRenderer::setDefaultParameters(params); - AudioRenderer::reset(); - } -} + if (!p.dirWritable /*|| p.system*/) + installed->setEnabled(false); + // if (p.system) loaded->setEnabled(false); -void -RvPreferences::audioChannelsChanged(int index) -{ - if (AudioRenderer::audioDisabledAlways()) return; + QList row; + row << installed << loaded << name << file << version << author + << organization; - bool hasChanged = true; + m_packageModel->appendRow(row); + } - if ( (index != -1) && (index < m_ui.audioDeviceLayoutCombo->count()) ) + void RvPreferences::loadPackages() { - AudioRenderer::RendererParameters params = AudioRenderer::defaultParameters(); + m_packageModel->clear(); + QStringList headers; + headers << "Installed" << "Load" << "Name" << "File" << "Version" + << "Author" << "Organization"; + m_packageModel->setHorizontalHeaderLabels(headers); - TwkAudio::Layout layoutChoice = (TwkAudio::Layout) m_ui.audioDeviceLayoutCombo->itemData(index).toInt(); + PackageManager::loadPackages(); - if (layoutChoice != params.layout) + for (int i = 0; i < headers.size(); i++) + m_ui.extTreeView->resizeColumnToContents(i); + } + + void RvPreferences::declarePackage(Package& p, size_t i) + { + if (!p.hidden || m_showHiddenPackages) { - params.layout = layoutChoice; - AudioRenderer::setDefaultParameters(params); + p.row = m_packageModel->rowCount(); + addPackageItem(p, i); } else { - hasChanged = false; + p.row = -1; } } - AudioRenderer* renderer = 0; - try { renderer = AudioRenderer::renderer(); } - catch(...) { /* cerr << "renderer() threw" << endl; */ } + void RvPreferences::packageSelection(const QItemSelection& selected, + const QItemSelection& deselected) + { + QItemSelectionModel* s = m_ui.extTreeView->selectionModel(); + QModelIndexList indices = s->selection().indexes(); + QTextBrowser* b = m_ui.extTextBrowser; - if (!renderer || !hasChanged) return; + b->clear(); - AudioRenderer::RendererParameters params = AudioRenderer::defaultParameters(); + if (indices.empty()) + return; - string deviceName = params.device; - int deviceIndex = renderer->findDeviceByName(deviceName); - if (deviceIndex == -1) deviceIndex = renderer->findDefaultDevice(); - const AudioRenderer::Device& d = renderer->outputDevices()[deviceIndex]; + ostringstream str; - AudioRenderer::Format currentFormat = AudioRenderer::defaultParameters().format; - size_t currentRate = size_t(AudioRenderer::defaultParameters().rate); + QStandardItem* pitem = m_packageModel->itemFromIndex(indices[0]); + int row = pitem->data().toInt(); + const Package& p = m_packages[row]; - AudioRenderer::FormatVector formats; - AudioRenderer::RateVector rates; + str << ""; - IPCore::App()->stopAll(); - renderer->shutdown(); - renderer->availableFormats(d, formats); - if (!formats.empty()) - { - for (int i=0; i < formats.size(); ) + if (getenv("RV_DARK") && *getenv("RV_DARK") == '1') { - if (formats[i] == currentFormat) break; - ++i; - if (i == formats.size()) - { - // Implies currentFormat isnt a valid choice - // for this device. - currentFormat = formats.front(); - } + str << ""; } - renderer->availableRates(d, currentFormat, rates); - } - IPCore::App()->resumeAll(); - // Create format choice list - bool initMenusOK = initAudioFormatMenu(params, formats, currentFormat); + str << "

" << p.name.toUtf8().data() << "

"; - // Create rates choice list - initMenusOK = initMenusOK && initAudioRatesMenu(params, rates, currentRate); + if (!p.compatible) + { + str << "

" << "-- NOT COMPATIBLE WITH THIS VERSION OF RV --" + << "

"; + } - if (initMenusOK) - { - AudioRenderer::setDefaultParameters(params); - AudioRenderer::reset(); - } -} + if (p.system) + { + str << "

-- THIS IS A BASE SYSTEM PACKAGE REQUIRED BY RV " + "--

"; + } + str << "
" + << ""; -void -RvPreferences::audioFormatChanged(int index) -{ - if (AudioRenderer::audioDisabledAlways()) return; + if (p.author != "") + str << ""; - bool hasChanged = true; + if (p.organization != "") + str << ""; - if ( (index != -1) && (index < m_ui.audioDeviceFormatCombo->count()) ) - { - AudioRenderer::RendererParameters params = AudioRenderer::defaultParameters(); + if (p.contact != "") + str << ""; - TwkAudio::Format formatChoice = (TwkAudio::Format) m_ui.audioDeviceFormatCombo->itemData(index).toInt(); + if (p.url != "") + str << ""; - if (formatChoice != params.format) - { - params.format = formatChoice; - AudioRenderer::setDefaultParameters(params); + if (p.version != "") + str << ""; - } - else - { - hasChanged = false; - } - } + if (p.requires != "") + str << ""; + + if (p.rvversion != "") + str << ""; - AudioRenderer* renderer = 0; - try { renderer = AudioRenderer::renderer(); } - catch(...) { /* cerr << "renderer() threw" << endl; */ } + if (p.openrvversion != "") + str << ""; - if (!renderer || !hasChanged) return; + str << ""; - AudioRenderer::RendererParameters params = AudioRenderer::defaultParameters(); + if (p.optional) + str << ""; - string deviceName = params.device; - int deviceIndex = renderer->findDeviceByName(deviceName); - if (deviceIndex == -1) deviceIndex = renderer->findDefaultDevice(); - const AudioRenderer::Device& d = renderer->outputDevices()[deviceIndex]; + str << "
Author " + << p.author.toUtf8().data() << "
Organization " + << p.organization.toUtf8().data() << "
Contact " + << p.contact.toUtf8().constData() << "
URL " + << p.url.toUtf8().constData() << "
Version " + << p.version.toUtf8().data() << "
Requires " + << p. + requires + .toUtf8() + .data() + << "
RV Version " + << p.rvversion.toUtf8().data() << "
OpenRV Version " + << p.openrvversion.toUtf8().data() << "
File " + << p.file.toUtf8().data() << "
Optional Package " + << "This package is not loaded by default
" + << "
" + << "

Description

" << p.description.toUtf8().data(); - AudioRenderer::Format currentFormat = AudioRenderer::defaultParameters().format; - size_t currentRate = size_t(AudioRenderer::defaultParameters().rate); + str << "

Modes in Package

\n
    \n"; - AudioRenderer::RateVector rates; + for (size_t q = 0; q < p.modes.size(); q++) + { + str << "
  • " << p.modes[q].file.toUtf8().data() << "
  • \n"; - IPCore::App()->stopAll(); - renderer->shutdown(); - renderer->availableRates(d, currentFormat, rates); - IPCore::App()->resumeAll(); + if (p.modes[q].requires.size()) + { + str << "\nRequires
      "; - // Create rates choice list - bool initMenusOK = initAudioRatesMenu(params, rates, currentRate); + for (int i = 0; i < p.modes[q].requires.size(); i++) + { + str << "
    • " + << p.modes[q] + . + requires[ + i] + .toUtf8() + .data() + << "
    • \n"; + } - if (initMenusOK) - { - AudioRenderer::setDefaultParameters(params); - AudioRenderer::reset(); - } -} + str << "
    \n"; + } + } + str << "
\n"; -void -RvPreferences::audioRateChanged(int index) -{ - if (AudioRenderer::audioDisabledAlways()) return; - size_t rate = m_ui.audioDeviceRateCombo->currentText().toInt(); + str << "

Files in Package

\n
    \n"; - AudioRenderer::RendererParameters params = AudioRenderer::defaultParameters(); - params.rate = rate; - AudioRenderer::setDefaultParameters(params); - AudioRenderer::reset(); -} + for (size_t q = 0; q < p.files.size(); q++) + { + str << "
  • " << p.files[q].toUtf8().data() << "
  • \n"; + } -void -RvPreferences::audioHoldOpenChanged(int state) -{ - AudioRenderer::RendererParameters params = AudioRenderer::defaultParameters(); - params.holdOpen = state == Qt::Checked; - AudioRenderer::setDefaultParameters(params); - AudioRenderer::reset(); -} - -void -RvPreferences::audioVideoSyncChanged(int state) -{ - AudioRenderer::RendererParameters params = AudioRenderer::defaultParameters(); - params.hardwareLock = state == Qt::Checked; - AudioRenderer::setDefaultParameters(params); - AudioRenderer::reset(); -} - -void -RvPreferences::audioPreRollChanged(int state) -{ - AudioRenderer::RendererParameters params = AudioRenderer::defaultParameters(); - params.preRoll = state == Qt::Checked; - AudioRenderer::setDefaultParameters(params); - AudioRenderer::reset(); -} + str << "
\n"; + str << ""; + b->insertHtml(QString::fromUtf8(str.str().c_str())); -void -RvPreferences::audioDevicePacketChanged() -{ - AudioRenderer::RendererParameters params = AudioRenderer::defaultParameters(); - params.framesPerBuffer = m_ui.audioDevicePacketEdit->text().toInt(); - AudioRenderer::setDefaultParameters(params); - AudioRenderer::reset(); -} - -void -RvPreferences::audioCachePacketChanged() -{ -} + m_ui.extRemoveButton->setEnabled(!p.installed + && (p.fileWritable && p.dirWritable)); + } -//---------------------------------------------------------------------- -// -// PACKAGE management -// + void RvPreferences::showHiddenPackages(bool b) + { + m_showHiddenPackages = b; + loadPackages(); + } -void -RvPreferences::clickedPackage(QModelIndex index) -{ - if (index.column() == 0) + void RvPreferences::addPackage(bool) { - QStandardItem* pitem = m_packageModel->itemFromIndex(index); - Package& package = m_packages[pitem->data().toInt()]; + // + // Figure out what dir to copy them to + // - if (!pitem->isEnabled()) return; + TwkApp::Bundle::PathVector supportDirs = + TwkApp::Bundle::mainBundle()->supportPath(); - if (package.compatible) + QStringList possiblePlaces; + + for (size_t i = 0; i < supportDirs.size(); i++) { - if (package.installed) - { - uninstallPackage(package); - } - else - { - installPackage(package); - } + QString pdirname = QString::fromUtf8(supportDirs[i].c_str()); + QDir pdir(pdirname); - for (int i = 0; i < m_packages.size(); i++) + if (pdir.exists()) { - const Package& p = m_packages[i]; - if (p.row >= 0) + if (!pdir.exists("Packages")) { - QStandardItem* iitem = m_packageModel->item(p.row, 0); - QStandardItem* litem = m_packageModel->item(p.row, 1); + if (!makeSupportDirTree(pdir)) + continue; + } - if (p.compatible) - { - iitem->setCheckState(p.installed ? Qt::Checked : Qt::Unchecked); - litem->setCheckState(p.installed && p.loadable ? Qt::Checked : Qt::Unchecked); - } + pdir.cd("Packages"); + + if (TwkUtil::isWritable( + UTF8::qconvert(pdir.absolutePath()).c_str())) + { + possiblePlaces.push_back(pdir.absolutePath()); } } - - m_ui.extRemoveButton->setEnabled(!package.installed && - (package.fileWritable && - package.dirWritable)); } - } - else if (index.column() == 1) - { - QStandardItem* pitem = m_packageModel->itemFromIndex(index); - Package& package = m_packages[pitem->data().toInt()]; - if (package.installed) + if (possiblePlaces.empty()) { - allowLoading(package, - pitem->checkState() != Qt::Checked, - 0); + QMessageBox box(this); + box.setWindowTitle(tr("Unable to Add Packages")); + box.setText(tr("No package installation locations were found.")); + box.setWindowModality(Qt::WindowModal); + QPushButton* b2 = box.addButton(tr("Ok"), QMessageBox::AcceptRole); + box.setIcon(QMessageBox::Critical); + box.exec(); + return; + } - size_t n = m_packageModel->rowCount(); + // + // + // - for (size_t q = 0; q < n; q++) - { - QStandardItem* item = m_packageModel->item(q, 1); - Package& package = m_packages[item->data().toInt()]; + RV_QSETTINGS; - if (package.installed && package.compatible) - { - item->setCheckState(package.loadable ? Qt::Checked : Qt::Unchecked); - } - } - } - } -} + settings.beginGroup("Packages"); + QString dirname = settings.value("lastPackageDir").toString(); -void -RvPreferences::addPackageItem(const Package& p, size_t index) -{ - QFileInfo finfo(p.file); +#if defined(PLATFORM_WINDOWS) + QFileDialog* fileDialog = + new QFileDialog(this, "Select rvpkg RV package files", dirname, + "rvpkg Package Files (*.zip *.rvpkg *.rvpkgs)"); - QStandardItem* installed = new QStandardItem(); - QStandardItem* loaded = new QStandardItem(); - QStandardItem* name = new QStandardItem(p.name); - QStandardItem* file = new QStandardItem(finfo.fileName()); - QStandardItem* version = new QStandardItem(p.version); - QStandardItem* author = new QStandardItem(p.author); - QStandardItem* organization = new QStandardItem(p.organization); + QStringList files; + if (fileDialog->exec()) + files = fileDialog->selectedFiles(); + delete fileDialog; - if (p.compatible) - { - loaded->setCheckState(p.loadable && p.installed ? Qt::Checked : Qt::Unchecked); - installed->setCheckState(p.installed ? Qt::Checked : Qt::Unchecked); - } - else - { - QBrush b = name->foreground(); - QColor c = b.color(); - c.setAlpha(128); - QBrush f = QBrush(c); +#else + QString selectedFilter; + QFileDialog::Options options; + // Using non native dialog on linux. + // Rationale: + // When using native QFileDialog (default) on linux, the following + // warning appears in the console: + // <> + // The warning does not appear when using non native dialog. + // Moreover, some users have reported that the dialog fails to show + // since RV was updated to Qt 5.15.3. +#if defined(PLATFORM_LINUX) + options |= QFileDialog::DontUseNativeDialog; +#endif + QStringList files = QFileDialog::getOpenFileNames( + this, "Select rvpkg RV package files", dirname, + "rvpkg Package Files (*.zip *.rvpkg *.rvpkgs, *.rvpkgs)", + &selectedFilter, options); +#endif - name->setForeground(f); - file->setForeground(f); - version->setForeground(f); - author->setForeground(f); - organization->setForeground(f); - } + if (files.size()) + { + QFileInfo info(files[0]); + settings.setValue("lastPackageDir", info.absolutePath()); + settings.endGroup(); + } + else + { + settings.endGroup(); + return; + } - installed->setData(QVariant(int(index))); - loaded->setData(QVariant(int(index))); + // if (possiblePlaces.size() > 1) + { + // + // Ask user where to put it + // - installed->setEditable(false); - loaded->setEditable(false); - name->setEditable(false); - file->setEditable(false); - version->setEditable(false); - author->setEditable(false); - organization->setEditable(false); + if (!m_packageLocationDialog) + { + m_packageLocationDialog = new QDialog(this, Qt::Sheet); + m_packageLocationUI.setupUi(m_packageLocationDialog); + } - if (!p.dirWritable /*|| p.system*/) installed->setEnabled(false); - //if (p.system) loaded->setEnabled(false); + QListWidget* list = m_packageLocationUI.packageLocationListWidget; + list->clear(); + list->setSelectionMode(QAbstractItemView::SingleSelection); - QList row; - row << installed << loaded << name << file << version << author << organization; + for (size_t i = 0; i < possiblePlaces.size(); i++) + { + list->addItem(possiblePlaces[i]); + } - m_packageModel->appendRow(row); -} + list->item(0)->setSelected(true); -void -RvPreferences::loadPackages() -{ - m_packageModel->clear(); - QStringList headers; - headers << "Installed" << "Load" << "Name" << "File" << "Version" << "Author" << "Organization"; - m_packageModel->setHorizontalHeaderLabels(headers); + m_packageLocationDialog->show(); + m_packageLocationDialog->exec(); - PackageManager::loadPackages(); + if (m_packageLocationDialog->result() == QDialog::Rejected) + { + return; + } - for (int i=0; i < headers.size(); i++) m_ui.extTreeView->resizeColumnToContents(i); -} + QList selection = list->selectedItems(); + int row = list->row(selection.front()); + QString l = possiblePlaces[row]; + possiblePlaces.clear(); + possiblePlaces.push_back(l); + } + QStringList nocopy; + QDir dir(possiblePlaces.front()); -void -RvPreferences::declarePackage(Package& p, size_t i) -{ - if (!p.hidden || m_showHiddenPackages) - { - p.row = m_packageModel->rowCount(); - addPackageItem(p, i); + addPackages(files, dir.absolutePath()); + loadPackages(); } - else + + void RvPreferences::removePackage(bool) { - p.row = -1; - } -} + QItemSelectionModel* s = m_ui.extTreeView->selectionModel(); + QModelIndexList indices = s->selection().indexes(); -void -RvPreferences::packageSelection(const QItemSelection& selected, - const QItemSelection& deselected) -{ - QItemSelectionModel* s = m_ui.extTreeView->selectionModel(); - QModelIndexList indices = s->selection().indexes(); - QTextBrowser* b = m_ui.extTextBrowser; - - b->clear(); + QMessageBox box(this); + box.setWindowTitle(tr("Confirm Removal")); - if (indices.empty()) return; + QString t = tr( + "Remove Packages ?\n\nThe following packages will be removed:\n"); + size_t count = 0; - ostringstream str; + for (size_t i = 0; i < indices.size(); i++) + { + int row = m_packageModel->itemFromIndex(indices[i])->data().toInt(); - QStandardItem* pitem = m_packageModel->itemFromIndex(indices[0]); - int row = pitem->data().toInt(); - const Package& p = m_packages[row]; + if (m_packages[row].zipFile && indices[i].column() == 0) + { + t += m_packages[row].file; + t += "\n"; + count++; + } + } - str << ""; - - if (getenv("RV_DARK") && *getenv("RV_DARK") == '1') - { - str << ""; - } + if (!count) + return; - str << "

" << p.name.toUtf8().data() << "

"; + box.setText(t); + box.setWindowModality(Qt::WindowModal); + QPushButton* b1 = box.addButton(tr("Abort"), QMessageBox::RejectRole); + QPushButton* b2 = box.addButton(tr("Remove"), QMessageBox::AcceptRole); + box.setIcon(QMessageBox::Question); + box.exec(); - if (!p.compatible) - { - str << "

" << "-- NOT COMPATIBLE WITH THIS VERSION OF RV --" << "

"; - } + if (box.clickedButton() == b1) + return; - if (p.system) - { - str << "

-- THIS IS A BASE SYSTEM PACKAGE REQUIRED BY RV --

"; - } + QStringList toremove; + QStringList files; - str << "
" - << ""; + for (size_t i = 0; i < indices.size(); i++) + { + if (indices[i].column() == 0) + { + int row = + m_packageModel->itemFromIndex(indices[i])->data().toInt(); + if (m_packages[row].zipFile) + { + files.push_back(m_packages[row].file); + } + } + } - if (p.author != "") - str << ""; + QTextBrowser* b = m_ui.extTextBrowser; + b->clear(); - if (p.organization != "") - str << ""; + removePackages(files); + } - if (p.contact != "") - str << ""; + //---------------------------------------------------------------------- - if (p.url != "") - str << ""; + bool RvPreferences::fixLoadability(const QString& msg) + { + QMessageBox box(this); + box.setWindowTitle(tr("Unloadable Package Dependencies")); + box.setText( + tr("Can't make package loadable because some of its dependencies " + "are not loadable. Try and fix them first?\n\nDetails:\n") + + msg); - if (p.version != "") - str << ""; + box.setWindowModality(Qt::WindowModal); + QPushButton* b1 = box.addButton(tr("Abort"), QMessageBox::RejectRole); + QPushButton* b2 = + box.addButton(tr("Continue"), QMessageBox::AcceptRole); + box.setIcon(QMessageBox::Critical); + box.exec(); - if (p.requires != "") - str << ""; + return box.clickedButton() != b1; + } - if (p.rvversion != "") - str << ""; + bool RvPreferences::fixUnloadability(const QString& msg) + { + QMessageBox box(this); + box.setWindowTitle(tr("Loadable Package Dependencies")); + box.setText(tr("Can't make package unloadable because some loaded " + "packages depend on it. Unload them too?\n\nDetails:\n") + + msg); - if (p.openrvversion != "") - str << ""; + box.setWindowModality(Qt::WindowModal); + QPushButton* b1 = box.addButton(tr("Abort"), QMessageBox::RejectRole); + QPushButton* b2 = + box.addButton(tr("Continue"), QMessageBox::AcceptRole); + box.setIcon(QMessageBox::Critical); + box.exec(); - str << ""; + return box.clickedButton() != b1; + } - if (p.optional) - str << ""; + bool RvPreferences::installDependantPackages(const QString& msg) + { + QMessageBox box(this); + box.setWindowTitle(tr("Some Packages Depend on This One")); + box.setText( + tr("Can't install package because some other packages dependend on " + "this one. Try and install them first?\n\nDetails:\n") + + msg); - str << "
Author " - << p.author.toUtf8().data() << "
Organization " - << p.organization.toUtf8().data() << "
Contact " - << p.contact.toUtf8().constData() << "
URL " - << p.url.toUtf8().constData() << "
Version " - << p.version.toUtf8().data() << "
Requires " - << p.requires.toUtf8().data() << "
RV Version " - << p.rvversion.toUtf8().data() << "
OpenRV Version " - << p.openrvversion.toUtf8().data() << "
File " - << p.file.toUtf8().data() << "
Optional Package " - << "This package is not loaded by default
" - << "
" - << "

Description

" - << p.description.toUtf8().data(); + box.setWindowModality(Qt::WindowModal); + QPushButton* b1 = box.addButton(tr("Abort"), QMessageBox::RejectRole); + QPushButton* b2 = + box.addButton(tr("Continue"), QMessageBox::AcceptRole); + box.setIcon(QMessageBox::Critical); + box.exec(); - str << "

Modes in Package

\n
    \n"; + return box.clickedButton() != b1; + } - for (size_t q = 0; q < p.modes.size(); q++) + bool RvPreferences::overwriteExistingFiles(const QString& msg) { - str << "
  • " << p.modes[q].file.toUtf8().data() << "
  • \n"; - - if (p.modes[q].requires.size()) - { - str << "\nRequires
      "; + QMessageBox box(this); + box.setWindowTitle(tr("Existing Package Files")); + box.setText(tr("Package files conflict with existing files? Overwrite " + "Existing Files?\n\nDetails:\n") + + msg); - for (int i = 0; i < p.modes[q].requires.size(); i++) - { - str << "
    • " << p.modes[q].requires[i].toUtf8().data() << "
    • \n"; - } + box.setWindowModality(Qt::WindowModal); + QPushButton* b1 = box.addButton(tr("Abort"), QMessageBox::RejectRole); + QPushButton* b2 = + box.addButton(tr("Overwrite"), QMessageBox::AcceptRole); + box.setIcon(QMessageBox::Critical); + box.exec(); - str << "
    \n"; - } + return box.clickedButton() != b1; } - - str << "
\n"; - - str << "

Files in Package

\n
    \n"; - for (size_t q = 0; q < p.files.size(); q++) + void RvPreferences::errorMissingPackageDependancies(const QString& msg) { - str << "
  • " << p.files[q].toUtf8().data() << "
  • \n"; - } - - str << "
\n"; - str << ""; - - b->insertHtml(QString::fromUtf8(str.str().c_str())); - - m_ui.extRemoveButton->setEnabled(!p.installed && - (p.fileWritable && - p.dirWritable)); -} + QMessageBox box(this); + box.setWindowTitle(tr("Missing Package Dependencies")); + box.setText(tr("Can't install package because some of its dependencies " + "are missing.\n\nDetails:\n") + + msg); -void -RvPreferences::showHiddenPackages(bool b) -{ - m_showHiddenPackages = b; - loadPackages(); -} + box.setWindowModality(Qt::WindowModal); + QPushButton* b1 = + box.addButton(tr("Abort Install"), QMessageBox::AcceptRole); + box.setIcon(QMessageBox::Critical); + box.exec(); + } -void -RvPreferences::addPackage(bool) -{ - // - // Figure out what dir to copy them to - // + bool RvPreferences::uninstallDependantPackages(const QString& msg) + { + QMessageBox box(this); + box.setWindowTitle(tr("Some Packages Depend on This One")); + box.setText( + tr("Can't uninstall package because some other packages dependend " + "on this one. Try and uninstall them first?\n\nDetails:\n") + + msg); - TwkApp::Bundle::PathVector supportDirs = - TwkApp::Bundle::mainBundle()->supportPath(); + box.setWindowModality(Qt::WindowModal); + QPushButton* b1 = box.addButton(tr("Abort"), QMessageBox::RejectRole); + QPushButton* b2 = + box.addButton(tr("Continue"), QMessageBox::AcceptRole); + box.setIcon(QMessageBox::Critical); + box.exec(); - QStringList possiblePlaces; + return box.clickedButton() != b1; + } - for (size_t i = 0; i < supportDirs.size(); i++) + void RvPreferences::informCannotRemoveSomeFiles(const QString& msg) { - QString pdirname = QString::fromUtf8(supportDirs[i].c_str()); - QDir pdir(pdirname); - - if (pdir.exists()) - { - if (!pdir.exists("Packages")) - { - if (!makeSupportDirTree(pdir)) continue; - } - - pdir.cd("Packages"); + QMessageBox box(this); + box.setWindowTitle(tr("Some Files Cannot Be Removed")); + box.setText( + tr("Could not remove some of the package files.\n\nDetails:\n") + + msg); - if (TwkUtil::isWritable(UTF8::qconvert(pdir.absolutePath()).c_str())) - { - possiblePlaces.push_back(pdir.absolutePath()); - } - } + box.setWindowModality(Qt::WindowModal); + QPushButton* b2 = box.addButton(tr("Ok"), QMessageBox::AcceptRole); + box.setIcon(QMessageBox::Critical); + box.exec(); } - if (possiblePlaces.empty()) + void RvPreferences::errorModeFileWriteFailed(const QString& file) { QMessageBox box(this); - box.setWindowTitle(tr("Unable to Add Packages")); - box.setText(tr("No package installation locations were found.")); + box.setWindowTitle(tr("File Write Failed")); + box.setText(tr("File cannot be written:\n") + file); box.setWindowModality(Qt::WindowModal); QPushButton* b2 = box.addButton(tr("Ok"), QMessageBox::AcceptRole); box.setIcon(QMessageBox::Critical); box.exec(); - return; } - // - // - // + void RvPreferences::informPackageFailedToCopy(const QString& msg) + { + QMessageBox box(this); + box.setWindowTitle(tr("Package Failed to Copy")); + box.setText(tr("Could not copy package files.\n\nDetails:\n") + msg); - RV_QSETTINGS; + box.setWindowModality(Qt::WindowModal); + QPushButton* b2 = box.addButton(tr("Ok"), QMessageBox::AcceptRole); + box.setIcon(QMessageBox::Critical); + box.exec(); + } - settings.beginGroup("Packages"); - QString dirname = settings.value("lastPackageDir").toString(); + bool RvPreferences::uninstallForRemoval(const QString& msg) + { + QMessageBox box(this); + box.setWindowTitle(tr("Package is currently installed")); + box.setText(tr("In order to remove the package it must be " + "uninstalled.\n\nDetails:\n") + + msg); -#if defined(PLATFORM_WINDOWS) - QFileDialog* fileDialog = new QFileDialog(this, - "Select rvpkg RV package files", - dirname, - "rvpkg Package Files (*.zip *.rvpkg *.rvpkgs)"); - - QStringList files; - if (fileDialog->exec()) files = fileDialog->selectedFiles(); - delete fileDialog; - -#else - QString selectedFilter; - QFileDialog::Options options; - // Using non native dialog on linux. - // Rationale: - // When using native QFileDialog (default) on linux, the following warning - // appears in the console: - // <> - // The warning does not appear when using non native dialog. - // Moreover, some users have reported that the dialog fails to show since RV - // was updated to Qt 5.15.3. -#if defined(PLATFORM_LINUX) - options |= QFileDialog::DontUseNativeDialog; -#endif - QStringList files = QFileDialog::getOpenFileNames(this, - "Select rvpkg RV package files", - dirname, - "rvpkg Package Files (*.zip *.rvpkg *.rvpkgs, *.rvpkgs)", - &selectedFilter, - options); -#endif + box.setWindowModality(Qt::WindowModal); + QPushButton* b1 = box.addButton(tr("Abort"), QMessageBox::RejectRole); + QPushButton* b2 = + box.addButton(tr("Continue"), QMessageBox::AcceptRole); + box.setIcon(QMessageBox::Critical); + box.exec(); - if (files.size()) - { - QFileInfo info(files[0]); - settings.setValue("lastPackageDir", info.absolutePath()); - settings.endGroup(); - } - else - { - settings.endGroup(); - return; + return box.clickedButton() != b1; } - //if (possiblePlaces.size() > 1) + void RvPreferences::updateVideo() { - // - // Ask user where to put it - // - - if (!m_packageLocationDialog) - { - m_packageLocationDialog = new QDialog(this, Qt::Sheet); - m_packageLocationUI.setupUi(m_packageLocationDialog); - } + const IPCore::Application::VideoModules& vmods = + RvApp()->videoModules(); - QListWidget* list = m_packageLocationUI.packageLocationListWidget; - list->clear(); - list->setSelectionMode(QAbstractItemView::SingleSelection); + Options& opts = Options::sharedOptions(); + m_ui.videoModuleCombo->clear(); - for (size_t i = 0; i < possiblePlaces.size(); i++) + if (m_currentVideoModule < 0) { - list->addItem(possiblePlaces[i]); - } + QString pdev = opts.presentDevice; + QStringList parts = pdev.split("/"); - list->item(0)->setSelected(true); + if (parts.size() == 2) + { + m_currentVideoModule = RvApp()->findVideoModuleIndexByName( + parts[0].toUtf8().constData()); + ; - m_packageLocationDialog->show(); - m_packageLocationDialog->exec(); + if (m_currentVideoDevice < 0 && m_currentVideoModule >= 0) + { + const auto m = vmods[m_currentVideoModule]; + const VideoModule::VideoDevices& devs = m->devices(); + string dname = parts[1].toUtf8().constData(); - if (m_packageLocationDialog->result() == QDialog::Rejected) - { - return; + for (size_t i = 0; i < devs.size(); i++) + { + if (devs[i]->name() == dname) + { + m_currentVideoDevice = i; + break; + } + } + } + } + else + { + m_currentVideoModule = 0; + } } - QList selection = list->selectedItems(); - int row = list->row(selection.front()); - QString l = possiblePlaces[row]; - possiblePlaces.clear(); - possiblePlaces.push_back(l); - } - - QStringList nocopy; - QDir dir(possiblePlaces.front()); - - addPackages(files, dir.absolutePath()); - loadPackages(); -} + if (m_currentVideoModule < 0) + m_currentVideoModule = 0; + if (m_currentVideoDevice < 0) + m_currentVideoDevice = 0; -void -RvPreferences::removePackage(bool) -{ - QItemSelectionModel* s = m_ui.extTreeView->selectionModel(); - QModelIndexList indices = s->selection().indexes(); + RvDocument* doc = reinterpret_cast( + TwkApp::Document::documents().front()->opaquePointer()); - QMessageBox box(this); - box.setWindowTitle(tr("Confirm Removal")); + for (size_t i = 0; i < vmods.size(); i++) + { + auto mod = vmods[i]; + m_ui.videoModuleCombo->addItem( + QString::fromUtf8(mod->name().c_str())); - QString t = tr("Remove Packages ?\n\nThe following packages will be removed:\n"); - size_t count = 0; + if (i == m_currentVideoModule) + { + if (!mod->isOpen()) + RvApp()->openVideoModule(mod.get()); + m_ui.videoModuleCombo->setCurrentIndex(i); + m_ui.videoDeviceCombo->clear(); + m_ui.videoDeviceCombo->hide(); - for (size_t i=0; i < indices.size(); i++) - { - int row = m_packageModel->itemFromIndex(indices[i])->data().toInt(); + QString sdk = UTF8::qconvert(mod->SDKIdentifier()); + QString info = UTF8::qconvert(mod->SDKInfo()); + if (info != "") + sdk = QString("%1 -- %2").arg(sdk).arg(info); + m_ui.videoModuleSDKLabel->setText(sdk); - if (m_packages[row].zipFile && indices[i].column() == 0) - { - t += m_packages[row].file; - t += "\n"; - count++; - } - } + const TwkApp::VideoModule::VideoDevices& devs = mod->devices(); - if (!count) return; + for (size_t j = 0; j < devs.size(); j++) + { + TwkApp::VideoDevice* d = devs[j]; + string hd = d->hardwareIdentification(); + string n = d->name(); + ostringstream str; - box.setText(t); - box.setWindowModality(Qt::WindowModal); - QPushButton* b1 = box.addButton(tr("Abort"), QMessageBox::RejectRole); - QPushButton* b2 = box.addButton(tr("Remove"), QMessageBox::AcceptRole); - box.setIcon(QMessageBox::Question); - box.exec(); + str << hd; + if (n != hd) + str << " (" << n << ")"; - if (box.clickedButton() == b1) return; + m_ui.videoDeviceCombo->addItem( + QString::fromUtf8(str.str().c_str())); - QStringList toremove; - QStringList files; + ostringstream mname; + mname << mod->name() << "/" << d->name(); - for (size_t i = 0; i < indices.size(); i++) - { - if (indices[i].column() == 0) - { - int row = m_packageModel->itemFromIndex(indices[i])->data().toInt(); + if (j == m_currentVideoDevice) + { + m_lockPresentCheck = true; + m_ui.presentationCheckBox->setCheckState( + mname.str() == opts.presentDevice ? Qt::Checked + : Qt::Unchecked); + m_lockPresentCheck = false; + + m_ui.videoDeviceCombo->setCurrentIndex(j); + string options = + RvApp()->setVideoDeviceStateFromSettings(d); + m_ui.additionalOptionsEdit->setText(options.c_str()); + updateVideoFormat(d); + updateVideo4KTransport(d); + updateVideoDataFormat(d); + updateVideoSync(d); + updateVideoSyncSource(d); + updateVideoAudioFormat(d); + updateVideoProfiles(d); + m_ui.videoSwapStereoEyesCheckBox->setCheckState( + d->swapStereoEyes() ? Qt::Checked : Qt::Unchecked); + } + } - if (m_packages[row].zipFile) - { - files.push_back(m_packages[row].file); + m_ui.videoDeviceCombo->show(); } } } - QTextBrowser* b = m_ui.extTextBrowser; - b->clear(); + void RvPreferences::updateVideoProfiles(TwkApp::VideoDevice* device) + { + // + // Profiles + // - removePackages(files); -} + IPCore::ProfileVector profiles; -//---------------------------------------------------------------------- + const TwkApp::Application::Documents& docs = RvApp()->documents(); + Rv::Session* s = static_cast(docs[0]); + profilesInPath(profiles, "display", &s->graph()); -bool -RvPreferences::fixLoadability(const QString& msg) -{ - QMessageBox box(this); - box.setWindowTitle(tr("Unloadable Package Dependencies")); - box.setText(tr("Can't make package loadable because some of its dependencies are not loadable. Try and fix them first?\n\nDetails:\n") + msg); - - box.setWindowModality(Qt::WindowModal); - QPushButton* b1 = box.addButton(tr("Abort"), QMessageBox::RejectRole); - QPushButton* b2 = box.addButton(tr("Continue"), QMessageBox::AcceptRole); - box.setIcon(QMessageBox::Critical); - box.exec(); - - return box.clickedButton() != b1; -} - -bool -RvPreferences::fixUnloadability(const QString& msg) -{ - QMessageBox box(this); - box.setWindowTitle(tr("Loadable Package Dependencies")); - box.setText(tr("Can't make package unloadable because some loaded packages depend on it. Unload them too?\n\nDetails:\n") + msg); - - box.setWindowModality(Qt::WindowModal); - QPushButton* b1 = box.addButton(tr("Abort"), QMessageBox::RejectRole); - QPushButton* b2 = box.addButton(tr("Continue"), QMessageBox::AcceptRole); - box.setIcon(QMessageBox::Critical); - box.exec(); - - return box.clickedButton() != b1; -} - -bool -RvPreferences::installDependantPackages(const QString& msg) -{ - QMessageBox box(this); - box.setWindowTitle(tr("Some Packages Depend on This One")); - box.setText(tr("Can't install package because some other packages dependend on this one. Try and install them first?\n\nDetails:\n") + msg); - - box.setWindowModality(Qt::WindowModal); - QPushButton* b1 = box.addButton(tr("Abort"), QMessageBox::RejectRole); - QPushButton* b2 = box.addButton(tr("Continue"), QMessageBox::AcceptRole); - box.setIcon(QMessageBox::Critical); - box.exec(); - - return box.clickedButton() != b1; -} - -bool -RvPreferences::overwriteExistingFiles(const QString& msg) -{ - QMessageBox box(this); - box.setWindowTitle(tr("Existing Package Files")); - box.setText(tr("Package files conflict with existing files? Overwrite Existing Files?\n\nDetails:\n") + msg); + QList combos; + combos.push_back(m_ui.moduleProfileCombo); + combos.push_back(m_ui.deviceProfileCombo); + combos.push_back(m_ui.formatProfileCombo); - box.setWindowModality(Qt::WindowModal); - QPushButton* b1 = box.addButton(tr("Abort"), QMessageBox::RejectRole); - QPushButton* b2 = box.addButton(tr("Overwrite"), QMessageBox::AcceptRole); - box.setIcon(QMessageBox::Critical); - box.exec(); + for (size_t i = 0; i < combos.size(); i++) + combos[i]->clear(); - return box.clickedButton() != b1; -} + RV_QSETTINGS; -void -RvPreferences::errorMissingPackageDependancies(const QString& msg) -{ - QMessageBox box(this); - box.setWindowTitle(tr("Missing Package Dependencies")); - box.setText(tr("Can't install package because some of its dependencies are missing.\n\nDetails:\n") + msg); - - box.setWindowModality(Qt::WindowModal); - QPushButton* b1 = box.addButton(tr("Abort Install"), QMessageBox::AcceptRole); - box.setIcon(QMessageBox::Critical); - box.exec(); -} - -bool -RvPreferences::uninstallDependantPackages(const QString& msg) -{ - QMessageBox box(this); - box.setWindowTitle(tr("Some Packages Depend on This One")); - box.setText(tr("Can't uninstall package because some other packages dependend on this one. Try and uninstall them first?\n\nDetails:\n") + msg); + string modName = device->humanReadableID(VideoDevice::ModuleNameID); + settings.beginGroup(QString::fromUtf8(modName.c_str())); + QString modProfile = settings.value("DisplayProfile", "").toString(); + settings.endGroup(); - box.setWindowModality(Qt::WindowModal); - QPushButton* b1 = box.addButton(tr("Abort"), QMessageBox::RejectRole); - QPushButton* b2 = box.addButton(tr("Continue"), QMessageBox::AcceptRole); - box.setIcon(QMessageBox::Critical); - box.exec(); + string devName = device->humanReadableID(VideoDevice::DeviceNameID); + settings.beginGroup(QString::fromUtf8(devName.c_str())); + QString devProfile = settings.value("DisplayProfile", "").toString(); + settings.endGroup(); - return box.clickedButton() != b1; -} + string formatName = + device->humanReadableID(VideoDevice::VideoAndDataFormatID); + settings.beginGroup(QString::fromUtf8(formatName.c_str())); + QString formatProfile = settings.value("DisplayProfile", "").toString(); + settings.endGroup(); -void -RvPreferences::informCannotRemoveSomeFiles(const QString& msg) -{ - QMessageBox box(this); - box.setWindowTitle(tr("Some Files Cannot Be Removed")); - box.setText(tr("Could not remove some of the package files.\n\nDetails:\n") + msg); - - box.setWindowModality(Qt::WindowModal); - QPushButton* b2 = box.addButton(tr("Ok"), QMessageBox::AcceptRole); - box.setIcon(QMessageBox::Critical); - box.exec(); -} - -void -RvPreferences::errorModeFileWriteFailed(const QString& file) -{ - QMessageBox box(this); - box.setWindowTitle(tr("File Write Failed")); - box.setText(tr("File cannot be written:\n") + file); - box.setWindowModality(Qt::WindowModal); - QPushButton* b2 = box.addButton(tr("Ok"), QMessageBox::AcceptRole); - box.setIcon(QMessageBox::Critical); - box.exec(); -} - -void -RvPreferences::informPackageFailedToCopy(const QString& msg) -{ - QMessageBox box(this); - box.setWindowTitle(tr("Package Failed to Copy")); - box.setText(tr("Could not copy package files.\n\nDetails:\n") + msg); - - box.setWindowModality(Qt::WindowModal); - QPushButton* b2 = box.addButton(tr("Ok"), QMessageBox::AcceptRole); - box.setIcon(QMessageBox::Critical); - box.exec(); -} - -bool -RvPreferences::uninstallForRemoval(const QString& msg) -{ - QMessageBox box(this); - box.setWindowTitle(tr("Package is currently installed")); - box.setText(tr("In order to remove the package it must be uninstalled.\n\nDetails:\n") + msg); + int modIndex = -1; + int devIndex = -1; + int formatIndex = -1; - box.setWindowModality(Qt::WindowModal); - QPushButton* b1 = box.addButton(tr("Abort"), QMessageBox::RejectRole); - QPushButton* b2 = box.addButton(tr("Continue"), QMessageBox::AcceptRole); - box.setIcon(QMessageBox::Critical); - box.exec(); + // + // Add the profile names + // - return box.clickedButton() != b1; -} + for (size_t i = 0; i < profiles.size(); i++) + { + QString name(profiles[i]->name().c_str()); -void -RvPreferences::updateVideo() -{ - const IPCore::Application::VideoModules& vmods = RvApp()->videoModules(); + for (size_t q = 0; q < combos.size(); q++) + { + combos[q]->addItem(name); + } - Options& opts = Options::sharedOptions(); - m_ui.videoModuleCombo->clear(); + if (name == modProfile) + modIndex = i; + if (name == devProfile) + devIndex = i; + if (name == formatProfile) + formatIndex = i; + } - if (m_currentVideoModule < 0) - { - QString pdev = opts.presentDevice; - QStringList parts = pdev.split("/"); + // + // Add the create and default items + // - if (parts.size() == 2) + for (size_t i = 0; i < combos.size(); i++) { - m_currentVideoModule = - RvApp()->findVideoModuleIndexByName(parts[0].toUtf8().constData());; + combos[i]->insertSeparator(combos[i]->count()); - if (m_currentVideoDevice < 0 && m_currentVideoModule >= 0) + switch (i) { - const auto m = vmods[m_currentVideoModule]; - const VideoModule::VideoDevices& devs = m->devices(); - string dname = parts[1].toUtf8().constData(); - - for (size_t i = 0; i < devs.size(); i++) - { - if (devs[i]->name() == dname) - { - m_currentVideoDevice = i; - break; - } - } + case 0: + combos[i]->addItem("- Use Default Profile -"); + break; + case 1: + combos[i]->addItem("- Use Module Profile -"); + break; + case 2: + combos[i]->addItem("- Use Device Profile -"); + break; } } - else - { - m_currentVideoModule = 0; - } - } - if (m_currentVideoModule < 0) m_currentVideoModule = 0; - if (m_currentVideoDevice < 0) m_currentVideoDevice = 0; + // + // Set current values + // - RvDocument* doc = - reinterpret_cast(TwkApp::Document::documents().front()->opaquePointer()); + combos[0]->setCurrentIndex(modIndex == -1 ? combos[0]->count() - 1 + : modIndex); + combos[1]->setCurrentIndex(devIndex == -1 ? combos[1]->count() - 1 + : devIndex); + combos[2]->setCurrentIndex(formatIndex == -1 ? combos[2]->count() - 1 + : formatIndex); + } - for (size_t i = 0; i < vmods.size(); i++) + void RvPreferences::updateVideoFormat(TwkApp::VideoDevice* d) { - auto mod = vmods[i]; - m_ui.videoModuleCombo->addItem(QString::fromUtf8(mod->name().c_str())); + m_ui.videoFormatCombo->clear(); - if (i == m_currentVideoModule) + if (d->numVideoFormats() == 0) { - if (!mod->isOpen()) RvApp()->openVideoModule(mod.get()); - m_ui.videoModuleCombo->setCurrentIndex(i); - m_ui.videoDeviceCombo->clear(); - m_ui.videoDeviceCombo->hide(); - - QString sdk = UTF8::qconvert(mod->SDKIdentifier()); - QString info = UTF8::qconvert(mod->SDKInfo()); - if (info != "") sdk = QString("%1 -- %2").arg(sdk).arg(info); - m_ui.videoModuleSDKLabel->setText(sdk); - - const TwkApp::VideoModule::VideoDevices& devs = mod->devices(); + m_ui.videoFormatCombo->addItem("N/A"); + m_ui.videoFormatCombo->setEnabled(false); + } + else + { + m_ui.videoFormatCombo->setEnabled(true); - for (size_t j = 0; j < devs.size(); j++) + for (size_t i = 0; i < d->numVideoFormats(); i++) { - TwkApp::VideoDevice* d = devs[j]; - string hd = d->hardwareIdentification(); - string n = d->name(); - ostringstream str; - - str << hd; - if (n != hd) str << " (" << n << ")"; - - m_ui.videoDeviceCombo->addItem(QString::fromUtf8(str.str().c_str())); - - ostringstream mname; - mname << mod->name() << "/" << d->name(); - - if (j == m_currentVideoDevice) - { - m_lockPresentCheck = true; - m_ui.presentationCheckBox->setCheckState(mname.str() == opts.presentDevice - ? Qt::Checked : Qt::Unchecked); - m_lockPresentCheck = false; - - m_ui.videoDeviceCombo->setCurrentIndex(j); - string options = RvApp()->setVideoDeviceStateFromSettings(d); - m_ui.additionalOptionsEdit->setText(options.c_str()); - updateVideoFormat(d); - updateVideo4KTransport(d); - updateVideoDataFormat(d); - updateVideoSync(d); - updateVideoSyncSource(d); - updateVideoAudioFormat(d); - updateVideoProfiles(d); - m_ui.videoSwapStereoEyesCheckBox->setCheckState( - d->swapStereoEyes() ? Qt::Checked : Qt::Unchecked); - } + m_ui.videoFormatCombo->addItem(QString::fromUtf8( + d->videoFormatAtIndex(i).description.c_str())); + if (i == d->currentVideoFormat()) + m_ui.videoFormatCombo->setCurrentIndex(i); } - - m_ui.videoDeviceCombo->show(); } } -} -void -RvPreferences::updateVideoProfiles(TwkApp::VideoDevice* device) -{ - // - // Profiles - // + void RvPreferences::updateVideo4KTransport(TwkApp::VideoDevice* d) + { + m_ui.video4KTransportCombo->clear(); - IPCore::ProfileVector profiles; + if (d->numVideo4KTransports() == 0) + { + m_ui.video4KTransportCombo->addItem("N/A"); + m_ui.video4KTransportCombo->setEnabled(false); + } + else + { + m_ui.video4KTransportCombo->setEnabled(true); - const TwkApp::Application::Documents& docs = RvApp()->documents(); - Rv::Session* s = static_cast(docs[0]); - profilesInPath(profiles, "display", &s->graph()); + for (size_t i = 0; i < d->numVideo4KTransports(); i++) + { + m_ui.video4KTransportCombo->addItem(QString::fromUtf8( + d->video4KTransportAtIndex(i).description.c_str())); + if (i == d->currentVideo4KTransport()) + m_ui.video4KTransportCombo->setCurrentIndex(i); + } + } + } - QList combos; - combos.push_back(m_ui.moduleProfileCombo); - combos.push_back(m_ui.deviceProfileCombo); - combos.push_back(m_ui.formatProfileCombo); + void RvPreferences::updateVideoAudioFormat(TwkApp::VideoDevice* d) + { + m_ui.videoAudioFormatCombo->clear(); + m_ui.videoAudioDeviceCheckBox->setEnabled(d->hasAudioOutput()); + m_ui.videoAudioDeviceCheckBox->setCheckState( + d->audioOutputEnabled() ? Qt::Checked : Qt::Unchecked); + m_ui.useVideoLatencyCheckBox->setEnabled(!d->hasAudioOutput() + || !d->audioOutputEnabled()); + m_ui.configureVideoLatencyButton->setEnabled( + !d->hasAudioOutput() || !d->audioOutputEnabled()); + m_ui.useVideoLatencyCheckBox->setCheckState( + d->useLatencyForAudio() ? Qt::Checked : Qt::Unchecked); - for (size_t i = 0; i < combos.size(); i++) combos[i]->clear(); + if (d->numAudioFormats() == 0) + { + m_ui.videoAudioFormatCombo->addItem("N/A"); + m_ui.videoAudioFormatCombo->setEnabled(false); + } + else + { + m_ui.videoAudioFormatCombo->setEnabled(true); - RV_QSETTINGS; + for (size_t i = 0; i < d->numAudioFormats(); i++) + { + m_ui.videoAudioFormatCombo->addItem(QString::fromUtf8( + d->audioFormatAtIndex(i).description.c_str())); + if (i == d->currentAudioFormat()) + m_ui.videoAudioFormatCombo->setCurrentIndex(i); + } + } + } - string modName = device->humanReadableID(VideoDevice::ModuleNameID); - settings.beginGroup(QString::fromUtf8(modName.c_str())); - QString modProfile = settings.value("DisplayProfile", "").toString(); - settings.endGroup(); + void RvPreferences::updateVideoDataFormat(TwkApp::VideoDevice* d) + { + m_ui.dataFormatCombo->clear(); - string devName = device->humanReadableID(VideoDevice::DeviceNameID); - settings.beginGroup(QString::fromUtf8(devName.c_str())); - QString devProfile = settings.value("DisplayProfile", "").toString(); - settings.endGroup(); + if (d->numDataFormats() == 0) + { + m_ui.dataFormatCombo->addItem("N/A"); + m_ui.dataFormatCombo->setEnabled(false); + } + else + { + m_ui.dataFormatCombo->setEnabled(true); - string formatName = device->humanReadableID(VideoDevice::VideoAndDataFormatID); - settings.beginGroup(QString::fromUtf8(formatName.c_str())); - QString formatProfile = settings.value("DisplayProfile", "").toString(); - settings.endGroup(); + for (size_t i = 0; i < d->numDataFormats(); i++) + { + m_ui.dataFormatCombo->addItem(QString::fromUtf8( + d->dataFormatAtIndex(i).description.c_str())); + if (i == d->currentDataFormat()) + m_ui.dataFormatCombo->setCurrentIndex(i); + } + } + } - int modIndex = -1; - int devIndex = -1; - int formatIndex = -1; + void RvPreferences::updateVideoSync(TwkApp::VideoDevice* d) + { + m_ui.syncMethodCombo->clear(); - // - // Add the profile names - // + if (d->numSyncModes() == 0) + { + m_ui.syncMethodCombo->addItem("N/A"); + m_ui.syncMethodCombo->setEnabled(false); + } + else + { + m_ui.syncMethodCombo->setEnabled(true); - for (size_t i = 0; i < profiles.size(); i++) + for (size_t i = 0; i < d->numSyncModes(); i++) + { + m_ui.syncMethodCombo->addItem(QString::fromUtf8( + d->syncModeAtIndex(i).description.c_str())); + if (i == d->currentSyncMode()) + m_ui.syncMethodCombo->setCurrentIndex(i); + } + } + } + + void RvPreferences::updateVideoSyncSource(TwkApp::VideoDevice* d) { - QString name(profiles[i]->name().c_str()); + m_ui.syncSourceCombo->clear(); - for (size_t q = 0; q < combos.size(); q++) + if (d->numSyncSources() == 0) { - combos[q]->addItem(name); + m_ui.syncSourceCombo->addItem("N/A"); + m_ui.syncSourceCombo->setEnabled(false); } + else + { + m_ui.syncSourceCombo->setEnabled(true); - if (name == modProfile) modIndex = i; - if (name == devProfile) devIndex = i; - if (name == formatProfile) formatIndex = i; + for (size_t i = 0; i < d->numSyncSources(); i++) + { + m_ui.syncSourceCombo->addItem(QString::fromUtf8( + d->syncSourceAtIndex(i).description.c_str())); + if (i == d->currentSyncSource()) + m_ui.syncSourceCombo->setCurrentIndex(i); + } + } } - // - // Add the create and default items - // - - for (size_t i = 0; i < combos.size(); i++) + void RvPreferences::videoModuleChanged(int index) { - combos[i]->insertSeparator(combos[i]->count()); - - switch (i) - { - case 0: combos[i]->addItem("- Use Default Profile -"); break; - case 1: combos[i]->addItem("- Use Module Profile -"); break; - case 2: combos[i]->addItem("- Use Device Profile -"); break; - } + m_currentVideoModule = index; + m_currentVideoDevice = -1; + updateVideo(); } - // - // Set current values - // - - combos[0]->setCurrentIndex(modIndex == -1 ? combos[0]->count() - 1 : modIndex); - combos[1]->setCurrentIndex(devIndex == -1 ? combos[1]->count() - 1 : devIndex); - combos[2]->setCurrentIndex(formatIndex == -1 ? combos[2]->count() - 1 : formatIndex); -} - -void -RvPreferences::updateVideoFormat(TwkApp::VideoDevice* d) -{ - m_ui.videoFormatCombo->clear(); - - if (d->numVideoFormats() == 0) + void RvPreferences::videoDeviceChanged(int index) { - m_ui.videoFormatCombo->addItem("N/A"); - m_ui.videoFormatCombo->setEnabled(false); + m_currentVideoDevice = index; + updateVideo(); } - else + + void RvPreferences::videoFormatChanged(int v) { - m_ui.videoFormatCombo->setEnabled(true); - - for (size_t i = 0; i < d->numVideoFormats(); i++) + if (VideoDevice* d = currentVideoDevice()) { - m_ui.videoFormatCombo->addItem(QString::fromUtf8(d->videoFormatAtIndex(i).description.c_str())); - if (i == d->currentVideoFormat()) - m_ui.videoFormatCombo->setCurrentIndex(i); + d->setVideoFormat(v); + const VideoModule* m = d->module(); + ostringstream str; + str << m->name() << "/" << d->name(); + + RV_QSETTINGS; + settings.beginGroup(QString::fromUtf8(str.str().c_str())); + settings.setValue("videoFormat", v); + settings.endGroup(); + + // The user has set a new video format which overrides the video + // format specified on the command line if any + Rv::Options::sharedOptions().presentFormat = nullptr; + + updateVideoDataFormat(d); + updateVideoSync(d); + updateVideoSyncSource(d); + updateVideoProfiles(d); } } -} - -void -RvPreferences::updateVideo4KTransport(TwkApp::VideoDevice* d) -{ - m_ui.video4KTransportCombo->clear(); - if (d->numVideo4KTransports() == 0) + void RvPreferences::video4KTransportChanged(int v) { - m_ui.video4KTransportCombo->addItem("N/A"); - m_ui.video4KTransportCombo->setEnabled(false); - } - else - { - m_ui.video4KTransportCombo->setEnabled(true); - - for (size_t i = 0; i < d->numVideo4KTransports(); i++) + if (VideoDevice* d = currentVideoDevice()) { - m_ui.video4KTransportCombo->addItem(QString::fromUtf8(d->video4KTransportAtIndex(i).description.c_str())); - if (i == d->currentVideo4KTransport()) - m_ui.video4KTransportCombo->setCurrentIndex(i); + d->setVideo4KTransport(v); + const VideoModule* m = d->module(); + ostringstream str; + str << m->name() << "/" << d->name(); + + RV_QSETTINGS; + settings.beginGroup(QString::fromUtf8(str.str().c_str())); + settings.setValue("video4KTransport", v); + settings.endGroup(); + + updateVideoProfiles(d); } } -} -void -RvPreferences::updateVideoAudioFormat(TwkApp::VideoDevice* d) -{ - m_ui.videoAudioFormatCombo->clear(); - m_ui.videoAudioDeviceCheckBox->setEnabled(d->hasAudioOutput()); - m_ui.videoAudioDeviceCheckBox->setCheckState(d->audioOutputEnabled() ? Qt::Checked : Qt::Unchecked); - m_ui.useVideoLatencyCheckBox->setEnabled(!d->hasAudioOutput() || !d->audioOutputEnabled()); - m_ui.configureVideoLatencyButton->setEnabled(!d->hasAudioOutput() || !d->audioOutputEnabled()); - m_ui.useVideoLatencyCheckBox->setCheckState(d->useLatencyForAudio() ? Qt::Checked : Qt::Unchecked); - - if (d->numAudioFormats() == 0) + void RvPreferences::videoAudioFormatChanged(int v) { - m_ui.videoAudioFormatCombo->addItem("N/A"); - m_ui.videoAudioFormatCombo->setEnabled(false); + if (VideoDevice* d = currentVideoDevice()) + { + d->setAudioFormat(v); + const VideoModule* m = d->module(); + ostringstream str; + str << m->name() << "/" << d->name(); + + RV_QSETTINGS; + settings.beginGroup(QString::fromUtf8(str.str().c_str())); + settings.setValue("audioFormat", v); + settings.endGroup(); + } } - else + + void RvPreferences::videoDataFormatChanged(int v) { - m_ui.videoAudioFormatCombo->setEnabled(true); - - for (size_t i = 0; i < d->numAudioFormats(); i++) + if (VideoDevice* d = currentVideoDevice()) { - m_ui.videoAudioFormatCombo->addItem(QString::fromUtf8(d->audioFormatAtIndex(i).description.c_str())); - if (i == d->currentAudioFormat()) - m_ui.videoAudioFormatCombo->setCurrentIndex(i); + d->setDataFormat(v); + const VideoModule* m = d->module(); + ostringstream str; + str << m->name() << "/" << d->name(); + + RV_QSETTINGS; + settings.beginGroup(QString::fromUtf8(str.str().c_str())); + settings.setValue("dataFormat", v); + settings.endGroup(); + + // The user has set a new video data format which overrides the + // video data format specified on the command line if any + Rv::Options::sharedOptions().presentData = nullptr; + + updateVideoSync(d); + updateVideoSyncSource(d); + updateVideoProfiles(d); } } -} - -void -RvPreferences::updateVideoDataFormat(TwkApp::VideoDevice* d) -{ - m_ui.dataFormatCombo->clear(); - if (d->numDataFormats() == 0) + void RvPreferences::syncMethodChanged(int v) { - m_ui.dataFormatCombo->addItem("N/A"); - m_ui.dataFormatCombo->setEnabled(false); + if (VideoDevice* d = currentVideoDevice()) + { + d->setSyncMode(v); + const VideoModule* m = d->module(); + ostringstream str; + str << m->name() << "/" << d->name(); + + RV_QSETTINGS; + settings.beginGroup(QString::fromUtf8(str.str().c_str())); + settings.setValue("syncMode", v); + settings.endGroup(); + + updateVideoSyncSource(d); + } } - else - { - m_ui.dataFormatCombo->setEnabled(true); - for (size_t i = 0; i < d->numDataFormats(); i++) + void RvPreferences::syncSourceChanged(int v) + { + if (VideoDevice* d = currentVideoDevice()) { - m_ui.dataFormatCombo->addItem(QString::fromUtf8(d->dataFormatAtIndex(i).description.c_str())); - if (i == d->currentDataFormat()) - m_ui.dataFormatCombo->setCurrentIndex(i); + d->setSyncSource(v); + const VideoModule* m = d->module(); + ostringstream str; + str << m->name() << "/" << d->name(); + + RV_QSETTINGS; + settings.beginGroup(QString::fromUtf8(str.str().c_str())); + settings.setValue("syncSource", v); + settings.endGroup(); } } -} - -void -RvPreferences::updateVideoSync(TwkApp::VideoDevice* d) -{ - m_ui.syncMethodCombo->clear(); - if (d->numSyncModes() == 0) + void RvPreferences::videoAudioCheckBoxChanged(int v) { - m_ui.syncMethodCombo->addItem("N/A"); - m_ui.syncMethodCombo->setEnabled(false); + if (VideoDevice* d = currentVideoDevice()) + { + const VideoModule* m = d->module(); + ostringstream str; + str << m->name() << "/" << d->name(); + + bool checked = v == Qt::Checked; + + m_ui.useVideoLatencyCheckBox->setEnabled(!checked); + m_ui.configureVideoLatencyButton->setEnabled(!checked); + + RV_QSETTINGS; + settings.beginGroup(QString::fromUtf8(str.str().c_str())); + settings.setValue("useAsAudioDevice", checked); + settings.endGroup(); + + // This user action overrides the presentAudio command line option + // if any + Rv::Options::sharedOptions().presentAudio = -1; + } } - else - { - m_ui.syncMethodCombo->setEnabled(true); - for (size_t i = 0; i < d->numSyncModes(); i++) + void RvPreferences::videoSwapStereoEyesChanged(int v) + { + if (VideoDevice* d = currentVideoDevice()) { - m_ui.syncMethodCombo->addItem(QString::fromUtf8(d->syncModeAtIndex(i).description.c_str())); - if (i == d->currentSyncMode()) - m_ui.syncMethodCombo->setCurrentIndex(i); + const VideoModule* m = d->module(); + ostringstream str; + str << m->name() << "/" << d->name(); + + bool checked = v == Qt::Checked; + + RV_QSETTINGS; + settings.beginGroup(QString::fromUtf8(str.str().c_str())); + settings.setValue("swapStereoEyes", checked); + settings.endGroup(); + + d->setSwapStereoEyes(checked); } } -} - -void -RvPreferences::updateVideoSyncSource(TwkApp::VideoDevice* d) -{ - m_ui.syncSourceCombo->clear(); - if (d->numSyncSources() == 0) + void RvPreferences::videoUseLatencyCheckBoxChanged(int v) { - m_ui.syncSourceCombo->addItem("N/A"); - m_ui.syncSourceCombo->setEnabled(false); + if (VideoDevice* d = currentVideoDevice()) + { + const VideoModule* m = d->module(); + ostringstream str; + str << m->name() << "/" << d->name(); + + bool checked = v == Qt::Checked; + + RV_QSETTINGS; + settings.beginGroup(QString::fromUtf8(str.str().c_str())); + settings.setValue("useLatencyForAudio", checked); + settings.endGroup(); + } } - else + + void RvPreferences::videoAdditionalOptionsChanged() { - m_ui.syncSourceCombo->setEnabled(true); - - for (size_t i = 0; i < d->numSyncSources(); i++) + if (VideoDevice* d = currentVideoDevice()) { - m_ui.syncSourceCombo->addItem(QString::fromUtf8(d->syncSourceAtIndex(i).description.c_str())); - if (i == d->currentSyncSource()) - m_ui.syncSourceCombo->setCurrentIndex(i); + const VideoModule* m = d->module(); + ostringstream str; + str << m->name() << "/" << d->name(); + + QString s = m_ui.additionalOptionsEdit->toPlainText(); + + RV_QSETTINGS; + settings.beginGroup(QString::fromUtf8(str.str().c_str())); + settings.setValue("additionalOptions", s); + settings.endGroup(); } } -} -void -RvPreferences::videoModuleChanged(int index) -{ - m_currentVideoModule = index; - m_currentVideoDevice = -1; - updateVideo(); -} + void RvPreferences::presentationCheckBoxChanged(int state) + { + if (m_lockPresentCheck) + return; -void -RvPreferences::videoDeviceChanged(int index) -{ - m_currentVideoDevice = index; - updateVideo(); -} + if (VideoDevice* d = currentVideoDevice()) + { + const VideoModule* m = d->module(); + ostringstream str; + str << m->name() << "/" << d->name(); + Options& opts = Options::sharedOptions(); -void -RvPreferences::videoFormatChanged(int v) -{ - if (VideoDevice* d = currentVideoDevice()) - { - d->setVideoFormat(v); - const VideoModule* m = d->module(); - ostringstream str; - str << m->name() << "/" << d->name(); + RV_QSETTINGS; + settings.beginGroup("Video"); - RV_QSETTINGS; - settings.beginGroup(QString::fromUtf8(str.str().c_str())); - settings.setValue("videoFormat", v); - settings.endGroup(); + // ALLOWED LEAKING! WINDOWS BUG! + // if (strcmp(opts.presentDevice, "")) free(opts.presentDevice); + opts.presentDevice = (char*)""; - // The user has set a new video format which overrides the video format - // specified on the command line if any - Rv::Options::sharedOptions().presentFormat=nullptr; + if (state == Qt::Checked) + { + settings.setValue("presentationDevice", + QString::fromUtf8(str.str().c_str())); + opts.presentDevice = strdup(str.str().c_str()); + } + else + { + settings.setValue("presentationDevice", QString()); + } - updateVideoDataFormat(d); - updateVideoSync(d); - updateVideoSyncSource(d); - updateVideoProfiles(d); + settings.endGroup(); + } } -} -void -RvPreferences::video4KTransportChanged(int v) -{ - if (VideoDevice* d = currentVideoDevice()) + TwkApp::VideoDevice* RvPreferences::currentVideoDevice() const { - d->setVideo4KTransport(v); - const VideoModule* m = d->module(); - ostringstream str; - str << m->name() << "/" << d->name(); - - RV_QSETTINGS; - settings.beginGroup(QString::fromUtf8(str.str().c_str())); - settings.setValue("video4KTransport", v); - settings.endGroup(); + if (m_currentVideoDevice == -1 || m_currentVideoModule == -1) + return 0; - updateVideoProfiles(d); + const IPCore::Application::VideoModules& vmods = + RvApp()->videoModules(); + const auto mod = vmods[m_currentVideoModule]; + const VideoModule::VideoDevices& devs = mod->devices(); + return devs[m_currentVideoDevice]; } -} -void -RvPreferences::videoAudioFormatChanged(int v) -{ - if (VideoDevice* d = currentVideoDevice()) + void RvPreferences::audioOffsetFinished() { - d->setAudioFormat(v); - const VideoModule* m = d->module(); - ostringstream str; - str << m->name() << "/" << d->name(); + const TwkApp::Application::Documents& docs = IPCore::App()->documents(); - RV_QSETTINGS; - settings.beginGroup(QString::fromUtf8(str.str().c_str())); - settings.setValue("audioFormat", v); - settings.endGroup(); + Options& opts = Options::sharedOptions(); + opts.audioGlobalOffset = m_ui.audioGlobalOffsetEdit->text().toDouble(); + + for (size_t i = 0; i < docs.size(); i++) + { + Session* s = static_cast(docs[i]); + s->setGlobalAudioOffset(opts.audioGlobalOffset); + } } -} -void -RvPreferences::videoDataFormatChanged(int v) -{ - if (VideoDevice* d = currentVideoDevice()) + void RvPreferences::audioDeviceLatencyFinished() { - d->setDataFormat(v); - const VideoModule* m = d->module(); - ostringstream str; - str << m->name() << "/" << d->name(); + AudioRenderer::RendererParameters params = + AudioRenderer::defaultParameters(); + Options& opts = Options::sharedOptions(); - RV_QSETTINGS; - settings.beginGroup(QString::fromUtf8(str.str().c_str())); - settings.setValue("dataFormat", v); - settings.endGroup(); + opts.audioDeviceLatency = + m_ui.audioDeviceLatencyEdit->text().toDouble(); - // The user has set a new video data format which overrides the video - // data format specified on the command line if any - Rv::Options::sharedOptions().presentData=nullptr; + // Convert from msecs to secs and reverse the sign. + params.latency = -opts.audioDeviceLatency / 1000.0; - updateVideoSync(d); - updateVideoSyncSource(d); - updateVideoProfiles(d); + AudioRenderer::setDefaultParameters(params); + + AudioRenderer::reset(); } -} -void -RvPreferences::syncMethodChanged(int v) -{ - if (VideoDevice* d = currentVideoDevice()) + void RvPreferences::latencyChanged(const QString& s, bool fixed) { - d->setSyncMode(v); - const VideoModule* m = d->module(); - ostringstream str; - str << m->name() << "/" << d->name(); + double v = s.toDouble(); + TwkApp::VideoDevice* d = currentVideoDevice(); - RV_QSETTINGS; - settings.beginGroup(QString::fromUtf8(str.str().c_str())); - settings.setValue("syncMode", v); - settings.endGroup(); + if (fixed) + d->setFixedLatency(v); + else + d->setFrameLatency(v); - updateVideoSyncSource(d); + double tl = d->totalLatencyInSeconds(); + m_videoLatencyUI.totalLatencyLabel->setText( + QString("%1 ms").arg(tl * 1000.0)); } -} -void -RvPreferences::syncSourceChanged(int v) -{ - if (VideoDevice* d = currentVideoDevice()) + void RvPreferences::frameLatencyChanged(const QString& s) { - d->setSyncSource(v); - const VideoModule* m = d->module(); - ostringstream str; - str << m->name() << "/" << d->name(); - - RV_QSETTINGS; - settings.beginGroup(QString::fromUtf8(str.str().c_str())); - settings.setValue("syncSource", v); - settings.endGroup(); + latencyChanged(s, false); } -} -void -RvPreferences::videoAudioCheckBoxChanged(int v) -{ - if (VideoDevice* d = currentVideoDevice()) + void RvPreferences::fixedLatencyChanged(const QString& s) { - const VideoModule* m = d->module(); - ostringstream str; - str << m->name() << "/" << d->name(); - - bool checked = v == Qt::Checked; + latencyChanged(s, true); + } - m_ui.useVideoLatencyCheckBox->setEnabled(!checked); - m_ui.configureVideoLatencyButton->setEnabled(!checked); + void RvPreferences::configVideoLatency() + { + if (!m_videoLatencyDialog) + { + m_videoLatencyDialog = new QDialog(this, Qt::Sheet); + m_videoLatencyUI.setupUi(m_videoLatencyDialog); - RV_QSETTINGS; - settings.beginGroup(QString::fromUtf8(str.str().c_str())); - settings.setValue("useAsAudioDevice", checked); - settings.endGroup(); + connect(m_videoLatencyUI.fixedLatencyEdit, + SIGNAL(textEdited(const QString&)), this, + SLOT(fixedLatencyChanged(const QString&))); - // This user action overrides the presentAudio command line option if any - Rv::Options::sharedOptions().presentAudio=-1; - } -} + connect(m_videoLatencyUI.frameLatencyEdit, + SIGNAL(textEdited(const QString&)), this, + SLOT(frameLatencyChanged(const QString&))); + } -void -RvPreferences::videoSwapStereoEyesChanged(int v) -{ - if (VideoDevice* d = currentVideoDevice()) - { - const VideoModule* m = d->module(); - ostringstream str; - str << m->name() << "/" << d->name(); + TwkApp::VideoDevice* d = currentVideoDevice(); - bool checked = v == Qt::Checked; + double dl = d->deviceLatency(); + double tl = d->totalLatencyInSeconds(); + double xl = d->fixedLatency(); + double fl = d->frameLatencyInFrames(); - RV_QSETTINGS; - settings.beginGroup(QString::fromUtf8(str.str().c_str())); - settings.setValue("swapStereoEyes", checked); - settings.endGroup(); + m_videoLatencyUI.computedLatencyLabel->setText( + QString("%1 ms").arg(dl * 1000.0)); + m_videoLatencyUI.totalLatencyLabel->setText( + QString("%1 ms").arg(tl * 1000.0)); + m_videoLatencyUI.fixedLatencyEdit->setText(QString("%1").arg(xl)); + m_videoLatencyUI.frameLatencyEdit->setText(QString("%1").arg(fl)); - d->setSwapStereoEyes(checked); - } -} + m_videoLatencyDialog->show(); + m_videoLatencyDialog->exec(); -void -RvPreferences::videoUseLatencyCheckBoxChanged(int v) -{ - if (VideoDevice* d = currentVideoDevice()) - { - const VideoModule* m = d->module(); - ostringstream str; - str << m->name() << "/" << d->name(); + if (m_videoLatencyDialog->result() == QDialog::Rejected) + { + return; + } - bool checked = v == Qt::Checked; + xl = m_videoLatencyUI.fixedLatencyEdit->text().toDouble(); + fl = m_videoLatencyUI.frameLatencyEdit->text().toDouble(); - RV_QSETTINGS; - settings.beginGroup(QString::fromUtf8(str.str().c_str())); - settings.setValue("useLatencyForAudio", checked); - settings.endGroup(); - } -} + d->setFixedLatency(xl); + d->setFrameLatency(fl); -void -RvPreferences::videoAdditionalOptionsChanged() -{ - if (VideoDevice* d = currentVideoDevice()) - { const VideoModule* m = d->module(); ostringstream str; str << m->name() << "/" << d->name(); - QString s = m_ui.additionalOptionsEdit->toPlainText(); - RV_QSETTINGS; settings.beginGroup(QString::fromUtf8(str.str().c_str())); - settings.setValue("additionalOptions", s); + settings.setValue("fixedLatency", xl); + settings.setValue("frameLatency", fl); settings.endGroup(); } -} - -void -RvPreferences::presentationCheckBoxChanged(int state) -{ - if (m_lockPresentCheck) return; - if (VideoDevice* d = currentVideoDevice()) + void RvPreferences::fontChanged() { - const VideoModule* m = d->module(); - ostringstream str; - str << m->name() << "/" << d->name(); Options& opts = Options::sharedOptions(); + bool mustUpdateCSS = false; - RV_QSETTINGS; - settings.beginGroup("Video"); - - // ALLOWED LEAKING! WINDOWS BUG! - //if (strcmp(opts.presentDevice, "")) free(opts.presentDevice); - opts.presentDevice = (char*)""; - - if (state == Qt::Checked) + if (QObject::sender() == m_ui.fontSizeSpinBox) { - settings.setValue("presentationDevice", QString::fromUtf8(str.str().c_str())); - opts.presentDevice = strdup(str.str().c_str()); + int f1 = opts.fontSize1; + opts.fontSize1 = m_ui.fontSizeSpinBox->value(); + if (f1 != opts.fontSize1) + mustUpdateCSS = true; } else { - settings.setValue("presentationDevice", QString()); + int f2 = opts.fontSize2; + opts.fontSize2 = m_ui.fontSize2SpinBox->value(); + if (f2 != opts.fontSize2) + mustUpdateCSS = true; } - settings.endGroup(); - } -} - -TwkApp::VideoDevice* -RvPreferences::currentVideoDevice() const -{ - if (m_currentVideoDevice == -1 || - m_currentVideoModule == -1) return 0; - - const IPCore::Application::VideoModules& vmods = RvApp()->videoModules(); - const auto mod = vmods[m_currentVideoModule]; - const VideoModule::VideoDevices& devs = mod->devices(); - return devs[m_currentVideoDevice]; -} - -void -RvPreferences::audioOffsetFinished() -{ - const TwkApp::Application::Documents& docs = IPCore::App()->documents(); - - Options& opts = Options::sharedOptions(); - opts.audioGlobalOffset = m_ui.audioGlobalOffsetEdit->text().toDouble(); - - for (size_t i = 0; i < docs.size(); i++) - { - Session* s = static_cast(docs[i]); - s->setGlobalAudioOffset(opts.audioGlobalOffset); + if (mustUpdateCSS) + updateStyleSheet(); } -} - -void -RvPreferences::audioDeviceLatencyFinished() -{ - AudioRenderer::RendererParameters params = AudioRenderer::defaultParameters(); - Options& opts = Options::sharedOptions(); - - opts.audioDeviceLatency = m_ui.audioDeviceLatencyEdit->text().toDouble(); - // Convert from msecs to secs and reverse the sign. - params.latency = -opts.audioDeviceLatency / 1000.0; - - AudioRenderer::setDefaultParameters(params); - - AudioRenderer::reset(); -} - -void -RvPreferences::latencyChanged(const QString& s, bool fixed) -{ - double v = s.toDouble(); - TwkApp::VideoDevice* d = currentVideoDevice(); - - if (fixed) d->setFixedLatency(v); - else d->setFrameLatency(v); - - double tl = d->totalLatencyInSeconds(); - m_videoLatencyUI.totalLatencyLabel->setText(QString("%1 ms").arg(tl * 1000.0)); -} - -void -RvPreferences::frameLatencyChanged(const QString& s) -{ - latencyChanged(s, false); -} - -void -RvPreferences::fixedLatencyChanged(const QString& s) -{ - latencyChanged(s, true); -} - -void -RvPreferences::configVideoLatency() -{ - if (!m_videoLatencyDialog) + void RvPreferences::modProfileChanged(int index) { - m_videoLatencyDialog = new QDialog(this, Qt::Sheet); - m_videoLatencyUI.setupUi(m_videoLatencyDialog); - - connect(m_videoLatencyUI.fixedLatencyEdit, - SIGNAL(textEdited(const QString&)), - this, - SLOT(fixedLatencyChanged(const QString&))); - - connect(m_videoLatencyUI.frameLatencyEdit, - SIGNAL(textEdited(const QString&)), - this, - SLOT(frameLatencyChanged(const QString&))); - } + TwkApp::VideoDevice* d = currentVideoDevice(); + size_t n = m_ui.moduleProfileCombo->count(); - TwkApp::VideoDevice* d = currentVideoDevice(); + RV_QSETTINGS; - double dl = d->deviceLatency(); - double tl = d->totalLatencyInSeconds(); - double xl = d->fixedLatency(); - double fl = d->frameLatencyInFrames(); + string modName = d->humanReadableID(VideoDevice::ModuleNameID); + settings.beginGroup(QString::fromUtf8(modName.c_str())); - m_videoLatencyUI.computedLatencyLabel->setText(QString("%1 ms").arg(dl * 1000.0)); - m_videoLatencyUI.totalLatencyLabel->setText(QString("%1 ms").arg(tl * 1000.0)); - m_videoLatencyUI.fixedLatencyEdit->setText(QString("%1").arg(xl)); - m_videoLatencyUI.frameLatencyEdit->setText(QString("%1").arg(fl)); + if (index < n - 2) + { + settings.setValue("DisplayProfile", + QVariant(m_ui.moduleProfileCombo->currentText())); + } + else if (index == n - 1) + { + settings.remove("DisplayProfile"); + } - m_videoLatencyDialog->show(); - m_videoLatencyDialog->exec(); + settings.endGroup(); - if (m_videoLatencyDialog->result() == QDialog::Rejected) - { - return; + updateVideoProfiles(d); } - xl = m_videoLatencyUI.fixedLatencyEdit->text().toDouble(); - fl = m_videoLatencyUI.frameLatencyEdit->text().toDouble(); - - d->setFixedLatency(xl); - d->setFrameLatency(fl); - - const VideoModule* m = d->module(); - ostringstream str; - str << m->name() << "/" << d->name(); - - RV_QSETTINGS; - settings.beginGroup(QString::fromUtf8(str.str().c_str())); - settings.setValue("fixedLatency", xl); - settings.setValue("frameLatency", fl); - settings.endGroup(); -} - -void -RvPreferences::fontChanged() -{ - Options& opts = Options::sharedOptions(); - bool mustUpdateCSS = false; - - if (QObject::sender() == m_ui.fontSizeSpinBox) - { - int f1 = opts.fontSize1; - opts.fontSize1 = m_ui.fontSizeSpinBox->value(); - if (f1 != opts.fontSize1) mustUpdateCSS = true; - } - else + void RvPreferences::devProfileChanged(int index) { - int f2 = opts.fontSize2; - opts.fontSize2 = m_ui.fontSize2SpinBox->value(); - if (f2 != opts.fontSize2) mustUpdateCSS = true; - } + TwkApp::VideoDevice* d = currentVideoDevice(); + size_t n = m_ui.deviceProfileCombo->count(); - if (mustUpdateCSS) updateStyleSheet(); -} + RV_QSETTINGS; -void -RvPreferences::modProfileChanged(int index) -{ - TwkApp::VideoDevice* d = currentVideoDevice(); - size_t n = m_ui.moduleProfileCombo->count(); + string devName = d->humanReadableID(VideoDevice::DeviceNameID); + settings.beginGroup(QString::fromUtf8(devName.c_str())); - RV_QSETTINGS; + if (index < n - 2) + { + settings.setValue("DisplayProfile", + QVariant(m_ui.deviceProfileCombo->currentText())); + } + else if (index == n - 1) + { + settings.remove("DisplayProfile"); + } - string modName = d->humanReadableID(VideoDevice::ModuleNameID); - settings.beginGroup(QString::fromUtf8(modName.c_str())); + settings.endGroup(); - if (index < n - 2) - { - settings.setValue("DisplayProfile", QVariant(m_ui.moduleProfileCombo->currentText())); - } - else if (index == n - 1) - { - settings.remove("DisplayProfile"); + updateVideoProfiles(d); } - settings.endGroup(); - - updateVideoProfiles(d); -} - -void -RvPreferences::devProfileChanged(int index) -{ - TwkApp::VideoDevice* d = currentVideoDevice(); - size_t n = m_ui.deviceProfileCombo->count(); - - RV_QSETTINGS; - - string devName = d->humanReadableID(VideoDevice::DeviceNameID); - settings.beginGroup(QString::fromUtf8(devName.c_str())); - - if (index < n - 2) - { - settings.setValue("DisplayProfile", QVariant(m_ui.deviceProfileCombo->currentText())); - } - else if (index == n - 1) + void RvPreferences::formatProfileChanged(int index) { - settings.remove("DisplayProfile"); - } - - settings.endGroup(); + TwkApp::VideoDevice* d = currentVideoDevice(); + size_t n = m_ui.formatProfileCombo->count(); - updateVideoProfiles(d); -} + RV_QSETTINGS; -void -RvPreferences::formatProfileChanged(int index) -{ - TwkApp::VideoDevice* d = currentVideoDevice(); - size_t n = m_ui.formatProfileCombo->count(); + string formatName = + d->humanReadableID(VideoDevice::VideoAndDataFormatID); + settings.beginGroup(QString::fromUtf8(formatName.c_str())); - RV_QSETTINGS; + if (index < n - 2) + { + settings.setValue("DisplayProfile", + QVariant(m_ui.formatProfileCombo->currentText())); + } + else if (index == n - 1) + { + settings.remove("DisplayProfile"); + } - string formatName = d->humanReadableID(VideoDevice::VideoAndDataFormatID); - settings.beginGroup(QString::fromUtf8(formatName.c_str())); + settings.endGroup(); - if (index < n - 2) - { - settings.setValue("DisplayProfile", QVariant(m_ui.formatProfileCombo->currentText())); - } - else if (index == n - 1) - { - settings.remove("DisplayProfile"); + updateVideoProfiles(d); } - settings.endGroup(); - - updateVideoProfiles(d); -} - - -} // Rv \ No newline at end of file +} // namespace Rv diff --git a/src/lib/app/RvCommon/RvProfileManager.cpp b/src/lib/app/RvCommon/RvProfileManager.cpp index 940907d34..1e3f4c5bf 100644 --- a/src/lib/app/RvCommon/RvProfileManager.cpp +++ b/src/lib/app/RvCommon/RvProfileManager.cpp @@ -1,13 +1,10 @@ // -// Copyright (c) 2013 Tweak Software. +// Copyright (c) 2013 Tweak Software. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// // - - - +// #include #include @@ -23,296 +20,320 @@ #include #include -namespace Rv { -using namespace std; -using namespace TwkApp; -using namespace IPCore; -using namespace TwkQtCoreUtil; - -RvProfileManager::RvProfileManager(QObject* obj) - : QDialog(), - m_model(0), - m_createDialog(0) +namespace Rv { - m_ui.setupUi(this); - loadModel(); + using namespace std; + using namespace TwkApp; + using namespace IPCore; + using namespace TwkQtCoreUtil; + + RvProfileManager::RvProfileManager(QObject* obj) + : QDialog() + , m_model(0) + , m_createDialog(0) + { + m_ui.setupUi(this); + loadModel(); + + m_createDialogUI.setupUi(m_createDialog = new QDialog(this, Qt::Sheet)); + + connect(m_ui.profileTreeView->selectionModel(), + SIGNAL(selectionChanged(const QItemSelection&, + const QItemSelection&)), + this, + SLOT(selectionChanged(const QItemSelection&, + const QItemSelection&))); + connect(m_ui.addButton, SIGNAL(released()), this, SLOT(addProfile())); + connect(m_ui.deleteButton, SIGNAL(released()), this, + SLOT(deleteProfile())); + connect(m_ui.applyButton, SIGNAL(pressed()), this, + SLOT(applyProfile())); + } - m_createDialogUI.setupUi(m_createDialog = new QDialog(this, Qt::Sheet)); + RvProfileManager::~RvProfileManager() {} - connect(m_ui.profileTreeView->selectionModel(), - SIGNAL(selectionChanged(const QItemSelection&,const QItemSelection&)), - this, SLOT(selectionChanged(const QItemSelection&,const QItemSelection&))); - connect(m_ui.addButton, SIGNAL(released()), this, SLOT(addProfile())); - connect(m_ui.deleteButton, SIGNAL(released()), this, SLOT(deleteProfile())); - connect(m_ui.applyButton, SIGNAL(pressed()),this, SLOT(applyProfile())); -} + void RvProfileManager::loadModel() + { + if (!m_model) + m_model = new QStandardItemModel(); + m_model->clear(); -RvProfileManager::~RvProfileManager() -{ -} + QStringList headers; + headers << "Name" << "Locked" << "Assigned" << "File"; + m_model->setHorizontalHeaderLabels(headers); -void -RvProfileManager::loadModel() -{ - if (!m_model) m_model = new QStandardItemModel(); - m_model->clear(); + RvSession* session = Rv::RvSession::currentRvSession(); + const IPCore::IPGraph::DisplayGroups& dgroups = + session->graph().displayGroups(); - QStringList headers; - headers << "Name" << "Locked" << "Assigned" << "File"; - m_model->setHorizontalHeaderLabels(headers); + // + // At the moment we only manage "display" profiles. + // + profilesInPath(m_profiles, "display", &session->graph()); - RvSession* session = Rv::RvSession::currentRvSession(); - const IPCore::IPGraph::DisplayGroups& dgroups = session->graph().displayGroups(); + for (size_t i = 0; i < m_profiles.size(); i++) + { + Profile* p = m_profiles[i]; + QString filename = p->fileName().c_str(); + QString name = p->name().c_str(); - // - // At the moment we only manage "display" profiles. - // - profilesInPath(m_profiles, "display", &session->graph()); + string assignName = ""; - for (size_t i = 0; i < m_profiles.size(); i++) - { - Profile* p = m_profiles[i]; - QString filename = p->fileName().c_str(); - QString name = p->name().c_str(); - - string assignName = ""; - - for (size_t q = 0; q < dgroups.size(); q++) - { - if (dgroups[q]->displayPipelineNode()->profile() == p->name()) + for (size_t q = 0; q < dgroups.size(); q++) { - if (assignName.size()) assignName += ", "; - assignName += dgroups[q]->physicalDevice()->name(); + if (dgroups[q]->displayPipelineNode()->profile() == p->name()) + { + if (assignName.size()) + assignName += ", "; + assignName += dgroups[q]->physicalDevice()->name(); + } } - } - QIcon icon = TwkUtil::isWritable(p->fileName().c_str()) ? QIcon() : QIcon(":images/lock_out.png"); + QIcon icon = TwkUtil::isWritable(p->fileName().c_str()) + ? QIcon() + : QIcon(":images/lock_out.png"); - QList row; + QList row; - QStandardItem* nameItem = new QStandardItem(name); - QStandardItem* lockedItem = new QStandardItem(icon, ""); - QStandardItem* assignItem = new QStandardItem(assignName.c_str()); - QStandardItem* fileItem = new QStandardItem(filename); + QStandardItem* nameItem = new QStandardItem(name); + QStandardItem* lockedItem = new QStandardItem(icon, ""); + QStandardItem* assignItem = new QStandardItem(assignName.c_str()); + QStandardItem* fileItem = new QStandardItem(filename); - nameItem->setData(QVariant((int)i)); + nameItem->setData(QVariant((int)i)); - row << nameItem - << lockedItem - << assignItem - << fileItem; + row << nameItem << lockedItem << assignItem << fileItem; - for (size_t q = 0; q < row.size(); q++) - { - row[q]->setEditable(false); + for (size_t q = 0; q < row.size(); q++) + { + row[q]->setEditable(false); + } + + m_model->appendRow(row); } - m_model->appendRow(row); + m_ui.profileTreeView->setModel(m_model); + m_ui.profileTreeView->setAlternatingRowColors(true); + for (int i = 0; i < 4; i++) + m_ui.profileTreeView->resizeColumnToContents(i); } - m_ui.profileTreeView->setModel(m_model); - m_ui.profileTreeView->setAlternatingRowColors(true); - for (int i=0; i < 4; i++) m_ui.profileTreeView->resizeColumnToContents(i); -} + void RvProfileManager::addProfile() + { -void -RvProfileManager::addProfile() -{ + // + // At the moment, new profiles are created in the user support area, + // but this may not be in the RV_SUPPORT_PATH, in which case newly + // created profiles will be invisible, hence confusion. Disallow + // creation in this case. Also check if the directory exists or can be + // created if not. - // - // At the moment, new profiles are created in the user support area, but - // this may not be in the RV_SUPPORT_PATH, in which case newly created - // profiles will be invisible, hence confusion. Disallow creation in this - // case. Also check if the directory exists or can be created if not. + TwkApp::Bundle* bundle = TwkApp::Bundle::mainBundle(); - TwkApp::Bundle* bundle = TwkApp::Bundle::mainBundle(); + QDir profilesDir(bundle->userPluginPath("Profiles").c_str()); - QDir profilesDir(bundle->userPluginPath("Profiles").c_str()); + // + // Check that user dir is in support Path + // - // - // Check that user dir is in support Path - // + QDir userDir(profilesDir); + userDir.cdUp(); - QDir userDir(profilesDir); - userDir.cdUp(); + bool foundIt = false; + vector supportPath = bundle->supportPath(); - bool foundIt = false; - vector supportPath = bundle->supportPath(); + for (int i = 0; i < supportPath.size(); ++i) + { + if (userDir.canonicalPath() + == QDir(supportPath[i].c_str()).canonicalPath()) + { + foundIt = true; + } + } - for (int i = 0; i < supportPath.size(); ++i) - { - if (userDir.canonicalPath() == QDir(supportPath[i].c_str()).canonicalPath()) - { - foundIt = true; - } - } + if (!foundIt) + { + cerr << "ERROR: New Display Profiles will be created in the user " + "support area: " + << endl + << "ERROR: '" << UTF8::qconvert(userDir.canonicalPath()) << "'" + << endl + << "ERROR: but that directory has been removed from the " + "RV_SUPPORT_PATH." + << endl + << "ERROR: Please consult your sysadmin." << endl; + return; + } - if (!foundIt) - { - cerr << "ERROR: New Display Profiles will be created in the user support area: " << endl - << "ERROR: '" << UTF8::qconvert(userDir.canonicalPath()) << "'" << endl - << "ERROR: but that directory has been removed from the RV_SUPPORT_PATH." << endl - << "ERROR: Please consult your sysadmin." << endl; - return; - } + // + // Check that Profiles subdir exists or can be created. + // - // - // Check that Profiles subdir exists or can be created. - // + profilesDir.mkpath(profilesDir.absolutePath()); - profilesDir.mkpath(profilesDir.absolutePath()); + if (!profilesDir.exists()) + { + cerr << "ERROR: target Profiles directory does not exist: " + << UTF8::qconvert(profilesDir.absolutePath()) << endl; + return; + } - if (!profilesDir.exists()) - { - cerr << "ERROR: target Profiles directory does not exist: " - << UTF8::qconvert(profilesDir.absolutePath()) - << endl; - return; - } + RvSession* session = Rv::RvSession::currentRvSession(); + const IPCore::IPGraph::DisplayGroups& dgroups = + session->graph().displayGroups(); + + m_createDialogUI.deviceComboBox->clear(); + + for (size_t i = 0; i < dgroups.size(); i++) + { + IPCore::DisplayGroupIPNode* dgroup = dgroups[i]; + m_createDialogUI.deviceComboBox->addItem( + dgroup->physicalDevice()->name().c_str()); + } + m_createDialog->show(); + m_createDialog->exec(); + if (m_createDialog->result() == QDialog::Rejected) + return; + + int index = m_createDialogUI.deviceComboBox->currentIndex(); + IPCore::DisplayGroupIPNode* node = dgroups[index]; + + Session::WriteRequest request; + request.setOption("comments", + string(m_createDialogUI.commentsEdit->toPlainText() + .toUtf8() + .constData())); + request.setOption("connections", true); + request.setOption("membership", true); + request.setOption("recursive", true); + request.setOption("sparse", false); + QString initName = m_createDialogUI.nameEdit->text().trimmed(); + if (initName.isEmpty()) + { + cerr << "ERROR: Profile name must contain non-white-space " + "characters." + << endl; + } + else + { + string name = initName.toUtf8().constData(); + // + // At the moment we only manage "display" profiles. + // + name += ".display.profile"; - RvSession* session = Rv::RvSession::currentRvSession(); - const IPCore::IPGraph::DisplayGroups& dgroups = session->graph().displayGroups(); + QFileInfo fileInfo(profilesDir, QString(name.c_str())); + QFileInfo dirInfo(profilesDir.canonicalPath()); - m_createDialogUI.deviceComboBox->clear(); + const bool isDirWritable = TwkUtil::isWritable( + UTF8::qconvert(profilesDir.canonicalPath()).c_str()); + const bool isFileWritable = TwkUtil::isWritable( + UTF8::qconvert(fileInfo.absoluteFilePath()).c_str()); - for (size_t i = 0; i < dgroups.size(); i++) - { - IPCore::DisplayGroupIPNode* dgroup = dgroups[i]; - m_createDialogUI.deviceComboBox->addItem( dgroup->physicalDevice()->name().c_str() ); + if (!isDirWritable || (fileInfo.exists() && !isFileWritable)) + { + cerr << "ERROR: User Profile directory \"" + << UTF8::qconvert(profilesDir.canonicalPath()) + << "\" is unwriteable! Profile not saved!" << endl; + } + else + { + QString file = profilesDir.absoluteFilePath(name.c_str()); + session->writeProfile(file.toUtf8().constData(), + node->displayPipelineNode(), request); + } + } + loadModel(); } - m_createDialog->show(); - m_createDialog->exec(); - if (m_createDialog->result() == QDialog::Rejected) return; - - int index = m_createDialogUI.deviceComboBox->currentIndex(); - IPCore::DisplayGroupIPNode* node = dgroups[index]; - - Session::WriteRequest request; - request.setOption("comments", string(m_createDialogUI.commentsEdit->toPlainText().toUtf8().constData())); - request.setOption("connections", true); - request.setOption("membership", true); - request.setOption("recursive", true); - request.setOption("sparse", false); - QString initName = m_createDialogUI.nameEdit->text().trimmed(); - if (initName.isEmpty()) + void RvProfileManager::clear() { - cerr << "ERROR: Profile name must contain non-white-space characters." << endl; + for (size_t i = 0; i < m_profiles.size(); i++) + delete m_profiles[i]; } - else - { - string name = initName.toUtf8().constData(); - // - // At the moment we only manage "display" profiles. - // - name += ".display.profile"; - QFileInfo fileInfo(profilesDir, QString(name.c_str())); - QFileInfo dirInfo(profilesDir.canonicalPath()); + Profile* RvProfileManager::currentProfile() + { + QModelIndex index = + m_ui.profileTreeView->selectionModel()->currentIndex(); + if (index.isValid()) + return m_profiles[index.row()]; + return 0; + } - const bool isDirWritable = TwkUtil::isWritable(UTF8::qconvert(profilesDir.canonicalPath()).c_str()); - const bool isFileWritable = TwkUtil::isWritable(UTF8::qconvert(fileInfo.absoluteFilePath()).c_str()); + void RvProfileManager::deleteProfile() + { + Profile* p = currentProfile(); + if (!p) + return; + QString filename = p->fileName().c_str(); - if (!isDirWritable || (fileInfo.exists() && !isFileWritable)) + if (TwkUtil::isWritable(p->fileName().c_str())) { - cerr << "ERROR: User Profile directory \"" - << UTF8::qconvert(profilesDir.canonicalPath()) - << "\" is unwriteable! Profile not saved!" - << endl; + QMessageBox box(this); + box.setWindowTitle(tr("Delete Profile")); + box.setText(tr("Are you sure you want to delete the profile?")); + + box.setWindowModality(Qt::WindowModal); + QPushButton* b1 = + box.addButton(tr("Cancel"), QMessageBox::RejectRole); + QPushButton* b2 = + box.addButton(tr("Delete"), QMessageBox::AcceptRole); + box.setIcon(QMessageBox::Critical); + box.exec(); + + if (box.clickedButton() != b1) + { + QFile::remove(filename); + clear(); + loadModel(); + } } - else - { - QString file = profilesDir.absoluteFilePath(name.c_str()); - session->writeProfile(file.toUtf8().constData(), node->displayPipelineNode(), request); - } } - loadModel(); -} -void -RvProfileManager::clear() -{ - for (size_t i = 0; i < m_profiles.size(); i++) delete m_profiles[i]; -} - -Profile* -RvProfileManager::currentProfile() -{ - QModelIndex index = m_ui.profileTreeView->selectionModel()->currentIndex(); - if (index.isValid()) return m_profiles[index.row()]; - return 0; -} - -void -RvProfileManager::deleteProfile() -{ - Profile* p = currentProfile(); - if (!p) return; - QString filename = p->fileName().c_str(); - - if (TwkUtil::isWritable(p->fileName().c_str())) + void RvProfileManager::selectionChanged(const QItemSelection&, + const QItemSelection&) { - QMessageBox box(this); - box.setWindowTitle(tr("Delete Profile")); - box.setText(tr("Are you sure you want to delete the profile?")); + Profile* profile = currentProfile(); + if (!profile) + return; + bool ok = true; - box.setWindowModality(Qt::WindowModal); - QPushButton* b1 = box.addButton(tr("Cancel"), QMessageBox::RejectRole); - QPushButton* b2 = box.addButton(tr("Delete"), QMessageBox::AcceptRole); - box.setIcon(QMessageBox::Critical); - box.exec(); - - if (box.clickedButton() != b1) + try { - QFile::remove(filename); - clear(); - loadModel(); + profile->load(); + } + catch (...) + { + ok = false; + m_ui.profileDescriptionBrowser->setText("ERROR: reading profile"); } - } -} -void -RvProfileManager::selectionChanged(const QItemSelection&, const QItemSelection&) -{ - Profile* profile = currentProfile(); - if (!profile) return; - bool ok = true; + if (ok) + { + string comment = profile->comment(); + m_ui.profileDescriptionBrowser->setText(comment.c_str()); + m_ui.profileDescriptionBrowser->append(""); + m_ui.profileDescriptionBrowser->append("Non-default Values:"); - try - { - profile->load(); - } - catch (...) - { - ok = false; - m_ui.profileDescriptionBrowser->setText("ERROR: reading profile"); + string desc = profile->structureDescription(); + m_ui.profileDescriptionBrowser->append(desc.c_str()); + } } - if (ok) + void RvProfileManager::applyProfile() { - string comment = profile->comment(); - m_ui.profileDescriptionBrowser->setText(comment.c_str()); - m_ui.profileDescriptionBrowser->append(""); - m_ui.profileDescriptionBrowser->append("Non-default Values:"); - - string desc = profile->structureDescription(); - m_ui.profileDescriptionBrowser->append(desc.c_str()); - } -} - -void -RvProfileManager::applyProfile() -{ - Profile* profile = currentProfile(); - if (!profile) return; - RvSession* session = Rv::RvSession::currentRvSession(); + Profile* profile = currentProfile(); + if (!profile) + return; + RvSession* session = Rv::RvSession::currentRvSession(); - profile->apply( session->graph().primaryDisplayGroup()->displayPipelineNode() ); + profile->apply( + session->graph().primaryDisplayGroup()->displayPipelineNode()); - loadModel(); - session->askForRedraw(); -} - -} // Rv + loadModel(); + session->askForRedraw(); + } +} // namespace Rv diff --git a/src/lib/app/RvCommon/RvSourceEditor.cpp b/src/lib/app/RvCommon/RvSourceEditor.cpp index 47673646c..9da26009d 100644 --- a/src/lib/app/RvCommon/RvSourceEditor.cpp +++ b/src/lib/app/RvCommon/RvSourceEditor.cpp @@ -1,12 +1,10 @@ // -// Copyright (c) 2013 Tweak Software. +// Copyright (c) 2013 Tweak Software. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// // - - +// #include #include @@ -24,586 +22,628 @@ #include #include -namespace Rv { -using namespace std; -using namespace TwkApp; -using namespace boost; -using namespace IPCore; - -RvSourceEditor::RvSourceEditor(Session* session, QWidget* parent) - : QMainWindow(parent), - EventNode("sourceEditor"), - m_session(session), - m_highlighter(0), - m_currentPage(0), - m_changeLock(false), - m_updateLock(false) +namespace Rv { - m_ui.setupUi(this); - m_publishDialog = new QDialog(this, Qt::Sheet); - m_publishUI.setupUi(m_publishDialog); + using namespace std; + using namespace TwkApp; + using namespace boost; + using namespace IPCore; + + RvSourceEditor::RvSourceEditor(Session* session, QWidget* parent) + : QMainWindow(parent) + , EventNode("sourceEditor") + , m_session(session) + , m_highlighter(0) + , m_currentPage(0) + , m_changeLock(false) + , m_updateLock(false) + { + m_ui.setupUi(this); + m_publishDialog = new QDialog(this, Qt::Sheet); + m_publishUI.setupUi(m_publishDialog); - m_typeComboBox = m_ui.typeComboBox; + m_typeComboBox = m_ui.typeComboBox; - listenTo(&(session->graph())); + listenTo(&(session->graph())); - QFont font; + QFont font; #ifdef PLATFORM_DARWIN - font.setFamily("Monaco"); + font.setFamily("Monaco"); #else - font.setFamily("Courier"); + font.setFamily("Courier"); #endif - font.setFixedPitch(true); - font.setPointSize(14); - - m_ui.textEdit->setFont(font); - m_ui.marginTextEdit->setFont(font); - m_ui.marginTextEdit->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - m_ui.marginTextEdit->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - - m_highlighter = new GLSLSyntaxHighlighter(m_ui.textEdit->document()); - - //m_typeComboBox->addItem("Source", QVariant("source")); - m_typeComboBox->addItem("Filter", QVariant("filter")); - m_typeComboBox->addItem("Color", QVariant("color")); - m_typeComboBox->addItem("Merge", QVariant("merge")); - m_typeComboBox->addItem("Transition", QVariant("transition")); - m_typeComboBox->addItem("Combine", QVariant("combine")); - - connect(m_ui.actionCompile, SIGNAL(triggered()), this, SLOT(compile())); - connect(m_ui.actionRevert, SIGNAL(triggered()), this, SLOT(revert())); - connect(m_ui.actionPublish, SIGNAL(triggered()), this, SLOT(publish())); - connect(m_typeComboBox, SIGNAL(activated(int)), this, SLOT(typeChanged(int))); - connect(m_ui.actionUndo, SIGNAL(triggered()), m_ui.textEdit, SLOT(undo())); - connect(m_ui.actionRedo, SIGNAL(triggered()), m_ui.textEdit, SLOT(redo())); - connect(m_ui.actionCut, SIGNAL(triggered()), m_ui.textEdit, SLOT(cut())); - connect(m_ui.actionCopy, SIGNAL(triggered()), m_ui.textEdit, SLOT(copy())); - connect(m_ui.actionPaste, SIGNAL(triggered()), m_ui.textEdit, SLOT(paste())); - connect(m_ui.actionSelectAll, SIGNAL(triggered()), m_ui.textEdit, SLOT(selectAll())); - connect(m_ui.actionDeselectAll, SIGNAL(triggered()), this, SLOT(deselectAll())); - connect(m_ui.actionBigger_Text, SIGNAL(triggered()), m_ui.textEdit, SLOT(zoomIn())); - connect(m_ui.actionSmaller_Text, SIGNAL(triggered()), m_ui.textEdit, SLOT(zoomOut())); - connect(m_ui.actionBigger_Text, SIGNAL(triggered()), m_ui.marginTextEdit, SLOT(zoomIn())); - connect(m_ui.actionSmaller_Text, SIGNAL(triggered()), m_ui.marginTextEdit, SLOT(zoomOut())); - connect(m_ui.actionBigger_Text, SIGNAL(triggered()), m_ui.outputTextEdit, SLOT(zoomIn())); - connect(m_ui.actionSmaller_Text, SIGNAL(triggered()), m_ui.outputTextEdit, SLOT(zoomOut())); - connect(m_ui.actionNext_Line, SIGNAL(triggered()), this, SLOT(downLine())); - connect(m_ui.actionPrevious_Line, SIGNAL(triggered()), this, SLOT(upLine())); - connect(m_ui.actionNext_Word, SIGNAL(triggered()), this, SLOT(forwardWord())); - connect(m_ui.actionPrevious_Word, SIGNAL(triggered()), this, SLOT(backWord())); - - connect(m_ui.textEdit->verticalScrollBar(), SIGNAL(valueChanged(int)), - m_ui.marginTextEdit->verticalScrollBar(), SLOT(setValue(int))); - - connect(m_ui.textEdit, SIGNAL(textChanged()), this, SLOT(sourceChanged())); - - connect(m_ui.tabWidget, SIGNAL(currentChanged(int)), this, SLOT(tabChanged(int))); - connect(m_ui.tabWidget, SIGNAL(tabCloseRequested(int)), this, SLOT(tabClosed(int))); - - connect(m_publishDialog, SIGNAL(accepted()), this, SLOT(publishAccepted())); -} - -RvSourceEditor::~RvSourceEditor() -{ -} + font.setFixedPitch(true); + font.setPointSize(14); + + m_ui.textEdit->setFont(font); + m_ui.marginTextEdit->setFont(font); + m_ui.marginTextEdit->setHorizontalScrollBarPolicy( + Qt::ScrollBarAlwaysOff); + m_ui.marginTextEdit->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + + m_highlighter = new GLSLSyntaxHighlighter(m_ui.textEdit->document()); + + // m_typeComboBox->addItem("Source", QVariant("source")); + m_typeComboBox->addItem("Filter", QVariant("filter")); + m_typeComboBox->addItem("Color", QVariant("color")); + m_typeComboBox->addItem("Merge", QVariant("merge")); + m_typeComboBox->addItem("Transition", QVariant("transition")); + m_typeComboBox->addItem("Combine", QVariant("combine")); + + connect(m_ui.actionCompile, SIGNAL(triggered()), this, SLOT(compile())); + connect(m_ui.actionRevert, SIGNAL(triggered()), this, SLOT(revert())); + connect(m_ui.actionPublish, SIGNAL(triggered()), this, SLOT(publish())); + connect(m_typeComboBox, SIGNAL(activated(int)), this, + SLOT(typeChanged(int))); + connect(m_ui.actionUndo, SIGNAL(triggered()), m_ui.textEdit, + SLOT(undo())); + connect(m_ui.actionRedo, SIGNAL(triggered()), m_ui.textEdit, + SLOT(redo())); + connect(m_ui.actionCut, SIGNAL(triggered()), m_ui.textEdit, + SLOT(cut())); + connect(m_ui.actionCopy, SIGNAL(triggered()), m_ui.textEdit, + SLOT(copy())); + connect(m_ui.actionPaste, SIGNAL(triggered()), m_ui.textEdit, + SLOT(paste())); + connect(m_ui.actionSelectAll, SIGNAL(triggered()), m_ui.textEdit, + SLOT(selectAll())); + connect(m_ui.actionDeselectAll, SIGNAL(triggered()), this, + SLOT(deselectAll())); + connect(m_ui.actionBigger_Text, SIGNAL(triggered()), m_ui.textEdit, + SLOT(zoomIn())); + connect(m_ui.actionSmaller_Text, SIGNAL(triggered()), m_ui.textEdit, + SLOT(zoomOut())); + connect(m_ui.actionBigger_Text, SIGNAL(triggered()), + m_ui.marginTextEdit, SLOT(zoomIn())); + connect(m_ui.actionSmaller_Text, SIGNAL(triggered()), + m_ui.marginTextEdit, SLOT(zoomOut())); + connect(m_ui.actionBigger_Text, SIGNAL(triggered()), + m_ui.outputTextEdit, SLOT(zoomIn())); + connect(m_ui.actionSmaller_Text, SIGNAL(triggered()), + m_ui.outputTextEdit, SLOT(zoomOut())); + connect(m_ui.actionNext_Line, SIGNAL(triggered()), this, + SLOT(downLine())); + connect(m_ui.actionPrevious_Line, SIGNAL(triggered()), this, + SLOT(upLine())); + connect(m_ui.actionNext_Word, SIGNAL(triggered()), this, + SLOT(forwardWord())); + connect(m_ui.actionPrevious_Word, SIGNAL(triggered()), this, + SLOT(backWord())); + + connect(m_ui.textEdit->verticalScrollBar(), SIGNAL(valueChanged(int)), + m_ui.marginTextEdit->verticalScrollBar(), SLOT(setValue(int))); + + connect(m_ui.textEdit, SIGNAL(textChanged()), this, + SLOT(sourceChanged())); + + connect(m_ui.tabWidget, SIGNAL(currentChanged(int)), this, + SLOT(tabChanged(int))); + connect(m_ui.tabWidget, SIGNAL(tabCloseRequested(int)), this, + SLOT(tabClosed(int))); + + connect(m_publishDialog, SIGNAL(accepted()), this, + SLOT(publishAccepted())); + } -EventNode::Result -RvSourceEditor::receiveEvent(const Event& event) -{ - if (const GenericStringEvent* gevent = - dynamic_cast(&event)) + RvSourceEditor::~RvSourceEditor() {} + + EventNode::Result RvSourceEditor::receiveEvent(const Event& event) { - if (event.name() == "graph-state-change") + if (const GenericStringEvent* gevent = + dynamic_cast(&event)) { - vector parts; - algorithm::split(parts, gevent->stringContent(), is_any_of(string("."))); + if (event.name() == "graph-state-change") + { + vector parts; + algorithm::split(parts, gevent->stringContent(), + is_any_of(string("."))); - IPNode* node = m_session->graph().findNode(parts.front()); + IPNode* node = m_session->graph().findNode(parts.front()); - if (node == m_node) - { - if (parts[1] == "node") + if (node == m_node) { - if (parts[2] == "evaluationType") + if (parts[1] == "node") { - TwkContainer::StringProperty* sp = node->property("node.evaluationType"); - QString etype = sp->front().c_str(); + if (parts[2] == "evaluationType") + { + TwkContainer::StringProperty* sp = + node->property( + "node.evaluationType"); + QString etype = sp->front().c_str(); - int n = m_typeComboBox->count(); + int n = m_typeComboBox->count(); - for (size_t i = 0; i < n; i++) - { - if (m_typeComboBox->itemData(i).toString() == etype) + for (size_t i = 0; i < n; i++) { - m_typeComboBox->setCurrentIndex(i); - break; + if (m_typeComboBox->itemData(i).toString() + == etype) + { + m_typeComboBox->setCurrentIndex(i); + break; + } } } } - } - else if (parts[1] == "function") - { - if (parts[2] == "glsl") + else if (parts[1] == "function") { - initFromNode(m_node); + if (parts[2] == "glsl") + { + initFromNode(m_node); + } } } - } - for (NodeEditStateMap::const_iterator i = m_stateMap.begin(); - i != m_stateMap.end(); - ++i) - { - if ((*i).second.node == node) + for (NodeEditStateMap::const_iterator i = m_stateMap.begin(); + i != m_stateMap.end(); ++i) { - if (parts[1] == "ui") + if ((*i).second.node == node) { - if (parts[2] == "name") + if (parts[1] == "ui") { - int index = m_ui.tabWidget->indexOf((*i).first); - m_ui.tabWidget->setTabText(index, node->uiName().c_str()); + if (parts[2] == "name") + { + int index = m_ui.tabWidget->indexOf((*i).first); + m_ui.tabWidget->setTabText( + index, node->uiName().c_str()); + } } } } } } - } - - return EventAcceptAndContinue; -} -void -RvSourceEditor::updateSourceMargin(bool force) -{ - size_t linesInEditor = m_ui.textEdit->document()->lineCount(); - size_t linesInMargin = m_ui.marginTextEdit->document()->lineCount(); + return EventAcceptAndContinue; + } - if (linesInEditor != linesInMargin || force) + void RvSourceEditor::updateSourceMargin(bool force) { - set errorLines; - set warningLines; - - // Mac/AMD style - regex errorRE("\\bERROR\\b:?\\s*([0-9]+):([0-9]+):"); - regex warningRE("\\bWARNING\\b:?\\s*([0-9]+):([0-9]+):"); - // NVIDIA style - regex errorRE2("([0-9]+)\\(([0-9]+)\\)\\s*:\\s*error\\s+"); - regex warningRE2("([0-9]+)\\(([0-9]+)\\)\\s*:\\s*warning\\s+"); - - smatch m; - string messages = m_node->outputMessage(); - vector lines; - algorithm::split(lines, messages, is_any_of(string("\n"))); - - for (size_t i = 0; i < lines.size(); i++) + size_t linesInEditor = m_ui.textEdit->document()->lineCount(); + size_t linesInMargin = m_ui.marginTextEdit->document()->lineCount(); + + if (linesInEditor != linesInMargin || force) { - if (regex_search(lines[i], m, errorRE)) - { - istringstream istr(m[2]); - int line; - istr >> line; - errorLines.insert(line); - } + set errorLines; + set warningLines; - if (regex_search(lines[i], m, errorRE2)) - { - istringstream istr(m[2]); - int line; - istr >> line; - errorLines.insert(line); - } - - if (regex_search(lines[i], m, warningRE)) - { - istringstream istr(m[2]); - int line; - istr >> line; - warningLines.insert(line); - } + // Mac/AMD style + regex errorRE("\\bERROR\\b:?\\s*([0-9]+):([0-9]+):"); + regex warningRE("\\bWARNING\\b:?\\s*([0-9]+):([0-9]+):"); + // NVIDIA style + regex errorRE2("([0-9]+)\\(([0-9]+)\\)\\s*:\\s*error\\s+"); + regex warningRE2("([0-9]+)\\(([0-9]+)\\)\\s*:\\s*warning\\s+"); - if (regex_search(lines[i], m, warningRE2)) - { - istringstream istr(m[2]); - int line; - istr >> line; - warningLines.insert(line); - } - } + smatch m; + string messages = m_node->outputMessage(); + vector lines; + algorithm::split(lines, messages, is_any_of(string("\n"))); - m_ui.marginTextEdit->clear(); - QString lineText; - - for (size_t i = 0; i < linesInEditor; i++) - { - if (errorLines.count(i+1)) - { - lineText += QString("%1
").arg(i+1); - } - else if (warningLines.count(i+1)) + for (size_t i = 0; i < lines.size(); i++) { - lineText += QString("%1
").arg(i+1); + if (regex_search(lines[i], m, errorRE)) + { + istringstream istr(m[2]); + int line; + istr >> line; + errorLines.insert(line); + } + + if (regex_search(lines[i], m, errorRE2)) + { + istringstream istr(m[2]); + int line; + istr >> line; + errorLines.insert(line); + } + + if (regex_search(lines[i], m, warningRE)) + { + istringstream istr(m[2]); + int line; + istr >> line; + warningLines.insert(line); + } + + if (regex_search(lines[i], m, warningRE2)) + { + istringstream istr(m[2]); + int line; + istr >> line; + warningLines.insert(line); + } } - else + + m_ui.marginTextEdit->clear(); + QString lineText; + + for (size_t i = 0; i < linesInEditor; i++) { - lineText += QString("%1
").arg(i+1); + if (errorLines.count(i + 1)) + { + lineText += + QString("%1
").arg(i + 1); + } + else if (warningLines.count(i + 1)) + { + lineText += + QString("%1
").arg(i + 1); + } + else + { + lineText += + QString("%1
").arg(i + 1); + } } + + m_ui.marginTextEdit->setHtml(lineText); + m_ui.marginTextEdit->verticalScrollBar()->setValue( + m_ui.textEdit->verticalScrollBar()->value()); } - - m_ui.marginTextEdit->setHtml(lineText); - m_ui.marginTextEdit->verticalScrollBar()->setValue(m_ui.textEdit->verticalScrollBar()->value()); } -} -void -RvSourceEditor::sourceChanged() -{ - updateSourceMargin(false); -} + void RvSourceEditor::sourceChanged() { updateSourceMargin(false); } -void -RvSourceEditor::initFromNode(IPCore::DynamicIPNode* node) -{ - if (m_updateLock) + void RvSourceEditor::initFromNode(IPCore::DynamicIPNode* node) { - if (m_currentPage && m_stateMap.count(m_currentPage) > 0) + if (m_updateLock) { - if (m_stateMap[m_currentPage].node == node) return; + if (m_currentPage && m_stateMap.count(m_currentPage) > 0) + { + if (m_stateMap[m_currentPage].node == node) + return; + } } - } - m_changeLock = true; + m_changeLock = true; - if (m_stateMap.empty() && !m_currentPage) - { - m_ui.tabWidget->clear(); - } - - if (m_currentPage) - { - if (m_stateMap.count(m_currentPage)) + if (m_stateMap.empty() && !m_currentPage) { - m_stateMap[m_currentPage].source = m_ui.textEdit->toPlainText().toUtf8().constData(); - m_stateMap[m_currentPage].node = m_node; + m_ui.tabWidget->clear(); } - } - - m_currentPage = 0; - for (NodeEditStateMap::const_iterator i = m_stateMap.begin(); - i != m_stateMap.end(); - ++i) - { - if ((*i).second.node == node) + if (m_currentPage) { - m_currentPage = (*i).first; + if (m_stateMap.count(m_currentPage)) + { + m_stateMap[m_currentPage].source = + m_ui.textEdit->toPlainText().toUtf8().constData(); + m_stateMap[m_currentPage].node = m_node; + } } - } - - if (!m_currentPage) - { - m_currentPage = new QWidget(m_ui.tabWidget); - int index = m_ui.tabWidget->addTab(m_currentPage, node->uiName().c_str()); - m_stateMap[m_currentPage] = NodeEditState(node, ""); - } - - m_ui.tabWidget->setCurrentWidget(m_currentPage); - m_node = node; - m_ui.textEdit->setPlainText(node->property("function.glsl")->front().c_str()); - m_ui.tabWidget->setTabText(m_ui.tabWidget->indexOf(m_currentPage), m_node->uiName().c_str()); - m_ui.outputTextEdit->clear(); - string etype = m_node->stringValue("node.evaluationType"); - QString es = etype.c_str(); + m_currentPage = 0; - for (size_t i = 0; i < m_typeComboBox->count(); i++) - { - if (m_typeComboBox->itemData(i).toString() == es) + for (NodeEditStateMap::const_iterator i = m_stateMap.begin(); + i != m_stateMap.end(); ++i) { - m_typeComboBox->setCurrentIndex(i); - break; + if ((*i).second.node == node) + { + m_currentPage = (*i).first; + } } - } - - m_changeLock = false; -} -void -RvSourceEditor::editNode(const string& nodeName) -{ - if (IPNode* node = m_session->graph().findNode(nodeName)) - { - if (DynamicIPNode* dnode = dynamic_cast(node)) + if (!m_currentPage) { - initFromNode(dnode); + m_currentPage = new QWidget(m_ui.tabWidget); + int index = + m_ui.tabWidget->addTab(m_currentPage, node->uiName().c_str()); + m_stateMap[m_currentPage] = NodeEditState(node, ""); } - } -} - -void -RvSourceEditor::typeChanged(int index) -{ -} - -void -RvSourceEditor::compile() -{ - if (m_node) - { - m_updateLock = true; - StringPropertyEditor etype(m_node, "node.evaluationType"); - int index = m_typeComboBox->currentIndex(); - QVariant data = m_typeComboBox->itemData(index); - etype.setValue(data.toString().toUtf8().constData()); + m_ui.tabWidget->setCurrentWidget(m_currentPage); - StringPropertyEditor code(m_node, "function.glsl"); - code.setValue(m_ui.textEdit->toPlainText().toUtf8().constData()); - - int n = m_typeComboBox->count(); - string message = m_node->outputMessage(); + m_node = node; + m_ui.textEdit->setPlainText( + node->property("function.glsl") + ->front() + .c_str()); + m_ui.tabWidget->setTabText(m_ui.tabWidget->indexOf(m_currentPage), + m_node->uiName().c_str()); + m_ui.outputTextEdit->clear(); + string etype = m_node->stringValue("node.evaluationType"); + QString es = etype.c_str(); - for (size_t i = 0; i < n; i++) + for (size_t i = 0; i < m_typeComboBox->count(); i++) { - if (m_typeComboBox->itemData(i).toString() == etype.value().c_str() && - m_typeComboBox->currentIndex() != i) + if (m_typeComboBox->itemData(i).toString() == es) { - if (message.size() && message[message.size()-1] != '\n') message += "\n"; - message += "INFO: Compile succeeded but evaluation type changed to "; - message += "\""; - message += etype.value(); - message += "\""; m_typeComboBox->setCurrentIndex(i); break; } } - m_session->askForRedraw(); - - m_ui.outputTextEdit->clear(); - - QDateTime dt = QDateTime::currentDateTime(); - QString dtString = QString("%1").arg(dt.toString("ddd MMMM d h:mm:ss")); + m_changeLock = false; + } - if (message == "") - { - m_ui.outputTextEdit->append(QString("Compilation Succeeded - %1").arg(dtString)); - } - else + void RvSourceEditor::editNode(const string& nodeName) + { + if (IPNode* node = m_session->graph().findNode(nodeName)) { - m_ui.outputTextEdit->append(QString("%1").arg(dtString)); + if (DynamicIPNode* dnode = dynamic_cast(node)) + { + initFromNode(dnode); + } } + } - QTextBlockFormat format; - format.setAlignment(Qt::AlignHCenter); - QTextCursor cursor = m_ui.outputTextEdit->textCursor(); - cursor.setBlockFormat(format); - m_ui.outputTextEdit->setTextCursor(cursor); + void RvSourceEditor::typeChanged(int index) {} - if (message != "") + void RvSourceEditor::compile() + { + if (m_node) { - // - // correct weird error messages - // - - regex manySyntaxRE("syntax error syntax error"); - message = regex_replace(message, manySyntaxRE, "syntax error"); - - // - // correct use of hashed function name - // - - regex hashRE("\\b" + m_node->outputFunctionCallName() + "\\b"); - message = regex_replace(message, hashRE, m_node->outputFunctionName()); + m_updateLock = true; - // - // Mac/AMD style output - // + StringPropertyEditor etype(m_node, "node.evaluationType"); + int index = m_typeComboBox->currentIndex(); + QVariant data = m_typeComboBox->itemData(index); + etype.setValue(data.toString().toUtf8().constData()); - regex berrorRE("\\bERROR:\\s+(\\D)"); - regex bwarningRE("\\bWARNING:\\s+(\\D)"); - message = regex_replace(message, berrorRE, "ERROR: \\1"); - message = regex_replace(message, bwarningRE, "WARNING: \\1"); + StringPropertyEditor code(m_node, "function.glsl"); + code.setValue(m_ui.textEdit->toPlainText().toUtf8().constData()); - // - // Mac/AMD style output - // + int n = m_typeComboBox->count(); + string message = m_node->outputMessage(); - regex errorRE("\\bERROR\\b:?\\s*([0-9]+):([0-9]+):"); - regex warningRE("\\bWARNING\\b:?\\s*([0-9]+):([0-9]+):"); - message = regex_replace(message, errorRE, "ERROR: line \\2: "); - message = regex_replace(message, warningRE, "WARNING: line \\2: "); + for (size_t i = 0; i < n; i++) + { + if (m_typeComboBox->itemData(i).toString() + == etype.value().c_str() + && m_typeComboBox->currentIndex() != i) + { + if (message.size() && message[message.size() - 1] != '\n') + message += "\n"; + message += "INFO: Compile succeeded but evaluation type " + "changed to "; + message += "\""; + message += etype.value(); + message += "\""; + m_typeComboBox->setCurrentIndex(i); + break; + } + } - // - // nvidia style output - // + m_session->askForRedraw(); - regex errorRE2("[0-9]+\\(([0-9]+)\\)\\s*:\\s*error\\s+"); - regex warningRE2("[0-9]+\\(([0-9]+)\\)\\s*:\\s*warning\\s+"); - message = regex_replace(message, errorRE2, "ERROR: line \\1: "); - message = regex_replace(message, warningRE2, "WARNING: line \\1: "); + m_ui.outputTextEdit->clear(); - // - // Internal style info output - // + QDateTime dt = QDateTime::currentDateTime(); + QString dtString = QString("%1") + .arg(dt.toString("ddd MMMM d h:mm:ss")); - regex infoRE("\\bINFO\\b:?"); - message = regex_replace(message, infoRE, "INFO:"); + if (message == "") + { + m_ui.outputTextEdit->append( + QString("Compilation " + "Succeeded - %1") + .arg(dtString)); + } + else + { + m_ui.outputTextEdit->append(QString("%1").arg(dtString)); + } - vector lines; - algorithm::split(lines, message, is_any_of(string("\n"))); + QTextBlockFormat format; + format.setAlignment(Qt::AlignHCenter); + QTextCursor cursor = m_ui.outputTextEdit->textCursor(); + cursor.setBlockFormat(format); + m_ui.outputTextEdit->setTextCursor(cursor); - for (size_t i = 0; i < lines.size(); i++) + if (message != "") { - string line = lines[i]; - - if (line != "") + // + // correct weird error messages + // + + regex manySyntaxRE("syntax error syntax error"); + message = regex_replace(message, manySyntaxRE, "syntax error"); + + // + // correct use of hashed function name + // + + regex hashRE("\\b" + m_node->outputFunctionCallName() + "\\b"); + message = regex_replace(message, hashRE, + m_node->outputFunctionName()); + + // + // Mac/AMD style output + // + + regex berrorRE("\\bERROR:\\s+(\\D)"); + regex bwarningRE("\\bWARNING:\\s+(\\D)"); + message = + regex_replace(message, berrorRE, + "ERROR: \\1"); + message = regex_replace( + message, bwarningRE, + "WARNING: \\1"); + + // + // Mac/AMD style output + // + + regex errorRE("\\bERROR\\b:?\\s*([0-9]+):([0-9]+):"); + regex warningRE("\\bWARNING\\b:?\\s*([0-9]+):([0-9]+):"); + message = regex_replace( + message, errorRE, + "ERROR: line \\2: "); + message = + regex_replace(message, warningRE, + "WARNING: " + "line \\2: "); + + // + // nvidia style output + // + + regex errorRE2("[0-9]+\\(([0-9]+)\\)\\s*:\\s*error\\s+"); + regex warningRE2("[0-9]+\\(([0-9]+)\\)\\s*:\\s*warning\\s+"); + message = regex_replace( + message, errorRE2, + "ERROR: line \\1: "); + message = + regex_replace(message, warningRE2, + "WARNING: " + "line \\1: "); + + // + // Internal style info output + // + + regex infoRE("\\bINFO\\b:?"); + message = regex_replace(message, infoRE, + "INFO:"); + + vector lines; + algorithm::split(lines, message, is_any_of(string("\n"))); + + for (size_t i = 0; i < lines.size(); i++) { - m_ui.outputTextEdit->append(line.c_str()); + string line = lines[i]; - QTextBlockFormat format; - format.setAlignment(Qt::AlignLeft); - QTextCursor cursor = m_ui.outputTextEdit->textCursor(); - cursor.setBlockFormat(format); - m_ui.outputTextEdit->setTextCursor(cursor); + if (line != "") + { + m_ui.outputTextEdit->append(line.c_str()); + + QTextBlockFormat format; + format.setAlignment(Qt::AlignLeft); + QTextCursor cursor = m_ui.outputTextEdit->textCursor(); + cursor.setBlockFormat(format); + m_ui.outputTextEdit->setTextCursor(cursor); + } } } + + updateSourceMargin(true); + + m_updateLock = false; } + } - updateSourceMargin(true); + void RvSourceEditor::importFile() {} - m_updateLock = false; + void RvSourceEditor::publish() + { + m_publishUI.typeNameEdit->setText( + m_node->stringValue("node.name").c_str()); + m_publishUI.fileNameEdit->setText( + m_node->stringValue("node.export").c_str()); + m_publishUI.authorEdit->setText( + m_node->stringValue("node.author").c_str()); + m_publishUI.companyEdit->setText( + m_node->stringValue("node.company").c_str()); + m_publishUI.commentEdit->setText( + m_node->stringValue("node.comment").c_str()); + m_publishUI.fetchesSpinBox->setValue( + m_node->intValue("function.fetches")); + m_publishUI.versionSpinBox->setValue(m_node->intValue("node.version")); + m_publishUI.userVisibleCheckBox->setChecked( + m_node->intValue("node.userVisible") == 0); + m_publishDialog->open(); + + /* + QString fileName = QFileDialog::getSaveFileName(this, + "Publish Node + Definition", + ".", + "Node Definition + File (*.gto)"); + */ + + // m_node->publish(fileName.toUtf8().constData()); } -} -void -RvSourceEditor::importFile() -{ -} - -void -RvSourceEditor::publish() -{ - m_publishUI.typeNameEdit->setText(m_node->stringValue("node.name").c_str()); - m_publishUI.fileNameEdit->setText(m_node->stringValue("node.export").c_str()); - m_publishUI.authorEdit->setText(m_node->stringValue("node.author").c_str()); - m_publishUI.companyEdit->setText(m_node->stringValue("node.company").c_str()); - m_publishUI.commentEdit->setText(m_node->stringValue("node.comment").c_str()); - m_publishUI.fetchesSpinBox->setValue(m_node->intValue("function.fetches")); - m_publishUI.versionSpinBox->setValue(m_node->intValue("node.version")); - m_publishUI.userVisibleCheckBox->setChecked(m_node->intValue("node.userVisible") == 0); - m_publishDialog->open(); - -/* - QString fileName = QFileDialog::getSaveFileName(this, - "Publish Node Definition", - ".", - "Node Definition File (*.gto)"); -*/ - - //m_node->publish(fileName.toUtf8().constData()); -} - -void -RvSourceEditor::publishAccepted() -{ - string typeName = m_publishUI.typeNameEdit->text().toUtf8().constData(); - string fileName = m_publishUI.fileNameEdit->text().toUtf8().constData(); - string author = m_publishUI.authorEdit->text().toUtf8().constData(); - string company = m_publishUI.companyEdit->text().toUtf8().constData(); - string comment = m_publishUI.commentEdit->text().toUtf8().constData(); - int version = m_publishUI.versionSpinBox->value(); - int fetches = m_publishUI.fetchesSpinBox->value(); - bool userVisible = m_publishUI.userVisibleCheckBox->isChecked(); - - m_node->setStringValue("node.name", typeName); - m_node->setStringValue("node.author", author); - m_node->setStringValue("node.company", company); - m_node->setStringValue("node.comment", comment); - m_node->setIntValue("node.version", version); - m_node->setIntValue("node.userVisible", userVisible ? 1 : 0); - m_node->setIntValue("function.fetches", fetches); - m_node->publish(fileName); -} - -void -RvSourceEditor::revert() -{ -} + void RvSourceEditor::publishAccepted() + { + string typeName = m_publishUI.typeNameEdit->text().toUtf8().constData(); + string fileName = m_publishUI.fileNameEdit->text().toUtf8().constData(); + string author = m_publishUI.authorEdit->text().toUtf8().constData(); + string company = m_publishUI.companyEdit->text().toUtf8().constData(); + string comment = m_publishUI.commentEdit->text().toUtf8().constData(); + int version = m_publishUI.versionSpinBox->value(); + int fetches = m_publishUI.fetchesSpinBox->value(); + bool userVisible = m_publishUI.userVisibleCheckBox->isChecked(); + + m_node->setStringValue("node.name", typeName); + m_node->setStringValue("node.author", author); + m_node->setStringValue("node.company", company); + m_node->setStringValue("node.comment", comment); + m_node->setIntValue("node.version", version); + m_node->setIntValue("node.userVisible", userVisible ? 1 : 0); + m_node->setIntValue("function.fetches", fetches); + m_node->publish(fileName); + } -void -RvSourceEditor::deselectAll() -{ - QTextCursor cursor = m_ui.textEdit->textCursor(); - cursor.clearSelection(); - m_ui.textEdit->setTextCursor(cursor); -} + void RvSourceEditor::revert() {} -void -RvSourceEditor::downLine() -{ - QTextCursor cursor = m_ui.textEdit->textCursor(); - cursor.movePosition(QTextCursor::Down); - m_ui.textEdit->setTextCursor(cursor); -} - void -RvSourceEditor::upLine() -{ - QTextCursor cursor = m_ui.textEdit->textCursor(); - cursor.movePosition(QTextCursor::Up); - m_ui.textEdit->setTextCursor(cursor); -} + void RvSourceEditor::deselectAll() + { + QTextCursor cursor = m_ui.textEdit->textCursor(); + cursor.clearSelection(); + m_ui.textEdit->setTextCursor(cursor); + } -void -RvSourceEditor::forwardWord() -{ - QTextCursor cursor = m_ui.textEdit->textCursor(); - cursor.movePosition(QTextCursor::NextWord); - m_ui.textEdit->setTextCursor(cursor); -} + void RvSourceEditor::downLine() + { + QTextCursor cursor = m_ui.textEdit->textCursor(); + cursor.movePosition(QTextCursor::Down); + m_ui.textEdit->setTextCursor(cursor); + } -void -RvSourceEditor::backWord() -{ - QTextCursor cursor = m_ui.textEdit->textCursor(); - cursor.movePosition(QTextCursor::PreviousWord); - m_ui.textEdit->setTextCursor(cursor); -} + void RvSourceEditor::upLine() + { + QTextCursor cursor = m_ui.textEdit->textCursor(); + cursor.movePosition(QTextCursor::Up); + m_ui.textEdit->setTextCursor(cursor); + } -void -RvSourceEditor::tabChanged(int index) -{ - if (m_changeLock) return; + void RvSourceEditor::forwardWord() + { + QTextCursor cursor = m_ui.textEdit->textCursor(); + cursor.movePosition(QTextCursor::NextWord); + m_ui.textEdit->setTextCursor(cursor); + } - if (QWidget* page = m_ui.tabWidget->widget(index)) + void RvSourceEditor::backWord() { - if (m_stateMap.count(page) > 0) initFromNode(m_stateMap[page].node); + QTextCursor cursor = m_ui.textEdit->textCursor(); + cursor.movePosition(QTextCursor::PreviousWord); + m_ui.textEdit->setTextCursor(cursor); } -} -void -RvSourceEditor::tabClosed(int index) -{ - if (QWidget* page = m_ui.tabWidget->widget(index)) + void RvSourceEditor::tabChanged(int index) { - if (m_stateMap.count(page) > 0) + if (m_changeLock) + return; + + if (QWidget* page = m_ui.tabWidget->widget(index)) { - if (m_currentPage == page && m_ui.tabWidget->count() == 1) - { - m_currentPage = 0; - m_stateMap.clear(); - hide(); - return; - } - else + if (m_stateMap.count(page) > 0) + initFromNode(m_stateMap[page].node); + } + } + + void RvSourceEditor::tabClosed(int index) + { + if (QWidget* page = m_ui.tabWidget->widget(index)) + { + if (m_stateMap.count(page) > 0) { - m_stateMap.erase(page); - m_ui.tabWidget->removeTab(index); - initFromNode(m_stateMap.begin()->second.node); + if (m_currentPage == page && m_ui.tabWidget->count() == 1) + { + m_currentPage = 0; + m_stateMap.clear(); + hide(); + return; + } + else + { + m_stateMap.erase(page); + m_ui.tabWidget->removeTab(index); + initFromNode(m_stateMap.begin()->second.node); + } } } } -} - - -} // Rv +} // namespace Rv diff --git a/src/lib/app/RvCommon/RvTopViewToolBar.cpp b/src/lib/app/RvCommon/RvTopViewToolBar.cpp index f9227976b..d1b64ecee 100644 --- a/src/lib/app/RvCommon/RvTopViewToolBar.cpp +++ b/src/lib/app/RvCommon/RvTopViewToolBar.cpp @@ -1,9 +1,9 @@ // -// Copyright (c) 2012 Tweak Software. +// Copyright (c) 2012 Tweak Software. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// // #include #include @@ -24,1411 +24,1442 @@ #include #include -namespace Rv { -using namespace std; -using namespace TwkApp; -using namespace boost; -using namespace TwkMath; -using namespace IPCore; -using namespace TwkContainer; -using namespace TwkQtCoreUtil; - -RvTopViewToolBar::RvTopViewToolBar(QWidget* parent) - : QToolBar("top", parent), - EventNode("topToolBar"), - m_loading(false), - m_session(0), - m_device(0), - m_outputDevice(0), - m_viewBackAction(0) -{ - // if we don't build up front the style sheet doesn't quite work - build(); - setObjectName("topToolBar"); -} - -void -RvTopViewToolBar::makeActive(bool b) -{ - if (b && !m_viewBackAction) build(); - setVisible(b); -} - -void -RvTopViewToolBar::makeActiveFromSettings() +namespace Rv { - RV_QSETTINGS; - settings.beginGroup("ViewToolBars"); + using namespace std; + using namespace TwkApp; + using namespace boost; + using namespace TwkMath; + using namespace IPCore; + using namespace TwkContainer; + using namespace TwkQtCoreUtil; + + RvTopViewToolBar::RvTopViewToolBar(QWidget* parent) + : QToolBar("top", parent) + , EventNode("topToolBar") + , m_loading(false) + , m_session(0) + , m_device(0) + , m_outputDevice(0) + , m_viewBackAction(0) + { + // if we don't build up front the style sheet doesn't quite work + build(); + setObjectName("topToolBar"); + } - // Policy is visible by default. - bool b = settings.value("top", true).toBool(); + void RvTopViewToolBar::makeActive(bool b) + { + if (b && !m_viewBackAction) + build(); + setVisible(b); + } - settings.endGroup(); - makeActive(b); -} + void RvTopViewToolBar::makeActiveFromSettings() + { + RV_QSETTINGS; + settings.beginGroup("ViewToolBars"); -void -RvTopViewToolBar::build() -{ - if (m_viewBackAction) return; - - QMenu* m; - QToolButton* b; - QFrame* qf; - QAction* a; - - m_iconMap["RVSourceGroup"] = colorAdjustedIcon(":/images/videofile_48x48.png"); - m_iconMap["RVImageSource"] = colorAdjustedIcon(":/images/videofile_48x48.png"); - m_iconMap["RVSwitchGroup"] = colorAdjustedIcon(":/images/shuffle_48x48.png"); - m_iconMap["RVRetimeGroup"] = colorAdjustedIcon(":/images/tempo_48x48.png"); - m_iconMap["RVLayoutGroup"] = colorAdjustedIcon(":/images/lgicn_48x48.png"); - m_iconMap["RVStackGroup"] = colorAdjustedIcon(":/images/photoalbum_48x48.png"); - m_iconMap["RVSequenceGroup"] = colorAdjustedIcon(":/images/playlist_48x48.png"); - m_iconMap["RVFolderGroup"] = colorAdjustedIcon(":/images/foldr_48x48.png"); - m_iconMap["RVFileSource"] = colorAdjustedIcon(":/images/videofile_48x48.png"); - m_iconMap[""] = colorAdjustedIcon(":/images/new_48x48.png"); - - setProperty("tbstyle", QVariant(QString("viewer"))); - - m_viewBackAction = addAction(""); - b = dynamic_cast(widgetForAction(m_viewBackAction)); - b->setIcon(QIcon(":/images/view_back.png")); - b->setProperty("tbstyle", QVariant(QString("view_menu"))); - b->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); - b->setToolTip("Switch to previous View"); - - m_viewForwardAction = addAction(""); - b = dynamic_cast(widgetForAction(m_viewForwardAction)); - b->setIcon(QIcon(":/images/view_forwd.png")); - b->setProperty("tbstyle", QVariant(QString("view_menu"))); - b->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); - b->setToolTip("Switch to next View"); - - connect(m_viewBackAction, SIGNAL(triggered(bool)), this, SLOT(previousViewNode())); - connect(m_viewForwardAction, SIGNAL(triggered(bool)), this, SLOT(nextViewNode())); - - QToolButton *viewButton = new QToolButton(this); - m_viewMenuAction = new QAction(this); - m_viewMenuAction->setToolTip("Select a View"); - viewButton->setDefaultAction(m_viewMenuAction); - viewButton->setProperty("tbstyle", QVariant(QString("view_menu"))); - viewButton->setPopupMode(QToolButton::InstantPopup); - viewButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); - - m_viewMenu = new QMenu(viewButton); - m_viewMenu->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); - m_viewMenu->setProperty("tbstyle", QVariant(QString("view_menu"))); - m_viewMenu->setStyleSheet("QMenu::item:checked { background-color: rgb(20,20,20); }"); - - viewButton->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); - viewButton->setMenu(m_viewMenu); - addWidget(viewButton); - - connect(m_viewMenu, SIGNAL(triggered(QAction*)), this, SLOT(viewMenuChanged(QAction*))); - connect(m_viewMenu, SIGNAL(aboutToShow()), this, SLOT(viewMenuUpdate())); - - m_fullScreenAction = addAction(""); - b = dynamic_cast(widgetForAction(m_fullScreenAction)); - b->setIcon(QIcon(":/images/fullscreen.png")); - b->setProperty("tbstyle", QVariant(QString("view_menu"))); - b->setToolButtonStyle(Qt::ToolButtonIconOnly); - b->setPopupMode(QToolButton::InstantPopup); - b->setToolTip("Toggle full-screen mode"); - - m_frameAction = addAction(""); - b = dynamic_cast(widgetForAction(m_frameAction)); - b->setIcon(QIcon(":/images/frame.png")); - b->setProperty("tbstyle", QVariant(QString("view_menu"))); - b->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); - b->setPopupMode(QToolButton::DelayedPopup); - b->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); - b->setToolTip("Frame image in view"); - - m = new QMenu(b); - a = m->addAction("Frame"); - a->setData(QString("extra_commands.frameImage()")); - a = m->addAction("Frame Width"); - a->setData(QString("rvui.frameWidth(nil)")); - - b->setMenu(m); - - connect(m, SIGNAL(triggered(QAction*)), this, SLOT(frameMenuChanged(QAction*))); - connect(m_frameAction, SIGNAL(triggered()), this, SLOT(frame())); - connect(m_fullScreenAction, SIGNAL(triggered()), this, SLOT(fullscreen())); - - m_bgMenuAction = addAction(""); - b = dynamic_cast(widgetForAction(m_bgMenuAction)); - b->setIcon(QIcon(":/images/checker.png")); - b->setProperty("tbstyle", QVariant(QString("view_menu"))); - b->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); - b->setPopupMode(QToolButton::InstantPopup); - b->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); - m = new QMenu(b); - m->addAction("Background")->setDisabled(true); - m_blackBGAction = m->addAction(" Black"); - m_18GreyBGAction = m->addAction(" 18% Grey"); - m_50GreyBGAction = m->addAction(" 50% Grey"); - m_whiteBGAction = m->addAction(" White"); - m_checkerBGAction = m->addAction(" Checker"); - m_crossHatchBGAction = m->addAction(" Cross Hatch"); - m->setStyleSheet("QMenu::item:checked { background-color: rgb(20,20,20); }"); - m_blackBGAction->setCheckable(true); - m_18GreyBGAction->setCheckable(true); - m_50GreyBGAction->setCheckable(true); - m_whiteBGAction->setCheckable(true); - m_checkerBGAction->setCheckable(true); - m_crossHatchBGAction->setCheckable(true); - m_blackBGAction->setIcon(QIcon(":/images/black.png")); - m_18GreyBGAction->setIcon(QIcon(":/images/grey18.png")); - m_50GreyBGAction->setIcon(QIcon(":/images/grey50.png")); - m_whiteBGAction->setIcon(QIcon(":/images/white.png")); - m_checkerBGAction->setIcon(QIcon(":/images/checker.png")); - m_crossHatchBGAction->setIcon(QIcon(":/images/cross_hatch.png")); - b->setMenu(m); - m_bgMenuAction->setToolTip("Select background style"); - - connect(m, SIGNAL(aboutToShow()), this, SLOT(bgMenuUpdate())); - connect(m_blackBGAction, SIGNAL(triggered()), this, SLOT(bgBlack())); - connect(m_18GreyBGAction, SIGNAL(triggered()), this, SLOT(bg18())); - connect(m_50GreyBGAction, SIGNAL(triggered()), this, SLOT(bg50())); - connect(m_whiteBGAction, SIGNAL(triggered()), this, SLOT(bgWhite())); - connect(m_checkerBGAction, SIGNAL(triggered()), this, SLOT(bgChecker())); - connect(m_crossHatchBGAction, SIGNAL(triggered()), this, SLOT(bgHatch())); - - m_stereoMenuAction = addAction("Mono"); - b = dynamic_cast(widgetForAction(m_stereoMenuAction)); - b->setProperty("tbstyle", QVariant(QString("view_menu"))); - b->setIcon(QIcon(":/images/stereo.png")); - b->setPopupMode(QToolButton::InstantPopup); - b->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); - m = new QMenu(b); - m->addAction("Stereo")->setDisabled(true); - m_monoStereoAction = m->addAction(" Mono"); - m_anaglyphStereoAction = m->addAction(" Anaglyph"); - m_lumanaglyphStereoAction = m->addAction(" Luminance Anaglyph"); - m_sideBySideStereoAction = m->addAction(" Side by Side"); - m_mirroredSideBySideStereoAction = m->addAction(" Mirrored"); - m_checkerStereoAction = m->addAction(" DLP Checker"); - m_scanlineStereoAction = m->addAction(" Scanline"); - m_leftStereoAction = m->addAction(" Left Only"); - m_rightStereoAction = m->addAction(" Right Only"); - m_shutterStereoAction = m->addAction(" Shutter"); - m_monoStereoAction->setCheckable(true); - m_anaglyphStereoAction->setCheckable(true); - m_lumanaglyphStereoAction->setCheckable(true); - m_sideBySideStereoAction->setCheckable(true); - m_mirroredSideBySideStereoAction->setCheckable(true); - m_checkerStereoAction->setCheckable(true); - m_scanlineStereoAction->setCheckable(true); - m_leftStereoAction->setCheckable(true); - m_rightStereoAction->setCheckable(true); - m_shutterStereoAction->setCheckable(true); - m_monoStereoAction->setData(QString("off")); - m_anaglyphStereoAction->setData(QString("anaglyph")); - m_lumanaglyphStereoAction->setData(QString("lumanaglyph")); - m_sideBySideStereoAction->setData(QString("pair")); - m_mirroredSideBySideStereoAction->setData(QString("mirror")); - m_checkerStereoAction->setData(QString("checker")); - m_scanlineStereoAction->setData(QString("scanline")); - m_leftStereoAction->setData(QString("left")); - m_rightStereoAction->setData(QString("right")); - m_shutterStereoAction->setData(QString("hardware")); - m->addSeparator(); - m_swapStereoAction = m->addAction("Swap Eyes"); - m_swapStereoAction->setCheckable(true); - b->setMenu(m); - stereoMenuUpdate(); - m_stereoMenuAction->setToolTip("Select stereoscopic output style"); - - m_stereoActions.push_back(m_monoStereoAction); - m_stereoActions.push_back(m_anaglyphStereoAction); - m_stereoActions.push_back(m_lumanaglyphStereoAction); - m_stereoActions.push_back(m_sideBySideStereoAction); - m_stereoActions.push_back(m_mirroredSideBySideStereoAction); - m_stereoActions.push_back(m_checkerStereoAction); - m_stereoActions.push_back(m_scanlineStereoAction); - m_stereoActions.push_back(m_leftStereoAction); - m_stereoActions.push_back(m_rightStereoAction); - m_stereoActions.push_back(m_shutterStereoAction); - - connect(m, SIGNAL(aboutToShow()), this, SLOT(stereoMenuUpdate())); - connect(m_monoStereoAction, SIGNAL(triggered()), this, SLOT(monoStereo())); - connect(m_anaglyphStereoAction, SIGNAL(triggered()), this, SLOT(anaglyphStereo())); - connect(m_lumanaglyphStereoAction, SIGNAL(triggered()), this, SLOT(lumanaglyphStereo())); - connect(m_sideBySideStereoAction, SIGNAL(triggered()), this, SLOT(sideBySideStereo())); - connect(m_mirroredSideBySideStereoAction, SIGNAL(triggered()), this, SLOT(mirroredStereo())); - connect(m_checkerStereoAction, SIGNAL(triggered()), this, SLOT(checkerStereo())); - connect(m_scanlineStereoAction, SIGNAL(triggered()), this, SLOT(scanlineStereo())); - connect(m_leftStereoAction, SIGNAL(triggered()), this, SLOT(leftStereo())); - connect(m_rightStereoAction, SIGNAL(triggered()), this, SLOT(rightStereo())); - connect(m_shutterStereoAction, SIGNAL(triggered()), this, SLOT(shutterStereo())); - connect(m_swapStereoAction, SIGNAL(triggered()), this, SLOT(swapEyes())); - - m_channelMenuAction = addAction("Color (RGB)"); - b = dynamic_cast(widgetForAction(m_channelMenuAction)); - b->setProperty("tbstyle", QVariant(QString("view_menu"))); - b->setIcon(QIcon(":/images/view_channel.png")); - b->setPopupMode(QToolButton::InstantPopup); - b->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); - m = new QMenu(b); - m->addAction("Channels")->setDisabled(true); - m_RGBChannelAction = m->addAction(" Color (RGB)"); - m_RChannelAction = m->addAction(" Red"); - m_GChannelAction = m->addAction(" Green"); - m_BChannelAction = m->addAction(" Blue"); - m_AChannelAction = m->addAction(" Alpha"); - m_LChannelAction = m->addAction(" Luminance"); - b->setMenu(m); - m_channelMenuAction->setToolTip("Color channel view control"); - - m_RGBChannelAction->setCheckable(true); - m_RChannelAction->setCheckable(true); - m_GChannelAction->setCheckable(true); - m_BChannelAction->setCheckable(true); - m_AChannelAction->setCheckable(true); - m_LChannelAction->setCheckable(true); - - connect(m, SIGNAL(aboutToShow()), this, SLOT(channelMenuUpdate())); - connect(m_RGBChannelAction, SIGNAL(triggered()), this, SLOT(channelsRGB())); - connect(m_RChannelAction, SIGNAL(triggered()), this, SLOT(channelsR())); - connect(m_GChannelAction, SIGNAL(triggered()), this, SLOT(channelsG())); - connect(m_BChannelAction, SIGNAL(triggered()), this, SLOT(channelsB())); - connect(m_AChannelAction, SIGNAL(triggered()), this, SLOT(channelsA())); - connect(m_LChannelAction, SIGNAL(triggered()), this, SLOT(channelsL())); - - m_monitorMenuAction = addAction("NO MONITOR"); - b = dynamic_cast(widgetForAction(m_monitorMenuAction)); - b->setProperty("tbstyle", QVariant(QString("view_menu"))); - b->setIcon(QIcon(":/images/view_display.png")); - b->setPopupMode(QToolButton::InstantPopup); - b->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); - m = new QMenu(b); - m_transferTitleAction = m->addAction("Transfer Function"); - m_transferTitleAction->setDisabled(true); - m_noTransferAction = m->addAction(" None"); - m_srgbAction = m->addAction(" sRGB"); - m_rec709Action = m->addAction(" Rec.709"); - m_g22Action = m->addAction(" Gamma 2.2"); - m_g24Action = m->addAction(" Gamma 2.4"); - m_g26Action = m->addAction(" Gamma 2.6"); - m_gOtherAction = m->addAction(" Other Gamma"); - m->addSeparator(); - m_primariesTitleAction = m->addAction("Primaries"); - m_primariesTitleAction->setDisabled(true); - m_primaries709Action = m->addAction(" Rec.709"); - m_primariesP3Action = m->addAction(" P3"); - m_primariesSMPTECAction = m->addAction(" SMPTE-C"); - m_primariesXYZAction = m->addAction(" CIE XYZ"); - m_primariesAdobeRGBAction = m->addAction(" Adobe RGB"); - m_primariesDreamColorAction = m->addAction(" DreamColor Full Gamut"); - m->addSeparator(); - m_ditherTitleAction = m->addAction("Dither"); - m_ditherTitleAction->setDisabled(true); - m_ditherOff = m->addAction(" Off"); - m_dither8 = m->addAction(" 8 Bit"); - m_dither10 = m->addAction(" 10 Bit"); - m->addSeparator(); - QWidgetAction* wa = new QWidgetAction(m); - QWidget* base = new QWidget(b); - QHBoxLayout* layout = new QHBoxLayout(base); - m_monitorInfoLabel = new QLabel(b); - m_monitorInfoLabel->setEnabled(false); - m_monitorInfoLabel->setTextFormat(Qt::RichText); - layout->addWidget(m_monitorInfoLabel); - wa->setDefaultWidget(base); - m->addAction(wa); - b->setMenu(m); - m_monitorMenu = m; - m_monitorMenuAction->setToolTip("Configure display device"); - - m_noTransferAction->setCheckable(true); - m_srgbAction->setCheckable(true); - m_rec709Action->setCheckable(true); - m_g22Action->setCheckable(true); - m_g24Action->setCheckable(true); - m_g26Action->setCheckable(true); - m_gOtherAction->setCheckable(true); - m_primaries709Action->setCheckable(true); - m_primariesP3Action->setCheckable(true); - m_primariesAdobeRGBAction->setCheckable(true); - m_primariesXYZAction->setCheckable(true); - m_primariesSMPTECAction->setCheckable(true); - m_primariesDreamColorAction->setCheckable(true); - m_ditherOff->setCheckable(true); - m_dither8->setCheckable(true); - m_dither10->setCheckable(true); - - connect(m_monitorMenu, SIGNAL(aboutToShow()), this, SLOT(monitorMenuUpdate())); - connect(m_noTransferAction, SIGNAL(triggered()), this, SLOT(transferNone())); - connect(m_srgbAction, SIGNAL(triggered()), this, SLOT(transferSRGB())); - connect(m_rec709Action, SIGNAL(triggered()), this, SLOT(transferRec709())); - connect(m_g22Action, SIGNAL(triggered()), this, SLOT(transfer22())); - connect(m_g24Action, SIGNAL(triggered()), this, SLOT(transfer24())); - connect(m_g26Action, SIGNAL(triggered()), this, SLOT(transfer26())); - connect(m_primaries709Action, SIGNAL(triggered()), this, SLOT(primaries709())); - connect(m_primariesP3Action, SIGNAL(triggered()), this, SLOT(primariesP3())); - connect(m_primariesSMPTECAction, SIGNAL(triggered()), this, SLOT(primariesSMPTEC())); - connect(m_primariesXYZAction, SIGNAL(triggered()), this, SLOT(primariesXYZ())); - connect(m_primariesAdobeRGBAction, SIGNAL(triggered()), this, SLOT(primariesAdobeRGB())); - connect(m_primariesDreamColorAction, SIGNAL(triggered()), this, SLOT(primariesDreamColor())); - connect(m_ditherOff, SIGNAL(triggered()), this, SLOT(ditherOff())); - connect(m_dither8, SIGNAL(triggered()), this, SLOT(dither8())); - connect(m_dither10, SIGNAL(triggered()), this, SLOT(dither10())); - - if (m_session) setSession(m_session); -} - -RvTopViewToolBar::~RvTopViewToolBar() -{ -} + // Policy is visible by default. + bool b = settings.value("top", true).toBool(); -void -RvTopViewToolBar::setSession(Session* s) -{ - m_session = s; + settings.endGroup(); + makeActive(b); + } - if (m_viewBackAction) + void RvTopViewToolBar::build() { - listenTo(s); - bgMenuUpdate(); + if (m_viewBackAction) + return; + + QMenu* m; + QToolButton* b; + QFrame* qf; + QAction* a; + + m_iconMap["RVSourceGroup"] = + colorAdjustedIcon(":/images/videofile_48x48.png"); + m_iconMap["RVImageSource"] = + colorAdjustedIcon(":/images/videofile_48x48.png"); + m_iconMap["RVSwitchGroup"] = + colorAdjustedIcon(":/images/shuffle_48x48.png"); + m_iconMap["RVRetimeGroup"] = + colorAdjustedIcon(":/images/tempo_48x48.png"); + m_iconMap["RVLayoutGroup"] = + colorAdjustedIcon(":/images/lgicn_48x48.png"); + m_iconMap["RVStackGroup"] = + colorAdjustedIcon(":/images/photoalbum_48x48.png"); + m_iconMap["RVSequenceGroup"] = + colorAdjustedIcon(":/images/playlist_48x48.png"); + m_iconMap["RVFolderGroup"] = + colorAdjustedIcon(":/images/foldr_48x48.png"); + m_iconMap["RVFileSource"] = + colorAdjustedIcon(":/images/videofile_48x48.png"); + m_iconMap[""] = colorAdjustedIcon(":/images/new_48x48.png"); + + setProperty("tbstyle", QVariant(QString("viewer"))); + + m_viewBackAction = addAction(""); + b = dynamic_cast(widgetForAction(m_viewBackAction)); + b->setIcon(QIcon(":/images/view_back.png")); + b->setProperty("tbstyle", QVariant(QString("view_menu"))); + b->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); + b->setToolTip("Switch to previous View"); + + m_viewForwardAction = addAction(""); + b = dynamic_cast(widgetForAction(m_viewForwardAction)); + b->setIcon(QIcon(":/images/view_forwd.png")); + b->setProperty("tbstyle", QVariant(QString("view_menu"))); + b->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); + b->setToolTip("Switch to next View"); + + connect(m_viewBackAction, SIGNAL(triggered(bool)), this, + SLOT(previousViewNode())); + connect(m_viewForwardAction, SIGNAL(triggered(bool)), this, + SLOT(nextViewNode())); + + QToolButton* viewButton = new QToolButton(this); + m_viewMenuAction = new QAction(this); + m_viewMenuAction->setToolTip("Select a View"); + viewButton->setDefaultAction(m_viewMenuAction); + viewButton->setProperty("tbstyle", QVariant(QString("view_menu"))); + viewButton->setPopupMode(QToolButton::InstantPopup); + viewButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); + + m_viewMenu = new QMenu(viewButton); + m_viewMenu->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); + m_viewMenu->setProperty("tbstyle", QVariant(QString("view_menu"))); + m_viewMenu->setStyleSheet( + "QMenu::item:checked { background-color: rgb(20,20,20); }"); + + viewButton->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); + viewButton->setMenu(m_viewMenu); + addWidget(viewButton); + + connect(m_viewMenu, SIGNAL(triggered(QAction*)), this, + SLOT(viewMenuChanged(QAction*))); + connect(m_viewMenu, SIGNAL(aboutToShow()), this, + SLOT(viewMenuUpdate())); + + m_fullScreenAction = addAction(""); + b = dynamic_cast(widgetForAction(m_fullScreenAction)); + b->setIcon(QIcon(":/images/fullscreen.png")); + b->setProperty("tbstyle", QVariant(QString("view_menu"))); + b->setToolButtonStyle(Qt::ToolButtonIconOnly); + b->setPopupMode(QToolButton::InstantPopup); + b->setToolTip("Toggle full-screen mode"); + + m_frameAction = addAction(""); + b = dynamic_cast(widgetForAction(m_frameAction)); + b->setIcon(QIcon(":/images/frame.png")); + b->setProperty("tbstyle", QVariant(QString("view_menu"))); + b->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); + b->setPopupMode(QToolButton::DelayedPopup); + b->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); + b->setToolTip("Frame image in view"); + + m = new QMenu(b); + a = m->addAction("Frame"); + a->setData(QString("extra_commands.frameImage()")); + a = m->addAction("Frame Width"); + a->setData(QString("rvui.frameWidth(nil)")); + + b->setMenu(m); + + connect(m, SIGNAL(triggered(QAction*)), this, + SLOT(frameMenuChanged(QAction*))); + connect(m_frameAction, SIGNAL(triggered()), this, SLOT(frame())); + connect(m_fullScreenAction, SIGNAL(triggered()), this, + SLOT(fullscreen())); + + m_bgMenuAction = addAction(""); + b = dynamic_cast(widgetForAction(m_bgMenuAction)); + b->setIcon(QIcon(":/images/checker.png")); + b->setProperty("tbstyle", QVariant(QString("view_menu"))); + b->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); + b->setPopupMode(QToolButton::InstantPopup); + b->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); + m = new QMenu(b); + m->addAction("Background")->setDisabled(true); + m_blackBGAction = m->addAction(" Black"); + m_18GreyBGAction = m->addAction(" 18% Grey"); + m_50GreyBGAction = m->addAction(" 50% Grey"); + m_whiteBGAction = m->addAction(" White"); + m_checkerBGAction = m->addAction(" Checker"); + m_crossHatchBGAction = m->addAction(" Cross Hatch"); + m->setStyleSheet( + "QMenu::item:checked { background-color: rgb(20,20,20); }"); + m_blackBGAction->setCheckable(true); + m_18GreyBGAction->setCheckable(true); + m_50GreyBGAction->setCheckable(true); + m_whiteBGAction->setCheckable(true); + m_checkerBGAction->setCheckable(true); + m_crossHatchBGAction->setCheckable(true); + m_blackBGAction->setIcon(QIcon(":/images/black.png")); + m_18GreyBGAction->setIcon(QIcon(":/images/grey18.png")); + m_50GreyBGAction->setIcon(QIcon(":/images/grey50.png")); + m_whiteBGAction->setIcon(QIcon(":/images/white.png")); + m_checkerBGAction->setIcon(QIcon(":/images/checker.png")); + m_crossHatchBGAction->setIcon(QIcon(":/images/cross_hatch.png")); + b->setMenu(m); + m_bgMenuAction->setToolTip("Select background style"); + + connect(m, SIGNAL(aboutToShow()), this, SLOT(bgMenuUpdate())); + connect(m_blackBGAction, SIGNAL(triggered()), this, SLOT(bgBlack())); + connect(m_18GreyBGAction, SIGNAL(triggered()), this, SLOT(bg18())); + connect(m_50GreyBGAction, SIGNAL(triggered()), this, SLOT(bg50())); + connect(m_whiteBGAction, SIGNAL(triggered()), this, SLOT(bgWhite())); + connect(m_checkerBGAction, SIGNAL(triggered()), this, + SLOT(bgChecker())); + connect(m_crossHatchBGAction, SIGNAL(triggered()), this, + SLOT(bgHatch())); + + m_stereoMenuAction = addAction("Mono"); + b = dynamic_cast(widgetForAction(m_stereoMenuAction)); + b->setProperty("tbstyle", QVariant(QString("view_menu"))); + b->setIcon(QIcon(":/images/stereo.png")); + b->setPopupMode(QToolButton::InstantPopup); + b->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); + m = new QMenu(b); + m->addAction("Stereo")->setDisabled(true); + m_monoStereoAction = m->addAction(" Mono"); + m_anaglyphStereoAction = m->addAction(" Anaglyph"); + m_lumanaglyphStereoAction = m->addAction(" Luminance Anaglyph"); + m_sideBySideStereoAction = m->addAction(" Side by Side"); + m_mirroredSideBySideStereoAction = m->addAction(" Mirrored"); + m_checkerStereoAction = m->addAction(" DLP Checker"); + m_scanlineStereoAction = m->addAction(" Scanline"); + m_leftStereoAction = m->addAction(" Left Only"); + m_rightStereoAction = m->addAction(" Right Only"); + m_shutterStereoAction = m->addAction(" Shutter"); + m_monoStereoAction->setCheckable(true); + m_anaglyphStereoAction->setCheckable(true); + m_lumanaglyphStereoAction->setCheckable(true); + m_sideBySideStereoAction->setCheckable(true); + m_mirroredSideBySideStereoAction->setCheckable(true); + m_checkerStereoAction->setCheckable(true); + m_scanlineStereoAction->setCheckable(true); + m_leftStereoAction->setCheckable(true); + m_rightStereoAction->setCheckable(true); + m_shutterStereoAction->setCheckable(true); + m_monoStereoAction->setData(QString("off")); + m_anaglyphStereoAction->setData(QString("anaglyph")); + m_lumanaglyphStereoAction->setData(QString("lumanaglyph")); + m_sideBySideStereoAction->setData(QString("pair")); + m_mirroredSideBySideStereoAction->setData(QString("mirror")); + m_checkerStereoAction->setData(QString("checker")); + m_scanlineStereoAction->setData(QString("scanline")); + m_leftStereoAction->setData(QString("left")); + m_rightStereoAction->setData(QString("right")); + m_shutterStereoAction->setData(QString("hardware")); + m->addSeparator(); + m_swapStereoAction = m->addAction("Swap Eyes"); + m_swapStereoAction->setCheckable(true); + b->setMenu(m); stereoMenuUpdate(); - channelMenuUpdate(); + m_stereoMenuAction->setToolTip("Select stereoscopic output style"); + + m_stereoActions.push_back(m_monoStereoAction); + m_stereoActions.push_back(m_anaglyphStereoAction); + m_stereoActions.push_back(m_lumanaglyphStereoAction); + m_stereoActions.push_back(m_sideBySideStereoAction); + m_stereoActions.push_back(m_mirroredSideBySideStereoAction); + m_stereoActions.push_back(m_checkerStereoAction); + m_stereoActions.push_back(m_scanlineStereoAction); + m_stereoActions.push_back(m_leftStereoAction); + m_stereoActions.push_back(m_rightStereoAction); + m_stereoActions.push_back(m_shutterStereoAction); + + connect(m, SIGNAL(aboutToShow()), this, SLOT(stereoMenuUpdate())); + connect(m_monoStereoAction, SIGNAL(triggered()), this, + SLOT(monoStereo())); + connect(m_anaglyphStereoAction, SIGNAL(triggered()), this, + SLOT(anaglyphStereo())); + connect(m_lumanaglyphStereoAction, SIGNAL(triggered()), this, + SLOT(lumanaglyphStereo())); + connect(m_sideBySideStereoAction, SIGNAL(triggered()), this, + SLOT(sideBySideStereo())); + connect(m_mirroredSideBySideStereoAction, SIGNAL(triggered()), this, + SLOT(mirroredStereo())); + connect(m_checkerStereoAction, SIGNAL(triggered()), this, + SLOT(checkerStereo())); + connect(m_scanlineStereoAction, SIGNAL(triggered()), this, + SLOT(scanlineStereo())); + connect(m_leftStereoAction, SIGNAL(triggered()), this, + SLOT(leftStereo())); + connect(m_rightStereoAction, SIGNAL(triggered()), this, + SLOT(rightStereo())); + connect(m_shutterStereoAction, SIGNAL(triggered()), this, + SLOT(shutterStereo())); + connect(m_swapStereoAction, SIGNAL(triggered()), this, + SLOT(swapEyes())); + + m_channelMenuAction = addAction("Color (RGB)"); + b = dynamic_cast(widgetForAction(m_channelMenuAction)); + b->setProperty("tbstyle", QVariant(QString("view_menu"))); + b->setIcon(QIcon(":/images/view_channel.png")); + b->setPopupMode(QToolButton::InstantPopup); + b->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); + m = new QMenu(b); + m->addAction("Channels")->setDisabled(true); + m_RGBChannelAction = m->addAction(" Color (RGB)"); + m_RChannelAction = m->addAction(" Red"); + m_GChannelAction = m->addAction(" Green"); + m_BChannelAction = m->addAction(" Blue"); + m_AChannelAction = m->addAction(" Alpha"); + m_LChannelAction = m->addAction(" Luminance"); + b->setMenu(m); + m_channelMenuAction->setToolTip("Color channel view control"); + + m_RGBChannelAction->setCheckable(true); + m_RChannelAction->setCheckable(true); + m_GChannelAction->setCheckable(true); + m_BChannelAction->setCheckable(true); + m_AChannelAction->setCheckable(true); + m_LChannelAction->setCheckable(true); + + connect(m, SIGNAL(aboutToShow()), this, SLOT(channelMenuUpdate())); + connect(m_RGBChannelAction, SIGNAL(triggered()), this, + SLOT(channelsRGB())); + connect(m_RChannelAction, SIGNAL(triggered()), this, SLOT(channelsR())); + connect(m_GChannelAction, SIGNAL(triggered()), this, SLOT(channelsG())); + connect(m_BChannelAction, SIGNAL(triggered()), this, SLOT(channelsB())); + connect(m_AChannelAction, SIGNAL(triggered()), this, SLOT(channelsA())); + connect(m_LChannelAction, SIGNAL(triggered()), this, SLOT(channelsL())); + + m_monitorMenuAction = addAction("NO MONITOR"); + b = dynamic_cast(widgetForAction(m_monitorMenuAction)); + b->setProperty("tbstyle", QVariant(QString("view_menu"))); + b->setIcon(QIcon(":/images/view_display.png")); + b->setPopupMode(QToolButton::InstantPopup); + b->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); + m = new QMenu(b); + m_transferTitleAction = m->addAction("Transfer Function"); + m_transferTitleAction->setDisabled(true); + m_noTransferAction = m->addAction(" None"); + m_srgbAction = m->addAction(" sRGB"); + m_rec709Action = m->addAction(" Rec.709"); + m_g22Action = m->addAction(" Gamma 2.2"); + m_g24Action = m->addAction(" Gamma 2.4"); + m_g26Action = m->addAction(" Gamma 2.6"); + m_gOtherAction = m->addAction(" Other Gamma"); + m->addSeparator(); + m_primariesTitleAction = m->addAction("Primaries"); + m_primariesTitleAction->setDisabled(true); + m_primaries709Action = m->addAction(" Rec.709"); + m_primariesP3Action = m->addAction(" P3"); + m_primariesSMPTECAction = m->addAction(" SMPTE-C"); + m_primariesXYZAction = m->addAction(" CIE XYZ"); + m_primariesAdobeRGBAction = m->addAction(" Adobe RGB"); + m_primariesDreamColorAction = m->addAction(" DreamColor Full Gamut"); + m->addSeparator(); + m_ditherTitleAction = m->addAction("Dither"); + m_ditherTitleAction->setDisabled(true); + m_ditherOff = m->addAction(" Off"); + m_dither8 = m->addAction(" 8 Bit"); + m_dither10 = m->addAction(" 10 Bit"); + m->addSeparator(); + QWidgetAction* wa = new QWidgetAction(m); + QWidget* base = new QWidget(b); + QHBoxLayout* layout = new QHBoxLayout(base); + m_monitorInfoLabel = new QLabel(b); + m_monitorInfoLabel->setEnabled(false); + m_monitorInfoLabel->setTextFormat(Qt::RichText); + layout->addWidget(m_monitorInfoLabel); + wa->setDefaultWidget(base); + m->addAction(wa); + b->setMenu(m); + m_monitorMenu = m; + m_monitorMenuAction->setToolTip("Configure display device"); + + m_noTransferAction->setCheckable(true); + m_srgbAction->setCheckable(true); + m_rec709Action->setCheckable(true); + m_g22Action->setCheckable(true); + m_g24Action->setCheckable(true); + m_g26Action->setCheckable(true); + m_gOtherAction->setCheckable(true); + m_primaries709Action->setCheckable(true); + m_primariesP3Action->setCheckable(true); + m_primariesAdobeRGBAction->setCheckable(true); + m_primariesXYZAction->setCheckable(true); + m_primariesSMPTECAction->setCheckable(true); + m_primariesDreamColorAction->setCheckable(true); + m_ditherOff->setCheckable(true); + m_dither8->setCheckable(true); + m_dither10->setCheckable(true); + + connect(m_monitorMenu, SIGNAL(aboutToShow()), this, + SLOT(monitorMenuUpdate())); + connect(m_noTransferAction, SIGNAL(triggered()), this, + SLOT(transferNone())); + connect(m_srgbAction, SIGNAL(triggered()), this, SLOT(transferSRGB())); + connect(m_rec709Action, SIGNAL(triggered()), this, + SLOT(transferRec709())); + connect(m_g22Action, SIGNAL(triggered()), this, SLOT(transfer22())); + connect(m_g24Action, SIGNAL(triggered()), this, SLOT(transfer24())); + connect(m_g26Action, SIGNAL(triggered()), this, SLOT(transfer26())); + connect(m_primaries709Action, SIGNAL(triggered()), this, + SLOT(primaries709())); + connect(m_primariesP3Action, SIGNAL(triggered()), this, + SLOT(primariesP3())); + connect(m_primariesSMPTECAction, SIGNAL(triggered()), this, + SLOT(primariesSMPTEC())); + connect(m_primariesXYZAction, SIGNAL(triggered()), this, + SLOT(primariesXYZ())); + connect(m_primariesAdobeRGBAction, SIGNAL(triggered()), this, + SLOT(primariesAdobeRGB())); + connect(m_primariesDreamColorAction, SIGNAL(triggered()), this, + SLOT(primariesDreamColor())); + connect(m_ditherOff, SIGNAL(triggered()), this, SLOT(ditherOff())); + connect(m_dither8, SIGNAL(triggered()), this, SLOT(dither8())); + connect(m_dither10, SIGNAL(triggered()), this, SLOT(dither10())); + + if (m_session) + setSession(m_session); } -} -void -RvTopViewToolBar::updateActionToolButton(QAction* action, - const string& text, - const string& icon, - bool forceRepaint) -{ - action->setText(text.c_str()); - QToolButton* b = dynamic_cast(widgetForAction(action)); + RvTopViewToolBar::~RvTopViewToolBar() {} - if (icon[0] == ':') + void RvTopViewToolBar::setSession(Session* s) { - b->setIcon(QIcon(icon.c_str())); + m_session = s; + + if (m_viewBackAction) + { + listenTo(s); + bgMenuUpdate(); + stereoMenuUpdate(); + channelMenuUpdate(); + } } - else + + void RvTopViewToolBar::updateActionToolButton(QAction* action, + const string& text, + const string& icon, + bool forceRepaint) { - QString iconName = ":/images/%1"; - b->setIcon(QIcon(iconName.arg(icon.c_str()))); - } - int w = b->sizeHint().width(); - if (w > b->minimumWidth()) b->setMinimumWidth(w); + action->setText(text.c_str()); + QToolButton* b = dynamic_cast(widgetForAction(action)); - if (forceRepaint) repaint(); - else update(); -} + if (icon[0] == ':') + { + b->setIcon(QIcon(icon.c_str())); + } + else + { + QString iconName = ":/images/%1"; + b->setIcon(QIcon(iconName.arg(icon.c_str()))); + } + int w = b->sizeHint().width(); + if (w > b->minimumWidth()) + b->setMinimumWidth(w); -EventNode::Result -RvTopViewToolBar::receiveEvent(const Event& event) -{ - if (const GenericStringEvent* gevent = - dynamic_cast(&event)) - { - const string& name = event.name(); - const string& contents = gevent->stringContent(); + if (forceRepaint) + repaint(); + else + update(); + } - if (name == "graph-state-change") + EventNode::Result RvTopViewToolBar::receiveEvent(const Event& event) + { + if (const GenericStringEvent* gevent = + dynamic_cast(&event)) { - vector parts; - algorithm::split(parts, contents, is_any_of(string("."))); - IPGraph::PropertyVector props; - - IPNode* node = m_session->graph().findNode(parts.front()); - m_session->graph().findProperty(m_session->currentFrame(), props, contents); - - if (!node) - { - cout << "ERROR: can't find node " << parts.front() << endl; - return EventAcceptAndContinue; - } + const string& name = event.name(); + const string& contents = gevent->stringContent(); - if (parts[2] == "type" && - parts[1] == "stereo" && - node->protocol() == "RVDisplayStereo") - { - stereoMenuUpdate(); - } - else if (node->protocol() == "RVDisplayColor") + if (name == "graph-state-change") { - if (parts[1] == "color") + vector parts; + algorithm::split(parts, contents, is_any_of(string("."))); + IPGraph::PropertyVector props; + + IPNode* node = m_session->graph().findNode(parts.front()); + m_session->graph().findProperty(m_session->currentFrame(), + props, contents); + + if (!node) { - if (parts[2] == "channelFlood") - { - channelMenuUpdate(); - } - else if (parts[2] == "sRGB" || - parts[2] == "Rec709" || - parts[2] == "gamma") + cout << "ERROR: can't find node " << parts.front() << endl; + return EventAcceptAndContinue; + } + + if (parts[2] == "type" && parts[1] == "stereo" + && node->protocol() == "RVDisplayStereo") + { + stereoMenuUpdate(); + } + else if (node->protocol() == "RVDisplayColor") + { + if (parts[1] == "color") { - //monitorMenuUpdate(); + if (parts[2] == "channelFlood") + { + channelMenuUpdate(); + } + else if (parts[2] == "sRGB" || parts[2] == "Rec709" + || parts[2] == "gamma") + { + // monitorMenuUpdate(); + } } } } - } - else if (name == "after-graph-view-change") - { - viewMenuUpdate(); - } - else if (name == "output-video-device-changed") - { - m_outputDevice = 0; - - if (contents != "") + else if (name == "after-graph-view-change") + { + viewMenuUpdate(); + } + else if (name == "output-video-device-changed") { - string::size_type p = contents.find('/'); - - if (p != string::npos) + m_outputDevice = 0; + + if (contents != "") { - const string deviceName = contents.substr(p+1); - const string moduleName = contents.substr(0, p); + string::size_type p = contents.find('/'); - for (const auto module : RvApp()->videoModules()) + if (p != string::npos) { - if (module->name() == moduleName) + const string deviceName = contents.substr(p + 1); + const string moduleName = contents.substr(0, p); + + for (const auto module : RvApp()->videoModules()) { - for (const auto device : module->devices()) + if (module->name() == moduleName) { - if (device->name() == deviceName) + for (const auto device : module->devices()) { - m_outputDevice = device; - updateActionToolButton(m_monitorMenuAction, - deviceName, - "view_display.png"); - return EventAcceptAndContinue; + if (device->name() == deviceName) + { + m_outputDevice = device; + updateActionToolButton( + m_monitorMenuAction, deviceName, + "view_display.png"); + return EventAcceptAndContinue; + } } } } } } - } - if (m_device || m_outputDevice) + if (m_device || m_outputDevice) + { + string t = m_outputDevice ? m_outputDevice->name() + : m_device->name(); + updateActionToolButton(m_monitorMenuAction, t, + "view_display.png"); + } + } + else if (name == "bg-pattern-change") { - string t = m_outputDevice ? m_outputDevice->name() : m_device->name(); - updateActionToolButton(m_monitorMenuAction, t, "view_display.png"); + bgMenuUpdate(); } } - else if (name == "bg-pattern-change") + else if (const VideoDeviceContextChangeEvent* vevent = + dynamic_cast(&event)) { - bgMenuUpdate(); - } - } - else if (const VideoDeviceContextChangeEvent* vevent = - dynamic_cast(&event)) - { - m_device = vevent->m_physicalDevice; + m_device = vevent->m_physicalDevice; - if (!m_outputDevice) - { - updateActionToolButton(m_monitorMenuAction, m_device->name(), "view_display.png"); + if (!m_outputDevice) + { + updateActionToolButton(m_monitorMenuAction, m_device->name(), + "view_display.png"); + } + + monitorMenuUpdate(); } - monitorMenuUpdate(); + return EventAcceptAndContinue; } - - return EventAcceptAndContinue; -} -void -RvTopViewToolBar::nextViewNode() -{ - string name = m_session->nextViewNode(); + void RvTopViewToolBar::nextViewNode() + { + string name = m_session->nextViewNode(); - if (!name.empty()) m_session->setViewNode(name); -} + if (!name.empty()) + m_session->setViewNode(name); + } -void -RvTopViewToolBar::previousViewNode() -{ - string name = m_session->previousViewNode(); + void RvTopViewToolBar::previousViewNode() + { + string name = m_session->previousViewNode(); - if (!name.empty()) m_session->setViewNode(name); -} + if (!name.empty()) + m_session->setViewNode(name); + } -bool -RvTopViewToolBar::isInPresentationMode() const -{ - RvApplication *rvApp = Rv::RvApp(); - if (rvApp) + bool RvTopViewToolBar::isInPresentationMode() const { - return rvApp->isInPresentationMode(); + RvApplication* rvApp = Rv::RvApp(); + if (rvApp) + { + return rvApp->isInPresentationMode(); + } + return false; } - return false; -} -void -RvTopViewToolBar::frame() -{ - m_session->userGenericEvent("remote-eval", "extra_commands.frameImage()"); -} + void RvTopViewToolBar::frame() + { + m_session->userGenericEvent("remote-eval", + "extra_commands.frameImage()"); + } -void -RvTopViewToolBar::fullscreen() -{ - m_session->userGenericEvent("remote-eval", "extra_commands.toggleFullScreen()"); -} + void RvTopViewToolBar::fullscreen() + { + m_session->userGenericEvent("remote-eval", + "extra_commands.toggleFullScreen()"); + } -void -RvTopViewToolBar::viewMenuChanged(QAction *action) -{ - if (!m_session) return; - string name = UTF8::qconvert(action->data().toString()); - m_session->setViewNode(name); -} + void RvTopViewToolBar::viewMenuChanged(QAction* action) + { + if (!m_session) + return; + string name = UTF8::qconvert(action->data().toString()); + m_session->setViewNode(name); + } -void -RvTopViewToolBar::frameMenuChanged(QAction *action) -{ - if (!m_session) return; - m_session->userGenericEvent("remote-eval", UTF8::qconvert(action->data().toString())); -} + void RvTopViewToolBar::frameMenuChanged(QAction* action) + { + if (!m_session) + return; + m_session->userGenericEvent("remote-eval", + UTF8::qconvert(action->data().toString())); + } + void RvTopViewToolBar::viewMenuUpdate() + { + if (!m_session) + return; -void -RvTopViewToolBar::viewMenuUpdate() -{ - if (!m_session) return; + m_viewMenu->clear(); + IPNode* vnode = m_session->graph().viewNode(); - m_viewMenu->clear(); - IPNode* vnode = m_session->graph().viewNode(); + const IPGraph::NodeMap& nodes = m_session->graph().viewableNodes(); - const IPGraph::NodeMap& nodes = m_session->graph().viewableNodes(); + for (IPGraph::NodeMap::const_iterator i = nodes.begin(); + i != nodes.end(); ++i) + { + IPNode* node = (*i).second; + string pname = node->protocol(); + string uiName = node->uiName(); + string nodeName = node->name(); + QString p = pname.c_str(); + QIcon icon = m_iconMap.contains(p) ? m_iconMap[p] : m_iconMap[""]; + QAction* action = + m_viewMenu->addAction(icon, UTF8::qconvert(uiName)); + + action->setData(UTF8::qconvert(nodeName)); + action->setCheckable(true); + action->setChecked(node == vnode); + + if (node == vnode) + { + m_viewMenuAction->setIcon(icon); + m_viewMenuAction->setText(UTF8::qconvert(uiName) + + QString(" ")); + update(); + } + } + } - for (IPGraph::NodeMap::const_iterator i = nodes.begin(); - i != nodes.end(); - ++i) + void RvTopViewToolBar::bgMenuUpdate() { - IPNode* node = (*i).second; - string pname = node->protocol(); - string uiName = node->uiName(); - string nodeName = node->name(); - QString p = pname.c_str(); - QIcon icon = m_iconMap.contains(p) ? m_iconMap[p] : m_iconMap[""]; - QAction* action = m_viewMenu->addAction(icon, UTF8::qconvert(uiName)); - - action->setData(UTF8::qconvert(nodeName)); - action->setCheckable(true); - action->setChecked(node == vnode); - - if (node == vnode) + try { - m_viewMenuAction->setIcon(icon); - m_viewMenuAction->setText(UTF8::qconvert(uiName) + QString(" ")); - update(); + m_blackBGAction->setEnabled(true); + m_18GreyBGAction->setEnabled(true); + m_50GreyBGAction->setEnabled(true); + m_whiteBGAction->setEnabled(true); + m_checkerBGAction->setEnabled(true); + m_crossHatchBGAction->setEnabled(true); + + bgMenuUpdate2(); + } + catch (...) + { + m_blackBGAction->setEnabled(false); + m_18GreyBGAction->setEnabled(false); + m_50GreyBGAction->setEnabled(false); + m_whiteBGAction->setEnabled(false); + m_checkerBGAction->setEnabled(false); + m_crossHatchBGAction->setEnabled(false); } } -} -void -RvTopViewToolBar::bgMenuUpdate() -{ - try + void RvTopViewToolBar::bgMenuUpdate2() { - m_blackBGAction->setEnabled(true); - m_18GreyBGAction->setEnabled(true); - m_50GreyBGAction->setEnabled(true); - m_whiteBGAction->setEnabled(true); - m_checkerBGAction->setEnabled(true); - m_crossHatchBGAction->setEnabled(true); - - bgMenuUpdate2(); + ImageRenderer::BGPattern bg = m_session->renderer()->bgPattern(); + + m_blackBGAction->setChecked(bg == ImageRenderer::Solid0); + m_18GreyBGAction->setChecked(bg == ImageRenderer::Solid18); + m_50GreyBGAction->setChecked(bg == ImageRenderer::Solid50); + m_whiteBGAction->setChecked(bg == ImageRenderer::Solid100); + m_checkerBGAction->setChecked(bg == ImageRenderer::Checker); + m_crossHatchBGAction->setChecked(bg == ImageRenderer::CrossHatch); + + const char* iconName = 0; + + switch (bg) + { + default: + case ImageRenderer::Solid0: + iconName = ":/images/black.png"; + break; + case ImageRenderer::Solid18: + iconName = ":/images/grey18.png"; + break; + case ImageRenderer::Solid50: + iconName = ":/images/grey50.png"; + break; + case ImageRenderer::Solid100: + iconName = ":/images/white.png"; + break; + case ImageRenderer::Checker: + iconName = ":/images/checker.png"; + break; + case ImageRenderer::CrossHatch: + iconName = ":/images/cross_hatch.png"; + break; + } + + m_bgMenuAction->setIcon(QIcon(iconName)); } - catch (...) + + void RvTopViewToolBar::bgBlack() { - m_blackBGAction->setEnabled(false); - m_18GreyBGAction->setEnabled(false); - m_50GreyBGAction->setEnabled(false); - m_whiteBGAction->setEnabled(false); - m_checkerBGAction->setEnabled(false); - m_crossHatchBGAction->setEnabled(false); + m_session->renderer()->setBGPattern(ImageRenderer::Solid0); + m_bgMenuAction->setIcon(QIcon(":/images/black.png")); } -} -void -RvTopViewToolBar::bgMenuUpdate2() -{ - ImageRenderer::BGPattern bg = m_session->renderer()->bgPattern(); + void RvTopViewToolBar::bg18() + { + m_session->renderer()->setBGPattern(ImageRenderer::Solid18); + m_bgMenuAction->setIcon(QIcon(":/images/grey18.png")); + } - m_blackBGAction->setChecked (bg == ImageRenderer::Solid0); - m_18GreyBGAction->setChecked (bg == ImageRenderer::Solid18); - m_50GreyBGAction->setChecked (bg == ImageRenderer::Solid50); - m_whiteBGAction->setChecked (bg == ImageRenderer::Solid100); - m_checkerBGAction->setChecked (bg == ImageRenderer::Checker); - m_crossHatchBGAction->setChecked(bg == ImageRenderer::CrossHatch); + void RvTopViewToolBar::bg50() + { + m_session->renderer()->setBGPattern(ImageRenderer::Solid50); + m_bgMenuAction->setIcon(QIcon(":/images/grey50.png")); + } - const char* iconName = 0; + void RvTopViewToolBar::bgWhite() + { + m_session->renderer()->setBGPattern(ImageRenderer::Solid100); + m_bgMenuAction->setIcon(QIcon(":/images/white.png")); + } - switch (bg) + void RvTopViewToolBar::bgChecker() { - default: - case ImageRenderer::Solid0: iconName = ":/images/black.png"; break; - case ImageRenderer::Solid18: iconName = ":/images/grey18.png"; break; - case ImageRenderer::Solid50: iconName = ":/images/grey50.png"; break; - case ImageRenderer::Solid100: iconName = ":/images/white.png"; break; - case ImageRenderer::Checker: iconName = ":/images/checker.png"; break; - case ImageRenderer::CrossHatch: iconName = ":/images/cross_hatch.png"; break; + m_session->renderer()->setBGPattern(ImageRenderer::Checker); + m_bgMenuAction->setIcon(QIcon(":/images/checker.png")); } - m_bgMenuAction->setIcon(QIcon(iconName)); -} + void RvTopViewToolBar::bgHatch() + { + m_session->renderer()->setBGPattern(ImageRenderer::CrossHatch); + m_bgMenuAction->setIcon(QIcon(":/images/cross_hatch.png")); + } -void -RvTopViewToolBar::bgBlack() -{ - m_session->renderer()->setBGPattern(ImageRenderer::Solid0); - m_bgMenuAction->setIcon(QIcon(":/images/black.png")); -} + void RvTopViewToolBar::stereoMenuUpdate() + { + m_stereoMenuAction->setText( + "DLP CHECKER"); // just a measurement string + QToolButton* b = + dynamic_cast(widgetForAction(m_stereoMenuAction)); + b->setIcon(QIcon(":/images/stereo.png")); + int w = b->sizeHint().width(); + b->setMinimumWidth(w); -void -RvTopViewToolBar::bg18() -{ - m_session->renderer()->setBGPattern(ImageRenderer::Solid18); - m_bgMenuAction->setIcon(QIcon(":/images/grey18.png")); -} + if (!m_session) + { + m_stereoMenuAction->setText("Mono"); + QToolButton* b = + dynamic_cast(widgetForAction(m_stereoMenuAction)); + b->setIcon(QIcon(":/images/stereo.png")); + return; + } -void -RvTopViewToolBar::bg50() -{ - m_session->renderer()->setBGPattern(ImageRenderer::Solid50); - m_bgMenuAction->setIcon(QIcon(":/images/grey50.png")); -} + StringPropertyEditor editor(m_session->graph(), + m_session->currentFrame(), + "@RVDisplayStereo.stereo.type"); -void -RvTopViewToolBar::bgWhite() -{ - m_session->renderer()->setBGPattern(ImageRenderer::Solid100); - m_bgMenuAction->setIcon(QIcon(":/images/white.png")); -} + string type = editor.value(); + if (type == "mono") + type = "off"; + QString t = type.c_str(); -void -RvTopViewToolBar::bgChecker() -{ - m_session->renderer()->setBGPattern(ImageRenderer::Checker); - m_bgMenuAction->setIcon(QIcon(":/images/checker.png")); -} + for (size_t i = 0; i < m_stereoActions.size(); i++) + { + QAction* a = m_stereoActions[i]; + bool checked = a->data().toString() == t; + a->setChecked(checked); -void -RvTopViewToolBar::bgHatch() -{ - m_session->renderer()->setBGPattern(ImageRenderer::CrossHatch); - m_bgMenuAction->setIcon(QIcon(":/images/cross_hatch.png")); -} + if (checked) + { + m_stereoMenuAction->setText(a->text()); + QToolButton* b = dynamic_cast( + widgetForAction(m_stereoMenuAction)); + b->setIcon(QIcon(":/images/stereo.png")); + } + } -void -RvTopViewToolBar::stereoMenuUpdate() -{ - m_stereoMenuAction->setText("DLP CHECKER"); // just a measurement string - QToolButton* b = dynamic_cast(widgetForAction(m_stereoMenuAction)); - b->setIcon(QIcon(":/images/stereo.png")); - int w = b->sizeHint().width(); - b->setMinimumWidth(w); + if ((type != "off") || isInPresentationMode()) + { + // Update the menu entry for Global Swap Eyes + // according to the property value. + IntPropertyEditor globalSwapEyes(m_session->graph(), + m_session->currentFrame(), + "@RVDisplayStereo.stereo.swap"); + m_swapStereoAction->setEnabled(true); + m_swapStereoAction->setChecked(globalSwapEyes.value() ? true + : false); + } + else + { + // If not in stereo/presentation mode gray out/disable the Global + // Swap entry. + m_swapStereoAction->setEnabled(false); + } + } - if (!m_session) + void RvTopViewToolBar::setStereo(const string& type) { - m_stereoMenuAction->setText("Mono"); - QToolButton* b = dynamic_cast(widgetForAction(m_stereoMenuAction)); - b->setIcon(QIcon(":/images/stereo.png")); - return; - } + Session::CachingMode m = m_session->cachingMode(); - StringPropertyEditor editor(m_session->graph(), - m_session->currentFrame(), - "@RVDisplayStereo.stereo.type"); + StringPropertyEditor editor(m_session->graph(), + m_session->currentFrame(), + "@RVDisplayStereo.stereo.type"); - string type = editor.value(); - if (type == "mono") type = "off"; - QString t = type.c_str(); + string oldType = editor.value(); + bool kickCache = (oldType == "off" && type != "off") + || (oldType != "off" && type == "off"); - for (size_t i = 0; i < m_stereoActions.size(); i++) - { - QAction* a = m_stereoActions[i]; - bool checked = a->data().toString() == t; - a->setChecked(checked); - - if (checked) + if (kickCache) + m_session->setCaching(Session::NeverCache); + + editor.setValue(type); + + if (oldType != "hardware" && type == "hardware") { - m_stereoMenuAction->setText(a->text()); - QToolButton* b = dynamic_cast(widgetForAction(m_stereoMenuAction)); - b->setIcon(QIcon(":/images/stereo.png")); + m_session->send(Session::stereoHardwareOnMessage()); + } + else if (oldType == "hardware" && type != "hardware") + { + m_session->send(Session::stereoHardwareOffMessage()); } - } - if ((type != "off") || isInPresentationMode() ) - { - // Update the menu entry for Global Swap Eyes - // according to the property value. - IntPropertyEditor globalSwapEyes(m_session->graph(), - m_session->currentFrame(), - "@RVDisplayStereo.stereo.swap"); - m_swapStereoAction->setEnabled(true); - m_swapStereoAction->setChecked(globalSwapEyes.value()?true:false); + if (kickCache) + m_session->setCaching(m); } - else + + void RvTopViewToolBar::setChannel(int c) { - // If not in stereo/presentation mode gray out/disable the Global Swap - // entry. - m_swapStereoAction->setEnabled(false); + IntPropertyEditor editor(m_session->graph(), m_session->currentFrame(), + "@RVDisplayColor.color.channelFlood"); + + editor.setValue(c); } -} -void -RvTopViewToolBar::setStereo(const string& type) -{ - Session::CachingMode m = m_session->cachingMode(); + void RvTopViewToolBar::monoStereo() { setStereo("off"); } - StringPropertyEditor editor(m_session->graph(), - m_session->currentFrame(), - "@RVDisplayStereo.stereo.type"); + void RvTopViewToolBar::anaglyphStereo() { setStereo("anaglyph"); } - string oldType = editor.value(); - bool kickCache = (oldType == "off" && type != "off") || - (oldType != "off" && type == "off"); + void RvTopViewToolBar::lumanaglyphStereo() { setStereo("lumanaglyph"); } - if (kickCache) m_session->setCaching(Session::NeverCache); + void RvTopViewToolBar::sideBySideStereo() { setStereo("pair"); } - editor.setValue(type); + void RvTopViewToolBar::mirroredStereo() { setStereo("mirror"); } - if (oldType != "hardware" && type == "hardware") - { - m_session->send(Session::stereoHardwareOnMessage()); - } - else - if (oldType == "hardware" && type != "hardware") + void RvTopViewToolBar::checkerStereo() { setStereo("checker"); } + + void RvTopViewToolBar::scanlineStereo() { setStereo("scanline"); } + + void RvTopViewToolBar::leftStereo() { setStereo("left"); } + + void RvTopViewToolBar::rightStereo() { setStereo("right"); } + + void RvTopViewToolBar::shutterStereo() { setStereo("hardware"); } + + void RvTopViewToolBar::swapEyes() { - m_session->send(Session::stereoHardwareOffMessage()); + IntPropertyEditor editor(m_session->graph(), m_session->currentFrame(), + "@RVDisplayStereo.stereo.swap"); + editor.setValue(editor.value() == 0); } - if (kickCache) m_session->setCaching(m); -} + void RvTopViewToolBar::channelMenuUpdate() + { + m_channelMenuAction->setText("MMMMMMMM"); // just a measurement string + QToolButton* b = + dynamic_cast(widgetForAction(m_channelMenuAction)); + b->setIcon(QIcon(":/images/view_channel.png")); + int w = b->sizeHint().width(); + b->setMinimumWidth(w); -void -RvTopViewToolBar::setChannel(int c) -{ - IntPropertyEditor editor(m_session->graph(), - m_session->currentFrame(), - "@RVDisplayColor.color.channelFlood"); - - editor.setValue(c); -} - -void RvTopViewToolBar::monoStereo() { setStereo("off"); } -void RvTopViewToolBar::anaglyphStereo() { setStereo("anaglyph"); } -void RvTopViewToolBar::lumanaglyphStereo() { setStereo("lumanaglyph"); } -void RvTopViewToolBar::sideBySideStereo() { setStereo("pair"); } -void RvTopViewToolBar::mirroredStereo() { setStereo("mirror"); } -void RvTopViewToolBar::checkerStereo() { setStereo("checker"); } -void RvTopViewToolBar::scanlineStereo() { setStereo("scanline"); } -void RvTopViewToolBar::leftStereo() { setStereo("left"); } -void RvTopViewToolBar::rightStereo() { setStereo("right"); } -void RvTopViewToolBar::shutterStereo() { setStereo("hardware"); } - -void -RvTopViewToolBar::swapEyes() -{ - IntPropertyEditor editor(m_session->graph(), - m_session->currentFrame(), - "@RVDisplayStereo.stereo.swap"); - editor.setValue(editor.value() == 0); -} - -void -RvTopViewToolBar::channelMenuUpdate() -{ - m_channelMenuAction->setText("MMMMMMMM"); // just a measurement string - QToolButton* b = dynamic_cast(widgetForAction(m_channelMenuAction)); - b->setIcon(QIcon(":/images/view_channel.png")); - int w = b->sizeHint().width(); - b->setMinimumWidth(w); + if (!m_session) + return; - if (!m_session) return; + if (hasStandardDisplayPipeline()) + { - if (hasStandardDisplayPipeline()) - { + IntPropertyEditor editor(m_session->graph(), + m_session->currentFrame(), + "@RVDisplayColor.color.channelFlood"); + + m_RGBChannelAction->setVisible(true); + m_RChannelAction->setVisible(true); + m_GChannelAction->setVisible(true); + m_BChannelAction->setVisible(true); + m_AChannelAction->setVisible(true); + m_LChannelAction->setVisible(true); + + m_RGBChannelAction->setEnabled(true); + m_RChannelAction->setEnabled(true); + m_GChannelAction->setEnabled(true); + m_BChannelAction->setEnabled(true); + m_AChannelAction->setEnabled(true); + m_LChannelAction->setEnabled(true); + + m_RGBChannelAction->setChecked(false); + m_RChannelAction->setChecked(false); + m_GChannelAction->setChecked(false); + m_BChannelAction->setChecked(false); + m_AChannelAction->setChecked(false); + m_LChannelAction->setChecked(false); + + QAction* a = 0; + + switch (editor.value()) + { + default: + case 0: + a = m_RGBChannelAction; + break; + case 1: + a = m_RChannelAction; + break; + case 2: + a = m_GChannelAction; + break; + case 3: + a = m_BChannelAction; + break; + case 4: + a = m_AChannelAction; + break; + case 5: + a = m_LChannelAction; + break; + } - IntPropertyEditor editor(m_session->graph(), - m_session->currentFrame(), - "@RVDisplayColor.color.channelFlood"); + a->setChecked(true); - m_RGBChannelAction->setVisible(true); - m_RChannelAction->setVisible(true); - m_GChannelAction->setVisible(true); - m_BChannelAction->setVisible(true); - m_AChannelAction->setVisible(true); - m_LChannelAction->setVisible(true); - - m_RGBChannelAction->setEnabled(true); - m_RChannelAction->setEnabled(true); - m_GChannelAction->setEnabled(true); - m_BChannelAction->setEnabled(true); - m_AChannelAction->setEnabled(true); - m_LChannelAction->setEnabled(true); - - m_RGBChannelAction->setChecked(false); - m_RChannelAction->setChecked(false); - m_GChannelAction->setChecked(false); - m_BChannelAction->setChecked(false); - m_AChannelAction->setChecked(false); - m_LChannelAction->setChecked(false); - - QAction *a = 0; - - switch (editor.value()) + m_channelMenuAction->setText(a->text()); + b = dynamic_cast( + widgetForAction(m_channelMenuAction)); + b->setIcon(QIcon(":/images/view_channel.png")); + } + else { - default: - case 0: a = m_RGBChannelAction; break; - case 1: a = m_RChannelAction; break; - case 2: a = m_GChannelAction; break; - case 3: a = m_BChannelAction; break; - case 4: a = m_AChannelAction; break; - case 5: a = m_LChannelAction; break; + m_RGBChannelAction->setEnabled(false); + m_RChannelAction->setEnabled(false); + m_GChannelAction->setEnabled(false); + m_BChannelAction->setEnabled(false); + m_AChannelAction->setEnabled(false); + m_LChannelAction->setEnabled(false); + + m_RGBChannelAction->setVisible(false); + m_RChannelAction->setVisible(false); + m_GChannelAction->setVisible(false); + m_BChannelAction->setVisible(false); + m_AChannelAction->setVisible(false); + m_LChannelAction->setVisible(false); + + m_channelMenuAction->setText(m_RGBChannelAction->text()); + b = dynamic_cast( + widgetForAction(m_channelMenuAction)); + b->setIcon(QIcon(":/images/view_channel.png")); } + } - a->setChecked(true); + void RvTopViewToolBar::channelsRGB() { setChannel(0); } - m_channelMenuAction->setText(a->text()); - b = dynamic_cast(widgetForAction(m_channelMenuAction)); - b->setIcon(QIcon(":/images/view_channel.png")); - } - else - { - m_RGBChannelAction->setEnabled(false); - m_RChannelAction->setEnabled(false); - m_GChannelAction->setEnabled(false); - m_BChannelAction->setEnabled(false); - m_AChannelAction->setEnabled(false); - m_LChannelAction->setEnabled(false); - - m_RGBChannelAction->setVisible(false); - m_RChannelAction->setVisible(false); - m_GChannelAction->setVisible(false); - m_BChannelAction->setVisible(false); - m_AChannelAction->setVisible(false); - m_LChannelAction->setVisible(false); - - m_channelMenuAction->setText(m_RGBChannelAction->text()); - b = dynamic_cast(widgetForAction(m_channelMenuAction)); - b->setIcon(QIcon(":/images/view_channel.png")); - } -} + void RvTopViewToolBar::channelsR() { setChannel(1); } -void RvTopViewToolBar::channelsRGB() { setChannel(0); } -void RvTopViewToolBar::channelsR() { setChannel(1); } -void RvTopViewToolBar::channelsG() { setChannel(2); } -void RvTopViewToolBar::channelsB() { setChannel(3); } -void RvTopViewToolBar::channelsA() { setChannel(4); } -void RvTopViewToolBar::channelsL() { setChannel(5); } + void RvTopViewToolBar::channelsG() { setChannel(2); } -bool -RvTopViewToolBar::hasStandardDisplayPipeline() -{ - if (!m_session) return false; + void RvTopViewToolBar::channelsB() { setChannel(3); } + + void RvTopViewToolBar::channelsA() { setChannel(4); } - StringPropertyEditor displayPipeline(m_session->graph(), - m_session->currentFrame(), - "@RVDisplayPipelineGroup.pipeline.nodes"); + void RvTopViewToolBar::channelsL() { setChannel(5); } - const StringPropertyEditor::ContainerType& pipelineNodes = displayPipeline.container(); - bool hasDisplay = false; - - for (size_t i = 0; i < pipelineNodes.size(); i++) + bool RvTopViewToolBar::hasStandardDisplayPipeline() { - if (pipelineNodes[i] == "RVDisplayColor") return true; - } + if (!m_session) + return false; - return false; -} + StringPropertyEditor displayPipeline( + m_session->graph(), m_session->currentFrame(), + "@RVDisplayPipelineGroup.pipeline.nodes"); -void -RvTopViewToolBar::monitorMenuUpdate() -{ - updateActionToolButton(m_monitorMenuAction, "MMMMMMMMMMMMM", "view_display.png"); - if (!m_device) return; + const StringPropertyEditor::ContainerType& pipelineNodes = + displayPipeline.container(); + bool hasDisplay = false; - string name = m_outputDevice ? m_outputDevice->name() : m_device->name(); - updateActionToolButton(m_monitorMenuAction, name, "view_display.png"); + for (size_t i = 0; i < pipelineNodes.size(); i++) + { + if (pipelineNodes[i] == "RVDisplayColor") + return true; + } - bool hasDisplay = hasStandardDisplayPipeline(); + return false; + } - try + void RvTopViewToolBar::monitorMenuUpdate() { + updateActionToolButton(m_monitorMenuAction, "MMMMMMMMMMMMM", + "view_display.png"); + if (!m_device) + return; + + string name = + m_outputDevice ? m_outputDevice->name() : m_device->name(); + updateActionToolButton(m_monitorMenuAction, name, "view_display.png"); - m_noTransferAction->setEnabled(hasDisplay); - m_srgbAction->setEnabled(hasDisplay); - m_rec709Action->setEnabled(hasDisplay); - m_g22Action->setEnabled(hasDisplay); - m_g24Action->setEnabled(hasDisplay); - m_g26Action->setEnabled(hasDisplay); - m_gOtherAction->setEnabled(hasDisplay); - m_primaries709Action->setEnabled(hasDisplay); - m_primariesP3Action->setEnabled(hasDisplay); - m_primariesSMPTECAction->setEnabled(hasDisplay); - m_primariesXYZAction->setEnabled(hasDisplay); - m_primariesAdobeRGBAction->setEnabled(hasDisplay); - m_primariesDreamColorAction->setEnabled(hasDisplay); - m_ditherOff->setEnabled(hasDisplay); - m_dither8->setEnabled(hasDisplay); - m_dither10->setEnabled(hasDisplay); - - m_transferTitleAction->setVisible(hasDisplay); - m_primariesTitleAction->setVisible(hasDisplay); - m_ditherTitleAction->setVisible(hasDisplay); - - m_noTransferAction->setVisible(hasDisplay); - m_srgbAction->setVisible(hasDisplay); - m_rec709Action->setVisible(hasDisplay); - m_g22Action->setVisible(hasDisplay); - m_g24Action->setVisible(hasDisplay); - m_g26Action->setVisible(hasDisplay); - m_gOtherAction->setVisible(hasDisplay); - m_primaries709Action->setVisible(hasDisplay); - m_primariesP3Action->setVisible(hasDisplay); - m_primariesSMPTECAction->setVisible(hasDisplay); - m_primariesXYZAction->setVisible(hasDisplay); - m_primariesAdobeRGBAction->setVisible(hasDisplay); - m_primariesDreamColorAction->setVisible(hasDisplay); - m_ditherOff->setVisible(hasDisplay); - m_dither8->setVisible(hasDisplay); - m_dither10->setVisible(hasDisplay); - - if (hasDisplay) + bool hasDisplay = hasStandardDisplayPipeline(); + + try { - try + + m_noTransferAction->setEnabled(hasDisplay); + m_srgbAction->setEnabled(hasDisplay); + m_rec709Action->setEnabled(hasDisplay); + m_g22Action->setEnabled(hasDisplay); + m_g24Action->setEnabled(hasDisplay); + m_g26Action->setEnabled(hasDisplay); + m_gOtherAction->setEnabled(hasDisplay); + m_primaries709Action->setEnabled(hasDisplay); + m_primariesP3Action->setEnabled(hasDisplay); + m_primariesSMPTECAction->setEnabled(hasDisplay); + m_primariesXYZAction->setEnabled(hasDisplay); + m_primariesAdobeRGBAction->setEnabled(hasDisplay); + m_primariesDreamColorAction->setEnabled(hasDisplay); + m_ditherOff->setEnabled(hasDisplay); + m_dither8->setEnabled(hasDisplay); + m_dither10->setEnabled(hasDisplay); + + m_transferTitleAction->setVisible(hasDisplay); + m_primariesTitleAction->setVisible(hasDisplay); + m_ditherTitleAction->setVisible(hasDisplay); + + m_noTransferAction->setVisible(hasDisplay); + m_srgbAction->setVisible(hasDisplay); + m_rec709Action->setVisible(hasDisplay); + m_g22Action->setVisible(hasDisplay); + m_g24Action->setVisible(hasDisplay); + m_g26Action->setVisible(hasDisplay); + m_gOtherAction->setVisible(hasDisplay); + m_primaries709Action->setVisible(hasDisplay); + m_primariesP3Action->setVisible(hasDisplay); + m_primariesSMPTECAction->setVisible(hasDisplay); + m_primariesXYZAction->setVisible(hasDisplay); + m_primariesAdobeRGBAction->setVisible(hasDisplay); + m_primariesDreamColorAction->setVisible(hasDisplay); + m_ditherOff->setVisible(hasDisplay); + m_dither8->setVisible(hasDisplay); + m_dither10->setVisible(hasDisplay); + + if (hasDisplay) { - monitorMenuRVUpdate(); + try + { + monitorMenuRVUpdate(); + } + catch (...) + { + } } - catch (...) + else { } } - else + catch (...) { } - } - catch (...) - { - } - // - // Display Info - // + // + // Display Info + // - QString html = ""; + QString html = + "
"; - for (const auto module : RvApp()->videoModules()) - { - for (const auto device : module->devices()) + for (const auto module : RvApp()->videoModules()) { - VideoDevice::VideoFormat format = device->videoFormatAtIndex(device->currentVideoFormat()); - VideoDevice::DataFormat data = device->dataFormatAtIndex(device->currentDataFormat()); + for (const auto device : module->devices()) + { + VideoDevice::VideoFormat format = + device->videoFormatAtIndex(device->currentVideoFormat()); + VideoDevice::DataFormat data = + device->dataFormatAtIndex(device->currentDataFormat()); - QString icon; + QString icon; - if (dynamic_cast(device)) - { - icon = ""; - } - else - { - icon = " "; - } - - string mname = module->name(); // windows - string dname = device->name(); - QString name; + if (dynamic_cast(device)) + { + icon = ""; + } + else + { + icon = " "; + } - if (mname != "Desktop") - { - name += mname.c_str(); - name += " / "; - } + string mname = module->name(); // windows + string dname = device->name(); + QString name; - name += dname.c_str(); + if (mname != "Desktop") + { + name += mname.c_str(); + name += " / "; + } - QString mon; + name += dname.c_str(); - if (format.width > 0 && format.height > 0) - { - mon = QString("" - "" - "" + "" + "" + "" + ""; + + html += mon; } - else - { - mon = QString("" - "" - ""; - - html += mon; } + + html += "
%6%1
%2 x %3 @ %4Hz
%5
") - .arg(name) - .arg(format.width) - .arg(format.height) - .arg(format.hz) - .arg(data.description.c_str()) - .arg(icon); + QString mon; + + if (format.width > 0 && format.height > 0) + { + mon = QString("
%6%1
%2 x %3 @ " + "%4Hz
%5
") + .arg(name) + .arg(format.width) + .arg(format.height) + .arg(format.hz) + .arg(data.description.c_str()) + .arg(icon); + } + else + { + mon = QString("
%1%2") + .arg(icon) + .arg(name); + } + + mon += "
%1%2") - .arg(icon) - .arg(name); - } - - mon += "
"; + m_monitorInfoLabel->setText(html); + m_monitorInfoLabel->setTextFormat(Qt::RichText); + + m_monitorMenu->update(); } - html += ""; - m_monitorInfoLabel->setText(html); - m_monitorInfoLabel->setTextFormat(Qt::RichText); + void RvTopViewToolBar::monitorMenuOCIOUpdate() {} - m_monitorMenu->update(); -} + void RvTopViewToolBar::monitorMenuRVUpdate() + { + IntPropertyEditor srgb(m_session->graph(), m_session->currentFrame(), + "@RVDisplayColor.color.sRGB"); -void -RvTopViewToolBar::monitorMenuOCIOUpdate() -{ -} + IntPropertyEditor rec709(m_session->graph(), m_session->currentFrame(), + "@RVDisplayColor.color.Rec709"); -void -RvTopViewToolBar::monitorMenuRVUpdate() -{ - IntPropertyEditor srgb(m_session->graph(), - m_session->currentFrame(), - "@RVDisplayColor.color.sRGB"); + FloatPropertyEditor gamma(m_session->graph(), m_session->currentFrame(), + "@RVDisplayColor.color.gamma"); - IntPropertyEditor rec709(m_session->graph(), - m_session->currentFrame(), - "@RVDisplayColor.color.Rec709"); + Vec2fPropertyEditor white(m_session->graph(), m_session->currentFrame(), + "@RVDisplayColor.chromaticities.white"); - FloatPropertyEditor gamma(m_session->graph(), - m_session->currentFrame(), - "@RVDisplayColor.color.gamma"); + Vec2fPropertyEditor red(m_session->graph(), m_session->currentFrame(), + "@RVDisplayColor.chromaticities.red"); - Vec2fPropertyEditor white(m_session->graph(), - m_session->currentFrame(), - "@RVDisplayColor.chromaticities.white"); + Vec2fPropertyEditor green(m_session->graph(), m_session->currentFrame(), + "@RVDisplayColor.chromaticities.green"); - Vec2fPropertyEditor red(m_session->graph(), - m_session->currentFrame(), - "@RVDisplayColor.chromaticities.red"); + Vec2fPropertyEditor blue(m_session->graph(), m_session->currentFrame(), + "@RVDisplayColor.chromaticities.blue"); - Vec2fPropertyEditor green(m_session->graph(), - m_session->currentFrame(), - "@RVDisplayColor.chromaticities.green"); + Vec2fPropertyEditor neutral(m_session->graph(), + m_session->currentFrame(), + "@RVDisplayColor.chromaticities.neutral"); - Vec2fPropertyEditor blue(m_session->graph(), - m_session->currentFrame(), - "@RVDisplayColor.chromaticities.blue"); + IntPropertyEditor active(m_session->graph(), m_session->currentFrame(), + "@RVDisplayColor.chromaticities.active"); - Vec2fPropertyEditor neutral(m_session->graph(), - m_session->currentFrame(), - "@RVDisplayColor.chromaticities.neutral"); + IntPropertyEditor adoptedNeutral( + m_session->graph(), m_session->currentFrame(), + "@RVDisplayColor.chromaticities.adoptedNeutral"); - IntPropertyEditor active(m_session->graph(), - m_session->currentFrame(), - "@RVDisplayColor.chromaticities.active"); + IntPropertyEditor dither(m_session->graph(), m_session->currentFrame(), + "@RVDisplayColor.color.dither"); - IntPropertyEditor adoptedNeutral(m_session->graph(), - m_session->currentFrame(), - "@RVDisplayColor.chromaticities.adoptedNeutral"); + m_noTransferAction->setChecked(false); + m_srgbAction->setChecked(false); + m_rec709Action->setChecked(false); + m_g22Action->setChecked(false); + m_g24Action->setChecked(false); + m_g26Action->setChecked(false); + m_gOtherAction->setChecked(false); + m_gOtherAction->setVisible(false); + m_gOtherAction->setText(" Other Gamma"); - IntPropertyEditor dither(m_session->graph(), - m_session->currentFrame(), - "@RVDisplayColor.color.dither"); + bool none = true; + if (srgb.value() == 1) + { + m_srgbAction->setChecked(true); + none = false; + }; + if (rec709.value() == 1) + { + m_rec709Action->setChecked(true); + none = false; + } + if (gamma.value() != 1.0f) + { + float y = gamma.value(); - m_noTransferAction->setChecked(false); - m_srgbAction->setChecked(false); - m_rec709Action->setChecked(false); - m_g22Action->setChecked(false); - m_g24Action->setChecked(false); - m_g26Action->setChecked(false); - m_gOtherAction->setChecked(false); - m_gOtherAction->setVisible(false); - m_gOtherAction->setText(" Other Gamma"); + if (y == 2.2f) + { + m_g22Action->setChecked(true); + } + else if (y == 2.4f) + { + m_g24Action->setChecked(true); + } + else if (y == 2.6f) + { + m_g26Action->setChecked(true); + } + else + { + m_gOtherAction->setChecked(true); + m_gOtherAction->setVisible(true); + m_gOtherAction->setText(QString(" Other Gamma (%1)").arg(y)); + // do something here + } - bool none = true; - if (srgb.value() == 1) { m_srgbAction->setChecked(true); none = false; }; - if (rec709.value() == 1) { m_rec709Action->setChecked(true); none = false; } + none = false; + } - if (gamma.value() != 1.0f) - { - float y = gamma.value(); + if (none) + { + m_noTransferAction->setChecked(true); + } + + // + // Primaries + // + + Chromaticities currentChr(red.value(), green.value(), + blue.value(), white.value()); - if (y == 2.2f) + m_primaries709Action->setChecked(false); + m_primariesP3Action->setChecked(false); + m_primariesAdobeRGBAction->setChecked(false); + m_primariesXYZAction->setChecked(false); + m_primariesSMPTECAction->setChecked(false); + m_primariesDreamColorAction->setChecked(false); + + if (currentChr == Chromaticities::Rec709()) { - m_g22Action->setChecked(true); + m_primaries709Action->setChecked(true); } - else if (y == 2.4f) + else if (currentChr == Chromaticities::P3()) { - m_g24Action->setChecked(true); + m_primariesP3Action->setChecked(true); } - else if (y == 2.6f) + else if (currentChr == Chromaticities::AdobeRGB()) { - m_g26Action->setChecked(true); + m_primariesAdobeRGBAction->setChecked(true); } - else + else if (currentChr == Chromaticities::XYZ()) { - m_gOtherAction->setChecked(true); - m_gOtherAction->setVisible(true); - m_gOtherAction->setText(QString(" Other Gamma (%1)").arg(y)); - // do something here + m_primariesXYZAction->setChecked(true); + } + else if (currentChr == Chromaticities::SMPTE_C()) + { + m_primariesSMPTECAction->setChecked(true); + } + else if (currentChr == Chromaticities::DreamcolorFull()) + { + m_primariesDreamColorAction->setChecked(true); } - none = false; + m_ditherOff->setChecked(dither.value() == 0); + m_dither8->setChecked(dither.value() == 8); + m_dither10->setChecked(dither.value() == 10); } - if (none) + void RvTopViewToolBar::setTransferFunction(const string& name, float value) { - m_noTransferAction->setChecked(true); - } - - // - // Primaries - // + IntPropertyEditor srgb(m_session->graph(), m_session->currentFrame(), + "@RVDisplayColor.color.sRGB"); - Chromaticities currentChr(red.value(), - green.value(), - blue.value(), - white.value()); + IntPropertyEditor rec709(m_session->graph(), m_session->currentFrame(), + "@RVDisplayColor.color.Rec709"); - m_primaries709Action->setChecked(false); - m_primariesP3Action->setChecked(false); - m_primariesAdobeRGBAction->setChecked(false); - m_primariesXYZAction->setChecked(false); - m_primariesSMPTECAction->setChecked(false); - m_primariesDreamColorAction->setChecked(false); + FloatPropertyEditor gamma(m_session->graph(), m_session->currentFrame(), + "@RVDisplayColor.color.gamma"); - if (currentChr == Chromaticities::Rec709()) - { - m_primaries709Action->setChecked(true); - } - else if (currentChr == Chromaticities::P3()) - { - m_primariesP3Action->setChecked(true); - } - else if (currentChr == Chromaticities::AdobeRGB()) - { - m_primariesAdobeRGBAction->setChecked(true); - } - else if (currentChr == Chromaticities::XYZ()) - { - m_primariesXYZAction->setChecked(true); - } - else if (currentChr == Chromaticities::SMPTE_C()) - { - m_primariesSMPTECAction->setChecked(true); - } - else if (currentChr == Chromaticities::DreamcolorFull()) - { - m_primariesDreamColorAction->setChecked(true); + if (name == "srgb") + { + rec709.setValue(0); + srgb.setValue(1); + gamma.setValue(1.0); + } + else if (name == "rec709") + { + rec709.setValue(1); + srgb.setValue(0); + gamma.setValue(1.0); + } + else if (name == "gamma") + { + rec709.setValue(0); + srgb.setValue(0); + gamma.setValue(value); + } + else if (name == "none") + { + rec709.setValue(0); + srgb.setValue(0); + gamma.setValue(1.0); + } } - m_ditherOff->setChecked(dither.value() == 0); - m_dither8->setChecked(dither.value() == 8); - m_dither10->setChecked(dither.value() == 10); -} - -void -RvTopViewToolBar::setTransferFunction(const string& name, float value) -{ - IntPropertyEditor srgb(m_session->graph(), - m_session->currentFrame(), - "@RVDisplayColor.color.sRGB"); - - IntPropertyEditor rec709(m_session->graph(), - m_session->currentFrame(), - "@RVDisplayColor.color.Rec709"); - - FloatPropertyEditor gamma(m_session->graph(), - m_session->currentFrame(), - "@RVDisplayColor.color.gamma"); - - if (name == "srgb") - { - rec709.setValue(0); - srgb.setValue(1); - gamma.setValue(1.0); - } - else if (name == "rec709") + void RvTopViewToolBar::setPrimaries(const Chromaticities& chr) { - rec709.setValue(1); - srgb.setValue(0); - gamma.setValue(1.0); - } - else if (name == "gamma") - { - rec709.setValue(0); - srgb.setValue(0); - gamma.setValue(value); - } - else if (name == "none") - { - rec709.setValue(0); - srgb.setValue(0); - gamma.setValue(1.0); - } -} + Vec2fPropertyEditor white(m_session->graph(), m_session->currentFrame(), + "@RVDisplayColor.chromaticities.white"); -void -RvTopViewToolBar::setPrimaries(const Chromaticities& chr) -{ - Vec2fPropertyEditor white(m_session->graph(), - m_session->currentFrame(), - "@RVDisplayColor.chromaticities.white"); + Vec2fPropertyEditor red(m_session->graph(), m_session->currentFrame(), + "@RVDisplayColor.chromaticities.red"); - Vec2fPropertyEditor red(m_session->graph(), - m_session->currentFrame(), - "@RVDisplayColor.chromaticities.red"); + Vec2fPropertyEditor green(m_session->graph(), m_session->currentFrame(), + "@RVDisplayColor.chromaticities.green"); - Vec2fPropertyEditor green(m_session->graph(), - m_session->currentFrame(), - "@RVDisplayColor.chromaticities.green"); + Vec2fPropertyEditor blue(m_session->graph(), m_session->currentFrame(), + "@RVDisplayColor.chromaticities.blue"); - Vec2fPropertyEditor blue(m_session->graph(), - m_session->currentFrame(), - "@RVDisplayColor.chromaticities.blue"); + Vec2fPropertyEditor neutral(m_session->graph(), + m_session->currentFrame(), + "@RVDisplayColor.chromaticities.neutral"); - Vec2fPropertyEditor neutral(m_session->graph(), - m_session->currentFrame(), - "@RVDisplayColor.chromaticities.neutral"); + IntPropertyEditor active(m_session->graph(), m_session->currentFrame(), + "@RVDisplayColor.chromaticities.active"); - IntPropertyEditor active(m_session->graph(), - m_session->currentFrame(), - "@RVDisplayColor.chromaticities.active"); + IntPropertyEditor adoptedNeutral( + m_session->graph(), m_session->currentFrame(), + "@RVDisplayColor.chromaticities.adoptedNeutral"); - IntPropertyEditor adoptedNeutral(m_session->graph(), - m_session->currentFrame(), - "@RVDisplayColor.chromaticities.adoptedNeutral"); - - active.setValue(1); - adoptedNeutral.setValue(1); - red.setValue(chr.red); - green.setValue(chr.green); - blue.setValue(chr.blue); - white.setValue(chr.white); - neutral.setValue(chr.white); -} - -void -RvTopViewToolBar::transferNone() -{ - setTransferFunction("none", 0); -} - -void -RvTopViewToolBar::transferSRGB() -{ - setTransferFunction("srgb", 0); -} + active.setValue(1); + adoptedNeutral.setValue(1); + red.setValue(chr.red); + green.setValue(chr.green); + blue.setValue(chr.blue); + white.setValue(chr.white); + neutral.setValue(chr.white); + } -void -RvTopViewToolBar::transferRec709() -{ - setTransferFunction("rec709", 0); -} + void RvTopViewToolBar::transferNone() { setTransferFunction("none", 0); } -void -RvTopViewToolBar::transfer22() -{ - setTransferFunction("gamma", 2.2); -} + void RvTopViewToolBar::transferSRGB() { setTransferFunction("srgb", 0); } -void -RvTopViewToolBar::transfer24() -{ - setTransferFunction("gamma", 2.4); -} + void RvTopViewToolBar::transferRec709() + { + setTransferFunction("rec709", 0); + } -void -RvTopViewToolBar::transfer26() -{ - setTransferFunction("gamma", 2.6); -} + void RvTopViewToolBar::transfer22() { setTransferFunction("gamma", 2.2); } -void -RvTopViewToolBar::primaries709() -{ - setPrimaries(Chromaticities::Rec709()); -} + void RvTopViewToolBar::transfer24() { setTransferFunction("gamma", 2.4); } -void -RvTopViewToolBar::primariesP3() -{ - setPrimaries(Chromaticities::P3()); -} + void RvTopViewToolBar::transfer26() { setTransferFunction("gamma", 2.6); } -void -RvTopViewToolBar::primariesSMPTEC() -{ - setPrimaries(Chromaticities::SMPTE_C()); -} + void RvTopViewToolBar::primaries709() + { + setPrimaries(Chromaticities::Rec709()); + } -void -RvTopViewToolBar::primariesXYZ() -{ - setPrimaries(Chromaticities::XYZ()); -} + void RvTopViewToolBar::primariesP3() + { + setPrimaries(Chromaticities::P3()); + } -void -RvTopViewToolBar::primariesAdobeRGB() -{ - setPrimaries(Chromaticities::AdobeRGB()); -} + void RvTopViewToolBar::primariesSMPTEC() + { + setPrimaries(Chromaticities::SMPTE_C()); + } -void -RvTopViewToolBar::primariesDreamColor() -{ - setPrimaries(Chromaticities::DreamcolorFull()); -} + void RvTopViewToolBar::primariesXYZ() + { + setPrimaries(Chromaticities::XYZ()); + } -void -RvTopViewToolBar::ditherOff() -{ - IntPropertyEditor editor(m_session->graph(), - m_session->currentFrame(), - "@RVDisplayColor.color.dither"); + void RvTopViewToolBar::primariesAdobeRGB() + { + setPrimaries(Chromaticities::AdobeRGB()); + } - editor.setValue(0); -} + void RvTopViewToolBar::primariesDreamColor() + { + setPrimaries(Chromaticities::DreamcolorFull()); + } -void -RvTopViewToolBar::dither8() -{ - IntPropertyEditor editor(m_session->graph(), - m_session->currentFrame(), - "@RVDisplayColor.color.dither"); + void RvTopViewToolBar::ditherOff() + { + IntPropertyEditor editor(m_session->graph(), m_session->currentFrame(), + "@RVDisplayColor.color.dither"); - editor.setValue(8); -} + editor.setValue(0); + } -void -RvTopViewToolBar::dither10() -{ - IntPropertyEditor editor(m_session->graph(), - m_session->currentFrame(), - "@RVDisplayColor.color.dither"); + void RvTopViewToolBar::dither8() + { + IntPropertyEditor editor(m_session->graph(), m_session->currentFrame(), + "@RVDisplayColor.color.dither"); - editor.setValue(10); -} + editor.setValue(8); + } -bool -RvTopViewToolBar::event(QEvent* qevent) -{ - if (qevent->type() == QEvent::Show) + void RvTopViewToolBar::dither10() { - //stereoMenuUpdate(); - } + IntPropertyEditor editor(m_session->graph(), m_session->currentFrame(), + "@RVDisplayColor.color.dither"); - return QToolBar::event(qevent); -} + editor.setValue(10); + } -void -RvTopViewToolBar::setFullscreen(bool fullscreen) -{ - QToolButton* b = dynamic_cast(widgetForAction(m_fullScreenAction)); - b->setIcon(QIcon(fullscreen ? ":/images/unfullscreen" : ":/images/fullscreen.png")); -} + bool RvTopViewToolBar::event(QEvent* qevent) + { + if (qevent->type() == QEvent::Show) + { + // stereoMenuUpdate(); + } + return QToolBar::event(qevent); + } -} // Rv + void RvTopViewToolBar::setFullscreen(bool fullscreen) + { + QToolButton* b = + dynamic_cast(widgetForAction(m_fullScreenAction)); + b->setIcon(QIcon(fullscreen ? ":/images/unfullscreen" + : ":/images/fullscreen.png")); + } +} // namespace Rv diff --git a/src/lib/app/RvCommon/RvWebManager.cpp b/src/lib/app/RvCommon/RvWebManager.cpp index 3733acddc..21da5ba62 100644 --- a/src/lib/app/RvCommon/RvWebManager.cpp +++ b/src/lib/app/RvCommon/RvWebManager.cpp @@ -1,9 +1,9 @@ // // Copyright (c) 2009 Tweak Software. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// // #include #include @@ -19,443 +19,437 @@ #include #include -namespace Rv { -using namespace std; -using namespace IPCore; -using namespace TwkQtCoreUtil; - -static QByteArray -rvUserAgentHeader() +namespace Rv { - static QByteArray userAgentString; + using namespace std; + using namespace IPCore; + using namespace TwkQtCoreUtil; - if (userAgentString.isEmpty()) + static QByteArray rvUserAgentHeader() { - ostringstream str; - int minVersion = TWK_DEPLOY_MINOR_VERSION(); - int relVersion = 2*(minVersion/2); - - str << "RV/3." << relVersion << " (rv:" << - TWK_DEPLOY_MAJOR_VERSION() << "." << - TWK_DEPLOY_MINOR_VERSION() << "." << - TWK_DEPLOY_PATCH_LEVEL() << ") Autodesk: www.autodesk.com"; - userAgentString = QByteArray (str.str().c_str()); - } - - return userAgentString; -} - -QNetworkReply* -LocalNetworkAccessManager::createRequest( - QNetworkAccessManager::Operation operation, - const QNetworkRequest& request, - QIODevice* device) -{ - // cerr << "createRequest url '" << request.url().toString().toStdString() << "'" << endl; - - QNetworkRequest* r = (QNetworkRequest*) &request; - - r->setRawHeader("User-Agent", rvUserAgentHeader()); + static QByteArray userAgentString; - return QNetworkAccessManager::createRequest (operation, request, device); -} + if (userAgentString.isEmpty()) + { + ostringstream str; + int minVersion = TWK_DEPLOY_MINOR_VERSION(); + int relVersion = 2 * (minVersion / 2); + + str << "RV/3." << relVersion + << " (rv:" << TWK_DEPLOY_MAJOR_VERSION() << "." + << TWK_DEPLOY_MINOR_VERSION() << "." << TWK_DEPLOY_PATCH_LEVEL() + << ") Autodesk: www.autodesk.com"; + userAgentString = QByteArray(str.str().c_str()); + } -static bool reportErrors = false; + return userAgentString; + } -NetworkReplyTimeout::NetworkReplyTimeout(QNetworkReply* reply, const int timeout) : - QObject(reply) -{ - if (reply) + QNetworkReply* LocalNetworkAccessManager::createRequest( + QNetworkAccessManager::Operation operation, + const QNetworkRequest& request, QIODevice* device) { - QTimer::singleShot(timeout, this, SLOT(timeout())); - } -} + // cerr << "createRequest url '" << + // request.url().toString().toStdString() << "'" << endl; -NetworkReplyTimeout::~NetworkReplyTimeout() -{ - // cerr << "*********************************** NetworkReplyTimeoutDeleted, reply " << static_cast(parent()) << endl; -} + QNetworkRequest* r = (QNetworkRequest*)&request; -void -NetworkReplyTimeout::timeout() -{ - bool authDebug = (getenv("RV_SHOTGUN_AUTH_DEBUG") != 0); - if (authDebug) cerr << "INFO: network reply timeout" << endl; + r->setRawHeader("User-Agent", rvUserAgentHeader()); - QNetworkReply* reply = static_cast(parent()); - if (reply->isRunning()) reply->close(); -} + return QNetworkAccessManager::createRequest(operation, request, device); + } -RvWebManager::RvWebManager (QObject* parent) - : QObject(parent) -{ - reportErrors = (0 != getenv("RV_REPORT_QNETWORK_ERRORS")); - - m_netManager = new LocalNetworkAccessManager(this); - - QStringList cacheLocations = QStandardPaths::standardLocations(QStandardPaths::CacheLocation); - QString cacheLocation = cacheLocations.front(); - - // - // XXX the below is lame. It looks like something goes wrong - // btween the cache and the webview, so that https pages cached - // by a previous RV process are not rendered. So we clear the - // https cache here. Should ask trolltech about it. - // - QDir cachePath(cacheLocation); - QDir httpsDir(cachePath.absoluteFilePath("https")); - QStringList entries = httpsDir.entryList(); - for (int i = 0; i < entries.size(); ++i) httpsDir.remove(entries[i]); - - // - // Add a disk cache - // - QNetworkDiskCache *diskCache = new QNetworkDiskCache(this); - diskCache->setCacheDirectory(cacheLocation); - m_netManager->setCache(diskCache); - - //QWebSettings::setMaximumPagesInCache(10); - - connect(m_netManager, SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*)), - this, SLOT(replyAuthentication(QNetworkReply*,QAuthenticator*))); - connect(m_netManager, SIGNAL(sslErrors(QNetworkReply*,QList)), - this, SLOT(managerSSLErrors(QNetworkReply*,QList))); -} - -RvWebManager::~RvWebManager () -{ -} - -void -RvWebManager::httpGet(const QString& url, - const HeaderList& headers, - Session* session, - const QString& replyEvent, - const QString& authenticationEvent, - const QString& progressEvent, - bool ignoreSslErrors, - bool urlIsEncoded) -{ - QUrl u = urlIsEncoded ? QUrl::fromEncoded(url.toUtf8()) : QUrl(url); - QNetworkRequest request(u); + static bool reportErrors = false; - for (size_t i = 0; i < headers.size(); i++) + NetworkReplyTimeout::NetworkReplyTimeout(QNetworkReply* reply, + const int timeout) + : QObject(reply) { - const StringPair& p = headers[i]; - QByteArray header = p.first.toUtf8(); - QByteArray value = p.second.toUtf8(); - request.setRawHeader(header, value); + if (reply) + { + QTimer::singleShot(timeout, this, SLOT(timeout())); + } } - // cerr << "INFO: RvWebManager GET from " << url.toStdString() << endl; - - QNetworkReply* reply = m_netManager->get(request); - - reply->setReadBufferSize(0); // unlimited - - connect(reply, SIGNAL(readyRead()), this, SLOT(replyRead())); - connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), - this, SLOT(replyError(QNetworkReply::NetworkError))); - connect(reply, SIGNAL(sslErrors(QList)), - this, SLOT(replySSLErrors(QList))); - - connect(m_netManager, SIGNAL(finished(QNetworkReply*)), - this, SLOT(replyDone(QNetworkReply*))); - - ReplyData rdata; - rdata.url = u; - rdata.session = session; - rdata.replyEvent = replyEvent; - rdata.authenticationEvent = authenticationEvent; - rdata.progressEvent = progressEvent; - rdata.ignoreSslErrors = ignoreSslErrors; - - m_replyMap.insert(reply, rdata); -} - -void -RvWebManager::httpPost(const QString& url, - const HeaderList& headers, - const QByteArray& postData, - Session* session, - const QString& replyEvent, - const QString& authenticationEvent, - const QString& progressEvent, - bool ignoreSslErrors, - bool urlIsEncoded, - void (*callback)(), - QString tag) -{ - QUrl u = urlIsEncoded ? QUrl::fromEncoded(url.toUtf8()) : QUrl(url); - QNetworkRequest request(u); - request.setRawHeader("User-Agent", rvUserAgentHeader()); + NetworkReplyTimeout::~NetworkReplyTimeout() + { + // cerr << "*********************************** + // NetworkReplyTimeoutDeleted, reply " << + // static_cast(parent()) << endl; + } - for (size_t i = 0; i < headers.size(); i++) + void NetworkReplyTimeout::timeout() { - const StringPair& p = headers[i]; - QByteArray header = p.first.toUtf8(); - QByteArray value = p.second.toUtf8(); - request.setRawHeader(header, value); + bool authDebug = (getenv("RV_SHOTGUN_AUTH_DEBUG") != 0); + if (authDebug) + cerr << "INFO: network reply timeout" << endl; + + QNetworkReply* reply = static_cast(parent()); + if (reply->isRunning()) + reply->close(); } - bool authDebug = (getenv("RV_SHOTGUN_AUTH_DEBUG") != 0); - if (authDebug) cerr << "INFO: RvWebManager POST to " << UTF8::qconvert(url) << endl; - /* - // - // Uncommenting this will reveal passwords, so not for release! - // - if (authDebug) + RvWebManager::RvWebManager(QObject* parent) + : QObject(parent) { - cerr << "POST DATA ----------- START" << endl; - QString postString(postData); - cerr << UTF8::qconvert(postString) << endl; - cerr << "POST DATA ----------- END" << endl; + reportErrors = (0 != getenv("RV_REPORT_QNETWORK_ERRORS")); + + m_netManager = new LocalNetworkAccessManager(this); + + QStringList cacheLocations = + QStandardPaths::standardLocations(QStandardPaths::CacheLocation); + QString cacheLocation = cacheLocations.front(); + + // + // XXX the below is lame. It looks like something goes wrong + // btween the cache and the webview, so that https pages cached + // by a previous RV process are not rendered. So we clear the + // https cache here. Should ask trolltech about it. + // + QDir cachePath(cacheLocation); + QDir httpsDir(cachePath.absoluteFilePath("https")); + QStringList entries = httpsDir.entryList(); + for (int i = 0; i < entries.size(); ++i) + httpsDir.remove(entries[i]); + + // + // Add a disk cache + // + QNetworkDiskCache* diskCache = new QNetworkDiskCache(this); + diskCache->setCacheDirectory(cacheLocation); + m_netManager->setCache(diskCache); + + // QWebSettings::setMaximumPagesInCache(10); + + connect(m_netManager, + SIGNAL(authenticationRequired(QNetworkReply*, QAuthenticator*)), + this, + SLOT(replyAuthentication(QNetworkReply*, QAuthenticator*))); + connect(m_netManager, + SIGNAL(sslErrors(QNetworkReply*, QList)), this, + SLOT(managerSSLErrors(QNetworkReply*, QList))); } - */ - QNetworkReply* reply = m_netManager->post(request, postData); - if (callback) + RvWebManager::~RvWebManager() {} + + void RvWebManager::httpGet(const QString& url, const HeaderList& headers, + Session* session, const QString& replyEvent, + const QString& authenticationEvent, + const QString& progressEvent, + bool ignoreSslErrors, bool urlIsEncoded) { - int timeout = 20000; - if (const char* to = getenv("RV_SHOTGUN_AUTH_TIMEOUT")) + QUrl u = urlIsEncoded ? QUrl::fromEncoded(url.toUtf8()) : QUrl(url); + QNetworkRequest request(u); + + for (size_t i = 0; i < headers.size(); i++) { - timeout = atoi(to); + const StringPair& p = headers[i]; + QByteArray header = p.first.toUtf8(); + QByteArray value = p.second.toUtf8(); + request.setRawHeader(header, value); } - new NetworkReplyTimeout(reply, timeout); - } - reply->setReadBufferSize(0); // unlimited - - connect(reply, SIGNAL(readyRead()), this, SLOT(replyRead())); - connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), - this, SLOT(replyError(QNetworkReply::NetworkError))); - connect(reply, SIGNAL(sslErrors(QList)), - this, SLOT(replySSLErrors(QList))); - - connect(m_netManager, SIGNAL(finished(QNetworkReply*)), - this, SLOT(replyDone(QNetworkReply*))); - - ReplyData rdata; - rdata.url = u; - rdata.session = session; - rdata.replyEvent = replyEvent; - rdata.authenticationEvent = authenticationEvent; - rdata.progressEvent = progressEvent; - rdata.ignoreSslErrors = ignoreSslErrors; - rdata.callback = callback; - rdata.tag = tag; - - m_replyMap.insert(reply, rdata); -} - -void -RvWebManager::httpPut( const QString& url, - const HeaderList& headers, - const QByteArray& putData, - Session* session, - const QString& replyEvent, - const QString& authenticationEvent, - const QString& progressEvent, - bool ignoreSslErrors, - bool urlIsEncoded, - void (*callback)(), - QString tag) -{ - QUrl u = urlIsEncoded ? QUrl::fromEncoded(url.toUtf8()) : QUrl(url); - QNetworkRequest request(u); - request.setRawHeader("User-Agent", rvUserAgentHeader()); + // cerr << "INFO: RvWebManager GET from " << url.toStdString() << endl; - for (size_t i = 0; i < headers.size(); i++) - { - const StringPair& p = headers[i]; - QByteArray header = p.first.toUtf8(); - QByteArray value = p.second.toUtf8(); - request.setRawHeader(header, value); - } + QNetworkReply* reply = m_netManager->get(request); - bool authDebug = (getenv("RV_SHOTGUN_AUTH_DEBUG") != 0); - if (authDebug) cerr << "INFO: RvWebManager PUT to " << UTF8::qconvert(url) << endl; - /* - // - // Uncommenting this will reveal passwords, so not for release! - // - if (authDebug) - { - cerr << "PUT URL ----------- START" << endl; - cerr << u.toString().toStdString() << endl; - cerr << "PUT URL ----------- END" << endl; - cerr << "PUT DATA ----------- START" << endl; - QString putString(putData); - cerr << UTF8::qconvert(putString) << endl; - cerr << "PUT DATA ----------- END" << endl; + reply->setReadBufferSize(0); // unlimited + + connect(reply, SIGNAL(readyRead()), this, SLOT(replyRead())); + connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, + SLOT(replyError(QNetworkReply::NetworkError))); + connect(reply, SIGNAL(sslErrors(QList)), this, + SLOT(replySSLErrors(QList))); + + connect(m_netManager, SIGNAL(finished(QNetworkReply*)), this, + SLOT(replyDone(QNetworkReply*))); + + ReplyData rdata; + rdata.url = u; + rdata.session = session; + rdata.replyEvent = replyEvent; + rdata.authenticationEvent = authenticationEvent; + rdata.progressEvent = progressEvent; + rdata.ignoreSslErrors = ignoreSslErrors; + + m_replyMap.insert(reply, rdata); } - */ - QNetworkReply* reply = m_netManager->put(request, putData); - if (callback) + void RvWebManager::httpPost(const QString& url, const HeaderList& headers, + const QByteArray& postData, Session* session, + const QString& replyEvent, + const QString& authenticationEvent, + const QString& progressEvent, + bool ignoreSslErrors, bool urlIsEncoded, + void (*callback)(), QString tag) { - int timeout = 20000; - if (const char* to = getenv("RV_SHOTGUN_AUTH_TIMEOUT")) + QUrl u = urlIsEncoded ? QUrl::fromEncoded(url.toUtf8()) : QUrl(url); + QNetworkRequest request(u); + request.setRawHeader("User-Agent", rvUserAgentHeader()); + + for (size_t i = 0; i < headers.size(); i++) + { + const StringPair& p = headers[i]; + QByteArray header = p.first.toUtf8(); + QByteArray value = p.second.toUtf8(); + request.setRawHeader(header, value); + } + + bool authDebug = (getenv("RV_SHOTGUN_AUTH_DEBUG") != 0); + if (authDebug) + cerr << "INFO: RvWebManager POST to " << UTF8::qconvert(url) + << endl; + /* + // + // Uncommenting this will reveal passwords, so not for release! + // + if (authDebug) + { + cerr << "POST DATA ----------- START" << endl; + QString postString(postData); + cerr << UTF8::qconvert(postString) << endl; + cerr << "POST DATA ----------- END" << endl; + } + */ + + QNetworkReply* reply = m_netManager->post(request, postData); + if (callback) { - timeout = atoi(to); + int timeout = 20000; + if (const char* to = getenv("RV_SHOTGUN_AUTH_TIMEOUT")) + { + timeout = atoi(to); + } + new NetworkReplyTimeout(reply, timeout); } - new NetworkReplyTimeout(reply, timeout); + + reply->setReadBufferSize(0); // unlimited + + connect(reply, SIGNAL(readyRead()), this, SLOT(replyRead())); + connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, + SLOT(replyError(QNetworkReply::NetworkError))); + connect(reply, SIGNAL(sslErrors(QList)), this, + SLOT(replySSLErrors(QList))); + + connect(m_netManager, SIGNAL(finished(QNetworkReply*)), this, + SLOT(replyDone(QNetworkReply*))); + + ReplyData rdata; + rdata.url = u; + rdata.session = session; + rdata.replyEvent = replyEvent; + rdata.authenticationEvent = authenticationEvent; + rdata.progressEvent = progressEvent; + rdata.ignoreSslErrors = ignoreSslErrors; + rdata.callback = callback; + rdata.tag = tag; + + m_replyMap.insert(reply, rdata); } - reply->setReadBufferSize(0); // unlimited + void RvWebManager::httpPut(const QString& url, const HeaderList& headers, + const QByteArray& putData, Session* session, + const QString& replyEvent, + const QString& authenticationEvent, + const QString& progressEvent, + bool ignoreSslErrors, bool urlIsEncoded, + void (*callback)(), QString tag) + { + QUrl u = urlIsEncoded ? QUrl::fromEncoded(url.toUtf8()) : QUrl(url); + QNetworkRequest request(u); + request.setRawHeader("User-Agent", rvUserAgentHeader()); - connect(reply, SIGNAL(readyRead()), this, SLOT(replyRead())); - connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), - this, SLOT(replyError(QNetworkReply::NetworkError))); - connect(reply, SIGNAL(sslErrors(QList)), - this, SLOT(replySSLErrors(QList))); + for (size_t i = 0; i < headers.size(); i++) + { + const StringPair& p = headers[i]; + QByteArray header = p.first.toUtf8(); + QByteArray value = p.second.toUtf8(); + request.setRawHeader(header, value); + } - connect(m_netManager, SIGNAL(finished(QNetworkReply*)), - this, SLOT(replyDone(QNetworkReply*))); + bool authDebug = (getenv("RV_SHOTGUN_AUTH_DEBUG") != 0); + if (authDebug) + cerr << "INFO: RvWebManager PUT to " << UTF8::qconvert(url) << endl; + /* + // + // Uncommenting this will reveal passwords, so not for release! + // + if (authDebug) + { + cerr << "PUT URL ----------- START" << endl; + cerr << u.toString().toStdString() << endl; + cerr << "PUT URL ----------- END" << endl; + cerr << "PUT DATA ----------- START" << endl; + QString putString(putData); + cerr << UTF8::qconvert(putString) << endl; + cerr << "PUT DATA ----------- END" << endl; + } + */ - ReplyData rdata; - rdata.url = u; - rdata.session = session; - rdata.replyEvent = replyEvent; - rdata.authenticationEvent = authenticationEvent; - rdata.progressEvent = progressEvent; - rdata.ignoreSslErrors = ignoreSslErrors; - rdata.callback = callback; - rdata.tag = tag; + QNetworkReply* reply = m_netManager->put(request, putData); + if (callback) + { + int timeout = 20000; + if (const char* to = getenv("RV_SHOTGUN_AUTH_TIMEOUT")) + { + timeout = atoi(to); + } + new NetworkReplyTimeout(reply, timeout); + } - m_replyMap.insert(reply, rdata); -} + reply->setReadBufferSize(0); // unlimited -void -RvWebManager::replyDone(QNetworkReply* reply) -{ - if (m_replyMap.count(reply) != 1) return; + connect(reply, SIGNAL(readyRead()), this, SLOT(replyRead())); + connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, + SLOT(replyError(QNetworkReply::NetworkError))); + connect(reply, SIGNAL(sslErrors(QList)), this, + SLOT(replySSLErrors(QList))); - ReplyData d = m_replyMap[reply]; - QString replyErrorString; + connect(m_netManager, SIGNAL(finished(QNetworkReply*)), this, + SLOT(replyDone(QNetworkReply*))); - bool authDebug = (getenv("RV_SHOTGUN_AUTH_DEBUG") != 0); + ReplyData rdata; + rdata.url = u; + rdata.session = session; + rdata.replyEvent = replyEvent; + rdata.authenticationEvent = authenticationEvent; + rdata.progressEvent = progressEvent; + rdata.ignoreSslErrors = ignoreSslErrors; + rdata.callback = callback; + rdata.tag = tag; - if (reply->error() != QNetworkReply::NoError) - { - if (reportErrors) - { - replyErrorString = reply->errorString(); - cerr << "ERROR: RvWebManager http reply: " << UTF8::qconvert(replyErrorString) << endl; - } + m_replyMap.insert(reply, rdata); } - /* - else + + void RvWebManager::replyDone(QNetworkReply* reply) { - cerr << "INFO: RvWebManager reply from " << reply->request().url().toString().toStdString() << endl; - } - */ + if (m_replyMap.count(reply) != 1) + return; - QByteArray array = reply->readAll(); - QString ctype = reply->header(QNetworkRequest::ContentTypeHeader).toString(); + ReplyData d = m_replyMap[reply]; + QString replyErrorString; - if (authDebug) cerr << "INFO: reply " << reply << ", replyDone (" << array.size() << " byes): '" << array.constData() << "'" << endl; + bool authDebug = (getenv("RV_SHOTGUN_AUTH_DEBUG") != 0); - if (d.session) - { - if (ctype.contains("text/", Qt::CaseInsensitive) - || ctype.contains("application/json", Qt::CaseInsensitive) - || !replyErrorString.isEmpty() ) + if (reply->error() != QNetworkReply::NoError) { - // - // Text, convert to UTF-8 for Mu - // - - QTextCodec* codec = QTextCodec::codecForHtml(array); - QString u = codec->toUnicode(array); - QByteArray utf8 = u.toUtf8(); - if (!replyErrorString.isEmpty()) utf8 = replyErrorString.toUtf8(); - - (void) d.session->userRawDataEvent(d.replyEvent.toUtf8().constData(), - ctype.toUtf8().constData(), - array.constData(), - array.size(), - utf8.constData()); + if (reportErrors) + { + replyErrorString = reply->errorString(); + cerr << "ERROR: RvWebManager http reply: " + << UTF8::qconvert(replyErrorString) << endl; + } } + /* else { - // - // Binary data, no text rep - // - - (void) d.session->userRawDataEvent(d.replyEvent.toUtf8().constData(), - ctype.toUtf8().constData(), - array.constData(), - array.size(), - 0); + cerr << "INFO: RvWebManager reply from " << + reply->request().url().toString().toStdString() << endl; } - } + */ - m_replyMap.remove(reply); - reply->deleteLater(); -} + QByteArray array = reply->readAll(); + QString ctype = + reply->header(QNetworkRequest::ContentTypeHeader).toString(); -void -RvWebManager::replyRead() -{ - // cerr << "INFO: RvWebManager: readReady signal" << endl; -} + if (authDebug) + cerr << "INFO: reply " << reply << ", replyDone (" << array.size() + << " byes): '" << array.constData() << "'" << endl; -void -RvWebManager::replyError(QNetworkReply::NetworkError error) -{ - if (reportErrors) cerr << "WARNING: reply error #" << error << endl; -} + if (d.session) + { + if (ctype.contains("text/", Qt::CaseInsensitive) + || ctype.contains("application/json", Qt::CaseInsensitive) + || !replyErrorString.isEmpty()) + { + // + // Text, convert to UTF-8 for Mu + // + + QTextCodec* codec = QTextCodec::codecForHtml(array); + QString u = codec->toUnicode(array); + QByteArray utf8 = u.toUtf8(); + if (!replyErrorString.isEmpty()) + utf8 = replyErrorString.toUtf8(); + + (void)d.session->userRawDataEvent( + d.replyEvent.toUtf8().constData(), + ctype.toUtf8().constData(), array.constData(), array.size(), + utf8.constData()); + } + else + { + // + // Binary data, no text rep + // + + (void)d.session->userRawDataEvent( + d.replyEvent.toUtf8().constData(), + ctype.toUtf8().constData(), array.constData(), array.size(), + 0); + } + } -void -RvWebManager::replySSLErrors(QList errList) -{ - if (reportErrors) - { - foreach (QSslError err, errList) - { - cerr << "WARNING: reply SSL error: " << UTF8::qconvert(err.errorString()) << endl; - } + m_replyMap.remove(reply); + reply->deleteLater(); } -} - -void -RvWebManager::managerSSLErrors(QNetworkReply* reply, QList errList) -{ - bool ignore = true; - - // - // Ignore ssl errors either if the user asked us to, or if the request was - // internally generated, so the user had no chance to specify the - // behavior. - // - if (m_replyMap.contains(reply)) + void RvWebManager::replyRead() { - ignore = m_replyMap[reply].ignoreSslErrors; + // cerr << "INFO: RvWebManager: readReady signal" << endl; } - if (ignore) reply->ignoreSslErrors(); + void RvWebManager::replyError(QNetworkReply::NetworkError error) + { + if (reportErrors) + cerr << "WARNING: reply error #" << error << endl; + } - if (reportErrors) + void RvWebManager::replySSLErrors(QList errList) { - foreach (QSslError err, errList) - { - cerr << "WARNING: " - << ((ignore) ? "ignoring" : "not ignoring") - << " SSL error: " - << UTF8::qconvert(err.errorString()) - << endl; - } + if (reportErrors) + { + foreach (QSslError err, errList) + { + cerr << "WARNING: reply SSL error: " + << UTF8::qconvert(err.errorString()) << endl; + } + } } -} -void -RvWebManager::replyAuthentication(QNetworkReply*,QAuthenticator*) -{ - // cerr << "replyAuthentication" << endl; -} + void RvWebManager::managerSSLErrors(QNetworkReply* reply, + QList errList) + { + bool ignore = true; + + // + // Ignore ssl errors either if the user asked us to, or if the request + // was internally generated, so the user had no chance to specify the + // behavior. + // + + if (m_replyMap.contains(reply)) + { + ignore = m_replyMap[reply].ignoreSslErrors; + } -} // Rv + if (ignore) + reply->ignoreSslErrors(); + if (reportErrors) + { + foreach (QSslError err, errList) + { + cerr << "WARNING: " << ((ignore) ? "ignoring" : "not ignoring") + << " SSL error: " << UTF8::qconvert(err.errorString()) + << endl; + } + } + } + + void RvWebManager::replyAuthentication(QNetworkReply*, QAuthenticator*) + { + // cerr << "replyAuthentication" << endl; + } +} // namespace Rv diff --git a/src/lib/app/RvCommon/StreamConnection.cpp b/src/lib/app/RvCommon/StreamConnection.cpp index f9724275a..8bed77c9c 100644 --- a/src/lib/app/RvCommon/StreamConnection.cpp +++ b/src/lib/app/RvCommon/StreamConnection.cpp @@ -1,7 +1,7 @@ // -// Copyright (C) 2023 Autodesk, Inc. All Rights Reserved. -// -// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2023 Autodesk, Inc. All Rights Reserved. +// +// SPDX-License-Identifier: Apache-2.0 // #include @@ -14,323 +14,323 @@ #include #endif -namespace Rv { -using namespace TwkQtCoreUtil; -using namespace TwkQtChat; -using namespace std; - -Connection* -StreamConnection::connectionFactory(QObject* obj, bool pingpong) +namespace Rv { - return new StreamConnection(obj, pingpong); -} + using namespace TwkQtCoreUtil; + using namespace TwkQtChat; + using namespace std; + + Connection* StreamConnection::connectionFactory(QObject* obj, bool pingpong) + { + return new StreamConnection(obj, pingpong); + } #define STREAM_CONNECTION_MAGIC_NUMBER 312967 #define STREAM_CONNECTION_VERSION 1 -StreamConnection::StreamConnection(QObject *parent, bool pingpong) : - TwkQtChat::Connection(parent, pingpong), - m_streamFile(0), - m_streamDataStream(0), - m_streamState(NormalState), - m_name("spoofer"), - m_app("rv"), - m_contactName("spoofer@localhost"), - m_timeScale(1.0), - m_verbose(false) -{ - m_intervalTimer.setSingleShot(true); -} - -StreamConnection::~StreamConnection() -{ - delete m_streamDataStream; - delete m_streamFile; -} - -void -StreamConnection::storeStream(const string &baseDir) -{ - QString fileName(baseDir.c_str()); - - #ifdef PLATFORM_WINDOWS - fileName.append(QString("/rv-network-stream-%1").arg((unsigned __int64)this)); - #else - fileName.append(QString("/rv-network-stream-%1").arg(uint64_t(this))); - #endif - - m_streamFile = new QFile(fileName); - - if (! m_streamFile->open(QIODevice::WriteOnly)) + StreamConnection::StreamConnection(QObject* parent, bool pingpong) + : TwkQtChat::Connection(parent, pingpong) + , m_streamFile(0) + , m_streamDataStream(0) + , m_streamState(NormalState) + , m_name("spoofer") + , m_app("rv") + , m_contactName("spoofer@localhost") + , m_timeScale(1.0) + , m_verbose(false) { - cerr << "ERROR: storeStream cannot open file '" - << UTF8::qconvert(fileName) - << endl; - return; + m_intervalTimer.setSingleShot(true); } - m_streamDataStream = new QDataStream(m_streamFile); - - *m_streamDataStream << int(STREAM_CONNECTION_MAGIC_NUMBER) << int(STREAM_CONNECTION_VERSION); - m_streamFile->flush(); - - m_eventTimer.start(); - - m_streamState = StoringState; -} - -static int -validateStreamConnection (QDataStream* stream, const string& fileName, bool verbose) -{ - int magic; - *stream >> magic; - if (verbose) cerr << "stream magic: " << magic << endl; - if (magic != STREAM_CONNECTION_MAGIC_NUMBER) + StreamConnection::~StreamConnection() { - cerr << "ERROR: file '" << fileName << "' is not an RV StreamConnection file." << endl; - return 0; + delete m_streamDataStream; + delete m_streamFile; } - int version; - *stream >> version; - if (verbose) cerr << "stream version: " << version << endl; - if (version != STREAM_CONNECTION_VERSION) + void StreamConnection::storeStream(const string& baseDir) { - cerr << "ERROR: file '" << fileName << "': unknown RV StreamConnection version: " << version << endl; - return 0; - } + QString fileName(baseDir.c_str()); - return version; -} +#ifdef PLATFORM_WINDOWS + fileName.append( + QString("/rv-network-stream-%1").arg((unsigned __int64)this)); +#else + fileName.append(QString("/rv-network-stream-%1").arg(uint64_t(this))); +#endif -void -StreamConnection::dumpStream(const string &fileName) -{ - m_streamFile = new QFile(fileName.c_str()); - m_streamFile->open(QIODevice::ReadOnly); - m_streamDataStream = new QDataStream(m_streamFile); + m_streamFile = new QFile(fileName); + + if (!m_streamFile->open(QIODevice::WriteOnly)) + { + cerr << "ERROR: storeStream cannot open file '" + << UTF8::qconvert(fileName) << endl; + return; + } + + m_streamDataStream = new QDataStream(m_streamFile); + + *m_streamDataStream << int(STREAM_CONNECTION_MAGIC_NUMBER) + << int(STREAM_CONNECTION_VERSION); + m_streamFile->flush(); - int version = validateStreamConnection (m_streamDataStream, fileName, true); - if (version == 0) return; + m_eventTimer.start(); - int currentType; - QString currentMessage; - QString currentInterp; - QByteArray currentData; + m_streamState = StoringState; + } - while (! m_streamDataStream->atEnd()) + static int validateStreamConnection(QDataStream* stream, + const string& fileName, bool verbose) { - *m_streamDataStream >> m_currentTime >> currentType; - switch (currentType) + int magic; + *stream >> magic; + if (verbose) + cerr << "stream magic: " << magic << endl; + if (magic != STREAM_CONNECTION_MAGIC_NUMBER) { - case MessageItemType: - *m_streamDataStream >> currentMessage; - cerr << "message " - << m_currentTime << " '" - << UTF8::qconvert(currentMessage) - << "'" - << endl; - break; + cerr << "ERROR: file '" << fileName + << "' is not an RV StreamConnection file." << endl; + return 0; + } - case DataItemType: - *m_streamDataStream >> m_currentTime >> currentData; - cerr << "data " - << m_currentTime - << " '" - << UTF8::qconvert(currentInterp) - << "', bytes: " - << currentData.size() + int version; + *stream >> version; + if (verbose) + cerr << "stream version: " << version << endl; + if (version != STREAM_CONNECTION_VERSION) + { + cerr << "ERROR: file '" << fileName + << "': unknown RV StreamConnection version: " << version << endl; - break; + return 0; } + + return version; } -} -void -StreamConnection::handleNextEvent() -{ - int currentType; - QString currentMessage; - QString currentInterp; - QByteArray currentData; + void StreamConnection::dumpStream(const string& fileName) + { + m_streamFile = new QFile(fileName.c_str()); + m_streamFile->open(QIODevice::ReadOnly); + m_streamDataStream = new QDataStream(m_streamFile); - *m_streamDataStream >> currentType; + int version = + validateStreamConnection(m_streamDataStream, fileName, true); + if (version == 0) + return; - float diff; + int currentType; + QString currentMessage; + QString currentInterp; + QByteArray currentData; - switch (currentType) - { - case MessageItemType: - *m_streamDataStream >> currentMessage; - if (m_verbose) - { - diff = 1000.0 * (m_timeScale*m_currentTime - float(m_eventTimer.elapsed())); - cerr << "message " - << m_currentTime - << " (diff " << diff << ") '" - << UTF8::qconvert(currentMessage) - << "'" - << endl; - } - emit newMessage(remoteContactName(), currentMessage); - break; - - case DataItemType: - *m_streamDataStream >> currentInterp >> currentData; - if (m_verbose) - { - diff = 1000.0 * (m_timeScale*m_currentTime - float(m_eventTimer.elapsed())); - cerr << "data " - << m_currentTime - << " (diff " << diff << ") '" + while (!m_streamDataStream->atEnd()) + { + *m_streamDataStream >> m_currentTime >> currentType; + switch (currentType) + { + case MessageItemType: + *m_streamDataStream >> currentMessage; + cerr << "message " << m_currentTime << " '" + << UTF8::qconvert(currentMessage) << "'" << endl; + break; + + case DataItemType: + *m_streamDataStream >> m_currentTime >> currentData; + cerr << "data " << m_currentTime << " '" << UTF8::qconvert(currentInterp) - << "', bytes: " - << currentData.size() - << endl; - } - emit newData(remoteContactName(), currentInterp, currentData); - break; + << "', bytes: " << currentData.size() << endl; + break; + } + } } - if (m_streamDataStream->atEnd()) return; + void StreamConnection::handleNextEvent() + { + int currentType; + QString currentMessage; + QString currentInterp; + QByteArray currentData; - *m_streamDataStream >> m_currentTime; + *m_streamDataStream >> currentType; - if (m_timeScale == 0.0) - { - // - // In this special case, we stream the events "asap" while still - // allowing time for other events. - // + float diff; - m_intervalTimer.start(0); - } - else - { - float diff = m_timeScale*m_currentTime - float(m_eventTimer.elapsed()); + switch (currentType) + { + case MessageItemType: + *m_streamDataStream >> currentMessage; + if (m_verbose) + { + diff = 1000.0 + * (m_timeScale * m_currentTime + - float(m_eventTimer.elapsed())); + cerr << "message " << m_currentTime << " (diff " << diff + << ") '" << UTF8::qconvert(currentMessage) << "'" << endl; + } + emit newMessage(remoteContactName(), currentMessage); + break; + + case DataItemType: + *m_streamDataStream >> currentInterp >> currentData; + if (m_verbose) + { + diff = 1000.0 + * (m_timeScale * m_currentTime + - float(m_eventTimer.elapsed())); + cerr << "data " << m_currentTime << " (diff " << diff << ") '" + << UTF8::qconvert(currentInterp) + << "', bytes: " << currentData.size() << endl; + } + emit newData(remoteContactName(), currentInterp, currentData); + break; + } - // - // If we're "behind" handle the next event immediately, otherwise - // schedule it to be handled at the appropriate time in the future. - // + if (m_streamDataStream->atEnd()) + return; - if (diff <= 0.0) handleNextEvent(); + *m_streamDataStream >> m_currentTime; + + if (m_timeScale == 0.0) + { + // + // In this special case, we stream the events "asap" while still + // allowing time for other events. + // + + m_intervalTimer.start(0); + } else { - int mSecs = int(1000.0 * diff); - m_intervalTimer.start(mSecs); + float diff = + m_timeScale * m_currentTime - float(m_eventTimer.elapsed()); + + // + // If we're "behind" handle the next event immediately, otherwise + // schedule it to be handled at the appropriate time in the future. + // + + if (diff <= 0.0) + handleNextEvent(); + else + { + int mSecs = int(1000.0 * diff); + m_intervalTimer.start(mSecs); + } } } -} -bool -StreamConnection::spoofStream(const string &fileName, bool verbose) -{ - m_verbose = verbose; - - m_streamFile = new QFile(fileName.c_str()); - if (!m_streamFile->open(QIODevice::ReadOnly)) + bool StreamConnection::spoofStream(const string& fileName, bool verbose) { - cerr << "ERROR: can't open network stream file '" << fileName << "'" << endl; - return false; - } + m_verbose = verbose; - if (m_verbose) cerr << "stream file: " << fileName << endl; + m_streamFile = new QFile(fileName.c_str()); + if (!m_streamFile->open(QIODevice::ReadOnly)) + { + cerr << "ERROR: can't open network stream file '" << fileName << "'" + << endl; + return false; + } - m_streamDataStream = new QDataStream(m_streamFile); + if (m_verbose) + cerr << "stream file: " << fileName << endl; - int version = validateStreamConnection (m_streamDataStream, fileName, verbose); - if (version == 0) - { - return false; - } + m_streamDataStream = new QDataStream(m_streamFile); - connect (&m_intervalTimer, SIGNAL(timeout()), this, SLOT(handleNextEvent())); + int version = + validateStreamConnection(m_streamDataStream, fileName, verbose); + if (version == 0) + { + return false; + } - m_streamState = SpoofingState; + connect(&m_intervalTimer, SIGNAL(timeout()), this, + SLOT(handleNextEvent())); - return true; -} + m_streamState = SpoofingState; -void -StreamConnection::startSpoofing(float timeScale) -{ - if (m_streamState == SpoofingState && ! m_streamDataStream->atEnd()) + return true; + } + + void StreamConnection::startSpoofing(float timeScale) { - m_timeScale = timeScale; - // - // Ignore timing of first event. - // - float t; - *m_streamDataStream >> t; - m_currentTime = 0.0; + if (m_streamState == SpoofingState && !m_streamDataStream->atEnd()) + { + m_timeScale = timeScale; + // + // Ignore timing of first event. + // + float t; + *m_streamDataStream >> t; + m_currentTime = 0.0; - m_eventTimer.start(); + m_eventTimer.start(); - handleNextEvent(); + handleNextEvent(); + } } -} -bool -StreamConnection::sendMessage(const QString &message) -{ - if (m_streamState == StoringState) + bool StreamConnection::sendMessage(const QString& message) { - *m_streamDataStream << float(m_eventTimer.elapsed()) << int(MessageItemType) << message; - m_streamFile->flush(); + if (m_streamState == StoringState) + { + *m_streamDataStream << float(m_eventTimer.elapsed()) + << int(MessageItemType) << message; + m_streamFile->flush(); + } + else if (m_streamState == SpoofingState) + { + return true; + } + return Connection::sendMessage(message); } - else - if (m_streamState == SpoofingState) + + bool StreamConnection::sendData(const QString& interp, + const QByteArray& data) { - return true; + if (m_streamState == StoringState) + { + *m_streamDataStream << float(m_eventTimer.elapsed()) + << int(DataItemType) << interp << data; + m_streamFile->flush(); + } + else if (m_streamState == SpoofingState) + { + return true; + } + return Connection::sendData(interp, data); } - return Connection::sendMessage(message); -} -bool -StreamConnection::sendData(const QString& interp, const QByteArray& data) -{ - if (m_streamState == StoringState) + bool StreamConnection::isLocal() { - *m_streamDataStream << float(m_eventTimer.elapsed()) << int(DataItemType) << interp << data; - m_streamFile->flush(); + if (m_streamState == SpoofingState) + return true; + else + return TwkQtChat::Connection::isLocal(); } - else - if (m_streamState == SpoofingState) + + const QString& StreamConnection::remoteName() const { - return true; + if (m_streamState == SpoofingState) + return m_name; + else + return TwkQtChat::Connection::remoteName(); } - return Connection::sendData(interp, data); -} - -bool -StreamConnection::isLocal() -{ - if (m_streamState == SpoofingState) return true; - else return TwkQtChat::Connection::isLocal(); -} - -const QString& -StreamConnection::remoteName() const -{ - if (m_streamState == SpoofingState) return m_name; - else return TwkQtChat::Connection::remoteName(); -} - -const QString& -StreamConnection::remoteApp() const -{ - if (m_streamState == SpoofingState) return m_app; - else return TwkQtChat::Connection::remoteApp(); -} - -const QString& -StreamConnection::remoteContactName() const -{ - if (m_streamState == SpoofingState) return m_contactName; - else return TwkQtChat::Connection::remoteContactName(); -} + const QString& StreamConnection::remoteApp() const + { + if (m_streamState == SpoofingState) + return m_app; + else + return TwkQtChat::Connection::remoteApp(); + } + const QString& StreamConnection::remoteContactName() const + { + if (m_streamState == SpoofingState) + return m_contactName; + else + return TwkQtChat::Connection::remoteContactName(); + } -}; +}; // namespace Rv diff --git a/src/lib/app/RvCommon/TwkQTAction.cpp b/src/lib/app/RvCommon/TwkQTAction.cpp index d1febe4f8..c3f529c78 100644 --- a/src/lib/app/RvCommon/TwkQTAction.cpp +++ b/src/lib/app/RvCommon/TwkQTAction.cpp @@ -1,23 +1,22 @@ //****************************************************************************** -// Copyright (c) 2007 Tweak Inc. +// Copyright (c) 2007 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #include -namespace Rv { - -TwkQTAction::TwkQTAction(const TwkApp::Menu::Item* i, - RvDocument* doc, - QObject* parent) - : QAction(parent), - m_item(i), - m_doc(doc) +namespace Rv { -} -} // Rv + TwkQTAction::TwkQTAction(const TwkApp::Menu::Item* i, RvDocument* doc, + QObject* parent) + : QAction(parent) + , m_item(i) + , m_doc(doc) + { + } +} // namespace Rv diff --git a/src/lib/app/RvPackage/PackageManager.cpp b/src/lib/app/RvPackage/PackageManager.cpp index d24c018fd..559e4f071 100644 --- a/src/lib/app/RvPackage/PackageManager.cpp +++ b/src/lib/app/RvPackage/PackageManager.cpp @@ -20,1985 +20,2109 @@ namespace Rv { - using namespace std; - - QString extractFile(unzFile uf, const string& outputPath) { - char filename[256]; - unz_file_info fileInfo; - - if (unzGetCurrentFileInfo(uf, &fileInfo, filename, sizeof(filename), nullptr, 0, nullptr, 0) != UNZ_OK) { - cerr << "ERROR: Unable to get file info" << endl; - return ""; - } - - if (unzOpenCurrentFile(uf) != UNZ_OK) { - cerr << "ERROR: Unable to open file in zip" << endl; - return ""; - } - - string fullPath = outputPath + "/" + filename; - FILE* outFile = std::fopen(fullPath.c_str(), "wb"); - if (outFile == nullptr) { - cerr << "ERROR: Unable to open output file" << endl; - unzCloseCurrentFile(uf); - return ""; - } - - char buffer[8192]; - int bytesRead = 0; - while ((bytesRead = unzReadCurrentFile(uf, buffer, sizeof(buffer))) > 0) { - fwrite(buffer, 1, bytesRead, outFile); - } - - fclose(outFile); - unzCloseCurrentFile(uf); - - return QString::fromStdString(fullPath); - } - - vector unzipBundle(const string& zipFilePath, const string& outputPath) - { - vector includedPackages; - - // Opening zip file - unzFile uf = unzOpen(zipFilePath.c_str()); - if (uf == nullptr) { - cerr << "ERROR: Unable to open zip file" << endl; - return {}; - } - - // Checking for the presence of files - if (unzGoToFirstFile(uf) != UNZ_OK) { - cerr << "ERROR: Unable to find first file in zip" << endl; - unzClose(uf); - return {}; - } - - // Extracting each file in the zip - do { - QString extractedFilePath = extractFile(uf, outputPath); - if (extractedFilePath == "") { - cerr << "ERROR: Unable to extract zip file" << endl; - } else { - includedPackages.push_back(extractedFilePath); - } - } while (unzGoToNextFile(uf) == UNZ_OK); - - unzClose(uf); - - return includedPackages; - } - - bool PackageManager::isBundle(const QString& infileNonCanonical) - { - - // Getting package file extension - string filePath = infileNonCanonical.toStdString(); - size_t dot = filePath.rfind('.'); - if (dot == string::npos) { - cerr << "ERROR: Unsupported file type. Ensure each package has the extension 'rvpkg', 'zip' or 'rvpkgs'" << endl; - return false; - } + using namespace std; - // Edge case, last character is dot - if (dot == filePath.size() - 1) { - cerr << "ERROR: File paths cannot end with a dot/period. Extension cannot be determined." << endl; - return false; - } - - // File extension - string ext = filePath.substr(dot + 1); - if (ext == "rvpkgs") { - return true; + QString extractFile(unzFile uf, const string& outputPath) + { + char filename[256]; + unz_file_info fileInfo; - // May or may not be a bundle - } else if (ext == "zip") { + if (unzGetCurrentFileInfo(uf, &fileInfo, filename, sizeof(filename), + nullptr, 0, nullptr, 0) + != UNZ_OK) + { + cerr << "ERROR: Unable to get file info" << endl; + return ""; + } - unzFile uf = unzOpen(filePath.c_str()); - if (!uf) { - cerr << "ERROR: Failed to open zip file" << endl; - return false; - } - - // Checking for presence of PACKAGE file - if (unzGoToFirstFile(uf) == UNZ_OK) { - do { - unz_file_info fileInfo; - char fileName[256]; - if ( - unzGetCurrentFileInfo(uf, &fileInfo, fileName, sizeof(fileName), nullptr, 0, nullptr, 0) == UNZ_OK - && strcmp(fileName, "PACKAGE") == 0 - ) { - return false; - } - } while (unzGoToNextFile(uf) == UNZ_OK); - } + if (unzOpenCurrentFile(uf) != UNZ_OK) + { + cerr << "ERROR: Unable to open file in zip" << endl; + return ""; + } - unzClose(uf); - return true; // Zip does not contain a PACKAGE file, therefore assume it is a bundle - } + string fullPath = outputPath + "/" + filename; + FILE* outFile = std::fopen(fullPath.c_str(), "wb"); + if (outFile == nullptr) + { + cerr << "ERROR: Unable to open output file" << endl; + unzCloseCurrentFile(uf); + return ""; + } - return false; // Extension is not zip or rvpkgs - } + char buffer[8192]; + int bytesRead = 0; + while ((bytesRead = unzReadCurrentFile(uf, buffer, sizeof(buffer))) > 0) + { + fwrite(buffer, 1, bytesRead, outFile); + } - vector PackageManager::handleBundle(const QString& bundlePath, const QString& outputPath) { + fclose(outFile); + unzCloseCurrentFile(uf); - // Attempting to unzip bundle into the Packages directory - vector includedPackages = unzipBundle(bundlePath.toStdString(), outputPath.toStdString()); - if (includedPackages.size() == 0) { - cerr << "ERROR: Unable to unzip bundle." << endl; - return {}; + return QString::fromStdString(fullPath); } - return includedPackages; - } + vector unzipBundle(const string& zipFilePath, + const string& outputPath) + { + vector includedPackages; - bool PackageManager::m_ignorePrefs = false; + // Opening zip file + unzFile uf = unzOpen(zipFilePath.c_str()); + if (uf == nullptr) + { + cerr << "ERROR: Unable to open zip file" << endl; + return {}; + } - PackageManager::PackageManager() : m_force( false ) {} + // Checking for the presence of files + if (unzGoToFirstFile(uf) != UNZ_OK) + { + cerr << "ERROR: Unable to find first file in zip" << endl; + unzClose(uf); + return {}; + } - PackageManager::~PackageManager() {} + // Extracting each file in the zip + do + { + QString extractedFilePath = extractFile(uf, outputPath); + if (extractedFilePath == "") + { + cerr << "ERROR: Unable to extract zip file" << endl; + } + else + { + includedPackages.push_back(extractedFilePath); + } + } while (unzGoToNextFile(uf) == UNZ_OK); - int PackageManager::findPackageIndexByZip( const QString& zipfile ) - { - QString zipfileCanonical = QFileInfo( zipfile ).canonicalFilePath(); - QString pattern = zipfile + "-.*\\.rvpkg"; - QRegExp rx( pattern ); + unzClose(uf); - for( size_t i = 0; i < m_packages.size(); i++ ) - { - QFileInfo info( m_packages[i].file ); - - if( info.fileName() == zipfile || info.absoluteFilePath() == zipfile || - info.absoluteFilePath() == zipfileCanonical || - rx.exactMatch( info.fileName() ) || - rx.exactMatch( info.absoluteFilePath() ) ) - { - return i; - } + return includedPackages; } - return -1; - } - - bool PackageManager::allowLoading( Package& package, bool allow, int depth ) - { - if( package.loadable == allow ) return true; - - if( allow ) + bool PackageManager::isBundle(const QString& infileNonCanonical) { - QList notloaded; - for( int i = 0; i < package.uses.size(); i++ ) - { - int index = package.uses[i]; - if( !m_packages[index].loadable ) notloaded.push_back( index ); - } + // Getting package file extension + string filePath = infileNonCanonical.toStdString(); + size_t dot = filePath.rfind('.'); + if (dot == string::npos) + { + cerr << "ERROR: Unsupported file type. Ensure each package has the " + "extension 'rvpkg', 'zip' or 'rvpkgs'" + << endl; + return false; + } - if( depth == 0 && notloaded.size() ) - { - QString s( "Package requires these unloadable packages:\n" ); + // Edge case, last character is dot + if (dot == filePath.size() - 1) + { + cerr << "ERROR: File paths cannot end with a dot/period. Extension " + "cannot be determined." + << endl; + return false; + } - for( size_t q = 0; q < notloaded.size(); q++ ) + // File extension + string ext = filePath.substr(dot + 1); + if (ext == "rvpkgs") { - s += m_packages[notloaded[q]].name; - s += "\n"; + return true; + + // May or may not be a bundle } + else if (ext == "zip") + { - if( !fixLoadability( s ) ) return false; - } + unzFile uf = unzOpen(filePath.c_str()); + if (!uf) + { + cerr << "ERROR: Failed to open zip file" << endl; + return false; + } - package.loadable = true; + // Checking for presence of PACKAGE file + if (unzGoToFirstFile(uf) == UNZ_OK) + { + do + { + unz_file_info fileInfo; + char fileName[256]; + if (unzGetCurrentFileInfo(uf, &fileInfo, fileName, + sizeof(fileName), nullptr, 0, + nullptr, 0) + == UNZ_OK + && strcmp(fileName, "PACKAGE") == 0) + { + return false; + } + } while (unzGoToNextFile(uf) == UNZ_OK); + } - for( size_t q = 0; q < notloaded.size(); q++ ) - { - if( !allowLoading( m_packages[notloaded[q]], allow, depth + 1 ) ) - { - return false; + unzClose(uf); + return true; // Zip does not contain a PACKAGE file, therefore + // assume it is a bundle } - } - - m_doNotLoadPackages.removeOne( package.file ); - if( package.optional && !m_optLoadPackages.contains( package.file ) ) - { - m_optLoadPackages.push_back( package.file ); - } + return false; // Extension is not zip or rvpkgs } - else - { - QList loaded; - for( int i = 0; i < package.usedBy.size(); i++ ) - { - int index = package.usedBy[i]; - if( m_packages[index].loadable ) loaded.push_back( index ); - } - - if( depth == 0 && loaded.size() ) - { - QString s( "Packages that would be unloaded:\n" ); + vector PackageManager::handleBundle(const QString& bundlePath, + const QString& outputPath) + { - for( size_t q = 0; q < loaded.size(); q++ ) + // Attempting to unzip bundle into the Packages directory + vector includedPackages = + unzipBundle(bundlePath.toStdString(), outputPath.toStdString()); + if (includedPackages.size() == 0) { - s += m_packages[loaded[q]].name; - s += "\n"; + cerr << "ERROR: Unable to unzip bundle." << endl; + return {}; } - if( !fixUnloadability( s ) ) return false; - } + return includedPackages; + } + + bool PackageManager::m_ignorePrefs = false; - package.loadable = false; + PackageManager::PackageManager() + : m_force(false) + { + } - for( size_t q = 0; q < loaded.size(); q++ ) - { - if( !allowLoading( m_packages[loaded[q]], allow, depth + 1 ) ) + PackageManager::~PackageManager() {} + + int PackageManager::findPackageIndexByZip(const QString& zipfile) + { + QString zipfileCanonical = QFileInfo(zipfile).canonicalFilePath(); + QString pattern = zipfile + "-.*\\.rvpkg"; + QRegExp rx(pattern); + + for (size_t i = 0; i < m_packages.size(); i++) { - return false; + QFileInfo info(m_packages[i].file); + + if (info.fileName() == zipfile || info.absoluteFilePath() == zipfile + || info.absoluteFilePath() == zipfileCanonical + || rx.exactMatch(info.fileName()) + || rx.exactMatch(info.absoluteFilePath())) + { + return i; + } } - } - m_doNotLoadPackages.push_back( package.file ); - m_doNotLoadPackages.removeDuplicates(); - m_optLoadPackages.removeDuplicates(); - m_optLoadPackages.removeOne( package.file ); + return -1; } - // - // Don't read/write settings unless this is the RV app (as opposed to - // rvpkg). - // - if( QCoreApplication::applicationName() == INTERNAL_APPLICATION_NAME ) + bool PackageManager::allowLoading(Package& package, bool allow, int depth) { - RV_QSETTINGS; - settings.beginGroup( "ModeManager" ); - settings.setValue( "doNotLoadPackages", - swapAppDir( m_doNotLoadPackages, true ) ); - settings.setValue( "optionalPackages", - swapAppDir( m_optLoadPackages, true ) ); - settings.endGroup(); - } + if (package.loadable == allow) + return true; - return true; - } + if (allow) + { + QList notloaded; - static bool versionCompatible( QString version, int maj, int min, int rev ) - { - if( version == "" ) return true; + for (int i = 0; i < package.uses.size(); i++) + { + int index = package.uses[i]; + if (!m_packages[index].loadable) + notloaded.push_back(index); + } - int cmajor = -1; - int cminor = -1; - int crev = -1; + if (depth == 0 && notloaded.size()) + { + QString s("Package requires these unloadable packages:\n"); - QStringList parts = version.split( "." ); + for (size_t q = 0; q < notloaded.size(); q++) + { + s += m_packages[notloaded[q]].name; + s += "\n"; + } - if( parts.size() > 0 ) cmajor = parts[0].toUInt(); - if( parts.size() > 1 ) cminor = parts[1].toUInt(); - if( parts.size() > 2 ) crev = parts[2].toUInt(); + if (!fixLoadability(s)) + return false; + } - bool compatible = false; + package.loadable = true; - if( cmajor > -1 ) - { - compatible = cmajor <= maj; + for (size_t q = 0; q < notloaded.size(); q++) + { + if (!allowLoading(m_packages[notloaded[q]], allow, depth + 1)) + { + return false; + } + } - if( cmajor == maj && cminor > -1 ) - { - compatible = cminor <= min; + m_doNotLoadPackages.removeOne(package.file); - if( cminor == min && crev > -1 ) - { - compatible = crev <= rev; + if (package.optional && !m_optLoadPackages.contains(package.file)) + { + m_optLoadPackages.push_back(package.file); + } } - } - } + else + { + QList loaded; - return compatible; - } + for (int i = 0; i < package.usedBy.size(); i++) + { + int index = package.usedBy[i]; + if (m_packages[index].loadable) + loaded.push_back(index); + } - bool PackageManager::installPackage( Package& package ) - { - // - // Checked the dependancies first - // + if (depth == 0 && loaded.size()) + { + QString s("Packages that would be unloaded:\n"); - if( package.installing ) return true; - - QStringList deps = package. - requires - .split( " ", QString::SkipEmptyParts ); - QStringList missing; - QStringList notinstalled; - QFileInfo info( package.file ); - QDir rdir = info.absoluteDir(); - rdir.cdUp(); - - if( !makeSupportDirTree( rdir ) ) return false; - - QDir mudir = rdir; - QDir pydir = rdir; - QDir supportdir = rdir; - QDir imgdir = rdir; - QDir movdir = rdir; - QDir libdir = rdir; - QDir nodedir = rdir; - QDir profdir = rdir; - - m_doNotLoadPackages.removeOne( package.file ); - m_optLoadPackages.removeOne( package.file ); - - mudir.cd( "Mu" ); - pydir.cd( "Python" ); - supportdir.cd( "SupportFiles" ); - imgdir.cd( "ImageFormats" ); - movdir.cd( "MovieFormats" ); - libdir.cd( "lib" ); - nodedir.cd( "Nodes" ); - profdir.cd( "Profiles" ); - - QFileInfo pfile( package.file ); - QString pname = package.baseName; - - if( pname.isEmpty() ) - { - cerr << "ERROR: Illegal package file name: " - << package.file.toUtf8().data() << endl - << " should be either .zip or -.rvpkg" - << endl; - return false; - } + for (size_t q = 0; q < loaded.size(); q++) + { + s += m_packages[loaded[q]].name; + s += "\n"; + } + + if (!fixUnloadability(s)) + return false; + } - if( !supportdir.exists( pname ) ) supportdir.mkdir( pname ); - supportdir.cd( pname ); + package.loadable = false; - // - // Test to see if any of the package files are already there - // + for (size_t q = 0; q < loaded.size(); q++) + { + if (!allowLoading(m_packages[loaded[q]], allow, depth + 1)) + { + return false; + } + } - QStringList existingFiles; + m_doNotLoadPackages.push_back(package.file); + m_doNotLoadPackages.removeDuplicates(); + m_optLoadPackages.removeDuplicates(); + m_optLoadPackages.removeOne(package.file); + } - for( size_t i = 0; i < package.files.size(); i++ ) - { - QString filename = package.files[i]; - string outfilename; - int auxIndex = auxFileIndex( package, filename ); - - // Once it is not an auxfile, the installer expects a flat list structure - // Therefore, need to check for basename and not the file name which - // can include directories - QFileInfo fInfo( filename ); - QString baseName = fInfo.fileName(); - - if( auxIndex != -1 ) - { - const AuxFile& a = package.auxFiles[auxIndex]; - QDir outdir( - rdir.absoluteFilePath( expandVarsInPath( package, a.location ) ) ); - QFileInfo auxfileInfo( a.file ); - QString auxfileName = auxfileInfo.fileName(); - outfilename = - outdir.absoluteFilePath( auxfileName ).toUtf8().constData(); - } - else if( filename.endsWith( ".mu" ) || filename.endsWith( ".mud" ) || - filename.endsWith( ".muc" ) ) - { - outfilename = mudir.absoluteFilePath( baseName ).toUtf8().constData(); - } - else if( filename.endsWith( ".py" ) || filename.endsWith( ".pyc" ) || - filename.endsWith( ".pyo" ) || filename.endsWith( ".pyd" ) ) - { - outfilename = pydir.absoluteFilePath( baseName ).toUtf8().constData(); - } - else if( filename.endsWith( ".glsl" ) || filename.endsWith( ".gto" ) ) - // - // Assume this is a NodeDefinition file (gto) or associated shader code. - // - { - outfilename = nodedir.absoluteFilePath( baseName ).toUtf8().constData(); - } - else if( filename.endsWith( ".profile" ) ) - // - // Assume this is a Profile - // - { - outfilename = profdir.absoluteFilePath( baseName ).toUtf8().constData(); - } - - QString n = QString::fromUtf8( outfilename.c_str(), outfilename.size() ); - QFile file( n ); - - if( file.exists() ) existingFiles.push_back( n ); + // + // Don't read/write settings unless this is the RV app (as opposed to + // rvpkg). + // + if (QCoreApplication::applicationName() == INTERNAL_APPLICATION_NAME) + { + RV_QSETTINGS; + settings.beginGroup("ModeManager"); + settings.setValue("doNotLoadPackages", + swapAppDir(m_doNotLoadPackages, true)); + settings.setValue("optionalPackages", + swapAppDir(m_optLoadPackages, true)); + settings.endGroup(); + } + + return true; } - if( existingFiles.size() ) + static bool versionCompatible(QString version, int maj, int min, int rev) { - QString s( "Package conflicts with these existing files:\n" ); + if (version == "") + return true; - for( size_t q = 0; q < existingFiles.size(); q++ ) - { - s += existingFiles[q]; - s += "\n"; - } + int cmajor = -1; + int cminor = -1; + int crev = -1; - if( !overwriteExistingFiles( s ) ) return false; - } + QStringList parts = version.split("."); - // - // Check dependencies - // + if (parts.size() > 0) + cmajor = parts[0].toUInt(); + if (parts.size() > 1) + cminor = parts[1].toUInt(); + if (parts.size() > 2) + crev = parts[2].toUInt(); - for( size_t i = 0; i < deps.size(); i++ ) - { - QString dep = deps[i]; - int di = findPackageIndexByZip( dep ); - - if( di == -1 ) - { - missing << dep; - } - else if( !m_packages[di].installed ) - { - notinstalled << dep; - } - } + bool compatible = false; - if( missing.size() ) - { - // - // We don't have some packages - // + if (cmajor > -1) + { + compatible = cmajor <= maj; - QString s( "Package requires these missing packages:\n" ); + if (cmajor == maj && cminor > -1) + { + compatible = cminor <= min; - for( size_t q = 0; q < missing.size(); q++ ) - { - s += missing[q]; - s += "\n"; - } + if (cminor == min && crev > -1) + { + compatible = crev <= rev; + } + } + } - errorMissingPackageDependancies( s ); - return false; + return compatible; } - if( notinstalled.size() ) + bool PackageManager::installPackage(Package& package) { - // - // Required packages not installed but available - // + // + // Checked the dependancies first + // - QString s( "Package requires these uninstalled packages:\n" ); + if (package.installing) + return true; - for( size_t q = 0; q < notinstalled.size(); q++ ) - { - s += notinstalled[q]; - s += "\n"; - } + QStringList deps = package. + requires + .split(" ", QString::SkipEmptyParts); + QStringList missing; + QStringList notinstalled; + QFileInfo info(package.file); + QDir rdir = info.absoluteDir(); + rdir.cdUp(); - if( !installDependantPackages( s ) ) return false; + if (!makeSupportDirTree(rdir)) + return false; - // - // Try and install them recursively - // + QDir mudir = rdir; + QDir pydir = rdir; + QDir supportdir = rdir; + QDir imgdir = rdir; + QDir movdir = rdir; + QDir libdir = rdir; + QDir nodedir = rdir; + QDir profdir = rdir; + + m_doNotLoadPackages.removeOne(package.file); + m_optLoadPackages.removeOne(package.file); + + mudir.cd("Mu"); + pydir.cd("Python"); + supportdir.cd("SupportFiles"); + imgdir.cd("ImageFormats"); + movdir.cd("MovieFormats"); + libdir.cd("lib"); + nodedir.cd("Nodes"); + profdir.cd("Profiles"); + + QFileInfo pfile(package.file); + QString pname = package.baseName; + + if (pname.isEmpty()) + { + cerr << "ERROR: Illegal package file name: " + << package.file.toUtf8().data() << endl + << " should be either .zip or " + "-.rvpkg" + << endl; + return false; + } - package.installing = true; + if (!supportdir.exists(pname)) + supportdir.mkdir(pname); + supportdir.cd(pname); + + // + // Test to see if any of the package files are already there + // - for( size_t q = 0; q < notinstalled.size(); q++ ) - { - int di = findPackageIndexByZip( notinstalled[q] ); + QStringList existingFiles; - if( !installPackage( m_packages[di] ) ) + for (size_t i = 0; i < package.files.size(); i++) { - break; - } - } + QString filename = package.files[i]; + string outfilename; + int auxIndex = auxFileIndex(package, filename); - package.installing = false; - } + // Once it is not an auxfile, the installer expects a flat list + // structure Therefore, need to check for basename and not the file + // name which can include directories + QFileInfo fInfo(filename); + QString baseName = fInfo.fileName(); - // - // Loop over the files in the zip file - // + if (auxIndex != -1) + { + const AuxFile& a = package.auxFiles[auxIndex]; + QDir outdir(rdir.absoluteFilePath( + expandVarsInPath(package, a.location))); + QFileInfo auxfileInfo(a.file); + QString auxfileName = auxfileInfo.fileName(); + outfilename = + outdir.absoluteFilePath(auxfileName).toUtf8().constData(); + } + else if (filename.endsWith(".mu") || filename.endsWith(".mud") + || filename.endsWith(".muc")) + { + outfilename = + mudir.absoluteFilePath(baseName).toUtf8().constData(); + } + else if (filename.endsWith(".py") || filename.endsWith(".pyc") + || filename.endsWith(".pyo") || filename.endsWith(".pyd")) + { + outfilename = + pydir.absoluteFilePath(baseName).toUtf8().constData(); + } + else if (filename.endsWith(".glsl") || filename.endsWith(".gto")) + // + // Assume this is a NodeDefinition file (gto) or associated shader + // code. + // + { + outfilename = + nodedir.absoluteFilePath(baseName).toUtf8().constData(); + } + else if (filename.endsWith(".profile")) + // + // Assume this is a Profile + // + { + outfilename = + profdir.absoluteFilePath(baseName).toUtf8().constData(); + } - bool fbio = false; + QString n = + QString::fromUtf8(outfilename.c_str(), outfilename.size()); + QFile file(n); - if( unzFile file = unzOpen( package.file.toUtf8().data() ) ) - { - for( size_t i = 0; i < package.files.size(); i++ ) - { - QString filename = package.files[i]; - QFileInfo fInfo( filename ); - QString baseName = fInfo.fileName(); - vector buffer( 4096 ); + if (file.exists()) + existingFiles.push_back(n); + } - if( unzLocateFile( file, filename.toUtf8().data(), 1 ) != UNZ_OK ) + if (existingFiles.size()) { - cerr << "ERROR: reading zip file " << package.file.toUtf8().data() - << endl; - break; - } + QString s("Package conflicts with these existing files:\n"); - unzOpenCurrentFile( file ); + for (size_t q = 0; q < existingFiles.size(); q++) + { + s += existingFiles[q]; + s += "\n"; + } - string outfilename; - int auxIndex = auxFileIndex( package, filename ); + if (!overwriteExistingFiles(s)) + return false; + } + + // + // Check dependencies + // - if( auxIndex != -1 ) + for (size_t i = 0; i < deps.size(); i++) { - const AuxFile& a = package.auxFiles[auxIndex]; - QDir outdir( rdir.absoluteFilePath( - expandVarsInPath( package, a.location ) ) ); - if( !outdir.exists() ) - { - bool success = outdir.mkpath( "." ); - if( !success ) + QString dep = deps[i]; + int di = findPackageIndexByZip(dep); + + if (di == -1) { - cerr << "ERROR: Failed to create needed auxiliary directory: " + - outdir.absolutePath().toStdString() - << endl; + missing << dep; + } + else if (!m_packages[di].installed) + { + notinstalled << dep; } - } - QFileInfo auxfileInfo( a.file ); - QString auxfileName = auxfileInfo.fileName(); - outfilename = - outdir.absoluteFilePath( auxfileName ).toUtf8().constData(); - } - else if( filename.endsWith( ".mu" ) || filename.endsWith( ".mud" ) || - filename.endsWith( ".muc" ) ) - { - outfilename = mudir.absoluteFilePath( baseName ).toUtf8().data(); } - else if( filename.endsWith( ".py" ) || filename.endsWith( ".pyc" ) || - filename.endsWith( ".pyo" ) || filename.endsWith( ".pyd" ) ) + + if (missing.size()) { - outfilename = pydir.absoluteFilePath( baseName ).toUtf8().data(); + // + // We don't have some packages + // + + QString s("Package requires these missing packages:\n"); + + for (size_t q = 0; q < missing.size(); q++) + { + s += missing[q]; + s += "\n"; + } + + errorMissingPackageDependancies(s); + return false; } - else if( filename.endsWith( ".so" ) || filename.endsWith( ".dll" ) || - filename.endsWith( ".dylib" ) ) + + if (notinstalled.size()) { - if( package.imageio.contains( filename ) ) - { - outfilename = imgdir.absoluteFilePath( baseName ).toUtf8().data(); - fbio = true; - } - else if( package.movieio.contains( filename ) ) - { - outfilename = movdir.absoluteFilePath( baseName ).toUtf8().data(); - } - else - { - for( size_t q = 0; q < package.modes.size(); q++ ) + // + // Required packages not installed but available + // + + QString s("Package requires these uninstalled packages:\n"); + + for (size_t q = 0; q < notinstalled.size(); q++) { - if( package.modes[q].file == filename ) - { - outfilename = - mudir.absoluteFilePath( baseName ).toUtf8().data(); - } + s += notinstalled[q]; + s += "\n"; + } + + if (!installDependantPackages(s)) + return false; + + // + // Try and install them recursively + // + + package.installing = true; + + for (size_t q = 0; q < notinstalled.size(); q++) + { + int di = findPackageIndexByZip(notinstalled[q]); + + if (!installPackage(m_packages[di])) + { + break; + } } - } - if( outfilename == "" ) - { - outfilename = libdir.absoluteFilePath( baseName ).toUtf8().data(); - } + package.installing = false; } - else if( filename.endsWith( ".glsl" ) || filename.endsWith( ".gto" ) ) + // - // Assume this is a NodeDefinition file (gto) or associated shader - // code. + // Loop over the files in the zip file // + + bool fbio = false; + + if (unzFile file = unzOpen(package.file.toUtf8().data())) { - outfilename = - nodedir.absoluteFilePath( baseName ).toUtf8().constData(); + for (size_t i = 0; i < package.files.size(); i++) + { + QString filename = package.files[i]; + QFileInfo fInfo(filename); + QString baseName = fInfo.fileName(); + vector buffer(4096); + + if (unzLocateFile(file, filename.toUtf8().data(), 1) != UNZ_OK) + { + cerr << "ERROR: reading zip file " + << package.file.toUtf8().data() << endl; + break; + } + + unzOpenCurrentFile(file); + + string outfilename; + int auxIndex = auxFileIndex(package, filename); + + if (auxIndex != -1) + { + const AuxFile& a = package.auxFiles[auxIndex]; + QDir outdir(rdir.absoluteFilePath( + expandVarsInPath(package, a.location))); + if (!outdir.exists()) + { + bool success = outdir.mkpath("."); + if (!success) + { + cerr << "ERROR: Failed to create needed auxiliary " + "directory: " + + outdir.absolutePath().toStdString() + << endl; + } + } + QFileInfo auxfileInfo(a.file); + QString auxfileName = auxfileInfo.fileName(); + outfilename = outdir.absoluteFilePath(auxfileName) + .toUtf8() + .constData(); + } + else if (filename.endsWith(".mu") || filename.endsWith(".mud") + || filename.endsWith(".muc")) + { + outfilename = + mudir.absoluteFilePath(baseName).toUtf8().data(); + } + else if (filename.endsWith(".py") || filename.endsWith(".pyc") + || filename.endsWith(".pyo") + || filename.endsWith(".pyd")) + { + outfilename = + pydir.absoluteFilePath(baseName).toUtf8().data(); + } + else if (filename.endsWith(".so") || filename.endsWith(".dll") + || filename.endsWith(".dylib")) + { + if (package.imageio.contains(filename)) + { + outfilename = + imgdir.absoluteFilePath(baseName).toUtf8().data(); + fbio = true; + } + else if (package.movieio.contains(filename)) + { + outfilename = + movdir.absoluteFilePath(baseName).toUtf8().data(); + } + else + { + for (size_t q = 0; q < package.modes.size(); q++) + { + if (package.modes[q].file == filename) + { + outfilename = mudir.absoluteFilePath(baseName) + .toUtf8() + .data(); + } + } + } + + if (outfilename == "") + { + outfilename = + libdir.absoluteFilePath(baseName).toUtf8().data(); + } + } + else if (filename.endsWith(".glsl") + || filename.endsWith(".gto")) + // + // Assume this is a NodeDefinition file (gto) or associated + // shader code. + // + { + outfilename = + nodedir.absoluteFilePath(baseName).toUtf8().constData(); + } + else if (filename.endsWith(".profile")) + { + outfilename = + profdir.absoluteFilePath(baseName).toUtf8().constData(); + } + else + { + outfilename = + supportdir.absoluteFilePath(baseName).toUtf8().data(); + } + + ofstream outfile(UNICODE_C_STR(outfilename.c_str()), + ios::binary); + + while (1) + { + int read = unzReadCurrentFile(file, &buffer.front(), + buffer.size()); + if (read == 0) + break; + else + outfile.write(&buffer.front(), read); + } + + if (fbio) + { + string makeFBIO = + TwkApp::Bundle::mainBundle()->executableFile( + "makeFBIOformats"); + QFileInfo info(outfilename.c_str()); + QString dir = info.dir().absolutePath(); + string cmd = makeFBIO; + cmd += " "; + cmd += dir.toUtf8().constData(); + + if (system(cmd.c_str()) == -1) + { + cerr << "ERROR: executing command " << cmd << endl; + } + + // QProcess process; + // QStringList args; + // args.push_back(dir); + // args.push_back(dir); + // process.start(makeFBIO.c_str(), args); + // process.waitForFinished(); + } + } + + unzClose(file); } - else if( filename.endsWith( ".profile" ) ) + + // + // Load the mode file (rvload) which needs to be updated + // + + QString rvloadV1 = mudir.absoluteFilePath("rvload"); + ModeEntryList mlistV1 = loadModeFile(rvloadV1); + QString rvloadV2 = mudir.absoluteFilePath("rvload2"); + ModeEntryList mlistV2 = loadModeFile(rvloadV2); + + for (size_t i = 0; i < package.modes.size(); i++) { - outfilename = - profdir.absoluteFilePath( baseName ).toUtf8().constData(); + const Mode& mode = package.modes[i]; + QString name = mode.file; + if (name.endsWith(".mu") || name.endsWith(".py")) + name.remove(name.size() - 3, 3); + + // + // Just as a sanity check -- if there's already an entry for this + // mode for some reason just delete the old one + // + + for (int q = mlistV1.size() - 1; q >= 0; q--) + { + if (mlistV1[q].name == name) + { + cerr << "WARNING: removing duplicate mode entry in " + << rvloadV1.toUtf8().data() << " for mode " + << name.toUtf8().data() << endl; + + mlistV1.erase(mlistV1.begin() + q); + } + } + for (int q = mlistV2.size() - 1; q >= 0; q--) + { + if (mlistV2[q].name == name) + { + cerr << "WARNING: removing duplicate mode entry in " + << rvloadV2.toUtf8().data() << " for mode " + << name.toUtf8().data() << endl; + + mlistV2.erase(mlistV2.begin() + q); + } + } + + QFileInfo pfile(package.file); + + ModeEntry entry; + entry.name = name; + entry.package = pfile.fileName(); + entry.menu = mode.menu; + entry.shortcut = mode.shortcut; + entry.event = mode.event; + entry. + requires + = mode. + requires; + entry.rvversion = package.rvversion; + entry.openrvversion = package.openrvversion; + entry.optional = package.optional; + + if (mode.load == "delay") + { + entry.loaded = false; + entry.active = false; + } + else if (mode.load == "immediate") + { + entry.loaded = true; + entry.active = true; + } + + if (versionCompatible(entry.rvversion, 3, 7, 99)) + mlistV1.push_back(entry); + else + mlistV2.push_back(entry); } - else + + // + // Write the mode file back out + // + + writeModeFile(rvloadV1, mlistV1, 1); + writeModeFile(rvloadV2, mlistV2); + package.installed = true; + + // + // Write the installation record + // + + QFileInfo rinfo(package.file); + writeInstallationFile( + rinfo.absoluteDir().absoluteFilePath("rvinstall")); + + return true; + } + + bool PackageManager::makeSupportDirTree(QDir& root) + { + const char* dirs[] = {"Mu", "Python", "SupportFiles", + "ConfigFiles", "ImageFormats", "MovieFormats", + "Packages", "lib", "libquicktime", + "Nodes", "Profiles", NULL}; + + for (const char** d = dirs; *d; d++) { - outfilename = supportdir.absoluteFilePath( baseName ).toUtf8().data(); + if (!root.exists(*d)) + { + if (!root.mkdir(*d)) + { + // QMessageBox::critical(this, + // QString("Support Directory Creation + // Failed"), QString("Unable to create + // %1 in directory + // %2\n").arg(QString(*d)).arg(root.absolutePath())); + return false; + } + } } - ofstream outfile( UNICODE_C_STR( outfilename.c_str() ), ios::binary ); + return true; + } - while( 1 ) + bool PackageManager::uninstallPackage(Package& package) + { + if (package.installing) + return true; + QFileInfo info(package.file); + QDir rdir = info.absoluteDir(); + rdir.cdUp(); + QDir mudir = rdir; + QDir pydir = rdir; + QDir supportdir = rdir; + QDir imgdir = rdir; + QDir movdir = rdir; + QDir libdir = rdir; + QDir nodedir = rdir; + QDir profdir = rdir; + + mudir.cd("Mu"); + pydir.cd("Python"); + supportdir.cd("SupportFiles"); + imgdir.cd("ImageFormats"); + movdir.cd("MovieFormats"); + libdir.cd("lib"); + nodedir.cd("Nodes"); + profdir.cd("Nodes"); + + QFileInfo pfile(package.file); + QRegExp rvpkgRE("(.*)-[0-9]+\\.[0-9]+\\.rvpkg"); + QRegExp zipRE("(.*)\\.zip"); + QRegExp rvpkgsRE("(.*)-[0-9]+\\.[0-9]+\\.rvpkgs"); + QString pname = package.baseName; + + if (!supportdir.exists(pname)) + supportdir.mkdir(pname); + supportdir.cd(pname); + + QList others; + + for (size_t i = 0; i < package.usedBy.size(); i++) { - int read = unzReadCurrentFile( file, &buffer.front(), buffer.size() ); - if( read == 0 ) - break; - else - outfile.write( &buffer.front(), read ); + int index = package.usedBy[i]; + const Package& other = m_packages[index]; + if (other.installed) + others.push_back(index); } - if( fbio ) + if (others.size()) { - string makeFBIO = - TwkApp::Bundle::mainBundle()->executableFile( "makeFBIOformats" ); - QFileInfo info( outfilename.c_str() ); - QString dir = info.dir().absolutePath(); - string cmd = makeFBIO; - cmd += " "; - cmd += dir.toUtf8().constData(); + // + // Packages that depend on this one are installed + // + + QString s("Package is used by these installed packages:\n"); - if( system( cmd.c_str() ) == -1 ) - { - cerr << "ERROR: executing command " << cmd << endl; - } + for (size_t q = 0; q < others.size(); q++) + { + s += m_packages[others[q]].file; + s += "("; + s += m_packages[others[q]].name; + s += ")\n"; + } - // QProcess process; - // QStringList args; - // args.push_back(dir); - // args.push_back(dir); - // process.start(makeFBIO.c_str(), args); - // process.waitForFinished(); + if (!uninstallDependantPackages(s)) + return false; } - } - unzClose( file ); - } + for (size_t i = 0; i < others.size(); i++) + { + uninstallPackage(m_packages[others[i]]); + } - // - // Load the mode file (rvload) which needs to be updated - // + // + // Loop over the files and remove them (if possible) + // - QString rvloadV1 = mudir.absoluteFilePath( "rvload" ); - ModeEntryList mlistV1 = loadModeFile( rvloadV1 ); - QString rvloadV2 = mudir.absoluteFilePath( "rvload2" ); - ModeEntryList mlistV2 = loadModeFile( rvloadV2 ); + QStringList notremoved; - for( size_t i = 0; i < package.modes.size(); i++ ) - { - const Mode& mode = package.modes[i]; - QString name = mode.file; - if( name.endsWith( ".mu" ) || name.endsWith( ".py" ) ) - name.remove( name.size() - 3, 3 ); - - // - // Just as a sanity check -- if there's already an entry for this - // mode for some reason just delete the old one - // - - for( int q = mlistV1.size() - 1; q >= 0; q-- ) - { - if( mlistV1[q].name == name ) - { - cerr << "WARNING: removing duplicate mode entry in " - << rvloadV1.toUtf8().data() << " for mode " - << name.toUtf8().data() << endl; - - mlistV1.erase( mlistV1.begin() + q ); - } - } - for( int q = mlistV2.size() - 1; q >= 0; q-- ) - { - if( mlistV2[q].name == name ) - { - cerr << "WARNING: removing duplicate mode entry in " - << rvloadV2.toUtf8().data() << " for mode " - << name.toUtf8().data() << endl; - - mlistV2.erase( mlistV2.begin() + q ); - } - } - - QFileInfo pfile( package.file ); - - ModeEntry entry; - entry.name = name; - entry.package = pfile.fileName(); - entry.menu = mode.menu; - entry.shortcut = mode.shortcut; - entry.event = mode.event; - entry. - requires - = mode. - requires; - entry.rvversion = package.rvversion; - entry.openrvversion = package.openrvversion; - entry.optional = package.optional; - - if( mode.load == "delay" ) - { - entry.loaded = false; - entry.active = false; - } - else if( mode.load == "immediate" ) - { - entry.loaded = true; - entry.active = true; - } - - if( versionCompatible( entry.rvversion, 3, 7, 99 ) ) - mlistV1.push_back( entry ); - else - mlistV2.push_back( entry ); - } + for (size_t i = 0; i < package.files.size(); i++) + { + QString outfilename; + QString filename = package.files[i]; + QFileInfo fInfo(filename); + QString baseName = fInfo.fileName(); - // - // Write the mode file back out - // + QStringList auxfiles; + int auxIndex = auxFileIndex(package, filename); - writeModeFile( rvloadV1, mlistV1, 1 ); - writeModeFile( rvloadV2, mlistV2 ); - package.installed = true; + if (auxIndex != -1) + { + const AuxFile& a = package.auxFiles[auxIndex]; + QDir outdir(rdir.absoluteFilePath( + expandVarsInPath(package, a.location))); + QFileInfo auxfileInfo(a.file); + QString auxfileName = auxfileInfo.fileName(); + outfilename = + outdir.absoluteFilePath(auxfileName).toUtf8().constData(); + } + else if (filename.endsWith(".mu") || filename.endsWith(".mud") + || filename.endsWith(".muc")) + { + outfilename = mudir.absoluteFilePath(baseName); - // - // Write the installation record - // + if (filename.endsWith(".mu")) + { + baseName.chop(3); + auxfiles.push_back( + mudir.absoluteFilePath(baseName + QString(".muc"))); + auxfiles.push_back( + mudir.absoluteFilePath(baseName + QString(".mud"))); + auxfiles.push_back( + mudir.absoluteFilePath(baseName + QString(".so"))); + } + } + else if (filename.endsWith(".py") || filename.endsWith(".pyc") + || filename.endsWith(".pyo") || filename.endsWith(".pyd")) + { + outfilename = pydir.absoluteFilePath(baseName); + + if (filename.endsWith(".py")) + { + baseName.chop(3); + auxfiles.push_back( + pydir.absoluteFilePath(baseName + QString(".pyc"))); + auxfiles.push_back( + pydir.absoluteFilePath(baseName + QString(".pyd"))); + auxfiles.push_back( + pydir.absoluteFilePath(baseName + QString(".pyo"))); + } + } + else if (filename.endsWith(".so") || filename.endsWith(".dll") + || filename.endsWith(".dylib")) + { + if (package.imageio.contains(filename)) + { + outfilename = imgdir.absoluteFilePath(baseName); + } + else if (package.movieio.contains(filename)) + { + outfilename = movdir.absoluteFilePath(baseName); + } + else + { + for (size_t q = 0; q < package.modes.size(); q++) + { + if (package.modes[q].file == filename) + { + outfilename = mudir.absoluteFilePath(baseName); + } + } + } - QFileInfo rinfo( package.file ); - writeInstallationFile( - rinfo.absoluteDir().absoluteFilePath( "rvinstall" ) ); + if (outfilename == "") + { + outfilename = libdir.absoluteFilePath(baseName); + } + } + else if (filename.endsWith(".glsl") || filename.endsWith(".gto")) + // + // Assume this is a NodeDefinition file (gto) or associated shader + // code. + // + { + outfilename = nodedir.absoluteFilePath(baseName); + } + else if (filename.endsWith(".profile")) + { + outfilename = profdir.absoluteFilePath(baseName); + } + else + { + outfilename = supportdir.absoluteFilePath(baseName); + } - return true; - } + QFile file(outfilename); + if (!file.remove()) + notremoved.push_back(outfilename); - bool PackageManager::makeSupportDirTree( QDir& root ) - { - const char* dirs[] = { "Mu", "Python", "SupportFiles", - "ConfigFiles", "ImageFormats", "MovieFormats", - "Packages", "lib", "libquicktime", - "Nodes", "Profiles", NULL }; + // + // Check for and remove any generated files (e.g. .pyc files + // created by python). + // - for( const char** d = dirs; *d; d++ ) - { - if( !root.exists( *d ) ) - { - if( !root.mkdir( *d ) ) - { - // QMessageBox::critical(this, - // QString("Support Directory Creation Failed"), - // QString("Unable to create %1 in directory - // %2\n").arg(QString(*d)).arg(root.absolutePath())); - return false; + for (size_t i = 0; i < auxfiles.size(); i++) + { + QFile file(auxfiles[i]); + if (file.exists()) + file.remove(); + } } - } - } - return true; - } - - bool PackageManager::uninstallPackage( Package& package ) - { - if( package.installing ) return true; - QFileInfo info( package.file ); - QDir rdir = info.absoluteDir(); - rdir.cdUp(); - QDir mudir = rdir; - QDir pydir = rdir; - QDir supportdir = rdir; - QDir imgdir = rdir; - QDir movdir = rdir; - QDir libdir = rdir; - QDir nodedir = rdir; - QDir profdir = rdir; - - mudir.cd( "Mu" ); - pydir.cd( "Python" ); - supportdir.cd( "SupportFiles" ); - imgdir.cd( "ImageFormats" ); - movdir.cd( "MovieFormats" ); - libdir.cd( "lib" ); - nodedir.cd( "Nodes" ); - profdir.cd( "Nodes" ); - - QFileInfo pfile( package.file ); - QRegExp rvpkgRE( "(.*)-[0-9]+\\.[0-9]+\\.rvpkg" ); - QRegExp zipRE( "(.*)\\.zip" ); - QRegExp rvpkgsRE( "(.*)-[0-9]+\\.[0-9]+\\.rvpkgs" ); - QString pname = package.baseName; - - if( !supportdir.exists( pname ) ) supportdir.mkdir( pname ); - supportdir.cd( pname ); - - QList others; - - for( size_t i = 0; i < package.usedBy.size(); i++ ) - { - int index = package.usedBy[i]; - const Package& other = m_packages[index]; - if( other.installed ) others.push_back( index ); - } + // + // Remove the dangling supportdir + // - if( others.size() ) - { - // - // Packages that depend on this one are installed - // + if (!supportdir.removeRecursively()) + notremoved.push_back(supportdir.absolutePath()); + + // + // Report what was unremovable + // - QString s( "Package is used by these installed packages:\n" ); + if (notremoved.size()) + { + QString s("Files which could not be removed:\n"); - for( size_t q = 0; q < others.size(); q++ ) - { - s += m_packages[others[q]].file; - s += "("; - s += m_packages[others[q]].name; - s += ")\n"; - } + for (size_t q = 0; q < notremoved.size(); q++) + { + s += notremoved[q]; + s += "\n"; + } - if( !uninstallDependantPackages( s ) ) return false; - } + informCannotRemoveSomeFiles(s); + } - for( size_t i = 0; i < others.size(); i++ ) - { - uninstallPackage( m_packages[others[i]] ); - } + // + // Purge the mode entries of this package + // - // - // Loop over the files and remove them (if possible) - // + QString rvloadV1 = mudir.absoluteFilePath("rvload"); + ModeEntryList mlistV1 = loadModeFile(rvloadV1); + QString rvloadV2 = mudir.absoluteFilePath("rvload2"); + ModeEntryList mlistV2 = loadModeFile(rvloadV2); - QStringList notremoved; + QFileInfo finfo(package.file); + QString packageZip = finfo.fileName(); - for( size_t i = 0; i < package.files.size(); i++ ) - { - QString outfilename; - QString filename = package.files[i]; - QFileInfo fInfo( filename ); - QString baseName = fInfo.fileName(); - - QStringList auxfiles; - int auxIndex = auxFileIndex( package, filename ); - - if( auxIndex != -1 ) - { - const AuxFile& a = package.auxFiles[auxIndex]; - QDir outdir( - rdir.absoluteFilePath( expandVarsInPath( package, a.location ) ) ); - QFileInfo auxfileInfo( a.file ); - QString auxfileName = auxfileInfo.fileName(); - outfilename = - outdir.absoluteFilePath( auxfileName ).toUtf8().constData(); - } - else if( filename.endsWith( ".mu" ) || filename.endsWith( ".mud" ) || - filename.endsWith( ".muc" ) ) - { - outfilename = mudir.absoluteFilePath( baseName ); - - if( filename.endsWith( ".mu" ) ) - { - baseName.chop( 3 ); - auxfiles.push_back( - mudir.absoluteFilePath( baseName + QString( ".muc" ) ) ); - auxfiles.push_back( - mudir.absoluteFilePath( baseName + QString( ".mud" ) ) ); - auxfiles.push_back( - mudir.absoluteFilePath( baseName + QString( ".so" ) ) ); - } - } - else if( filename.endsWith( ".py" ) || filename.endsWith( ".pyc" ) || - filename.endsWith( ".pyo" ) || filename.endsWith( ".pyd" ) ) - { - outfilename = pydir.absoluteFilePath( baseName ); - - if( filename.endsWith( ".py" ) ) - { - baseName.chop( 3 ); - auxfiles.push_back( - pydir.absoluteFilePath( baseName + QString( ".pyc" ) ) ); - auxfiles.push_back( - pydir.absoluteFilePath( baseName + QString( ".pyd" ) ) ); - auxfiles.push_back( - pydir.absoluteFilePath( baseName + QString( ".pyo" ) ) ); - } - } - else if( filename.endsWith( ".so" ) || filename.endsWith( ".dll" ) || - filename.endsWith( ".dylib" ) ) - { - if( package.imageio.contains( filename ) ) - { - outfilename = imgdir.absoluteFilePath( baseName ); - } - else if( package.movieio.contains( filename ) ) - { - outfilename = movdir.absoluteFilePath( baseName ); + for (int q = mlistV1.size() - 1; q >= 0; q--) + { + if (mlistV1[q].package == packageZip) + { + mlistV1.erase(mlistV1.begin() + q); + } } - else + for (int q = mlistV2.size() - 1; q >= 0; q--) { - for( size_t q = 0; q < package.modes.size(); q++ ) - { - if( package.modes[q].file == filename ) - { - outfilename = mudir.absoluteFilePath( baseName ); - } - } - } - - if( outfilename == "" ) - { - outfilename = libdir.absoluteFilePath( baseName ); - } - } - else if( filename.endsWith( ".glsl" ) || filename.endsWith( ".gto" ) ) - // - // Assume this is a NodeDefinition file (gto) or associated shader code. - // - { - outfilename = nodedir.absoluteFilePath( baseName ); - } - else if( filename.endsWith( ".profile" ) ) - { - outfilename = profdir.absoluteFilePath( baseName ); - } - else - { - outfilename = supportdir.absoluteFilePath( baseName ); - } - - QFile file( outfilename ); - if( !file.remove() ) notremoved.push_back( outfilename ); - - // - // Check for and remove any generated files (e.g. .pyc files - // created by python). - // - - for( size_t i = 0; i < auxfiles.size(); i++ ) - { - QFile file( auxfiles[i] ); - if( file.exists() ) file.remove(); - } - } + if (mlistV2[q].package == packageZip) + { + mlistV2.erase(mlistV2.begin() + q); + } + } - // - // Remove the dangling supportdir - // + writeModeFile(rvloadV1, mlistV1, 1); + writeModeFile(rvloadV2, mlistV2); - if( !supportdir.removeRecursively() ) - notremoved.push_back( supportdir.absolutePath() ); + // + // Update the install file + // - // - // Report what was unremovable - // + package.installed = false; + QFileInfo rinfo(package.file); + writeInstallationFile( + rinfo.absoluteDir().absoluteFilePath("rvinstall")); + + return true; + } - if( notremoved.size() ) + // Called on every package on Preference menu load and everytime a new + // package or bundle is added + void PackageManager::loadPackageInfo(const QString& infileNonCanonical) { - QString s( "Files which could not be removed:\n" ); - for( size_t q = 0; q < notremoved.size(); q++ ) - { - s += notremoved[q]; - s += "\n"; - } + if (findPackageIndexByZip(infileNonCanonical) == -1) + { + // + // Under Windows, using canonical file pathing + // for unzOpen can sometimes fail if the path + // contains a symlink to a UNC mapped dir. + // e.g. 'rvpkgs -> \\server\plugins\rvpkgs'. + // So if unzOpen is unsuccessful using the canonical + // file path we try again with the original + // non-canonical absolute file path. + + // NB: The file path we use for m_packages + // i.e. 'infile' should be the file path that was + // successful for unzOpen(). + // + QString infile = QFileInfo(infileNonCanonical).canonicalFilePath(); + unzFile file = unzOpen(infile.toUtf8().data()); + if (!file) + { + infile = QFileInfo(infileNonCanonical).absoluteFilePath(); + file = unzOpen(infile.toUtf8().data()); + } - informCannotRemoveSomeFiles( s ); - } + if (file) + { + vector buffer; + m_packages.push_back(Package()); + m_packages.back().file = infile; + m_packageMap.insert(infile, m_packages.size() - 1); - // - // Purge the mode entries of this package - // + QFileInfo finfo(infile); - QString rvloadV1 = mudir.absoluteFilePath( "rvload" ); - ModeEntryList mlistV1 = loadModeFile( rvloadV1 ); - QString rvloadV2 = mudir.absoluteFilePath( "rvload2" ); - ModeEntryList mlistV2 = loadModeFile( rvloadV2 ); + m_packages.back().fileWritable = TwkUtil::isWritable( + TwkQtCoreUtil::UTF8::qconvert(infile).c_str()); + m_packages.back().dirWritable = TwkUtil::isWritable( + TwkQtCoreUtil::UTF8::qconvert(finfo.absolutePath()) + .c_str()); - QFileInfo finfo( package.file ); - QString packageZip = finfo.fileName(); + unz_global_info info; + unzGetGlobalInfo(file, &info); - for( int q = mlistV1.size() - 1; q >= 0; q-- ) - { - if( mlistV1[q].package == packageZip ) - { - mlistV1.erase( mlistV1.begin() + q ); - } - } - for( int q = mlistV2.size() - 1; q >= 0; q-- ) - { - if( mlistV2[q].package == packageZip ) - { - mlistV2.erase( mlistV2.begin() + q ); - } - } + unzLocateFile(file, "PACKAGE", 1); + unzOpenCurrentFile(file); - writeModeFile( rvloadV1, mlistV1, 1 ); - writeModeFile( rvloadV2, mlistV2 ); + unzGoToFirstFile(file); - // - // Update the install file - // + QStringList files; - package.installed = false; - QFileInfo rinfo( package.file ); - writeInstallationFile( - rinfo.absoluteDir().absoluteFilePath( "rvinstall" ) ); + do + { + // unz_file_info info; + char temp[256]; + unzGetCurrentFileInfo(file, NULL /*&info*/, temp, 256, NULL, + 0, NULL, 0); + temp[255] = 0; + files.push_back(temp); + QString f = temp; + + // Check if it's a directory + QFileInfo fInfo(f); + if (!finfo.isDir()) + { + if (f != "PACKAGE") + m_packages.back().files.push_back(f); + } + } while (unzGoToNextFile(file) == UNZ_OK); + + while (!unzeof(file)) + { + buffer.resize(buffer.size() + 256); + int read = + unzReadCurrentFile(file, &buffer.back() - 255, 256); + if (read != 256) + buffer.resize(buffer.size() - 256 + read); + } - return true; - } + unzClose(file); - // Called on every package on Preference menu load and everytime a new package or bundle is added - void PackageManager::loadPackageInfo( const QString& infileNonCanonical ) - { + if (!buffer.empty()) + { + yaml_parser_t parser; + yaml_event_t input_event; + memset(&parser, 0, sizeof(parser)); + memset(&input_event, 0, sizeof(input_event)); + + if (!yaml_parser_initialize(&parser)) + { + cerr << "ERROR: Could not initialize the YAML parser " + "object" + << endl; + return; + } + + yaml_parser_set_input_string( + &parser, (const unsigned char*)&buffer.front(), + buffer.size()); + + Package& package = m_packages.back(); + package.installed = false; + package.hidden = false; + package.system = false; + package.optional = false; + package.openrvversion = "1.0.0"; + bool modeState = false; + bool auxFileState = false; + bool auxFolderState = false; + bool valueState = false; + QString pname; + QString auxFile; + QString auxFolder; + + for (bool done = false; !done;) + { + if (!yaml_parser_parse(&parser, &input_event)) + { + cerr << "ERROR: YAML parser failed on PACKAGE file " + "in " + << infile.toStdString() << endl; + break; + } + + if (input_event.type == YAML_STREAM_END_EVENT) + done = true; + + switch (input_event.type) + { + case YAML_STREAM_START_EVENT: + case YAML_STREAM_END_EVENT: + case YAML_DOCUMENT_START_EVENT: + case YAML_DOCUMENT_END_EVENT: + case YAML_ALIAS_EVENT: + break; + case YAML_SEQUENCE_START_EVENT: + // cout << "seq start" << endl; + break; + case YAML_SEQUENCE_END_EVENT: + // cout << "seq end" << endl; + if (modeState) + modeState = false; + if (auxFileState) + auxFileState = false; + if (auxFolderState) + auxFolderState = false; + break; + case YAML_MAPPING_START_EVENT: + // cout << "map start" << endl; + if (modeState) + package.modes.push_back(Mode()); + else if (auxFileState) + { + package.auxFiles.push_back(AuxFile()); + package.auxFiles.back().file = auxFile; + } + else if (auxFolderState) + { + package.auxFolders.push_back(AuxFolder()); + package.auxFolders.back().folder = auxFolder; + } + break; + case YAML_MAPPING_END_EVENT: + // cout << "map end" << endl; + break; + case YAML_SCALAR_EVENT: + { + QString v = QString::fromUtf8( + (const char*)input_event.data.scalar.value); + // cout << "scalar " << v.toUtf8().data() << endl; + + if (!valueState) + { + pname = v; + + if (v == "modes") + modeState = true; + else if (v == "files") + auxFileState = true; + else if (v == "folders") + auxFolderState = true; + else + valueState = true; + } + else if (modeState) + { + if (package.modes.size()) + { + Mode& m = package.modes.back(); + + if (pname == "file") + m.file = v; + else if (pname == "menu") + m.menu = v; + else if (pname == "shortcut") + m.shortcut = v; + else if (pname == "event") + m.event = v; + else if (pname == "load") + m.load = v; + else if (pname == "icon") + m.icon = v; + else if (pname == "requires") + m. + requires + = v.split(" "); + } + + valueState = false; + } + else if (auxFileState) + { + if (package.auxFiles.size()) + { + AuxFile& a = package.auxFiles.back(); + if (pname == "file") + a.file = v; + else if (pname == "location") + a.location = v; + } + + valueState = false; + } + else if (auxFolderState) + { + if (package.auxFolders.size()) + { + AuxFolder& a = package.auxFolders.back(); + if (pname == "folder") + a.folder = v; + else if (pname == "location") + a.location = v; + } + + valueState = false; + } + else + { + if (pname == "package") + package.name = v; + else if (pname == "url") + package.url = v; + else if (pname == "icon") + package.icon = v; + else if (pname == "description") + package.description = v; + else if (pname == "author") + package.author = v; + else if (pname == "organization") + package.organization = v; + else if (pname == "contact") + package.contact = v; + else if (pname == "version") + package.version = v; + else if (pname == "requires") + package. + requires + = v; + else if (pname == "rv") package.rvversion = v; + else if (pname == "openrv") + package.openrvversion = v; + else if (pname == "imageio") package.imageio = + v.split(" "); + else if (pname == "movieio") package.movieio = + v.split(" "); + else if (pname == "hidden") package.hidden = + v == "true"; + else if (pname == "system") package.system = + v == "true"; + else if (pname == "optional") package.optional = + v == "true"; + valueState = false; + } + } + break; + default: + break; + } + } + + static const bool isOpenRV = + std::string_view(INTERNAL_APPLICATION_NAME) == "OpenRV"; + + package.compatible = versionCompatible( + isOpenRV ? package.openrvversion : package.rvversion, + TWK_DEPLOY_MAJOR_VERSION(), TWK_DEPLOY_MINOR_VERSION(), + TWK_DEPLOY_PATCH_LEVEL()); + + package.zipFile = true; + package.installing = false; + yaml_event_delete(&input_event); + yaml_parser_delete(&parser); + + for (auto& auxFolder : package.auxFolders) + { + // Iterate through files and compare paths + std::for_each( + package.files.begin(), package.files.end(), + [&](const QString& fullPath) + { + // Check if the file is in the current folder or + // any of its subdirectories + if (fullPath.startsWith(auxFolder.folder + '/')) + { + // Separate the filename and directory + // structure information + QFileInfo fileInfo(fullPath); + QString fileName = fileInfo.fileName(); + QString directory = fileInfo.dir().path(); + + AuxFile newAuxFile; + newAuxFile.file = fullPath; + newAuxFile.location = + auxFolder.location + "/" + directory; + package.auxFiles.push_back(newAuxFile); + } + }); + } + + QRegExp rvpkgRE("(.*)-[0-9]+\\.[0-9]+\\.rvpkg"); + QRegExp zipRE("(.*)\\.zip"); + + if (rvpkgRE.exactMatch(finfo.fileName())) + { + pname = rvpkgRE.capturedTexts()[1]; + } + else if (zipRE.exactMatch(finfo.fileName())) + { + pname = zipRE.capturedTexts()[1]; + } + + package.baseName = pname; + } + } + } + } - if( findPackageIndexByZip( infileNonCanonical ) == -1 ) + PackageManager::ModeEntryList + PackageManager::loadModeFile(const QString& filename) { - // - // Under Windows, using canonical file pathing - // for unzOpen can sometimes fail if the path - // contains a symlink to a UNC mapped dir. - // e.g. 'rvpkgs -> \\server\plugins\rvpkgs'. - // So if unzOpen is unsuccessful using the canonical - // file path we try again with the original - // non-canonical absolute file path. - - // NB: The file path we use for m_packages - // i.e. 'infile' should be the file path that was - // successful for unzOpen(). - // - QString infile = QFileInfo( infileNonCanonical ).canonicalFilePath(); - unzFile file = unzOpen( infile.toUtf8().data() ); - if( !file ) - { - infile = QFileInfo( infileNonCanonical ).absoluteFilePath(); - file = unzOpen( infile.toUtf8().data() ); - } - - if( file ) - { - vector buffer; - m_packages.push_back( Package() ); - m_packages.back().file = infile; - m_packageMap.insert( infile, m_packages.size() - 1 ); - - QFileInfo finfo( infile ); - - m_packages.back().fileWritable = TwkUtil::isWritable( TwkQtCoreUtil::UTF8::qconvert(infile).c_str() ); - m_packages.back().dirWritable = TwkUtil::isWritable( TwkQtCoreUtil::UTF8::qconvert(finfo.absolutePath()).c_str() ); - - unz_global_info info; - unzGetGlobalInfo( file, &info ); - - unzLocateFile( file, "PACKAGE", 1 ); - unzOpenCurrentFile( file ); - - unzGoToFirstFile( file ); - - QStringList files; + QFile file(filename); + bool exists = file.exists(); + bool ok = file.open(QIODevice::ReadOnly); + bool first = true; - do + ModeEntryList list; + int rvloadVersion = 0; + + while (ok && !file.atEnd()) { - // unz_file_info info; - char temp[256]; - unzGetCurrentFileInfo( file, NULL /*&info*/, temp, 256, NULL, 0, NULL, - 0 ); - temp[255] = 0; - files.push_back( temp ); - QString f = temp; + QByteArray barray = file.readLine().trimmed(); + barray.push_back(char(0)); + QString line = QString::fromUtf8(barray.constData()); - // Check if it's a directory - QFileInfo fInfo( f ); - if( !finfo.isDir() ) - { - if( f != "PACKAGE" ) m_packages.back().files.push_back( f ); - } - } while( unzGoToNextFile( file ) == UNZ_OK ); + if (first) + { + rvloadVersion = line.toInt(); + // if (rvloadVersion >= 4) break; + first = false; + } + else + { + QStringList parts = line.split(",", QString::KeepEmptyParts); - while( !unzeof( file ) ) - { - buffer.resize( buffer.size() + 256 ); - int read = unzReadCurrentFile( file, &buffer.back() - 255, 256 ); - if( read != 256 ) buffer.resize( buffer.size() - 256 + read ); + if (parts.size() >= 7 && parts[0] != "#") + { + int index = 0; + + ModeEntry entry; + entry.name = parts[index++]; + entry.package = parts[index++]; + entry.menu = parts[index++]; + entry.shortcut = parts[index++]; + entry.event = parts[index++]; + entry.loaded = parts[index++] == "true"; + entry.active = parts[index++] == "true"; + entry.rvversion = + (rvloadVersion == 1) ? "" : parts[index++]; + entry.optional = (rvloadVersion >= 3 && parts.size() >= 9 + ? parts[index++] == "true" + : false); + entry.openrvversion = + (rvloadVersion >= 4 && parts.size() >= 10 + ? parts[index++] + : ""); + + int requiresIndex = index; + for (int i = requiresIndex; i < parts.size(); i++) + entry. + requires + .push_back(parts[i]); + + list.push_back(entry); + } + } } - unzClose( file ); + return list; + } - if( !buffer.empty() ) + void PackageManager::writeModeFile(const QString& filename, + const ModeEntryList& list, int version) + { + QFile file(filename); + + if (file.open(QIODevice::WriteOnly)) { - yaml_parser_t parser; - yaml_event_t input_event; - memset( &parser, 0, sizeof( parser ) ); - memset( &input_event, 0, sizeof( input_event ) ); + file.write((version == 1) ? "1\n" : "4\n", 2); - if( !yaml_parser_initialize( &parser ) ) - { - cerr << "ERROR: Could not initialize the YAML parser object" - << endl; - return; - } - - yaml_parser_set_input_string( - &parser, (const unsigned char*)&buffer.front(), buffer.size() ); - - Package& package = m_packages.back(); - package.installed = false; - package.hidden = false; - package.system = false; - package.optional = false; - package.openrvversion = "1.0.0"; - bool modeState = false; - bool auxFileState = false; - bool auxFolderState = false; - bool valueState = false; - QString pname; - QString auxFile; - QString auxFolder; - - for( bool done = false; !done; ) - { - if( !yaml_parser_parse( &parser, &input_event ) ) - { - cerr << "ERROR: YAML parser failed on PACKAGE file in " - << infile.toStdString() << endl; - break; - } - - if( input_event.type == YAML_STREAM_END_EVENT ) done = true; - - switch( input_event.type ) - { - case YAML_STREAM_START_EVENT: - case YAML_STREAM_END_EVENT: - case YAML_DOCUMENT_START_EVENT: - case YAML_DOCUMENT_END_EVENT: - case YAML_ALIAS_EVENT: - break; - case YAML_SEQUENCE_START_EVENT: - // cout << "seq start" << endl; - break; - case YAML_SEQUENCE_END_EVENT: - // cout << "seq end" << endl; - if( modeState ) modeState = false; - if( auxFileState ) auxFileState = false; - if( auxFolderState ) auxFolderState = false; - break; - case YAML_MAPPING_START_EVENT: - // cout << "map start" << endl; - if( modeState ) - package.modes.push_back( Mode() ); - else if( auxFileState ) + for (size_t i = 0; i < list.size(); i++) + { + const ModeEntry& e = list[i]; + + QString line = + QString("%1,%2,%3,%4,%5,%6,%7") + .arg(e.name) + .arg(e.package) + .arg(e.menu == "" ? QString("nil") : e.menu) + .arg(e.shortcut == "" ? QString("nil") : e.shortcut) + .arg(e.event == "" ? QString("nil") : e.event) + .arg(e.loaded ? QString("true") : QString("false")) + .arg(e.active ? QString("true") : QString("false")); + + if (version > 1 || version == 0) { - package.auxFiles.push_back( AuxFile() ); - package.auxFiles.back().file = auxFile; + line += QString(",") + e.rvversion; } - else if( auxFolderState ) + + if (version >= 3 || version == 0) { - package.auxFolders.push_back( AuxFolder() ); - package.auxFolders.back().folder = auxFolder; + line += QString(e.optional ? ",true" : ",false"); } - break; - case YAML_MAPPING_END_EVENT: - // cout << "map end" << endl; - break; - case YAML_SCALAR_EVENT: - { - QString v = QString::fromUtf8( - (const char*)input_event.data.scalar.value ); - // cout << "scalar " << v.toUtf8().data() << endl; - - if( !valueState ) + + if (version >= 4 || version == 0) { - pname = v; - - if( v == "modes" ) - modeState = true; - else if( v == "files" ) - auxFileState = true; - else if( v == "folders" ) - auxFolderState = true; - else - valueState = true; + line += QString(",") + e.openrvversion; } - else if( modeState ) + + if (!e.requires.empty()) { - if( package.modes.size() ) - { - Mode& m = package.modes.back(); - - if( pname == "file" ) - m.file = v; - else if( pname == "menu" ) - m.menu = v; - else if( pname == "shortcut" ) - m.shortcut = v; - else if( pname == "event" ) - m.event = v; - else if( pname == "load" ) - m.load = v; - else if( pname == "icon" ) - m.icon = v; - else if( pname == "requires" ) - m. - requires - = v.split( " " ); - } - - valueState = false; + for (int q = 0; q < e.requires.size(); q++) + { + line += QString(",%1").arg(e.requires[q]); + } } - else if( auxFileState ) + + line += "\n"; + + QByteArray a = line.toUtf8(); + file.write(a.data(), a.size()); + } + } + else + { + errorModeFileWriteFailed(filename); + } + } + + void PackageManager::loadInstalltionFile(const QDir& dir, + const QString& filename) + { + QFile file(filename); + bool exists = file.exists(); + bool ok = file.open(QIODevice::ReadOnly); + + while (ok && !file.atEnd()) + { + QString line(file.readLine().trimmed()); + bool installed = line.size() > 1 && line[0] == '*'; + if (installed) + line.remove(0, 1); + QString path = + QFileInfo(dir.absoluteFilePath(line)).canonicalFilePath(); + QMap::iterator i = m_packageMap.find(path); + + if (i == m_packageMap.end()) + { + // Now try with the nonCanonicalPath for dir; This is is + // really to handle Windows symlinks with UNC pathing. + path = dir.absoluteFilePath(line); + i = m_packageMap.find(path); + if (i == m_packageMap.end()) { - if( package.auxFiles.size() ) - { - AuxFile& a = package.auxFiles.back(); - if( pname == "file" ) - a.file = v; - else if( pname == "location" ) - a.location = v; - } - - valueState = false; + m_packages.push_back(Package()); + m_packages.back().file = line; + m_packages.back().installed = installed; + m_packages.back().zipFile = false; + m_packages.back().name = "Missing Package"; + m_packages.back().description = + "

The original zip file for this package is " + "missing

"; + m_packageMap.insert(line, m_packages.size() - 1); } - else if( auxFolderState ) + else { - if( package.auxFolders.size() ) - { - AuxFolder& a = package.auxFolders.back(); - if( pname == "folder" ) - a.folder = v; - else if( pname == "location" ) - a.location = v; - } - - valueState = false; + m_packages[i.value()].installed = installed; } - else + } + else + { + m_packages[i.value()].installed = installed; + } + } + } + + void PackageManager::writeInstallationFile(const QString& filename) + { + QFileInfo fileinfo(filename); + QDir filedir = fileinfo.absoluteDir(); + QFile file(filename); + + if (file.open(QIODevice::WriteOnly)) + { + for (size_t i = 0; i < m_packages.size(); i++) + { + const Package& package = m_packages[i]; + + QFileInfo info(package.file); + + if (info.absoluteDir() == filedir) { - if( pname == "package" ) - package.name = v; - else if( pname == "url" ) - package.url = v; - else if( pname == "icon" ) - package.icon = v; - else if( pname == "description" ) - package.description = v; - else if( pname == "author" ) - package.author = v; - else if( pname == "organization" ) - package.organization = v; - else if( pname == "contact" ) - package.contact = v; - else if( pname == "version" ) - package.version = v; - else if( pname == "requires" ) - package. - requires - = v; - else if( pname == "rv" ) package.rvversion = v; - else if( pname == "openrv" ) package.openrvversion = v; - else if( pname == "imageio" ) package.imageio = - v.split( " " ); - else if( pname == "movieio" ) package.movieio = - v.split( " " ); - else if( pname == "hidden" ) package.hidden = v == "true"; - else if( pname == "system" ) package.system = v == "true"; - else if( pname == "optional" ) package.optional = v == "true"; - valueState = false; + if (package.installed) + file.write("*", 1); + QByteArray n = info.fileName().toUtf8(); + file.write(n.data(), n.size()); + file.write("\n", 1); } - } - break; - default: - break; - } - } - - static const bool isOpenRV = - std::string_view( INTERNAL_APPLICATION_NAME ) == "OpenRV"; - - package.compatible = versionCompatible( - isOpenRV ? package.openrvversion : package.rvversion, - TWK_DEPLOY_MAJOR_VERSION(), TWK_DEPLOY_MINOR_VERSION(), - TWK_DEPLOY_PATCH_LEVEL() ); - - package.zipFile = true; - package.installing = false; - yaml_event_delete( &input_event ); - yaml_parser_delete( &parser ); - - for( auto& auxFolder : package.auxFolders ) - { - // Iterate through files and compare paths - std::for_each( package.files.begin(), package.files.end(), - [&]( const QString& fullPath ) - { - // Check if the file is in the current folder or - // any of its subdirectories - if( fullPath.startsWith( auxFolder.folder + '/' ) ) - { - // Separate the filename and directory structure - // information - QFileInfo fileInfo( fullPath ); - QString fileName = fileInfo.fileName(); - QString directory = fileInfo.dir().path(); - - AuxFile newAuxFile; - newAuxFile.file = fullPath; - newAuxFile.location = - auxFolder.location + "/" + directory; - package.auxFiles.push_back( newAuxFile ); - } - } ); - } - - QRegExp rvpkgRE( "(.*)-[0-9]+\\.[0-9]+\\.rvpkg" ); - QRegExp zipRE( "(.*)\\.zip" ); - - if( rvpkgRE.exactMatch( finfo.fileName() ) ) - { - pname = rvpkgRE.capturedTexts()[1]; - } - else if( zipRE.exactMatch( finfo.fileName() ) ) - { - pname = zipRE.capturedTexts()[1]; - } - - package.baseName = pname; - } - } + } + } } - } - PackageManager::ModeEntryList PackageManager::loadModeFile( - const QString& filename ) - { - QFile file( filename ); - bool exists = file.exists(); - bool ok = file.open( QIODevice::ReadOnly ); - bool first = true; + void PackageManager::findPackageDependencies() + { + for (size_t i = 0; i < m_packages.size(); i++) + { + Package& package = m_packages[i]; + QStringList deps = package. + requires + .split(" ", QString::SkipEmptyParts); + + for (size_t q = 0; q < deps.size(); q++) + { + int di = findPackageIndexByZip(deps[q]); + + if (di != -1) + { + m_packages[di].usedBy.push_back(i); + package.uses.push_back(di); + if (!m_packages[di].compatible) + package.compatible = false; + } + } + } + } - ModeEntryList list; - int rvloadVersion = 0; + // + // Swap $APPLICATION_DIR in for the actual (canonical) directory if it + // appears at the head of the package file path. This is to enable a + // optional package that was switched "on" to be "remembered" across + // use of different versions of RV (stored in different directories). + // - while( ok && !file.atEnd() ) + QStringList PackageManager::swapAppDir(const QStringList& packages, + bool swapIn) { - QByteArray barray = file.readLine().trimmed(); - barray.push_back( char( 0 ) ); - QString line = QString::fromUtf8( barray.constData() ); - - if( first ) - { - rvloadVersion = line.toInt(); - // if (rvloadVersion >= 4) break; - first = false; - } - else - { - QStringList parts = line.split( ",", QString::KeepEmptyParts ); - - if( parts.size() >= 7 && parts[0] != "#" ) - { - int index = 0; - - ModeEntry entry; - entry.name = parts[index++]; - entry.package = parts[index++]; - entry.menu = parts[index++]; - entry.shortcut = parts[index++]; - entry.event = parts[index++]; - entry.loaded = parts[index++] == "true"; - entry.active = parts[index++] == "true"; - entry.rvversion = ( rvloadVersion == 1 ) ? "" : parts[index++]; - entry.optional = ( rvloadVersion >= 3 && parts.size() >= 9 - ? parts[index++] == "true" - : false ); - entry.openrvversion = - ( rvloadVersion >= 4 && parts.size() >= 10 ? parts[index++] - : "" ); - - int requiresIndex = index; - for( int i = requiresIndex; i < parts.size(); i++ ) - entry. - requires - .push_back( parts[i] ); - - list.push_back( entry ); - } - } + QString appDirSymbol("$APPLICATION_DIR"); + QFileInfo topInfo(TwkApp::Bundle::mainBundle()->top().c_str()); + QString top = topInfo.canonicalFilePath(); + QStringList ret; + + for (int i = 0; i < packages.size(); ++i) + { + QString path = packages[i]; + + if (swapIn) + { + QFileInfo info(path); + + if (info.exists()) + path = info.canonicalFilePath(); + if (path.startsWith(top)) + path.replace(top, appDirSymbol); + } + else + { + if (path.startsWith(appDirSymbol)) + path.replace(appDirSymbol, top); + } + + ret.push_back(path); + } + + return ret; } - return list; - } + void PackageManager::loadPackages() + { + typedef TwkApp::Bundle Bundle; + Bundle* bundle = Bundle::mainBundle(); + Bundle::PathVector paths = bundle->pluginPath("Packages"); + + m_packages.clear(); + + // + // Don't read/write settings unless this is the RV app (as opposed to + // rvpkg). + // + if (QCoreApplication::applicationName() == INTERNAL_APPLICATION_NAME) + { + RV_QSETTINGS; + settings.beginGroup("ModeManager"); + m_doNotLoadPackages = + swapAppDir(settings.value("doNotLoadPackages", QStringList()) + .toStringList(), + false); + m_optLoadPackages = + swapAppDir(settings.value("optionalPackages", QStringList()) + .toStringList(), + false); + settings.endGroup(); + } + + m_doNotLoadPackages.removeDuplicates(); + m_optLoadPackages.removeDuplicates(); - void PackageManager::writeModeFile( const QString& filename, - const ModeEntryList& list, int version ) - { - QFile file( filename ); + for (size_t i = 0; i < paths.size(); i++) + { + QDir dir(paths[i].c_str()); - if( file.open( QIODevice::WriteOnly ) ) - { - file.write( ( version == 1 ) ? "1\n" : "4\n", 2 ); + if (dir.exists()) + { + QFileInfoList entries = dir.entryInfoList(QDir::Files); - for( size_t i = 0; i < list.size(); i++ ) - { - const ModeEntry& e = list[i]; + for (size_t q = 0; q < entries.size(); q++) + { + if (entries[q].fileName().endsWith(".zip") + || entries[q].fileName().endsWith("rvpkg") + || entries[q].fileName().endsWith("rvpkgs")) + { + loadPackageInfo(entries[q].filePath()); + } + } - QString line = - QString( "%1,%2,%3,%4,%5,%6,%7" ) - .arg( e.name ) - .arg( e.package ) - .arg( e.menu == "" ? QString( "nil" ) : e.menu ) - .arg( e.shortcut == "" ? QString( "nil" ) : e.shortcut ) - .arg( e.event == "" ? QString( "nil" ) : e.event ) - .arg( e.loaded ? QString( "true" ) : QString( "false" ) ) - .arg( e.active ? QString( "true" ) : QString( "false" ) ); + // + // Load the installation file + // - if( version > 1 || version == 0 ) - { - line += QString( "," ) + e.rvversion; + if (dir.exists("rvinstall")) + { + loadInstalltionFile(dir, dir.absoluteFilePath("rvinstall")); + } + } } - if( version >= 3 || version == 0 ) - { - line += QString( e.optional ? ",true" : ",false" ); - } + // + // Check for optional packages that have been opted into + // - if( version >= 4 || version == 0 ) - { - line += QString( "," ) + e.openrvversion; - } + paths = bundle->pluginPath("Mu"); - if( !e.requires.empty() ) + for (size_t i = 0; i < paths.size(); i++) { - for( int q = 0; q < e.requires.size(); q++ ) - { - line += QString( ",%1" ).arg( e.requires[q] ); - } + QDir dir(paths[i].c_str()); + + if (dir.exists()) + { + if (dir.exists("rvload2")) + { + PackageManager::ModeEntryList entries = + loadModeFile(dir.absoluteFilePath("rvload2")); + + for (size_t i = 0; i < entries.size(); i++) + { + PackageManager::ModeEntry& entry = entries[i]; + + if (entry.optional == false) + { + for (size_t i = 0; i < m_packages.size(); i++) + { + if (QFileInfo(m_packages[i].file).fileName() + == entry.package + && m_packages[i].optional) + // + // Then this package has been "opted in" so + // reset optional flag + // + { + m_packages[i].optional = false; + } + } + } + } + } + } } - line += "\n"; + findPackageDependencies(); - QByteArray a = line.toUtf8(); - file.write( a.data(), a.size() ); - } - } - else - { - errorModeFileWriteFailed( filename ); - } - } + for (size_t i = 0; i < m_packages.size(); i++) + { + m_packages[i].loadable = + !m_doNotLoadPackages.contains(m_packages[i].file); - void PackageManager::loadInstalltionFile( const QDir& dir, - const QString& filename ) - { - QFile file( filename ); - bool exists = file.exists(); - bool ok = file.open( QIODevice::ReadOnly ); + if (m_packages[i].optional) + { + m_packages[i].loadable = + m_optLoadPackages.contains(m_packages[i].file); + } - while( ok && !file.atEnd() ) - { - QString line( file.readLine().trimmed() ); - bool installed = line.size() > 1 && line[0] == '*'; - if( installed ) line.remove( 0, 1 ); - QString path = - QFileInfo( dir.absoluteFilePath( line ) ).canonicalFilePath(); - QMap::iterator i = m_packageMap.find( path ); - - if( i == m_packageMap.end() ) - { - // Now try with the nonCanonicalPath for dir; This is is - // really to handle Windows symlinks with UNC pathing. - path = dir.absoluteFilePath( line ); - i = m_packageMap.find( path ); - if( i == m_packageMap.end() ) - { - m_packages.push_back( Package() ); - m_packages.back().file = line; - m_packages.back().installed = installed; - m_packages.back().zipFile = false; - m_packages.back().name = "Missing Package"; - m_packages.back().description = - "

The original zip file for this package is missing

"; - m_packageMap.insert( line, m_packages.size() - 1 ); - } - else - { - m_packages[i.value()].installed = installed; + declarePackage(m_packages[i], i); } - } - else - { - m_packages[i.value()].installed = installed; - } } - } - - void PackageManager::writeInstallationFile( const QString& filename ) - { - QFileInfo fileinfo( filename ); - QDir filedir = fileinfo.absoluteDir(); - QFile file( filename ); - if( file.open( QIODevice::WriteOnly ) ) + bool PackageManager::addPackages(const QStringList& files, + const QString& path) { - for( size_t i = 0; i < m_packages.size(); i++ ) - { - const Package& package = m_packages[i]; + // + // First check that package files exist and have legal names + // - QFileInfo info( package.file ); + QRegExp rvpkgRE("(.*)-[0-9]+\\.[0-9]+\\.rvpkg"); + QRegExp rvpkgsRE("(.*)-[0-9]+\\.[0-9]+\\.rvpkgs"); // Bundle + QRegExp zipRE("(.*)\\.zip"); - if( info.absoluteDir() == filedir ) + for (size_t i = 0; i < files.size(); i++) { - if( package.installed ) file.write( "*", 1 ); - QByteArray n = info.fileName().toUtf8(); - file.write( n.data(), n.size() ); - file.write( "\n", 1 ); - } - } - } - } - void PackageManager::findPackageDependencies() - { - for( size_t i = 0; i < m_packages.size(); i++ ) - { - Package& package = m_packages[i]; - QStringList deps = package. - requires - .split( " ", QString::SkipEmptyParts ); + // Unpacking any bundles + if (isBundle(files[i])) + { + cout << "INFO: Bundle detected, adding subpackages now." + << endl; - for( size_t q = 0; q < deps.size(); q++ ) - { - int di = findPackageIndexByZip( deps[q] ); + // Installing bundle + vector includedPackages = handleBundle(files[i], path); + if (includedPackages.size() > 0) + { + cout << "INFO: Bundle subpackages added." << endl; + } + else + { + cerr << "ERROR: Unable to add subpackages." << endl; + } - if( di != -1 ) - { - m_packages[di].usedBy.push_back( i ); - package.uses.push_back( di ); - if( !m_packages[di].compatible ) package.compatible = false; - } - } - } - } - - // - // Swap $APPLICATION_DIR in for the actual (canonical) directory if it - // appears at the head of the package file path. This is to enable a - // optional package that was switched "on" to be "remembered" across - // use of different versions of RV (stored in different directories). - // - - QStringList PackageManager::swapAppDir( const QStringList& packages, - bool swapIn ) - { - QString appDirSymbol( "$APPLICATION_DIR" ); - QFileInfo topInfo( TwkApp::Bundle::mainBundle()->top().c_str() ); - QString top = topInfo.canonicalFilePath(); - QStringList ret; - - for( int i = 0; i < packages.size(); ++i ) - { - QString path = packages[i]; + continue; // Bundle itself does not need to be copied + }; - if( swapIn ) - { - QFileInfo info( path ); + QFileInfo info(files[i]); - if( info.exists() ) path = info.canonicalFilePath(); - if( path.startsWith( top ) ) path.replace( top, appDirSymbol ); - } - else - { - if( path.startsWith( appDirSymbol ) ) path.replace( appDirSymbol, top ); - } + if (!info.exists()) + { + QString t("This package file does not exist: "); + t += files[i]; + informPackageFailedToCopy(t); + return false; + } - ret.push_back( path ); - } + if (!rvpkgRE.exactMatch(info.fileName()) + && !zipRE.exactMatch(info.fileName()) + && !rvpkgsRE.exactMatch(info.fileName())) + { + QString t("ERROR: Illegal package file name: "); + t += info.fileName(); + t += ", should be either .zip, \n-.rvpkg " + "or -.rvpkgs"; + informPackageFailedToCopy(t); + return false; + } + } - return ret; - } + QDir dir(path); + if (dir.dirName() == "Packages") + dir.cdUp(); - void PackageManager::loadPackages() - { - typedef TwkApp::Bundle Bundle; - Bundle* bundle = Bundle::mainBundle(); - Bundle::PathVector paths = bundle->pluginPath( "Packages" ); + if (!dir.exists()) + { + cerr << "ERROR: target support directory " + << dir.absolutePath().toUtf8().constData() + << " does not exist: please create it first" << endl; + return false; + } - m_packages.clear(); + makeSupportDirTree(dir); + dir.cd("Packages"); // User should not include the Packages directory in + // their add directory argument + QStringList nocopy; - // - // Don't read/write settings unless this is the RV app (as opposed to - // rvpkg). - // - if( QCoreApplication::applicationName() == INTERNAL_APPLICATION_NAME ) - { - RV_QSETTINGS; - settings.beginGroup( "ModeManager" ); - m_doNotLoadPackages = swapAppDir( - settings.value( "doNotLoadPackages", QStringList() ).toStringList(), - false ); - m_optLoadPackages = swapAppDir( - settings.value( "optionalPackages", QStringList() ).toStringList(), - false ); - settings.endGroup(); - } + for (size_t i = 0; i < files.size(); i++) + { - m_doNotLoadPackages.removeDuplicates(); - m_optLoadPackages.removeDuplicates(); + // Bundles do not need to be copied + if (isBundle(files[i])) + continue; - for( size_t i = 0; i < paths.size(); i++ ) - { - QDir dir( paths[i].c_str() ); + QFileInfo info(files[i]); + QString fromFile(files[i]); + QString toFile(dir.absoluteFilePath(info.fileName())); - if( dir.exists() ) - { - QFileInfoList entries = dir.entryInfoList( QDir::Files ); + QFileInfo toinfo(toFile); - for( size_t q = 0; q < entries.size(); q++ ) - { - if( entries[q].fileName().endsWith( ".zip" ) || - entries[q].fileName().endsWith( "rvpkg" ) || - entries[q].fileName().endsWith( "rvpkgs" )) - { - loadPackageInfo( entries[q].filePath() ); - } - } + if (toinfo.exists() && m_force) + { + QStringList files; + files.push_back(toFile); + removePackages(files); + } - // - // Load the installation file - // + if (!QFile::copy(fromFile, toFile)) + { + nocopy.push_back(fromFile); + } + } - if( dir.exists( "rvinstall" ) ) + if (nocopy.size()) { - loadInstalltionFile( dir, dir.absoluteFilePath( "rvinstall" ) ); - } - } - } + QString t("The following files failed to copy:\n"); + for (size_t i = 0; i < nocopy.size(); i++) + { + t += nocopy[i]; + t += "\n"; + } - // - // Check for optional packages that have been opted into - // + informPackageFailedToCopy(t); + return false; + } - paths = bundle->pluginPath( "Mu" ); + loadPackages(); + return true; + } - for( size_t i = 0; i < paths.size(); i++ ) + void PackageManager::removePackages(const QStringList& files) { - QDir dir( paths[i].c_str() ); + QStringList toremove; - if( dir.exists() ) - { - if( dir.exists( "rvload2" ) ) + for (size_t i = 0; i < files.size(); i++) { - PackageManager::ModeEntryList entries = - loadModeFile( dir.absoluteFilePath( "rvload2" ) ); - - for( size_t i = 0; i < entries.size(); i++ ) - { - PackageManager::ModeEntry& entry = entries[i]; - - if( entry.optional == false ) + for (size_t q = 0; q < m_packages.size(); q++) { - for( size_t i = 0; i < m_packages.size(); i++ ) - { - if( QFileInfo( m_packages[i].file ).fileName() == - entry.package && - m_packages[i].optional ) - // - // Then this package has been "opted in" so reset optional flag + // Must canonicalize these to guard against things like varying + // capitalization of driver letters on windows. // + QFileInfo packageFI(m_packages[q].file); + QFileInfo incomingFI(files[i]); + + if (packageFI.canonicalFilePath() + == incomingFI.canonicalFilePath()) { - m_packages[i].optional = false; + if (m_packages[q].installed) + { + if (!uninstallForRemoval(m_packages[q].file)) + { + cerr << "SKIPPING: " + << m_packages[q].file.toUtf8().constData() + << endl; + continue; + } + + uninstallPackage(m_packages[q]); + } + + m_packages.erase(m_packages.begin() + q); + + if (!QFile::remove(files[i])) + { + cerr << "ERROR: " << files[i].toUtf8().constData() + << " not removed" << endl; + } + else + { + toremove.push_back(files[i]); + } + + break; } - } } - } } - } - } - findPackageDependencies(); + for (size_t q = 0; q < m_packages.size(); q++) + { + m_packages[q].usedBy.clear(); + m_packages[q].uses.clear(); + } - for( size_t i = 0; i < m_packages.size(); i++ ) - { - m_packages[i].loadable = - !m_doNotLoadPackages.contains( m_packages[i].file ); + findPackageDependencies(); - if( m_packages[i].optional ) - { - m_packages[i].loadable = - m_optLoadPackages.contains( m_packages[i].file ); - } + for (size_t i = 0; i < toremove.size(); i++) + { + QFileInfo info(toremove[i]); + writeInstallationFile( + info.absoluteDir().absoluteFilePath("rvinstall")); + } - declarePackage( m_packages[i], i ); + loadPackages(); } - } - bool PackageManager::addPackages( const QStringList& files, - const QString& path ) - { + //---------------------------------------------------------------------- // - // First check that package files exist and have legal names + // Default implementation uses cin/cout // - QRegExp rvpkgRE( "(.*)-[0-9]+\\.[0-9]+\\.rvpkg" ); - QRegExp rvpkgsRE( "(.*)-[0-9]+\\.[0-9]+\\.rvpkgs" ); // Bundle - QRegExp zipRE( "(.*)\\.zip" ); - - for( size_t i = 0; i < files.size(); i++ ) + bool PackageManager::yesOrNo(const char* m1, const char* m2, + const QString& msg, const char* q) { + char yorn = 0; - // Unpacking any bundles - if (isBundle(files[i])) { - cout << "INFO: Bundle detected, adding subpackages now." << endl; + cout << m1 << endl << m2 << endl << msg.toUtf8().constData(); - // Installing bundle - vector includedPackages = handleBundle(files[i], path); - if (includedPackages.size() > 0) { - cout << "INFO: Bundle subpackages added." << endl; - } else { - cerr << "ERROR: Unable to add subpackages." << endl; + while (yorn != 'y' && yorn != 'n') + { + cout << endl << q << " (y or n): " << flush; + if (m_force) + { + cout << "y" << endl; + yorn = 'y'; + } + else + cin >> yorn; } - continue; // Bundle itself does not need to be copied - }; - - QFileInfo info( files[i] ); - - if( !info.exists() ) - { - QString t( "This package file does not exist: " ); - t += files[i]; - informPackageFailedToCopy( t ); - return false; - } - - if( !rvpkgRE.exactMatch( info.fileName() ) && - !zipRE.exactMatch( info.fileName() ) && - !rvpkgsRE.exactMatch(info.fileName() ) ) - { - QString t( "ERROR: Illegal package file name: " ); - t += info.fileName(); - t += ", should be either .zip, \n-.rvpkg or -.rvpkgs"; - informPackageFailedToCopy( t ); - return false; - } + return yorn == 'y'; } - QDir dir( path ); - if( dir.dirName() == "Packages" ) dir.cdUp(); - - if( !dir.exists() ) + bool PackageManager::fixLoadability(const QString& msg) { - cerr << "ERROR: target support directory " - << dir.absolutePath().toUtf8().constData() - << " does not exist: please create it first" << endl; - return false; + return yesOrNo("Unloadable Package Dependencies", + "Can't make package loadable because some of its " + "dependencies are not loadable.", + msg, "Load other packages first?"); } - makeSupportDirTree( dir ); - dir.cd( "Packages" ); // User should not include the Packages directory in their add directory argument - QStringList nocopy; - - for( size_t i = 0; i < files.size(); i++ ) + bool PackageManager::fixUnloadability(const QString& msg) { - - // Bundles do not need to be copied - if (isBundle(files[i])) continue; - - QFileInfo info( files[i] ); - QString fromFile( files[i] ); - QString toFile( dir.absoluteFilePath( info.fileName() ) ); - - QFileInfo toinfo( toFile ); - - if( toinfo.exists() && m_force ) - { - QStringList files; - files.push_back( toFile ); - removePackages( files ); - } - - if( !QFile::copy( fromFile, toFile ) ) - { - nocopy.push_back( fromFile ); - } + return yesOrNo("Loadable Package Dependencies", + "Can't make package unloadable because some loaded " + "packages depend on it.", + msg, "Unload other packages too?"); } - if( nocopy.size() ) + bool PackageManager::installDependantPackages(const QString& msg) { - QString t( "The following files failed to copy:\n" ); - for( size_t i = 0; i < nocopy.size(); i++ ) - { - t += nocopy[i]; - t += "\n"; - } - - informPackageFailedToCopy( t ); - return false; + return yesOrNo("Some Packages Depend on This One", + "Can't install package because some other packages " + "dependend on this one.", + msg, "Try and install others first?"); } - loadPackages(); - return true; - } - - void PackageManager::removePackages( const QStringList& files ) - { - QStringList toremove; - - for( size_t i = 0; i < files.size(); i++ ) + bool PackageManager::overwriteExistingFiles(const QString& msg) { - for( size_t q = 0; q < m_packages.size(); q++ ) - { - // Must canonicalize these to guard against things like varying - // capitalization of driver letters on windows. - // - QFileInfo packageFI( m_packages[q].file ); - QFileInfo incomingFI( files[i] ); - - if( packageFI.canonicalFilePath() == incomingFI.canonicalFilePath() ) - { - if( m_packages[q].installed ) - { - if( !uninstallForRemoval( m_packages[q].file ) ) - { - cerr << "SKIPPING: " << m_packages[q].file.toUtf8().constData() - << endl; - continue; - } - - uninstallPackage( m_packages[q] ); - } - - m_packages.erase( m_packages.begin() + q ); - - if( !QFile::remove( files[i] ) ) - { - cerr << "ERROR: " << files[i].toUtf8().constData() << " not removed" - << endl; - } - else - { - toremove.push_back( files[i] ); - } - - break; - } - } + return yesOrNo("Existing Package Files", + "Package files conflict with existing files.", msg, + "Overwrite existing files?"); } - for( size_t q = 0; q < m_packages.size(); q++ ) + void PackageManager::errorMissingPackageDependancies(const QString& msg) { - m_packages[q].usedBy.clear(); - m_packages[q].uses.clear(); + cerr << "ERROR: Some package dependancies are missing" << endl + << msg.toUtf8().constData() << endl; } - findPackageDependencies(); - - for( size_t i = 0; i < toremove.size(); i++ ) + bool PackageManager::uninstallDependantPackages(const QString& msg) { - QFileInfo info( toremove[i] ); - writeInstallationFile( - info.absoluteDir().absoluteFilePath( "rvinstall" ) ); + return yesOrNo("Some Packages Depend on This One", + "Can't uninstall package because some other packages " + "dependend on this one.", + msg, "Try and uninstall them first?"); } - loadPackages(); - } - - //---------------------------------------------------------------------- - // - // Default implementation uses cin/cout - // + void PackageManager::informCannotRemoveSomeFiles(const QString& msg) + { + cout << "INFO: Some Files Cannot Be Removed" << endl + << msg.toUtf8().constData() << endl; + } - bool PackageManager::yesOrNo( const char* m1, const char* m2, - const QString& msg, const char* q ) - { - char yorn = 0; + void PackageManager::errorModeFileWriteFailed(const QString& file) + { + cerr << "ERROR: File write failed: " << file.toUtf8().constData() + << endl; + } - cout << m1 << endl << m2 << endl << msg.toUtf8().constData(); + void PackageManager::informPackageFailedToCopy(const QString& msg) + { + cout << "INFO: package failed to copy: " << msg.toUtf8().constData() + << endl; + } - while( yorn != 'y' && yorn != 'n' ) + void PackageManager::declarePackage(Package&, size_t) { - cout << endl << q << " (y or n): " << flush; - if( m_force ) - { - cout << "y" << endl; - yorn = 'y'; - } - else - cin >> yorn; + // for UI } - return yorn == 'y'; - } - - bool PackageManager::fixLoadability( const QString& msg ) - { - return yesOrNo( "Unloadable Package Dependencies", - "Can't make package loadable because some of its " - "dependencies are not loadable.", - msg, "Load other packages first?" ); - } - - bool PackageManager::fixUnloadability( const QString& msg ) - { - return yesOrNo( "Loadable Package Dependencies", - "Can't make package unloadable because some loaded " - "packages depend on it.", - msg, "Unload other packages too?" ); - } - - bool PackageManager::installDependantPackages( const QString& msg ) - { - return yesOrNo( "Some Packages Depend on This One", - "Can't install package because some other packages " - "dependend on this one.", - msg, "Try and install others first?" ); - } - - bool PackageManager::overwriteExistingFiles( const QString& msg ) - { - return yesOrNo( "Existing Package Files", - "Package files conflict with existing files.", msg, - "Overwrite existing files?" ); - } - - void PackageManager::errorMissingPackageDependancies( const QString& msg ) - { - cerr << "ERROR: Some package dependancies are missing" << endl - << msg.toUtf8().constData() << endl; - } - - bool PackageManager::uninstallDependantPackages( const QString& msg ) - { - return yesOrNo( "Some Packages Depend on This One", - "Can't uninstall package because some other packages " - "dependend on this one.", - msg, "Try and uninstall them first?" ); - } - - void PackageManager::informCannotRemoveSomeFiles( const QString& msg ) - { - cout << "INFO: Some Files Cannot Be Removed" << endl - << msg.toUtf8().constData() << endl; - } - - void PackageManager::errorModeFileWriteFailed( const QString& file ) - { - cerr << "ERROR: File write failed: " << file.toUtf8().constData() << endl; - } - - void PackageManager::informPackageFailedToCopy( const QString& msg ) - { - cout << "INFO: package failed to copy: " << msg.toUtf8().constData() - << endl; - } - - void PackageManager::declarePackage( Package&, size_t ) - { - // for UI - } - - bool PackageManager::uninstallForRemoval( const QString& msg ) - { - return yesOrNo( "Package is installed", - "In order to remove the package it must be uninstalled", - msg, "Uninstall?" ); - } - - int PackageManager::auxFileIndex( Package& p, const QString& file ) - { - for( int i = 0; i < p.auxFiles.size(); i++ ) + bool PackageManager::uninstallForRemoval(const QString& msg) { - if( p.auxFiles[i].file == file ) return i; + return yesOrNo("Package is installed", + "In order to remove the package it must be uninstalled", + msg, "Uninstall?"); } - return -1; - } + int PackageManager::auxFileIndex(Package& p, const QString& file) + { + for (int i = 0; i < p.auxFiles.size(); i++) + { + if (p.auxFiles[i].file == file) + return i; + } + + return -1; + } - QString PackageManager::expandVarsInPath( Package& p, const QString& path ) - { - QString s = path; - s.replace( "$PACKAGE", p.baseName ); - return s; - } + QString PackageManager::expandVarsInPath(Package& p, const QString& path) + { + QString s = path; + s.replace("$PACKAGE", p.baseName); + return s; + } #ifdef PLATFORM_WINDOWS #define SEP ";" @@ -2006,336 +2130,346 @@ namespace Rv #define SEP ":" #endif - RvSettings* RvSettings::m_globalSettingsP = 0; + RvSettings* RvSettings::m_globalSettingsP = 0; - RvSettings& RvSettings::globalSettings() - { - if( m_globalSettingsP == 0 ) m_globalSettingsP = new RvSettings(); + RvSettings& RvSettings::globalSettings() + { + if (m_globalSettingsP == 0) + m_globalSettingsP = new RvSettings(); - return *m_globalSettingsP; - } + return *m_globalSettingsP; + } - void RvSettings::cleanupGlobalSettings() - { - if( m_globalSettingsP ) + void RvSettings::cleanupGlobalSettings() { - m_globalSettingsP->sync(); - delete m_globalSettingsP; + if (m_globalSettingsP) + { + m_globalSettingsP->sync(); + delete m_globalSettingsP; + } } - } - static void assembleSettings( RvSettings::SettingsMap& map, - const char* envVar, QString prefFileName ) - { - const char* p = getenv( envVar ); - if( !p ) return; + static void assembleSettings(RvSettings::SettingsMap& map, + const char* envVar, QString prefFileName) + { + const char* p = getenv(envVar); + if (!p) + return; - // - // Get list of dirs from path env var - // + // + // Get list of dirs from path env var + // - vector tokens; - stl_ext::tokenize( tokens, p, SEP ); + vector tokens; + stl_ext::tokenize(tokens, p, SEP); - QList prefDirs; + QList prefDirs; - for( size_t i = 0; i < tokens.size(); i++ ) - { - prefDirs.push_back( QDir( tokens[i].c_str() ) ); - } + for (size_t i = 0; i < tokens.size(); i++) + { + prefDirs.push_back(QDir(tokens[i].c_str())); + } - for( int i = prefDirs.size() - 1; i >= 0; --i ) - { - if( !prefDirs[i].exists( prefFileName ) ) continue; + for (int i = prefDirs.size() - 1; i >= 0; --i) + { + if (!prefDirs[i].exists(prefFileName)) + continue; - QString overrideFileName = prefDirs[i].absoluteFilePath( prefFileName ); - QFileInfo overrideFileInfo( overrideFileName ); + QString overrideFileName = + prefDirs[i].absoluteFilePath(prefFileName); + QFileInfo overrideFileInfo(overrideFileName); #ifdef PLATFORM_WINDOWS - QSettings::Format format( QSettings::IniFormat ); + QSettings::Format format(QSettings::IniFormat); #else - QSettings::Format format( QSettings::NativeFormat ); + QSettings::Format format(QSettings::NativeFormat); #endif - QSettings overrideSettings( overrideFileName, format ); - overrideSettings.setFallbacksEnabled( false ); - if( overrideSettings.status() != QSettings::NoError ) - { - cerr << "ERROR: RvSettings was unable to read settings for: '" - << overrideSettings.fileName().toStdString() - << "' err: " << overrideSettings.status() << endl; - continue; - } - - QStringList overrideKeys = overrideSettings.allKeys(); - - for( int j = 0; j < overrideKeys.size(); ++j ) - { - map[overrideKeys[j]] = overrideSettings.value( overrideKeys[j] ); - // cerr << " '" << overrideKeys[j].toStdString() << "'" << endl; - } + QSettings overrideSettings(overrideFileName, format); + overrideSettings.setFallbacksEnabled(false); + if (overrideSettings.status() != QSettings::NoError) + { + cerr << "ERROR: RvSettings was unable to read settings for: '" + << overrideSettings.fileName().toStdString() + << "' err: " << overrideSettings.status() << endl; + continue; + } + + QStringList overrideKeys = overrideSettings.allKeys(); + + for (int j = 0; j < overrideKeys.size(); ++j) + { + map[overrideKeys[j]] = overrideSettings.value(overrideKeys[j]); + // cerr << " '" << overrideKeys[j].toStdString() << "'" << + // endl; + } + } + + return; } - return; - } - - static QString defaultSettingsFileName() - { - QString name; -#if defined( PLATFORM_WINDOWS ) - QString path; - const char* p = getenv( "APPDATA" ); - if( p ) - path = p; - else - path = QDir::homePath(); - name = QFileInfo( path ).canonicalFilePath() + "/" + INTERNAL_ORGANIZATION_NAME + "/" + - INTERNAL_APPLICATION_NAME + ".ini"; -#elif defined( PLATFORM_DARWIN ) - name = QDir::homePath() + "/Library/Preferences/com." + INTERNAL_ORGANIZATION_NAME + "." + - INTERNAL_APPLICATION_NAME + ".plist"; + static QString defaultSettingsFileName() + { + QString name; +#if defined(PLATFORM_WINDOWS) + QString path; + const char* p = getenv("APPDATA"); + if (p) + path = p; + else + path = QDir::homePath(); + name = QFileInfo(path).canonicalFilePath() + "/" + + INTERNAL_ORGANIZATION_NAME + "/" + INTERNAL_APPLICATION_NAME + + ".ini"; +#elif defined(PLATFORM_DARWIN) + name = QDir::homePath() + "/Library/Preferences/com." + + INTERNAL_ORGANIZATION_NAME + "." + INTERNAL_APPLICATION_NAME + + ".plist"; #else - name = QDir::homePath() + "/.config/" + INTERNAL_ORGANIZATION_NAME + "/" + INTERNAL_APPLICATION_NAME + - ".conf"; + name = QDir::homePath() + "/.config/" + INTERNAL_ORGANIZATION_NAME + "/" + + INTERNAL_APPLICATION_NAME + ".conf"; #endif - return name; - } + return name; + } - RvSettings::RvSettings() - { - // - // This function should only ever be called once per run. - // + RvSettings::RvSettings() + { + // + // This function should only ever be called once per run. + // - if( m_globalSettingsP ) - cerr << "ERROR: RvSettings instantiated multiple times!" << endl; + if (m_globalSettingsP) + cerr << "ERROR: RvSettings instantiated multiple times!" << endl; #ifdef PLATFORM_WINDOWS - QSettings::setDefaultFormat( QSettings::IniFormat ); + QSettings::setDefaultFormat(QSettings::IniFormat); #endif - QCoreApplication::setOrganizationName( INTERNAL_ORGANIZATION_NAME ); - QCoreApplication::setOrganizationDomain( INTERNAL_ORGANIZATION_DOMAIN ); + QCoreApplication::setOrganizationName(INTERNAL_ORGANIZATION_NAME); + QCoreApplication::setOrganizationDomain(INTERNAL_ORGANIZATION_DOMAIN); - // - // If -noPrefs command line flag was used, use empty alternate - // prefs file, so that default values are used, and any changes - // the users makes do not affect stored prefs. - // - if( PackageManager::ignoringPrefs() ) - { - m_userSettings = getQSettings(); - // - // Empty the prefs file. - // - m_userSettings->clear(); - // - // Reload from empty file. - // - delete m_userSettings; - m_userSettings = getQSettings(); - // - // Note that in the noPrefs mode, overriding and clobbering settings - // are also ignored. - // - return; - } + // + // If -noPrefs command line flag was used, use empty alternate + // prefs file, so that default values are used, and any changes + // the users makes do not affect stored prefs. + // + if (PackageManager::ignoringPrefs()) + { + m_userSettings = getQSettings(); + // + // Empty the prefs file. + // + m_userSettings->clear(); + // + // Reload from empty file. + // + delete m_userSettings; + m_userSettings = getQSettings(); + // + // Note that in the noPrefs mode, overriding and clobbering + // settings are also ignored. + // + return; + } - QString prefsFileName = QFileInfo( defaultSettingsFileName() ).fileName(); + QString prefsFileName = QFileInfo(defaultSettingsFileName()).fileName(); - assembleSettings( m_overridingSettings, "RV_PREFS_OVERRIDE_PATH", - prefsFileName ); - assembleSettings( m_clobberingSettings, "RV_PREFS_CLOBBER_PATH", - prefsFileName ); + assembleSettings(m_overridingSettings, "RV_PREFS_OVERRIDE_PATH", + prefsFileName); + assembleSettings(m_clobberingSettings, "RV_PREFS_CLOBBER_PATH", + prefsFileName); - QCoreApplication::setApplicationName( INTERNAL_APPLICATION_NAME ); + QCoreApplication::setApplicationName(INTERNAL_APPLICATION_NAME); - m_userSettings = getQSettings(); - } + m_userSettings = getQSettings(); + } - RvSettings::~RvSettings() - { - if( !m_userSettingsErrorAlredyReported && - ( m_userSettings->status() != QSettings::NoError ) ) + RvSettings::~RvSettings() { - cerr << "ERROR: RvSettings encountered error with: '" - << m_userSettings->fileName().toStdString() - << "' err: " << m_userSettings->status() << endl; + if (!m_userSettingsErrorAlredyReported + && (m_userSettings->status() != QSettings::NoError)) + { + cerr << "ERROR: RvSettings encountered error with: '" + << m_userSettings->fileName().toStdString() + << "' err: " << m_userSettings->status() << endl; - m_userSettingsErrorAlredyReported = true; + m_userSettingsErrorAlredyReported = true; + } + delete m_userSettings; } - delete m_userSettings; - } - QSettings* RvSettings::getQSettings() - { + QSettings* RvSettings::getQSettings() + { #ifdef PLATFORM_WINDOWS - QSettings::Format format( QSettings::IniFormat ); + QSettings::Format format(QSettings::IniFormat); #else - QSettings::Format format( QSettings::NativeFormat ); + QSettings::Format format(QSettings::NativeFormat); #endif - QSettings* qs = new QSettings( - format, QSettings::UserScope, INTERNAL_ORGANIZATION_NAME, - PackageManager::ignoringPrefs() ? "RVALT" : INTERNAL_APPLICATION_NAME ); - qs->setFallbacksEnabled( false ); + QSettings* qs = new QSettings( + format, QSettings::UserScope, INTERNAL_ORGANIZATION_NAME, + PackageManager::ignoringPrefs() ? "RVALT" + : INTERNAL_APPLICATION_NAME); + qs->setFallbacksEnabled(false); - if( qs->status() != QSettings::NoError ) - { - cerr << "ERROR: RvSettings was unable to read settings for: '" - << qs->fileName().toStdString() << "' err: " << qs->status() << endl; - } + if (qs->status() != QSettings::NoError) + { + cerr << "ERROR: RvSettings was unable to read settings for: '" + << qs->fileName().toStdString() << "' err: " << qs->status() + << endl; + } - return qs; - } + return qs; + } - static QString rebuildGroup( QStringList& stack ) - { - QString g; - for( int i = 0; i < stack.size(); ++i ) + static QString rebuildGroup(QStringList& stack) { - if( i ) g += "/"; - g += stack[i]; + QString g; + for (int i = 0; i < stack.size(); ++i) + { + if (i) + g += "/"; + g += stack[i]; + } + + return g; } - return g; - } + void RvSettings::beginGroup(const QString& prefix) + { + // + // We only use two levels of settings, so safer to + // ensure that beginGroup() always starts from the top level. + // XXX note that this _forbids_ the use of more than one level + // of preferences. + // + while (!m_userSettings->group().isEmpty()) + m_userSettings->endGroup(); - void RvSettings::beginGroup( const QString& prefix ) - { - // - // We only use two levels of settings, so safer to - // ensure that beginGroup() always starts from the top level. - // XXX note that this _forbids_ the use of more than one level - // of preferences. - // - while( !m_userSettings->group().isEmpty() ) m_userSettings->endGroup(); + m_userSettings->beginGroup(prefix); + } - m_userSettings->beginGroup( prefix ); - } + void RvSettings::endGroup() { m_userSettings->endGroup(); } - void RvSettings::endGroup() - { - m_userSettings->endGroup(); - } + QVariant RvSettings::value(const QString& key, + const QVariant& defaultValue) const + { + SettingsMap::const_iterator i; - QVariant RvSettings::value( const QString& key, - const QVariant& defaultValue ) const - { - SettingsMap::const_iterator i; + QString fullKey = m_userSettings->group() + "/" + key; - QString fullKey = m_userSettings->group() + "/" + key; + if ((i = m_clobberingSettings.find(fullKey)) + != m_clobberingSettings.end()) + // + // Clobbering value always wins + // + { + return i.value(); + } + else if (m_userSettings->contains(key)) + // + // User prefs have this key + // + { + return m_userSettings->value(key, defaultValue); + } + else if ((i = m_overridingSettings.find(fullKey)) + != m_overridingSettings.end()) + // + // No user key either, so use the overriding initializer + // + { + return i.value(); + } - if( ( i = m_clobberingSettings.find( fullKey ) ) != - m_clobberingSettings.end() ) - // - // Clobbering value always wins - // - { - return i.value(); - } - else if( m_userSettings->contains( key ) ) - // - // User prefs have this key - // - { - return m_userSettings->value( key, defaultValue ); + return defaultValue; } - else if( ( i = m_overridingSettings.find( fullKey ) ) != - m_overridingSettings.end() ) - // - // No user key either, so use the overriding initializer - // + + void RvSettings::setValue(const QString& key, const QVariant& value) { - return i.value(); - } + SettingsMap::iterator i; - return defaultValue; - } + QString fullKey = m_userSettings->group() + "/" + key; - void RvSettings::setValue( const QString& key, const QVariant& value ) - { - SettingsMap::iterator i; + if ((i = m_clobberingSettings.find(fullKey)) + != m_clobberingSettings.end()) + // + // Value came from clobbering settings, so check that incoming value is + // different, then remove from clobbering settings (otherwise, + // value() will still return the clobbering setting. + // + { + if (value == i.value()) + return; + m_clobberingSettings.erase(i); + } - QString fullKey = m_userSettings->group() + "/" + key; + if ((i = m_overridingSettings.find(fullKey)) + != m_overridingSettings.end() + && !m_userSettings->contains(key)) + // + // Value came from overriding settings, so check that incoming value is + // different, then remove from overriding settings (otherwise, + // value() will still return the overriding setting. + // + { + if (value == i.value()) + return; + m_overridingSettings.erase(i); + } - if( ( i = m_clobberingSettings.find( fullKey ) ) != - m_clobberingSettings.end() ) - // - // Value came from clobbering settings, so check that incoming value is - // different, then remove from clobbering settings (otherwise, - // value() will still return the clobbering setting. - // - { - if( value == i.value() ) return; - m_clobberingSettings.erase( i ); + // + // Finally save setting in user settings, so that next time the value + // comes from user settings, unless it is clobbered. + // + m_userSettings->setValue(key, value); + sync(); } - if( ( i = m_overridingSettings.find( fullKey ) ) != - m_overridingSettings.end() && - !m_userSettings->contains( key ) ) - // - // Value came from overriding settings, so check that incoming value is - // different, then remove from overriding settings (otherwise, - // value() will still return the overriding setting. - // + void RvSettings::sync() { - if( value == i.value() ) return; - m_overridingSettings.erase( i ); + m_userSettings->sync(); + if (!m_userSettingsErrorAlredyReported + && (m_userSettings->status() != QSettings::NoError)) + { + cerr << "ERROR: RvSettings was unable to write settings for: '" + << m_userSettings->fileName().toStdString() + << "' err: " << m_userSettings->status() << endl; + + m_userSettingsErrorAlredyReported = true; + } } - // - // Finally save setting in user settings, so that next time the value - // comes from user settings, unless it is clobbered. - // - m_userSettings->setValue( key, value ); - sync(); - } - - void RvSettings::sync() - { - m_userSettings->sync(); - if( !m_userSettingsErrorAlredyReported && - ( m_userSettings->status() != QSettings::NoError ) ) + void RvSettings::remove(const QString& key) { - cerr << "ERROR: RvSettings was unable to write settings for: '" - << m_userSettings->fileName().toStdString() - << "' err: " << m_userSettings->status() << endl; + QString fullKey = m_userSettings->group() + "/" + key; - m_userSettingsErrorAlredyReported = true; + if (!m_clobberingSettings.contains(fullKey) + && m_userSettings->contains(key)) + // + // Only remove key from user settings if it didn't come from the + // clobbering settings in the first place. + // + { + m_userSettings->remove(key); + } } - } - - void RvSettings::remove( const QString& key ) - { - QString fullKey = m_userSettings->group() + "/" + key; - if( !m_clobberingSettings.contains( fullKey ) && - m_userSettings->contains( key ) ) - // - // Only remove key from user settings if it didn't come from the clobbering - // settings in the first place. - // + bool RvSettings::contains(const QString& key) const { - m_userSettings->remove( key ); - } - } + QString fullKey = m_userSettings->group() + "/" + key; - bool RvSettings::contains( const QString& key ) const - { - QString fullKey = m_userSettings->group() + "/" + key; + if (m_clobberingSettings.contains(fullKey) + || m_userSettings->contains(key) + || m_overridingSettings.contains(fullKey)) + // + // The setting is provided by clobbering settings, or by user settings, + // or by overriding settings. + // + { + return true; + } - if( m_clobberingSettings.contains( fullKey ) || - m_userSettings->contains( key ) || - m_overridingSettings.contains( fullKey ) ) - // - // The setting is provided by clobbering settings, or by user settings, - // or by overriding settings. - // - { - return true; + return false; } - return false; - } - -} // namespace Rv \ No newline at end of file +} // namespace Rv diff --git a/src/lib/app/RvPackage/RvPackage/PackageManager.h b/src/lib/app/RvPackage/RvPackage/PackageManager.h index 73071529e..ca09e088c 100644 --- a/src/lib/app/RvPackage/RvPackage/PackageManager.h +++ b/src/lib/app/RvPackage/RvPackage/PackageManager.h @@ -1,237 +1,251 @@ // -// Copyright (c) 2010 Tweak Software. +// Copyright (c) 2010 Tweak Software. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// // #ifndef __RvPackage__PackageManager__h__ #define __RvPackage__PackageManager__h__ #include #include -namespace Rv { - -#define RV_QSETTINGS Rv::RvSettings& settings = Rv::RvSettings::globalSettings(); - -class RvSettings -{ - public: - - typedef QMap SettingsMap; - - // - // QSettings API - // - void beginGroup (const QString& prefix); - void endGroup(); - QVariant value (const QString& key, const QVariant& defaultValue = QVariant()) const; - void setValue (const QString& key, const QVariant& value); - void remove (const QString & key); - bool contains (const QString& key) const; - void sync(); - - QString fileName() const { return m_userSettings->fileName(); } - bool isWritable() const { return m_userSettings->isWritable(); } - - // - // Get (possibly create) the single global settings object - // - static RvSettings& globalSettings(); - static void cleanupGlobalSettings(); - - private: - - RvSettings(); - ~RvSettings(); - - QSettings* getQSettings(); - - QSettings* m_userSettings; - - // The QSettings class does not reset its error status: once an error status - // has been flagged, it is never cleared. - // For reference : https://bugreports.qt.io/browse/QTBUG-23857 - // With the aim of preventing the occurence of numerous duplicated error - // messages, this class will only report the first time an error is detected. - bool m_userSettingsErrorAlredyReported{false}; - - SettingsMap m_overridingSettings; - SettingsMap m_clobberingSettings; - - static RvSettings* m_globalSettingsP; -}; - -class PackageManager +namespace Rv { - public: - struct Mode - { - QString file; - QString menu; - QString shortcut; - QString event; - QString load; - QString icon; - QStringList requires; - }; - - struct AuxFile - { - QString file; - QString location; - }; +#define RV_QSETTINGS \ + Rv::RvSettings& settings = Rv::RvSettings::globalSettings(); - struct AuxFolder + class RvSettings { - QString folder; - QString location; + public: + typedef QMap SettingsMap; + + // + // QSettings API + // + void beginGroup(const QString& prefix); + void endGroup(); + QVariant value(const QString& key, + const QVariant& defaultValue = QVariant()) const; + void setValue(const QString& key, const QVariant& value); + void remove(const QString& key); + bool contains(const QString& key) const; + void sync(); + + QString fileName() const { return m_userSettings->fileName(); } + + bool isWritable() const { return m_userSettings->isWritable(); } + + // + // Get (possibly create) the single global settings object + // + static RvSettings& globalSettings(); + static void cleanupGlobalSettings(); + + private: + RvSettings(); + ~RvSettings(); + + QSettings* getQSettings(); + + QSettings* m_userSettings; + + // The QSettings class does not reset its error status: once an error + // status has been flagged, it is never cleared. For reference : + // https://bugreports.qt.io/browse/QTBUG-23857 With the aim of + // preventing the occurence of numerous duplicated error messages, this + // class will only report the first time an error is detected. + bool m_userSettingsErrorAlredyReported{false}; + + SettingsMap m_overridingSettings; + SettingsMap m_clobberingSettings; + + static RvSettings* m_globalSettingsP; }; - struct Package + class PackageManager { - Package() : installed(false), - loadable(false), - zipFile(false), - installing(false), - hidden(false), - system(false), - optional(false), - compatible(false), - fileWritable(false), - dirWritable(false), - row(-1) {} - - QString name; - QString baseName; - QString file; - QString dir; - QString author; - QString organization; - QString contact; - QString version; - QString url; - QString icon; - QString requires; - QStringList imageio; - QStringList movieio; - QString rvversion; - QString openrvversion; - QString description; - QList modes; - QStringList files; - - QList auxFiles; - QList auxFolders; - - bool installed; - bool loadable; - bool zipFile; - bool installing; - bool hidden; - bool system; - bool optional; - bool compatible; - bool fileWritable; - bool dirWritable; - int row; // row in tree widget - - QList uses; - QList usedBy; + public: + struct Mode + { + QString file; + QString menu; + QString shortcut; + QString event; + QString load; + QString icon; + QStringList + requires; + }; + + struct AuxFile + { + QString file; + QString location; + }; + + struct AuxFolder + { + QString folder; + QString location; + }; + + struct Package + { + Package() + : installed(false) + , loadable(false) + , zipFile(false) + , installing(false) + , hidden(false) + , system(false) + , optional(false) + , compatible(false) + , fileWritable(false) + , dirWritable(false) + , row(-1) + { + } + + QString name; + QString baseName; + QString file; + QString dir; + QString author; + QString organization; + QString contact; + QString version; + QString url; + QString icon; + QString + requires; + QStringList imageio; + QStringList movieio; + QString rvversion; + QString openrvversion; + QString description; + QList modes; + QStringList files; + + QList auxFiles; + QList auxFolders; + + bool installed; + bool loadable; + bool zipFile; + bool installing; + bool hidden; + bool system; + bool optional; + bool compatible; + bool fileWritable; + bool dirWritable; + int row; // row in tree widget + + QList uses; + QList usedBy; + }; + + struct ModeEntry + { + ModeEntry() + : loaded(false) + , active(false) + { + } + + QString name; + QString package; + QString menu; + QString shortcut; + QString event; + QString rvversion; + QString openrvversion; + bool loaded; + bool active; + bool optional; + QStringList + requires; + }; + + typedef QList PackageList; + typedef QList ModeEntryList; + typedef QMap PackageMap; + + PackageManager(); + virtual ~PackageManager(); + + virtual void loadPackages(); + virtual void loadPackageInfo(const QString&); + virtual void loadInstalltionFile(const QDir&, const QString&); + virtual void writeInstallationFile(const QString&); + virtual bool addPackages(const QStringList& files, const QString& path); + virtual void removePackages(const QStringList& files); + + virtual bool installPackage(Package&); + virtual bool uninstallPackage(Package&); + + virtual bool isBundle(const QString&); + virtual std::vector handleBundle(const QString&, + const QString&); + + virtual ModeEntryList loadModeFile(const QString&); + virtual void writeModeFile(const QString&, const ModeEntryList&, + int version = 0); + + virtual int findPackageIndexByZip(const QString&); + virtual void findPackageDependencies(); + + virtual bool allowLoading(Package&, bool, int d = 0); + virtual bool makeSupportDirTree(QDir& root); + + // + // Override these for UI versions. The defaults use cin/cout to + // collect responses from the user. + // + + virtual bool fixLoadability(const QString& msg); + virtual bool fixUnloadability(const QString& msg); + virtual bool overwriteExistingFiles(const QString& msg); + virtual bool installDependantPackages(const QString& msg); + virtual void errorMissingPackageDependancies(const QString& msg); + virtual bool uninstallDependantPackages(const QString& msg); + virtual void informCannotRemoveSomeFiles(const QString& msg); + virtual void errorModeFileWriteFailed(const QString& file); + virtual void informPackageFailedToCopy(const QString& msg); + virtual void declarePackage(Package&, size_t); + virtual bool uninstallForRemoval(const QString& msg); + + int auxFileIndex(Package&, const QString&); + QString expandVarsInPath(Package&, const QString&); + + PackageList& packageList() { return m_packages; } + + void setNoConfirmation(bool force = true) { m_force = force; } + + static void setIgnorePrefs(bool b) { m_ignorePrefs = b; } + + static bool ignoringPrefs() { return m_ignorePrefs; } + + // + // Swap symbolic application dir name in/out for the actual directory. + // + static QStringList swapAppDir(const QStringList& packages, bool swapIn); + + private: + bool yesOrNo(const char*, const char*, const QString&, const char*); + + protected: + PackageList m_packages; + PackageMap m_packageMap; + QStringList m_doNotLoadPackages; + QStringList m_optLoadPackages; + bool m_force; + + static bool m_ignorePrefs; }; - struct ModeEntry - { - ModeEntry() : loaded(false), active(false) {} - QString name; - QString package; - QString menu; - QString shortcut; - QString event; - QString rvversion; - QString openrvversion; - bool loaded; - bool active; - bool optional; - QStringList requires; - }; - - typedef QList PackageList; - typedef QList ModeEntryList; - typedef QMap PackageMap; - - PackageManager(); - virtual ~PackageManager(); - - virtual void loadPackages(); - virtual void loadPackageInfo(const QString&); - virtual void loadInstalltionFile(const QDir&, const QString&); - virtual void writeInstallationFile(const QString&); - virtual bool addPackages(const QStringList& files, const QString& path); - virtual void removePackages(const QStringList& files); - - virtual bool installPackage(Package&); - virtual bool uninstallPackage(Package&); - - virtual bool isBundle(const QString&); - virtual std::vector handleBundle(const QString&, const QString&); - - virtual ModeEntryList loadModeFile(const QString&); - virtual void writeModeFile(const QString&, const ModeEntryList&, int version=0); - - virtual int findPackageIndexByZip(const QString&); - virtual void findPackageDependencies(); - - virtual bool allowLoading(Package&,bool,int d=0); - virtual bool makeSupportDirTree(QDir& root); - - // - // Override these for UI versions. The defaults use cin/cout to - // collect responses from the user. - // - - virtual bool fixLoadability(const QString& msg); - virtual bool fixUnloadability(const QString& msg); - virtual bool overwriteExistingFiles(const QString& msg); - virtual bool installDependantPackages(const QString& msg); - virtual void errorMissingPackageDependancies(const QString& msg); - virtual bool uninstallDependantPackages(const QString& msg); - virtual void informCannotRemoveSomeFiles(const QString& msg); - virtual void errorModeFileWriteFailed(const QString& file); - virtual void informPackageFailedToCopy(const QString& msg); - virtual void declarePackage(Package&, size_t); - virtual bool uninstallForRemoval(const QString& msg); - - int auxFileIndex(Package&, const QString&); - QString expandVarsInPath(Package&, const QString&); - - PackageList& packageList() { return m_packages; } - - void setNoConfirmation(bool force = true) { m_force = force; } - - static void setIgnorePrefs(bool b) { m_ignorePrefs = b; } - static bool ignoringPrefs() { return m_ignorePrefs; } - - // - // Swap symbolic application dir name in/out for the actual directory. - // - static QStringList swapAppDir (const QStringList& packages, bool swapIn); - - private: - bool yesOrNo(const char*, const char*, const QString&, const char*); - - protected: - PackageList m_packages; - PackageMap m_packageMap; - QStringList m_doNotLoadPackages; - QStringList m_optLoadPackages; - bool m_force; - - static bool m_ignorePrefs; -}; - - -} // Rv +} // namespace Rv -#endif // __RvPackage__PackageManager__h__ \ No newline at end of file +#endif // __RvPackage__PackageManager__h__ diff --git a/src/lib/app/TwkApp/Action.cpp b/src/lib/app/TwkApp/Action.cpp index 68fb740a8..ff23da345 100644 --- a/src/lib/app/TwkApp/Action.cpp +++ b/src/lib/app/TwkApp/Action.cpp @@ -1,16 +1,18 @@ //****************************************************************************** -// Copyright (c) 2004 Tweak Inc. +// Copyright (c) 2004 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #include -namespace TwkApp { +namespace TwkApp +{ -Action::~Action() {} -void Action::execute(Document*, const Event&) const {} - -} // TwkApp + Action::~Action() {} + + void Action::execute(Document*, const Event&) const {} + +} // namespace TwkApp diff --git a/src/lib/app/TwkApp/Application.cpp b/src/lib/app/TwkApp/Application.cpp index d8380b402..3eda13275 100644 --- a/src/lib/app/TwkApp/Application.cpp +++ b/src/lib/app/TwkApp/Application.cpp @@ -1,9 +1,9 @@ //****************************************************************************** -// Copyright (c) 2005 Tweak Inc. +// Copyright (c) 2005 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #include @@ -12,86 +12,77 @@ #include #include -namespace TwkApp { -using namespace stl_ext; - -Application* Application::m_app = 0; - -Application::Application() : TwkUtil::Notifier() +namespace TwkApp { - assert(m_app == 0); - m_app = this; -} + using namespace stl_ext; -Application::~Application() -{ - m_app = 0; + Application* Application::m_app = 0; - // Make sure to release all the video modules before we unload the plugins - m_videoModules.clear(); -} + Application::Application() + : TwkUtil::Notifier() + { + assert(m_app == 0); + m_app = this; + } -void -Application::add(Document* d) -{ - d->addNotification(this, Document::deleteMessage()); - m_documents.push_back(d); -} + Application::~Application() + { + m_app = 0; -void -Application::remove(Document* d) -{ - stl_ext::remove(m_documents, d); -} + // Make sure to release all the video modules before we unload the + // plugins + m_videoModules.clear(); + } -bool -Application::receive(Notifier* originator, - Notifier* sender, - Notifier::MessageId id, - Notifier::MessageData* data) -{ - if (id == Document::deleteMessage()) + void Application::add(Document* d) { - remove(static_cast(originator)); + d->addNotification(this, Document::deleteMessage()); + m_documents.push_back(d); } - return true; -} + void Application::remove(Document* d) { stl_ext::remove(m_documents, d); } -VideoModule* -Application::primaryVideoModule() const -{ - return m_videoModules.empty() ? 0 : m_videoModules.front().get(); -} + bool Application::receive(Notifier* originator, Notifier* sender, + Notifier::MessageId id, + Notifier::MessageData* data) + { + if (id == Document::deleteMessage()) + { + remove(static_cast(originator)); + } -void -Application::loadOutputPlugins(const std::string& envvar) -{ - m_outputPlugins.loadPlugins(envvar); - for (auto outputPlugin : m_outputPlugins.plugins()) + return true; + } + + VideoModule* Application::primaryVideoModule() const { - int moduleIndex = 0; - TwkApp::VideoModule* outputModule = nullptr; - do + return m_videoModules.empty() ? 0 : m_videoModules.front().get(); + } + + void Application::loadOutputPlugins(const std::string& envvar) + { + m_outputPlugins.loadPlugins(envvar); + for (auto outputPlugin : m_outputPlugins.plugins()) { - outputModule = outputPlugin->output_module_create(OUTPUT_PLUGIN_VERSION, moduleIndex++); - if (outputModule) + int moduleIndex = 0; + TwkApp::VideoModule* outputModule = nullptr; + do { - addVideoModule(outputModule); - for (auto d : outputModule->devices()) + outputModule = outputPlugin->output_module_create( + OUTPUT_PLUGIN_VERSION, moduleIndex++); + if (outputModule) { - std::cout << "INFO: " << outputModule->name() << " found " << d->name() << std::endl; + addVideoModule(outputModule); + for (auto d : outputModule->devices()) + { + std::cout << "INFO: " << outputModule->name() + << " found " << d->name() << std::endl; + } } - } - } while (outputModule!=nullptr); + } while (outputModule != nullptr); + } } -} - -void -Application::unloadOutputPlugins() -{ - m_outputPlugins.unloadPlugins(); -} + void Application::unloadOutputPlugins() { m_outputPlugins.unloadPlugins(); } -} // TwkApp +} // namespace TwkApp diff --git a/src/lib/app/TwkApp/Bundle.cpp b/src/lib/app/TwkApp/Bundle.cpp index 48d6532de..c6ae077c7 100644 --- a/src/lib/app/TwkApp/Bundle.cpp +++ b/src/lib/app/TwkApp/Bundle.cpp @@ -1,9 +1,9 @@ //****************************************************************************** -// Copyright (c) 2007 Tweak Inc. +// Copyright (c) 2007 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #include @@ -11,130 +11,112 @@ #include #include -namespace TwkApp { -using namespace std; -using namespace boost; - -Bundle* Bundle::m_mainBundle = 0; - -Bundle::Bundle(const std::string& appName, - size_t major_version, - size_t minor_version, - size_t revision_number, - bool sandboxed, - bool inheritedSandbox) - : m_applicationName(appName), - m_majorVersion(major_version), - m_minorVersion(minor_version), - m_revisionNumber(revision_number), - m_sandboxed(sandboxed), - m_inheritedSandbox(inheritedSandbox) +namespace TwkApp { - ostringstream str; - str << m_majorVersion; - m_majorVersionDir = str.str(); - str << "." << m_minorVersion; - m_versionDir = str.str(); - - if (!m_mainBundle) m_mainBundle = this; -} - -Bundle::~Bundle() -{ - if (m_mainBundle == this) m_mainBundle = 0; -} + using namespace std; + using namespace boost; + + Bundle* Bundle::m_mainBundle = 0; + + Bundle::Bundle(const std::string& appName, size_t major_version, + size_t minor_version, size_t revision_number, bool sandboxed, + bool inheritedSandbox) + : m_applicationName(appName) + , m_majorVersion(major_version) + , m_minorVersion(minor_version) + , m_revisionNumber(revision_number) + , m_sandboxed(sandboxed) + , m_inheritedSandbox(inheritedSandbox) + { + ostringstream str; + str << m_majorVersion; + m_majorVersionDir = str.str(); + str << "." << m_minorVersion; + m_versionDir = str.str(); + + if (!m_mainBundle) + m_mainBundle = this; + } -namespace { + Bundle::~Bundle() + { + if (m_mainBundle == this) + m_mainBundle = 0; + } -} + namespace + { -void -Bundle::rescanCache(const string& cacheName) -{ -} + } -bool -Bundle::hasCacheItem(const string& cacheName, const CacheItemName& item) -{ - Path cachePath = cacheItemPath(cacheName, item); - return cachePath != "" && TwkUtil::fileExists(cachePath.c_str()); -} + void Bundle::rescanCache(const string& cacheName) {} -Bundle::Path -Bundle::cacheItemPath(const string& cacheName, const CacheItemName& item) -{ - boost::filesystem::path cachePath(userCacheDir()); - cachePath /= cacheName; - cachePath /= item; - return cachePath.string(); -} - -void -Bundle::addCacheItem(const string& cacheName, const CacheItemName& item, size_t size) -{ - Path cachePath = cacheItemPath(cacheName, item); -} + bool Bundle::hasCacheItem(const string& cacheName, + const CacheItemName& item) + { + Path cachePath = cacheItemPath(cacheName, item); + return cachePath != "" && TwkUtil::fileExists(cachePath.c_str()); + } -Bundle::FileAccessPermission -Bundle::permissionForFileAccess(const Path&, bool readonly) const -{ - return FileAccessPermission(); -} + Bundle::Path Bundle::cacheItemPath(const string& cacheName, + const CacheItemName& item) + { + boost::filesystem::path cachePath(userCacheDir()); + cachePath /= cacheName; + cachePath /= item; + return cachePath.string(); + } -Bundle::AccessObject -Bundle::beginFileAccessWithPermission(const FileAccessPermission&) const -{ - return AccessObject(0); -} + void Bundle::addCacheItem(const string& cacheName, + const CacheItemName& item, size_t size) + { + Path cachePath = cacheItemPath(cacheName, item); + } -void -Bundle::endFileAccessWithPermission(AccessObject) const -{ -} + Bundle::FileAccessPermission + Bundle::permissionForFileAccess(const Path&, bool readonly) const + { + return FileAccessPermission(); + } -string -Bundle::getEnvVar(const EnvVar& name, const std::string& defaultValue) -{ - if (const char* v = getenv(name.c_str())) + Bundle::AccessObject + Bundle::beginFileAccessWithPermission(const FileAccessPermission&) const { - return v; + return AccessObject(0); } - else + + void Bundle::endFileAccessWithPermission(AccessObject) const {} + + string Bundle::getEnvVar(const EnvVar& name, + const std::string& defaultValue) { - return defaultValue; + if (const char* v = getenv(name.c_str())) + { + return v; + } + else + { + return defaultValue; + } } -} -Bundle::Path -Bundle::userHome() -{ + Bundle::Path Bundle::userHome() + { #if defined(PLATFORM_APPLE_MACH_BSD) || defined(PLATFORM_LINUX) - return getEnvVar("HOME", "/"); + return getEnvVar("HOME", "/"); #endif #if defined(PLATFORM_WINDOWS) - string udrive = getEnvVar("HOMEDRIVE", "c:"); - string upath = getEnvVar("HOMEPATH", "/"); - return udrive + upath; + string udrive = getEnvVar("HOMEDRIVE", "c:"); + string upath = getEnvVar("HOMEPATH", "/"); + return udrive + upath; #endif -} + } -Bundle::Path -Bundle::userMovies() -{ - return userHome() + "/Movies"; -} + Bundle::Path Bundle::userMovies() { return userHome() + "/Movies"; } -Bundle::Path -Bundle::userMusic() -{ - return userHome() + "/Music"; -} + Bundle::Path Bundle::userMusic() { return userHome() + "/Music"; } -Bundle::Path -Bundle::userPictures() -{ - return userHome() + "/Pictures"; -} + Bundle::Path Bundle::userPictures() { return userHome() + "/Pictures"; } -} // TwkApp +} // namespace TwkApp diff --git a/src/lib/app/TwkApp/Command.cpp b/src/lib/app/TwkApp/Command.cpp index bb5e03849..ddf56aef4 100644 --- a/src/lib/app/TwkApp/Command.cpp +++ b/src/lib/app/TwkApp/Command.cpp @@ -1,520 +1,513 @@ //****************************************************************************** -// Copyright (c) 2004 Tweak Inc. +// Copyright (c) 2004 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #include #include -namespace TwkApp { -using namespace std; - -CommandInfo::CommandInfos CommandInfo::m_commands; -CompoundCommandInfo* CommandHistory::m_ccinfo = 0; - - -CommandInfo::CommandInfo(const string& name, UndoType type) - : m_name(name), - m_type(type) +namespace TwkApp { - m_commands[name] = this; -} + using namespace std; -CommandInfo::~CommandInfo() -{ -} - -const CommandInfo* -CommandInfo::findByName(const std::string& name) -{ - return m_commands[name]; -} + CommandInfo::CommandInfos CommandInfo::m_commands; + CompoundCommandInfo* CommandHistory::m_ccinfo = 0; -//---------------------------------------------------------------------- - -Command::Command(const CommandInfo* info) - : m_commandInfo(info) -{ -} + CommandInfo::CommandInfo(const string& name, UndoType type) + : m_name(name) + , m_type(type) + { + m_commands[name] = this; + } -Command::~Command() {} -void Command::undo() { doit(); } -void Command::redo() { doit(); } + CommandInfo::~CommandInfo() {} -std::string -Command::name() const -{ - return info()->name(); -} + const CommandInfo* CommandInfo::findByName(const std::string& name) + { + return m_commands[name]; + } -//---------------------------------------------------------------------- + //---------------------------------------------------------------------- -CommandHistory::CommandHistory() - : m_compound(0), - m_historyState(EditingState) -{ - if (!m_ccinfo) + Command::Command(const CommandInfo* info) + : m_commandInfo(info) { - m_ccinfo = new CompoundCommandInfo(); } -} -CommandHistory::~CommandHistory() -{ - assert(m_historyState == EditingState); - if (m_compound) delete m_compound; - clearHistory(); -} + Command::~Command() {} -void -CommandHistory::beginCompoundCommand(const std::string& name) -{ - assert(m_historyState == EditingState); - if (m_historyState != EditingState) return; + void Command::undo() { doit(); } + + void Command::redo() { doit(); } - if (compoundActive()) + std::string Command::name() const { return info()->name(); } + + //---------------------------------------------------------------------- + + CommandHistory::CommandHistory() + : m_compound(0) + , m_historyState(EditingState) { - m_compound->beginCompoundCommand(name); + if (!m_ccinfo) + { + m_ccinfo = new CompoundCommandInfo(); + } } - else + + CommandHistory::~CommandHistory() { - m_compound = static_cast(m_ccinfo->newCommand()); - m_compound->setName(name); - m_compound->setDescription(name); + assert(m_historyState == EditingState); + if (m_compound) + delete m_compound; + clearHistory(); } -} -void -CommandHistory::endCompoundCommand() -{ - assert(m_historyState == EditingState); - if (m_historyState != EditingState) return; - - if (compoundActive()) + void CommandHistory::beginCompoundCommand(const std::string& name) { - if (m_compound->compoundActive()) + assert(m_historyState == EditingState); + if (m_historyState != EditingState) + return; + + if (compoundActive()) { - m_compound->endCompoundCommand(); + m_compound->beginCompoundCommand(name); } else { - m_undoStack.push_front(m_compound); - m_compound = 0; - m_undoSizeChangedSignal(); - clearRedoHistory(); + m_compound = static_cast(m_ccinfo->newCommand()); + m_compound->setName(name); + m_compound->setDescription(name); } } -} -void -CommandHistory::clearUndoHistory() -{ - assert(m_historyState == EditingState); - - if (m_compound) + void CommandHistory::endCompoundCommand() { - m_compound->clearUndoHistory(); + assert(m_historyState == EditingState); + if (m_historyState != EditingState) + return; + + if (compoundActive()) + { + if (m_compound->compoundActive()) + { + m_compound->endCompoundCommand(); + } + else + { + m_undoStack.push_front(m_compound); + m_compound = 0; + m_undoSizeChangedSignal(); + clearRedoHistory(); + } + } } - else + + void CommandHistory::clearUndoHistory() { - stl_ext::delete_contents(m_undoStack); - m_undoStack.clear(); - } + assert(m_historyState == EditingState); - m_undoSizeChangedSignal(); -} + if (m_compound) + { + m_compound->clearUndoHistory(); + } + else + { + stl_ext::delete_contents(m_undoStack); + m_undoStack.clear(); + } -void -CommandHistory::clearRedoHistory() -{ - assert(m_historyState == EditingState); + m_undoSizeChangedSignal(); + } - if (m_compound) + void CommandHistory::clearRedoHistory() { - m_compound->clearRedoHistory(); - } - else - { - stl_ext::delete_contents(m_redoStack); - m_redoStack.clear(); + assert(m_historyState == EditingState); + + if (m_compound) + { + m_compound->clearRedoHistory(); + } + else + { + stl_ext::delete_contents(m_redoStack); + m_redoStack.clear(); + } + + redoSizeChangedSignal(); } - redoSizeChangedSignal(); -} + namespace + { -namespace { + void removeUniqueMarkers(MarkerCommand* m, CommandStack& commandStack) + { + if (!m->isUnique()) + return; -void -removeUniqueMarkers(MarkerCommand* m, CommandStack& commandStack) -{ - if (!m->isUnique()) return; + for (int i = 0; i < commandStack.size(); i++) + { + if (commandStack[i]->isMarker()) + { + MarkerCommand* cm = + static_cast(commandStack[i]); + + if (cm->name() == m->name()) + { + commandStack.erase(commandStack.begin() + i); + i--; + delete cm; + } + } + } + } + + bool hasMarkerInCommandStack(const string& name, + const CommandStack& commandStack) + { + for (int i = 0; i < commandStack.size(); i++) + { + if (commandStack[i]->isMarker()) + { + MarkerCommand* cm = + static_cast(commandStack[i]); + if (cm->name() == name) + return true; + } + } - for (int i = 0; i < commandStack.size(); i++) + return false; + } + + } // namespace + + string CommandHistory::topOfStackDescription(const CommandStack& s) { - if (commandStack[i]->isMarker()) + if (!s.empty()) { - MarkerCommand* cm = static_cast(commandStack[i]); - - if (cm->name() == m->name()) + if (s[0]->isMarker() && s.size() > 1) + { + return s[1]->description(); + } + else if (!s.empty()) { - commandStack.erase(commandStack.begin() + i); - i--; - delete cm; + return s[0]->description(); } } + + return ""; } -} -bool -hasMarkerInCommandStack(const string& name, const CommandStack& commandStack) -{ - for (int i = 0; i < commandStack.size(); i++) + bool CommandHistory::hasMarkerCommand(const string& name) const + { + return hasMarkerInCommandStack(name, m_undoStack) + || hasMarkerInCommandStack(name, m_redoStack); + } + + bool CommandHistory::isMarkerCommandRecent(const string& name) const { - if (commandStack[i]->isMarker()) + if (!m_undoStack.empty() && m_undoStack[0]->isMarker()) { - MarkerCommand* cm = static_cast(commandStack[i]); - if (cm->name() == name) return true; + MarkerCommand* cm = static_cast(m_undoStack[0]); + return cm->name() == name; } - } - return false; -} + return false; + } -} + void CommandHistory::doCommand(Command* c) + { + ScopedLock lock(m_commandQueueMutex); + if (!m_commandQueue.empty()) + flushCommandQueueInternal(); + doCommandInternal(c); + } -string -CommandHistory::topOfStackDescription(const CommandStack& s) -{ - if (!s.empty()) + void CommandHistory::doCommandInternal(Command* c) { - if (s[0]->isMarker() && s.size() > 1) + assert(m_historyState == EditingState); + + if (m_historyState != EditingState) { - return s[1]->description(); + delete c; + return; } - else if (!s.empty()) + + if (m_compound) { - return s[0]->description(); + m_compound->doCommand(c); } - } - - return ""; -} + else + { + if (c->isUndoable()) + { + clearRedoHistory(); + c->doit(); + m_undoStack.push_front(c); + m_undoSizeChangedSignal(); + } + else if (c->isMarker()) + { + MarkerCommand* m = static_cast(c); -bool -CommandHistory::hasMarkerCommand(const string& name) const -{ - return hasMarkerInCommandStack(name, m_undoStack) || - hasMarkerInCommandStack(name, m_redoStack); -} + // + // Remove all markers with the same name in the history + // if its a "unqiue" marker + // -bool -CommandHistory::isMarkerCommandRecent(const string& name) const -{ - if (!m_undoStack.empty() && m_undoStack[0]->isMarker()) - { - MarkerCommand* cm = static_cast(m_undoStack[0]); - return cm->name() == name; + removeUniqueMarkers(m, m_undoStack); + removeUniqueMarkers(m, m_redoStack); + m_undoStack.push_front(c); + } + else + { + if (!c->isEditOnly()) + clearHistory(); + c->doit(); + delete c; + } + } } - return false; -} + void CommandHistory::undoCommand() + { + assert(!m_compound); + if (m_compound) + return; -void -CommandHistory::doCommand(Command* c) -{ - ScopedLock lock(m_commandQueueMutex); - if (!m_commandQueue.empty()) flushCommandQueueInternal(); - doCommandInternal(c); -} + assert(m_historyState == EditingState); + m_historyState = UndoState; -void -CommandHistory::doCommandInternal(Command* c) -{ - assert(m_historyState == EditingState); + try + { + undoCommandInternal(); + } + catch (...) + { + } - if (m_historyState != EditingState) - { - delete c; - return; + m_historyState = EditingState; } - if (m_compound) - { - m_compound->doCommand(c); - } - else + void CommandHistory::redoCommand() { - if (c->isUndoable()) + assert(!m_compound); + if (m_compound) + return; + + assert(m_historyState == EditingState); + m_historyState = RedoState; + + try { - clearRedoHistory(); - c->doit(); - m_undoStack.push_front(c); - m_undoSizeChangedSignal(); + redoCommandInternal(); } - else if (c->isMarker()) + catch (...) { - MarkerCommand* m = static_cast(c); + } - // - // Remove all markers with the same name in the history - // if its a "unqiue" marker - // + m_historyState = EditingState; + } - removeUniqueMarkers(m, m_undoStack); - removeUniqueMarkers(m, m_redoStack); - m_undoStack.push_front(c); - } - else + void CommandHistory::undoCommandInternal() + { + if (!m_undoStack.empty()) { - if (!c->isEditOnly()) clearHistory(); - c->doit(); - delete c; + Command* c = m_undoStack.front(); + m_undoStack.pop_front(); + c->undo(); + m_redoStack.push_front(c); + + if (!m_undoStack.empty() && c->isMarker()) + undoCommandInternal(); } + + m_redoSizeChangedSignal(); + m_undoSizeChangedSignal(); } -} -void -CommandHistory::undoCommand() -{ - assert(!m_compound); - if (m_compound) return; + void CommandHistory::redoCommandInternal() + { + if (!m_redoStack.empty()) + { + Command* c = m_redoStack.front(); + m_redoStack.pop_front(); + c->redo(); + m_undoStack.push_front(c); + if (!m_redoStack.empty() && m_redoStack.front()->isMarker()) + redoCommandInternal(); + } - assert(m_historyState == EditingState); - m_historyState = UndoState; + m_redoSizeChangedSignal(); + m_undoSizeChangedSignal(); + } - try + void CommandHistory::undoAllCommands() { - undoCommandInternal(); + while (!m_undoStack.empty()) + undoCommand(); } - catch (...) + + void CommandHistory::redoAllCommands() { + while (!m_redoStack.empty()) + redoCommand(); } - m_historyState = EditingState; -} - -void -CommandHistory::redoCommand() -{ - assert(!m_compound); - if (m_compound) return; - - assert(m_historyState == EditingState); - m_historyState = RedoState; - - try + void CommandHistory::queueCommand(Command* c) { - redoCommandInternal(); + ScopedLock lock(m_commandQueueMutex); + m_commandQueue.push_back(c); } - catch (...) + + void CommandHistory::flushCommandQueue() { + ScopedLock lock(m_commandQueueMutex); + flushCommandQueueInternal(); } - m_historyState = EditingState; -} - -void -CommandHistory::undoCommandInternal() -{ - if (!m_undoStack.empty()) + void CommandHistory::flushCommandQueueInternal() { - Command* c = m_undoStack.front(); - m_undoStack.pop_front(); - c->undo(); - m_redoStack.push_front(c); + for (size_t i = 0; i < m_commandQueue.size(); i++) + { + doCommandInternal(m_commandQueue[i]); + } - if (!m_undoStack.empty() && c->isMarker()) undoCommandInternal(); + m_commandQueue.clear(); } - m_redoSizeChangedSignal(); - m_undoSizeChangedSignal(); -} + //------------------------------------------------------------------------------ -void -CommandHistory::redoCommandInternal() -{ - if (!m_redoStack.empty()) + CompoundCommand::CompoundCommand(const CompoundCommandInfo* info) + : Command(info) { - Command* c = m_redoStack.front(); - m_redoStack.pop_front(); - c->redo(); - m_undoStack.push_front(c); - if (!m_redoStack.empty() && m_redoStack.front()->isMarker()) redoCommandInternal(); } - m_redoSizeChangedSignal(); - m_undoSizeChangedSignal(); -} + CompoundCommand::~CompoundCommand() {} -void -CommandHistory::undoAllCommands() -{ - while (!m_undoStack.empty()) undoCommand(); -} + void CompoundCommand::doit() {} -void -CommandHistory::redoAllCommands() -{ - while (!m_redoStack.empty()) redoCommand(); -} + void CompoundCommand::undo() { undoAllCommands(); } -void -CommandHistory::queueCommand(Command* c) -{ - ScopedLock lock(m_commandQueueMutex); - m_commandQueue.push_back(c); -} + void CompoundCommand::redo() { redoAllCommands(); } -void -CommandHistory::flushCommandQueue() -{ - ScopedLock lock(m_commandQueueMutex); - flushCommandQueueInternal(); -} + std::string CompoundCommand::name() const { return m_name; } -void -CommandHistory::flushCommandQueueInternal() -{ - for (size_t i = 0; i < m_commandQueue.size(); i++) + //---------------------------------------------------------------------- + + CompoundCommandInfo::CompoundCommandInfo() + : CommandInfo("compound") { - doCommandInternal(m_commandQueue[i]); } - m_commandQueue.clear(); -} + CompoundCommandInfo::~CompoundCommandInfo() {} + Command* CompoundCommandInfo::newCommand() const + { + return new CompoundCommand(this); + } -//------------------------------------------------------------------------------ - -CompoundCommand::CompoundCommand(const CompoundCommandInfo* info) - : Command(info) -{ -} - -CompoundCommand::~CompoundCommand() {} - -void CompoundCommand::doit() {} + //------------------------------------------------------------------------------ -void -CompoundCommand::undo() -{ - undoAllCommands(); -} + MarkerCommand::MarkerCommand(const MarkerCommandInfo* info) + : Command(info) + , m_unique(true) + { + } -void -CompoundCommand::redo() -{ - redoAllCommands(); -} + MarkerCommand::~MarkerCommand() {} -std::string -CompoundCommand::name() const -{ - return m_name; -} + void MarkerCommand::doit() {} -//---------------------------------------------------------------------- + void MarkerCommand::undo() {} -CompoundCommandInfo::CompoundCommandInfo() : CommandInfo("compound") -{ -} + void MarkerCommand::redo() {} -CompoundCommandInfo::~CompoundCommandInfo() {} + std::string MarkerCommand::name() const { return m_name; } -Command* -CompoundCommandInfo::newCommand() const -{ - return new CompoundCommand(this); -} + //---------------------------------------------------------------------- -//------------------------------------------------------------------------------ + MarkerCommandInfo::MarkerCommandInfo() + : CommandInfo("marker", Marker) + { + } -MarkerCommand::MarkerCommand(const MarkerCommandInfo* info) - : Command(info), m_unique(true) -{ -} + MarkerCommandInfo::~MarkerCommandInfo() {} -MarkerCommand::~MarkerCommand() {} + Command* MarkerCommandInfo::newCommand() const + { + return new MarkerCommand(this); + } -void MarkerCommand::doit() {} -void MarkerCommand::undo() {} -void MarkerCommand::redo() {} + //------------------------------------------------------------------------------ -std::string -MarkerCommand::name() const -{ - return m_name; -} + HistoryCommand::HistoryCommand(const HistoryCommandInfo* info) + : Command(info) + , m_commandType(NoOpCommandType) + , m_history(0) + { + } -//---------------------------------------------------------------------- + HistoryCommand::~HistoryCommand() {} -MarkerCommandInfo::MarkerCommandInfo() : CommandInfo("marker", Marker) { } -MarkerCommandInfo::~MarkerCommandInfo() {} -Command* MarkerCommandInfo::newCommand() const { return new MarkerCommand(this); } + void HistoryCommand::doit() + { + if (m_history) + { + switch (m_commandType) + { + case UndoCommandType: + m_history->undoCommand(); + break; + case RedoCommandType: + m_history->redoCommand(); + break; + case ClearCommandType: + m_history->clearHistory(); + break; + case BeginCompoundCommandType: + m_history->beginCompoundCommand(m_name); + break; + case EndCompoundCommandType: + m_history->endCompoundCommand(); + break; + default: + break; + } -//------------------------------------------------------------------------------ + m_history = 0; + m_commandType = NoOpCommandType; + } + } -HistoryCommand::HistoryCommand(const HistoryCommandInfo* info) - : Command(info), - m_commandType(NoOpCommandType), - m_history(0) -{ -} + void HistoryCommand::undo() { abort(); } // should never get here -HistoryCommand::~HistoryCommand() {} + void HistoryCommand::redo() { abort(); } // should never get here -void -HistoryCommand::doit() -{ - if (m_history) + void HistoryCommand::setArgs(CommandHistory* h, CommandType t, + const string& name) { - switch (m_commandType) - { - case UndoCommandType: - m_history->undoCommand(); - break; - case RedoCommandType: - m_history->redoCommand(); - break; - case ClearCommandType: - m_history->clearHistory(); - break; - case BeginCompoundCommandType: - m_history->beginCompoundCommand(m_name); - break; - case EndCompoundCommandType: - m_history->endCompoundCommand(); - break; - default: - break; - } - - m_history = 0; - m_commandType = NoOpCommandType; + m_history = h; + m_commandType = t; + m_name = name; } -} -void HistoryCommand::undo() { abort(); } // should never get here -void HistoryCommand::redo() { abort(); } // should never get here + //---------------------------------------------------------------------- -void -HistoryCommand::setArgs(CommandHistory* h, CommandType t, const string& name) -{ - m_history = h; - m_commandType = t; - m_name = name; -} - -//---------------------------------------------------------------------- + HistoryCommandInfo::HistoryCommandInfo() + : CommandInfo("history", EditOnly) + { + } -HistoryCommandInfo::HistoryCommandInfo() : CommandInfo("history", EditOnly) { } -HistoryCommandInfo::~HistoryCommandInfo() {} -Command* HistoryCommandInfo::newCommand() const { return new HistoryCommand(this); } + HistoryCommandInfo::~HistoryCommandInfo() {} -//------------------------------------------------------------------------------ + Command* HistoryCommandInfo::newCommand() const + { + return new HistoryCommand(this); + } + //------------------------------------------------------------------------------ -} // TwkApp +} // namespace TwkApp diff --git a/src/lib/app/TwkApp/Document.cpp b/src/lib/app/TwkApp/Document.cpp index 05ac782fe..05897cfb6 100644 --- a/src/lib/app/TwkApp/Document.cpp +++ b/src/lib/app/TwkApp/Document.cpp @@ -1,9 +1,9 @@ //****************************************************************************** // Copyright (c) 2002 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #include #include @@ -15,668 +15,637 @@ #include #include -namespace TwkApp { -using namespace TwkUtil; -using namespace std; -using namespace TwkMath; - -Document::Documents Document::m_documents; -Document* Document::m_eventDocument = 0; - -NOTIFIER_MESSAGE_IMP(Document, modeChangedMessage, "document mode changed") -NOTIFIER_MESSAGE_IMP(Document, menuChangedMessage, "document menu changed") -NOTIFIER_MESSAGE_IMP(Document, selectionChangedMessage, "document selection changed") -NOTIFIER_MESSAGE_IMP(Document, activeMessage, "document active") -NOTIFIER_MESSAGE_IMP(Document, bindingsChangedMessage, "document bindings changed") -NOTIFIER_MESSAGE_IMP(Document, modeAddedMessage, "document mode added") -NOTIFIER_MESSAGE_IMP(Document, historyChangedMessage, "document history changed") -NOTIFIER_MESSAGE_IMP(Document, deleteMessage, "document deleted") -NOTIFIER_MESSAGE_IMP(Document, filenameChangedMessage, "document filename changed") - -Document::Document() - : TwkUtil::Notifier(), - EventNode("document"), - m_majorMode(0), - m_menu(0), - m_eventTableDirty(true), - m_event(0), - m_opaquePointer(0), - m_focusTable(0), - m_fileName("Untitled") -{ - m_documents.push_back(this); - if (App()) App()->add(this); -} - -Document::~Document() -{ - bool active = activeDocument() == this; - - deleteModes(); - - stl_ext::remove(m_documents, this); - - if (active && !m_documents.empty()) +namespace TwkApp +{ + using namespace TwkUtil; + using namespace std; + using namespace TwkMath; + + Document::Documents Document::m_documents; + Document* Document::m_eventDocument = 0; + + NOTIFIER_MESSAGE_IMP(Document, modeChangedMessage, "document mode changed") + NOTIFIER_MESSAGE_IMP(Document, menuChangedMessage, "document menu changed") + NOTIFIER_MESSAGE_IMP(Document, selectionChangedMessage, + "document selection changed") + NOTIFIER_MESSAGE_IMP(Document, activeMessage, "document active") + NOTIFIER_MESSAGE_IMP(Document, bindingsChangedMessage, + "document bindings changed") + NOTIFIER_MESSAGE_IMP(Document, modeAddedMessage, "document mode added") + NOTIFIER_MESSAGE_IMP(Document, historyChangedMessage, + "document history changed") + NOTIFIER_MESSAGE_IMP(Document, deleteMessage, "document deleted") + NOTIFIER_MESSAGE_IMP(Document, filenameChangedMessage, + "document filename changed") + + Document::Document() + : TwkUtil::Notifier() + , EventNode("document") + , m_majorMode(0) + , m_menu(0) + , m_eventTableDirty(true) + , m_event(0) + , m_opaquePointer(0) + , m_focusTable(0) + , m_fileName("Untitled") { - m_documents.front()->makeActive(); + m_documents.push_back(this); + if (App()) + App()->add(this); } - m_deleteSignal(this); - send(deleteMessage(), this); -} - -void -Document::deleteModes() -{ - for (Modes::iterator i = m_modes.begin(); i != m_modes.end(); ++i) + Document::~Document() { - delete (*i).second; - } + bool active = activeDocument() == this; - m_modes.clear(); - m_majorMode = 0; - m_minorModes.clear(); - delete m_menu; - m_menu = 0; - m_menuChangedSignal(this); - send(menuChangedMessage()); -} - -void -Document::makeActive() -{ - Documents::iterator i = find(m_documents.begin(), m_documents.end(), this); + deleteModes(); - if (i != m_documents.end()) - { - swap(m_documents.front(), *i); - m_activeSignal(this); - send(activeMessage(), this); - } -} + stl_ext::remove(m_documents, this); -void -Document::setFileName(const std::string& newName) -{ - m_fileName = newName; - m_fileNameChangedSignal(this); - send(filenameChangedMessage()); -} + if (active && !m_documents.empty()) + { + m_documents.front()->makeActive(); + } -const std::string& -Document::fileName() const -{ - return m_fileName; -} + m_deleteSignal(this); + send(deleteMessage(), this); + } -std::string -Document::filePath() const -{ - return m_fileName; -} + void Document::deleteModes() + { + for (Modes::iterator i = m_modes.begin(); i != m_modes.end(); ++i) + { + delete (*i).second; + } -void -Document::read(const string&, const ReadRequest&) -{ - // nothing -} + m_modes.clear(); + m_majorMode = 0; + m_minorModes.clear(); + delete m_menu; + m_menu = 0; + m_menuChangedSignal(this); + send(menuChangedMessage()); + } -void -Document::write(const string&, const WriteRequest&) -{ - // nothing -} + void Document::makeActive() + { + Documents::iterator i = + find(m_documents.begin(), m_documents.end(), this); -void -Document::clear() -{ -} + if (i != m_documents.end()) + { + swap(m_documents.front(), *i); + m_activeSignal(this); + send(activeMessage(), this); + } + } -void -Document::doCommand(Command* c) -{ - CommandHistory::doCommand(c); - m_historyChangedSignal(this); - send(historyChangedMessage(), this); -} + void Document::setFileName(const std::string& newName) + { + m_fileName = newName; + m_fileNameChangedSignal(this); + send(filenameChangedMessage()); + } -void -Document::undoCommand() -{ - CommandHistory::undoCommand(); - m_historyChangedSignal(this); - send(historyChangedMessage(), this); -} + const std::string& Document::fileName() const { return m_fileName; } -void -Document::redoCommand() -{ - CommandHistory::redoCommand(); - m_historyChangedSignal(this); - send(historyChangedMessage(), this); -} + std::string Document::filePath() const { return m_fileName; } -void -Document::activateMode(const std::string& name) -{ - if (Mode* m = findModeByName(name)) - { - activateMode(m); - } - else + void Document::read(const string&, const ReadRequest&) { - cerr << "WARNING: tried to activate non-existant mode " - << name - << endl; + // nothing } -} -void -Document::deactivateMode(const std::string& name) -{ - if (Mode* m = findModeByName(name)) + void Document::write(const string&, const WriteRequest&) { - deactivateMode(m); + // nothing } - else + + void Document::clear() {} + + void Document::doCommand(Command* c) { + CommandHistory::doCommand(c); + m_historyChangedSignal(this); + send(historyChangedMessage(), this); } -} -bool -Document::isModeActive(const std::string& name) -{ - if (Mode* m = findModeByName(name)) + void Document::undoCommand() { - return isModeActive(m); + CommandHistory::undoCommand(); + m_historyChangedSignal(this); + send(historyChangedMessage(), this); } - else + + void Document::redoCommand() { - return false; + CommandHistory::redoCommand(); + m_historyChangedSignal(this); + send(historyChangedMessage(), this); } -} -void -Document::activateMode(Mode* mode) -{ - if (MajorMode *majorMode = dynamic_cast(mode)) + void Document::activateMode(const std::string& name) { - if (m_majorMode == majorMode) return; - - if (m_majorMode) + if (Mode* m = findModeByName(name)) { - m_majorMode->deactivate(); + activateMode(m); } - - if (m_majorMode = majorMode) + else { - m_majorMode->activate(); + cerr << "WARNING: tried to activate non-existant mode " << name + << endl; } } - else - { - MinorMode *minorMode = static_cast(mode); - MinorModes::iterator i = find(m_minorModes.begin(), - m_minorModes.end(), minorMode); - if (i == m_minorModes.end()) + void Document::deactivateMode(const std::string& name) + { + if (Mode* m = findModeByName(name)) { - m_minorModes.insert(minorMode); - minorMode->activate(); + deactivateMode(m); } else { - return; } } - // see header file note - invalidateEventTables(); - m_modeChangedSignal(this); - send(modeChangedMessage()); - if (mode->menu()) invalidateMenu(); -} - -void -Document::deactivateMode(Mode* mode) -{ - if (MajorMode *majorMode = dynamic_cast(mode)) + bool Document::isModeActive(const std::string& name) { - return; - } - else - { - MinorMode *minorMode = static_cast(mode); - MinorModes::iterator i = find(m_minorModes.begin(), - m_minorModes.end(), minorMode); - - if (i != m_minorModes.end()) + if (Mode* m = findModeByName(name)) { - m_minorModes.erase(i); - minorMode->deactivate(); + return isModeActive(m); } else { - return; + return false; } } - // see header file note - invalidateEventTables(); - m_modeChangedSignal(this); - send(modeChangedMessage()); - if (mode->menu()) invalidateMenu(); -} + void Document::activateMode(Mode* mode) + { + if (MajorMode* majorMode = dynamic_cast(mode)) + { + if (m_majorMode == majorMode) + return; -bool -Document::isModeActive(Mode* m) -{ - if (m == m_majorMode) return true; + if (m_majorMode) + { + m_majorMode->deactivate(); + } - if (MinorMode *minorMode = dynamic_cast(m)) - { - MinorModes::iterator i = find(m_minorModes.begin(), - m_minorModes.end(), - minorMode); - return i != m_minorModes.end(); - } + if (m_majorMode = majorMode) + { + m_majorMode->activate(); + } + } + else + { + MinorMode* minorMode = static_cast(mode); + MinorModes::iterator i = + find(m_minorModes.begin(), m_minorModes.end(), minorMode); - return false; -} + if (i == m_minorModes.end()) + { + m_minorModes.insert(minorMode); + minorMode->activate(); + } + else + { + return; + } + } -Mode * -Document::findModeByName(const std::string& name) const -{ - Modes::const_iterator i = m_modes.find(name); - if (i == m_modes.end()) return 0; - return (*i).second; -} + // see header file note + invalidateEventTables(); + m_modeChangedSignal(this); + send(modeChangedMessage()); + if (mode->menu()) + invalidateMenu(); + } -void -Document::addMode(Mode *mode) -{ - if (findModeByName(mode->name())) + void Document::deactivateMode(Mode* mode) { - TWK_THROW_STREAM(DocumentException, "Duplicate mode: " << mode->name()); + if (MajorMode* majorMode = dynamic_cast(mode)) + { + return; + } + else + { + MinorMode* minorMode = static_cast(mode); + MinorModes::iterator i = + find(m_minorModes.begin(), m_minorModes.end(), minorMode); + + if (i != m_minorModes.end()) + { + m_minorModes.erase(i); + minorMode->deactivate(); + } + else + { + return; + } + } + + // see header file note + invalidateEventTables(); + m_modeChangedSignal(this); + send(modeChangedMessage()); + if (mode->menu()) + invalidateMenu(); } - m_modes.insert(Modes::value_type(mode->name(), mode)); - invalidateEventTables(); - m_modeAddedSignal(this); - send(modeAddedMessage()); -} + bool Document::isModeActive(Mode* m) + { + if (m == m_majorMode) + return true; -void -Document::setSelection(const SelectionState &state) -{ - m_selectionState = state; - m_selectionChangedSignal(this); - send(selectionChangedMessage()); -} + if (MinorMode* minorMode = dynamic_cast(m)) + { + MinorModes::iterator i = + find(m_minorModes.begin(), m_minorModes.end(), minorMode); + return i != m_minorModes.end(); + } -void -Document::invalidateMenu() -{ - delete m_menu; - m_menu = 0; - m_menuChangedSignal(this); - send(menuChangedMessage()); -} - -void -Document::invalidateEventTables() -{ - m_eventTableDirty = true; -} + return false; + } -Menu* -Document::menu() -{ - if (!m_menu && m_majorMode) + Mode* Document::findModeByName(const std::string& name) const { - m_menu = new Menu(m_majorMode->menu()); + Modes::const_iterator i = m_modes.find(name); + if (i == m_modes.end()) + return 0; + return (*i).second; + } - for (MinorModes::iterator i = m_minorModes.begin(); - i != m_minorModes.end(); - ++i) + void Document::addMode(Mode* mode) + { + if (findModeByName(mode->name())) { - m_menu->merge((*i)->menu()); + TWK_THROW_STREAM(DocumentException, + "Duplicate mode: " << mode->name()); } - } - return m_menu; -} + m_modes.insert(Modes::value_type(mode->name(), mode)); + invalidateEventTables(); + m_modeAddedSignal(this); + send(modeAddedMessage()); + } -void -Document::buildEventTables() -{ - m_eventTableStack.clear(); + void Document::setSelection(const SelectionState& state) + { + m_selectionState = state; + m_selectionChangedSignal(this); + send(selectionChangedMessage()); + } - if (m_eventTableNameStack.empty()) + void Document::invalidateMenu() { - m_eventTableNameStack.push_back("global"); + delete m_menu; + m_menu = 0; + m_menuChangedSignal(this); + send(menuChangedMessage()); } - - // - // Retain minormode ordering here, so that event tables are - // checked in the correct order. - // - - for (EventTableNameStack::const_iterator ni = m_eventTableNameStack.begin(); - ni != m_eventTableNameStack.end(); - ++ni) + + void Document::invalidateEventTables() { m_eventTableDirty = true; } + + Menu* Document::menu() { - const string& tname = *ni; + if (!m_menu && m_majorMode) + { + m_menu = new Menu(m_majorMode->menu()); - // - // do the major mode - // - - EventTables::const_iterator ti = m_majorMode->eventTables().find(tname); + for (MinorModes::iterator i = m_minorModes.begin(); + i != m_minorModes.end(); ++i) + { + m_menu->merge((*i)->menu()); + } + } + + return m_menu; + } + + void Document::buildEventTables() + { + m_eventTableStack.clear(); - if (ti != m_majorMode->eventTables().end()) + if (m_eventTableNameStack.empty()) { - m_eventTableStack.push_back(ti->second); + m_eventTableNameStack.push_back("global"); } // - // do the minor modes + // Retain minormode ordering here, so that event tables are + // checked in the correct order. // - for (MinorModes::reverse_iterator mi = m_minorModes.rbegin(); - mi != m_minorModes.rend(); - ++mi) + for (EventTableNameStack::const_iterator ni = + m_eventTableNameStack.begin(); + ni != m_eventTableNameStack.end(); ++ni) { - const EventTables& tables = (*mi)->eventTables(); - EventTables::const_iterator ti = tables.find(tname); + const string& tname = *ni; - if (ti != tables.end()) + // + // do the major mode + // + + EventTables::const_iterator ti = + m_majorMode->eventTables().find(tname); + + if (ti != m_majorMode->eventTables().end()) { m_eventTableStack.push_back(ti->second); } + + // + // do the minor modes + // + + for (MinorModes::reverse_iterator mi = m_minorModes.rbegin(); + mi != m_minorModes.rend(); ++mi) + { + const EventTables& tables = (*mi)->eventTables(); + EventTables::const_iterator ti = tables.find(tname); + + if (ti != tables.end()) + { + m_eventTableStack.push_back(ti->second); + } + } } + setFocusTable(0); + m_eventTableDirty = false; + m_bindingsChangedSignal(this); + send(bindingsChangedMessage()); } - setFocusTable(0); - m_eventTableDirty = false; - m_bindingsChangedSignal(this); - send(bindingsChangedMessage()); -} + void Document::setFocusTable(const EventTable* t) { m_focusTable = t; } -void -Document::setFocusTable(const EventTable* t) -{ - m_focusTable = t; -} - -Document::ActionTablePair -Document::queryEvent(const Event& event, const Action* after) -{ - const EventTable* t = 0; + Document::ActionTablePair Document::queryEvent(const Event& event, + const Action* after) + { + const EventTable* t = 0; - bool foundAfter = after ? false : true; + bool foundAfter = after ? false : true; - const PointerEvent* pe = - dynamic_cast(&event); + const PointerEvent* pe = dynamic_cast(&event); - if (pe && m_focusTable) - { - if (pe->buttonStates() == 0) - { - setFocusTable(0); - } - else if (const Action* a = m_focusTable->query(event.name())) + if (pe && m_focusTable) { - if (foundAfter) + if (pe->buttonStates() == 0) + { + setFocusTable(0); + } + else if (const Action* a = m_focusTable->query(event.name())) { - return ActionTablePair(a, m_focusTable); + if (foundAfter) + { + return ActionTablePair(a, m_focusTable); + } + else + { + return ActionTablePair((const Action*)0, + (const EventTable*)0); + } } else { return ActionTablePair((const Action*)0, (const EventTable*)0); } } - else - { - return ActionTablePair((const Action*)0, (const EventTable*)0); - } - } - - for (int i=m_eventTableStack.size() - 1; - t == 0 && i >= 0; - i--) - { - t = m_eventTableStack[i]; - - if (t && pe) + for (int i = m_eventTableStack.size() - 1; t == 0 && i >= 0; i--) { - Vec2i start(pe->startX(), pe->startY()); - Vec2i current(pe->x(), pe->y()); - - if (t->bbox().intersects(start) || - t->bbox().intersects(current)) + t = m_eventTableStack[i]; + + if (t && pe) { - if (pe->buttonStates()) + Vec2i start(pe->startX(), pe->startY()); + Vec2i current(pe->x(), pe->y()); + + if (t->bbox().intersects(start) + || t->bbox().intersects(current)) { - setFocusTable(t); + if (pe->buttonStates()) + { + setFocusTable(t); + } + } + else + { + t = 0; } } - else + + if (t) { + const Action* a = t->query(event.name()); + + if (foundAfter && a) + { + return ActionTablePair(a, t); + } + else if (a == after) + { + foundAfter = true; + } + t = 0; } } - if (t) + if (after && !foundAfter) { - const Action* a = t->query(event.name()); - - if (foundAfter && a) - { - return ActionTablePair(a, t); - } - else if (a == after) - { - foundAfter = true; - } + // + // This is a special case -- if an event action remapped the + // event and rejected it, you won't find after. So let's + // assume that happened and the intention is to find a taker + // in the remapped event. In other words -- start over + // - t = 0; + return queryEvent(event, 0); + } + else + { + return ActionTablePair((const Action*)0, (const EventTable*)0); } } - if (after && !foundAfter) - { - // - // This is a special case -- if an event action remapped the - // event and rejected it, you won't find after. So let's - // assume that happened and the intention is to find a taker - // in the remapped event. In other words -- start over - // + static bool showEvents = false; - return queryEvent(event, 0); - } - else + void Document::executeAction(const Event& event) { - return ActionTablePair((const Action*)0, (const EventTable*)0); - } -} + const Action* after = 0; + static TwkUtil::Timer* debugTimer = 0; + float startTime; -static bool showEvents = false; - -void -Document::executeAction(const Event& event) -{ - const Action* after = 0; - static TwkUtil::Timer* debugTimer = 0; - float startTime; + if (showEvents && !debugTimer) + { + debugTimer = new TwkUtil::Timer(); + debugTimer->start(); + } - if (showEvents && !debugTimer) - { - debugTimer = new TwkUtil::Timer(); - debugTimer->start(); - } + for (;;) + { + ActionTablePair atp = queryEvent(event, after); - for (;;) - { - ActionTablePair atp = queryEvent(event, after); + if (const Action* a = atp.first) + { + event.m_table = atp.second; - if (const Action* a = atp.first) - { - event.m_table = atp.second; + bool outputEvent = + (showEvents && event.name() != "render" + && event.name() != "pre-render" + && event.name() != "post-render" + && event.name() != "per-render-event-processing"); - bool outputEvent = (showEvents && event.name() != "render" && - event.name() != "pre-render" && - event.name() != "post-render" && - event.name() != "per-render-event-processing"); + if (outputEvent) + { + cerr << "Action begin on Event: '" << event.name() << "'" + << endl; + startTime = debugTimer->elapsed(); + } - if (outputEvent) - { - cerr << "Action begin on Event: '" << event.name() << "'" << endl; - startTime = debugTimer->elapsed(); - } + a->execute(this, event); - a->execute(this, event); + if (outputEvent) + { + /* + XXX For some reason the docString() below is sometimes so + corrupted that RV will crash. Haven't been able to + figure out why. + + cerr << "Action complete on Event: '" << event.name() << "' + " << + ((event.handled) ? "handled" : "processed") << + " by action '" << a->docString() << "' from table "; + */ + + cerr << "Action complete on Event: '" << event.name() + << "' " << ((event.handled) ? "handled" : "processed") + << " by table "; + if (atp.second->mode()) + cerr << atp.second->mode()->name() << ":"; + cerr << atp.second->name() << " (" + << 1000.0 * (debugTimer->elapsed() - startTime) + << "ms)" << endl; + } - if (outputEvent) - { - /* - XXX For some reason the docString() below is sometimes so - corrupted that RV will crash. Haven't been able to figure out - why. - - cerr << "Action complete on Event: '" << event.name() << "' " << - ((event.handled) ? "handled" : "processed") << - " by action '" << a->docString() << "' from table "; - */ - - cerr << "Action complete on Event: '" << event.name() << "' " << - ((event.handled) ? "handled" : "processed") << " by table "; - if (atp.second->mode()) cerr << atp.second->mode()->name() << ":"; - cerr << atp.second->name() << " (" << 1000.0*(debugTimer->elapsed() - startTime) << "ms)" << endl; + if (event.handled) + return; + else if (atp.second == m_focusTable) + // + // At this point m_focusTable has rejected the event, so reset + // m_focusTable so that other tables have a chance at the event + // next time around. + // + { + setFocusTable(0); + } } - - if (event.handled) return; - else - if (atp.second == m_focusTable) - // - // At this point m_focusTable has rejected the event, so reset - // m_focusTable so that other tables have a chance at the event - // next time around. - // + else { - setFocusTable(0); + event.handled = false; + return; } + + after = atp.first; } - else + } + + void Document::pushTable(const string& name) + { + EventTableNameStack::iterator i = find( + m_eventTableNameStack.begin(), m_eventTableNameStack.end(), name); + + if (i != m_eventTableNameStack.end()) { - event.handled = false; - return; + m_eventTableNameStack.erase(i); } - after = atp.first; - } -} - -void -Document::pushTable(const string& name) -{ - EventTableNameStack::iterator i = find(m_eventTableNameStack.begin(), - m_eventTableNameStack.end(), - name); + m_eventTableNameStack.push_back(name); + m_eventTableDirty = true; + setFocusTable(0); + } - if (i != m_eventTableNameStack.end()) + void Document::popTable() { - m_eventTableNameStack.erase(i); - } + if (m_eventTableNameStack.empty()) + { + TWK_THROW_STREAM(DocumentException, "event table empty; can't pop"); + } + else + { + m_eventTableNameStack.resize(m_eventTableNameStack.size() - 1); - m_eventTableNameStack.push_back(name); - m_eventTableDirty = true; - setFocusTable(0); -} + if (m_eventTableNameStack.empty()) + { + m_eventTableNameStack.push_back("global"); + } -void -Document::popTable() -{ - if (m_eventTableNameStack.empty()) - { - TWK_THROW_STREAM(DocumentException, "event table empty; can't pop"); + m_eventTableDirty = true; + } } - else + + void Document::popTable(const string& name) { - m_eventTableNameStack.resize(m_eventTableNameStack.size() - 1); + setFocusTable(0); - if (m_eventTableNameStack.empty()) + EventTableNameStack::iterator i = find( + m_eventTableNameStack.begin(), m_eventTableNameStack.end(), name); + + if (i != m_eventTableNameStack.end()) { - m_eventTableNameStack.push_back("global"); + m_eventTableNameStack.erase(i); + } + else + { + TWK_THROW_STREAM(DocumentException, + "bad event table name: \"" << name << "\""); } m_eventTableDirty = true; } -} -void -Document::popTable(const string& name) -{ - setFocusTable(0); - - EventTableNameStack::iterator i = find(m_eventTableNameStack.begin(), - m_eventTableNameStack.end(), - name); + void Document::debugEvents() { showEvents = true; } - if (i != m_eventTableNameStack.end()) - { - m_eventTableNameStack.erase(i); - } - else + const Document::EventTableStack& Document::eventTableStack() const { - TWK_THROW_STREAM(DocumentException, - "bad event table name: \"" << name << "\""); + if (m_eventTableDirty) + const_cast(this)->buildEventTables(); + return m_eventTableStack; } - m_eventTableDirty = true; -} - -void -Document::debugEvents() -{ - showEvents = true; -} - -const Document::EventTableStack& -Document::eventTableStack() const -{ - if (m_eventTableDirty) const_cast(this)->buildEventTables(); - return m_eventTableStack; -} - -EventNode::Result -Document::receiveEvent(const Event& event) -{ - const Event* lastEvent = m_event; - Document* d = m_eventDocument; - m_eventDocument = this; + EventNode::Result Document::receiveEvent(const Event& event) + { + const Event* lastEvent = m_event; + Document* d = m_eventDocument; + m_eventDocument = this; - bool outputEvent = (showEvents && event.name() != "render" && - event.name() != "pre-render" && - event.name() != "post-render" && - event.name() != "per-render-event-processing"); + bool outputEvent = + (showEvents && event.name() != "render" + && event.name() != "pre-render" && event.name() != "post-render" + && event.name() != "per-render-event-processing"); - if (outputEvent) - { - cerr << event; - if (const RenderEvent* e = dynamic_cast (&event)) cerr << " '" << e->stringContent() << "'"; - else if (const DragDropEvent* e = dynamic_cast (&event)) cerr << " '" << e->stringContent() << "'"; - else if (const GenericStringEvent* e = dynamic_cast (&event)) cerr << " '" << e->stringContent() << "'"; - cerr << endl; + if (outputEvent) + { + cerr << event; + if (const RenderEvent* e = dynamic_cast(&event)) + cerr << " '" << e->stringContent() << "'"; + else if (const DragDropEvent* e = + dynamic_cast(&event)) + cerr << " '" << e->stringContent() << "'"; + else if (const GenericStringEvent* e = + dynamic_cast(&event)) + cerr << " '" << e->stringContent() << "'"; + cerr << endl; + } + m_event = &event; + if (m_eventTableDirty) + buildEventTables(); + executeAction(event); + m_event = lastEvent; + m_eventDocument = d; + return event.handled ? EventAccept : EventIgnored; } - m_event = &event; - if (m_eventTableDirty) buildEventTables(); - executeAction(event); - m_event = lastEvent; - m_eventDocument = d; - return event.handled ? EventAccept : EventIgnored; -} - -} // TwkApp + +} // namespace TwkApp diff --git a/src/lib/app/TwkApp/Event.cpp b/src/lib/app/TwkApp/Event.cpp index 7463a46bb..17387bb79 100644 --- a/src/lib/app/TwkApp/Event.cpp +++ b/src/lib/app/TwkApp/Event.cpp @@ -1,54 +1,58 @@ //****************************************************************************** -// Copyright (c) 2004 Tweak Inc. +// Copyright (c) 2004 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #include #include -namespace TwkApp { -using namespace std; - -void -Event::output(ostream& o) const -{ - o << "Event: " << m_name << " from " << ((m_sender) ? m_sender->name() : ""); -} - -void -ModifierEvent::output(ostream& o) const -{ - Event::output(o); - o << " ["; - if (m_modifiers & Shift) o << "Shift"; - if (m_modifiers & Control) o << "|Control"; - if (m_modifiers & Alt) o << "|Alt"; - if (m_modifiers & Meta) o << "|Meta"; - if (m_modifiers & Super) o << "|Super"; - if (m_modifiers & CapLock) o << "|CapLock"; - if (m_modifiers & NumLock) o << "|NumLock"; - if (m_modifiers & ScrollLock) o << "|ScrollLock"; - o << "]"; -} - -void -KeyEvent::output(ostream& o) const +namespace TwkApp { - ModifierEvent::output(o); - o << " '" << char(m_key) << "' " << hex << "0x" << m_key << dec; -} - -void -PointerEvent::output(ostream& o) const -{ - ModifierEvent::output(o); - o << " (" << m_x << "/" << m_w - << "," << m_y << "/" << m_h - << ") start: (" << m_px << "," << m_py << ")"; -} - - -} // TwkApp + using namespace std; + + void Event::output(ostream& o) const + { + o << "Event: " << m_name << " from " + << ((m_sender) ? m_sender->name() : ""); + } + + void ModifierEvent::output(ostream& o) const + { + Event::output(o); + o << " ["; + if (m_modifiers & Shift) + o << "Shift"; + if (m_modifiers & Control) + o << "|Control"; + if (m_modifiers & Alt) + o << "|Alt"; + if (m_modifiers & Meta) + o << "|Meta"; + if (m_modifiers & Super) + o << "|Super"; + if (m_modifiers & CapLock) + o << "|CapLock"; + if (m_modifiers & NumLock) + o << "|NumLock"; + if (m_modifiers & ScrollLock) + o << "|ScrollLock"; + o << "]"; + } + + void KeyEvent::output(ostream& o) const + { + ModifierEvent::output(o); + o << " '" << char(m_key) << "' " << hex << "0x" << m_key << dec; + } + + void PointerEvent::output(ostream& o) const + { + ModifierEvent::output(o); + o << " (" << m_x << "/" << m_w << "," << m_y << "/" << m_h + << ") start: (" << m_px << "," << m_py << ")"; + } + +} // namespace TwkApp diff --git a/src/lib/app/TwkApp/EventNode.cpp b/src/lib/app/TwkApp/EventNode.cpp index badffc87f..ca7cdee7d 100644 --- a/src/lib/app/TwkApp/EventNode.cpp +++ b/src/lib/app/TwkApp/EventNode.cpp @@ -1,98 +1,98 @@ //****************************************************************************** -// Copyright (c) 2002 Tweak Inc. +// Copyright (c) 2002 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #include #include -namespace TwkApp { -using namespace stl_ext; - -EventNode::Timer EventNode::m_timer; - -EventNode::EventNode(const char *name) : m_name(name) +namespace TwkApp { - // std::cerr << "EventNode '" << name << "'" << std::endl; -} + using namespace stl_ext; -EventNode::~EventNode() -{ - while (m_listeners.size()) breakConnection(m_listeners.front()); - while (m_senders.size()) breakConnection(m_senders.front()); -} + EventNode::Timer EventNode::m_timer; -void -EventNode::listenTo(EventNode *node) -{ - node->m_listeners.push_back(this); - m_senders.push_back(node); -} - -void -EventNode::breakConnection(EventNode *node) -{ - remove_unsorted(node->m_senders, this); - remove_unsorted(node->m_listeners, this); - remove_unsorted(m_listeners, node); - remove_unsorted(m_senders, node); -} - -EventNode::Result -EventNode::receiveEvent(const Event&) -{ - // - // Default is to simply let the event continue - // + EventNode::EventNode(const char* name) + : m_name(name) + { + // std::cerr << "EventNode '" << name << "'" << std::endl; + } - return EventIgnored; -} + EventNode::~EventNode() + { + while (m_listeners.size()) + breakConnection(m_listeners.front()); + while (m_senders.size()) + breakConnection(m_senders.front()); + } -EventNode::Result -EventNode::sendEvent(const Event &event) -{ - if (!m_timer.isRunning()) m_timer.start(); - event.m_timeStamp = m_timer.elapsed(); - return propagateEvent(event); -} + void EventNode::listenTo(EventNode* node) + { + node->m_listeners.push_back(this); + m_senders.push_back(node); + } -EventNode::Result -EventNode::propagateEvent(const Event &event) -{ - // - // If the receiver accepts the event, then stop - // - // std::cerr << "propagateEvent '" << event.name() << "' from '" << m_name << "'" << std::endl; + void EventNode::breakConnection(EventNode* node) + { + remove_unsorted(node->m_senders, this); + remove_unsorted(node->m_listeners, this); + remove_unsorted(m_listeners, node); + remove_unsorted(m_senders, node); + } - if (receiveEvent(event) == EventAccept) + EventNode::Result EventNode::receiveEvent(const Event&) { - return EventAccept; + // + // Default is to simply let the event continue + // + + return EventIgnored; } - Result rval = EventIgnored; + EventNode::Result EventNode::sendEvent(const Event& event) + { + if (!m_timer.isRunning()) + m_timer.start(); + event.m_timeStamp = m_timer.elapsed(); + return propagateEvent(event); + } - for (int i=0; ipropagateEvent(event)) + // + // If the receiver accepts the event, then stop + // + // std::cerr << "propagateEvent '" << event.name() << "' from '" << + // m_name << "'" << std::endl; + + if (receiveEvent(event) == EventAccept) { - case EventAccept: - return EventAccept; - case Error: - return Error; - case EventAcceptAndContinue: - rval = EventAcceptAndContinue; - case EventIgnored: - break; + return EventAccept; } - } - return rval; -} + Result rval = EventIgnored; + + for (int i = 0; i < m_listeners.size(); i++) + { + EventNode* n = m_listeners[i]; + + switch (n->propagateEvent(event)) + { + case EventAccept: + return EventAccept; + case Error: + return Error; + case EventAcceptAndContinue: + rval = EventAcceptAndContinue; + case EventIgnored: + break; + } + } + return rval; + } -} // TwkApp +} // namespace TwkApp diff --git a/src/lib/app/TwkApp/EventTable.cpp b/src/lib/app/TwkApp/EventTable.cpp index 93efad63a..2d04f1e5e 100644 --- a/src/lib/app/TwkApp/EventTable.cpp +++ b/src/lib/app/TwkApp/EventTable.cpp @@ -1,111 +1,110 @@ //****************************************************************************** -// Copyright (c) 2004 Tweak Inc. +// Copyright (c) 2004 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #include #include #include -namespace TwkApp { -using namespace std; -using namespace TwkUtil; - -EventTable::EventTable(const string& name) : m_name(name), m_mode(0) -{ - m_bbox.makeInfinite(); -} - -EventTable::EventTable(const char* name) : m_name(name), m_mode(0) +namespace TwkApp { - m_bbox.makeInfinite(); -} + using namespace std; + using namespace TwkUtil; -EventTable::~EventTable() { clear(); } + EventTable::EventTable(const string& name) + : m_name(name) + , m_mode(0) + { + m_bbox.makeInfinite(); + } -void -EventTable::bind(const std::string& event, Action* action) -{ - unbind(event); - m_map[event] = action; -} + EventTable::EventTable(const char* name) + : m_name(name) + , m_mode(0) + { + m_bbox.makeInfinite(); + } -void -EventTable::bindRegex(const std::string& eventRegex, Action* action) -{ - unbindRegex(eventRegex); - m_reBindings.push_back(RegExBinding(eventRegex, action)); -} + EventTable::~EventTable() { clear(); } -void -EventTable::unbind(const std::string& event) -{ - BindingMap::iterator i = m_map.find(event); + void EventTable::bind(const std::string& event, Action* action) + { + unbind(event); + m_map[event] = action; + } - if (i != m_map.end()) + void EventTable::bindRegex(const std::string& eventRegex, Action* action) { - delete (*i).second; - m_map.erase(i); + unbindRegex(eventRegex); + m_reBindings.push_back(RegExBinding(eventRegex, action)); } -} -void -EventTable::unbindRegex(const std::string& eventRegex) -{ - for (int i=0; i < m_reBindings.size(); i++) + void EventTable::unbind(const std::string& event) { - if (m_reBindings[i].first.pattern() == eventRegex) + BindingMap::iterator i = m_map.find(event); + + if (i != m_map.end()) { - m_reBindings.erase(m_reBindings.begin() + i); - i--; + delete (*i).second; + m_map.erase(i); } } -} - -static void deleteAction(EventTable::Binding& b) { delete b.second; } -void -EventTable::clear() -{ - for_each(m_map.begin(), m_map.end(), deleteAction); - m_map.clear(); - - for (int i=0; i < m_reBindings.size(); i++) + void EventTable::unbindRegex(const std::string& eventRegex) { - delete m_reBindings[i].second; + for (int i = 0; i < m_reBindings.size(); i++) + { + if (m_reBindings[i].first.pattern() == eventRegex) + { + m_reBindings.erase(m_reBindings.begin() + i); + i--; + } + } } - m_reBindings.clear(); -} - -const Action* -EventTable::query(const string& event) const -{ - BindingMap::const_iterator i = m_map.find(event); + static void deleteAction(EventTable::Binding& b) { delete b.second; } - if (i != m_map.end()) - { - return (*i).second; - } - else if (m_reBindings.empty()) + void EventTable::clear() { - return 0; + for_each(m_map.begin(), m_map.end(), deleteAction); + m_map.clear(); + + for (int i = 0; i < m_reBindings.size(); i++) + { + delete m_reBindings[i].second; + } + + m_reBindings.clear(); } - else + + const Action* EventTable::query(const string& event) const { - for (int i=0; i < m_reBindings.size(); i++) + BindingMap::const_iterator i = m_map.find(event); + + if (i != m_map.end()) + { + return (*i).second; + } + else if (m_reBindings.empty()) { - if (Match(m_reBindings[i].first, event)) + return 0; + } + else + { + for (int i = 0; i < m_reBindings.size(); i++) { - return m_reBindings[i].second; + if (Match(m_reBindings[i].first, event)) + { + return m_reBindings[i].second; + } } } + + return 0; } - - return 0; -} -} // TwkApp +} // namespace TwkApp diff --git a/src/lib/app/TwkApp/Exception.cpp b/src/lib/app/TwkApp/Exception.cpp index d5306f773..503e55ad5 100644 --- a/src/lib/app/TwkApp/Exception.cpp +++ b/src/lib/app/TwkApp/Exception.cpp @@ -1,15 +1,15 @@ //****************************************************************************** -// Copyright (c) 2005 Tweak Inc. +// Copyright (c) 2005 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #include -namespace TwkApp { +namespace TwkApp +{ -TWK_DERIVED_EXCEPTION_IMP(DocumentException) + TWK_DERIVED_EXCEPTION_IMP(DocumentException) - -} // TwkApp +} // namespace TwkApp diff --git a/src/lib/app/TwkApp/Menu.cpp b/src/lib/app/TwkApp/Menu.cpp index 73be33d0c..e691e4e5a 100644 --- a/src/lib/app/TwkApp/Menu.cpp +++ b/src/lib/app/TwkApp/Menu.cpp @@ -1,126 +1,121 @@ //****************************************************************************** // Copyright (c) 2002 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #include #include #include -namespace TwkApp { -using namespace std; - -Menu::StateFunc::StateFunc() {} -Menu::StateFunc::~StateFunc() {} - -void -Menu::Item::copyFrom(const Menu::Item *item) +namespace TwkApp { - assert( item ); - m_title = item->title(); - m_action = item->action() ? item->action()->copy() : 0; - m_key = item->key(); - m_stateFunc = item->stateFunc() ? item->stateFunc()->copy() : 0; - m_subMenu = item->subMenu() ? new Menu(item->subMenu()) : 0; -} + using namespace std; + Menu::StateFunc::StateFunc() {} -Menu::Menu(const std::string &name) - : m_name(name) -{ -} + Menu::StateFunc::~StateFunc() {} -Menu::Menu(const Menu *menu) -{ - if (menu) + void Menu::Item::copyFrom(const Menu::Item* item) { - m_name = menu->name(); + assert(item); + m_title = item->title(); + m_action = item->action() ? item->action()->copy() : 0; + m_key = item->key(); + m_stateFunc = item->stateFunc() ? item->stateFunc()->copy() : 0; + m_subMenu = item->subMenu() ? new Menu(item->subMenu()) : 0; + } - const Items &items = menu->items(); + Menu::Menu(const std::string& name) + : m_name(name) + { + } - for (int i=0; i < items.size(); i++) + Menu::Menu(const Menu* menu) + { + if (menu) { - addItem(new Item(items[i])); + m_name = menu->name(); + + const Items& items = menu->items(); + + for (int i = 0; i < items.size(); i++) + { + addItem(new Item(items[i])); + } } } -} -Menu::~Menu() -{ - clear(); -} + Menu::~Menu() { clear(); } -Menu::Item* -Menu::matchingItem(const Menu::Item *item) -{ - if (item->title() != "_") + Menu::Item* Menu::matchingItem(const Menu::Item* item) { - for (int i=0; i < m_items.size(); i++) + if (item->title() != "_") { - if (m_items[i]->title() == item->title()) + for (int i = 0; i < m_items.size(); i++) { - return m_items[i]; + if (m_items[i]->title() == item->title()) + { + return m_items[i]; + } } } - } - return 0; -} - -void -Menu::merge(const Menu *menu) -{ - if (!menu) return; - const Items &items = menu->items(); + return 0; + } - for (int i=0; i < items.size(); i++) + void Menu::merge(const Menu* menu) { - Item *item = items[i]; + if (!menu) + return; + const Items& items = menu->items(); - if (Item *m = matchingItem(item)) + for (int i = 0; i < items.size(); i++) { - if (m->subMenu() && item->subMenu()) - // - // If existing item has a submenu, merge incoming submenu. - // + Item* item = items[i]; + + if (Item* m = matchingItem(item)) { - m->subMenu()->merge(item->subMenu()); + if (m->subMenu() && item->subMenu()) + // + // If existing item has a submenu, merge incoming submenu. + // + { + m->subMenu()->merge(item->subMenu()); + } + else if (item->subMenu()) + // + // If the incoming item has a submenu, add one to the existing + // item + // + { + m->subMenu(new Menu(item->subMenu())); + } + else + // + // Otherwise, copy new item over old one. + // + { + m->copyFrom(item); + } } - else if (item->subMenu()) - // - // If the incoming item has a submenu, add one to the existing - // item - // + else { - m->subMenu(new Menu(item->subMenu())); + addItem(new Item(item)); } - else - // - // Otherwise, copy new item over old one. - // - { - m->copyFrom(item); - } - } - else - { - addItem(new Item(item)); } } -} -void -Menu::clear() -{ - for (int i = 0; i < m_items.size(); ++i) + void Menu::clear() { - delete m_items[i]; - } + for (int i = 0; i < m_items.size(); ++i) + { + delete m_items[i]; + } - m_items.clear(); -} + m_items.clear(); + } -} // TwkApp +} // namespace TwkApp diff --git a/src/lib/app/TwkApp/Mode.cpp b/src/lib/app/TwkApp/Mode.cpp index fb6197fdb..f57095d7f 100644 --- a/src/lib/app/TwkApp/Mode.cpp +++ b/src/lib/app/TwkApp/Mode.cpp @@ -1,100 +1,115 @@ //****************************************************************************** -// Copyright (c) 2002 Tweak Inc. +// Copyright (c) 2002 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #include #include #include -namespace TwkApp { +namespace TwkApp +{ -Mode::Mode(const char *name, Document *doc) - : m_name(name), m_document(doc), m_defaultMenu(0) {} -Mode::~Mode() { clearEventTables(); } -void Mode::activate() {} -void Mode::deactivate() {} -Menu* Mode::menu() { return m_defaultMenu; } -std::string Mode::sortKey() const { return m_name; } + Mode::Mode(const char* name, Document* doc) + : m_name(name) + , m_document(doc) + , m_defaultMenu(0) + { + } -void -Mode::addEventTable(EventTable* table) -{ - removeEventTable(table->name()); - m_eventTables[table->name()] = table; - table->m_mode = this; - - // - // m_document has a copy of this table, so invalidate it. - // - m_document->invalidateEventTables(); -} - -void -Mode::removeEventTable(const std::string& name) -{ - EventTables::iterator i = m_eventTables.find(name); + Mode::~Mode() { clearEventTables(); } + + void Mode::activate() {} + + void Mode::deactivate() {} + + Menu* Mode::menu() { return m_defaultMenu; } + + std::string Mode::sortKey() const { return m_name; } - if (i != m_eventTables.end()) + void Mode::addEventTable(EventTable* table) { - delete (*i).second; - m_eventTables.erase(i); + removeEventTable(table->name()); + m_eventTables[table->name()] = table; + table->m_mode = this; + // // m_document has a copy of this table, so invalidate it. // m_document->invalidateEventTables(); } -} -static void deleteTable(Mode::EventTableEntry& e) { delete e.second; } + void Mode::removeEventTable(const std::string& name) + { + EventTables::iterator i = m_eventTables.find(name); -void -Mode::clearEventTables() -{ - for_each(m_eventTables.begin(), m_eventTables.end(), deleteTable); - m_eventTables.clear(); - // - // m_document has a copy of this table, so invalidate it. - // - m_document->invalidateEventTables(); -} - -EventTable* -Mode::findTableByName(const std::string& name) -{ - EventTables::iterator i = m_eventTables.find(name); - return i == m_eventTables.end() ? 0 : (*i).second; -} + if (i != m_eventTables.end()) + { + delete (*i).second; + m_eventTables.erase(i); + // + // m_document has a copy of this table, so invalidate it. + // + m_document->invalidateEventTables(); + } + } -void -Mode::merge(Menu* m) -{ - if (Menu* mm = menu()) + static void deleteTable(Mode::EventTableEntry& e) { delete e.second; } + + void Mode::clearEventTables() + { + for_each(m_eventTables.begin(), m_eventTables.end(), deleteTable); + m_eventTables.clear(); + // + // m_document has a copy of this table, so invalidate it. + // + m_document->invalidateEventTables(); + } + + EventTable* Mode::findTableByName(const std::string& name) { - mm->merge(m); + EventTables::iterator i = m_eventTables.find(name); + return i == m_eventTables.end() ? 0 : (*i).second; } - else + + void Mode::merge(Menu* m) + { + if (Menu* mm = menu()) + { + mm->merge(m); + } + else + { + delete m_defaultMenu; + m_defaultMenu = m; + } + } + + void Mode::setMenu(Menu* m) { delete m_defaultMenu; m_defaultMenu = m; } -} -void -Mode::setMenu(Menu* m) -{ - delete m_defaultMenu; - m_defaultMenu = m; -} + MajorMode::MajorMode(const char* name, Document* doc) + : Mode(name, doc) + { + } + + MinorMode::MinorMode(const char* name, Document* doc) + : Mode(name, doc) + , m_sortkey(name) + , m_order(0) + { + } + + MajorMode::~MajorMode() {} + MinorMode::~MinorMode() {} -MajorMode::MajorMode(const char *name, Document *doc) : Mode(name,doc) {} -MinorMode::MinorMode(const char *name, Document *doc) : Mode(name,doc), m_sortkey(name), m_order(0) {} -MajorMode::~MajorMode() {} -MinorMode::~MinorMode() {} -std::string MinorMode::sortKey() const { return m_sortkey; } + std::string MinorMode::sortKey() const { return m_sortkey; } -} // TwkApp +} // namespace TwkApp diff --git a/src/lib/app/TwkApp/OutputPlugin.cpp b/src/lib/app/TwkApp/OutputPlugin.cpp index 1d413fecd..97e2c21ee 100644 --- a/src/lib/app/TwkApp/OutputPlugin.cpp +++ b/src/lib/app/TwkApp/OutputPlugin.cpp @@ -1,7 +1,7 @@ // -// Copyright (C) 2023 Autodesk, Inc. All Rights Reserved. -// -// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2023 Autodesk, Inc. All Rights Reserved. +// +// SPDX-License-Identifier: Apache-2.0 // #include @@ -10,83 +10,84 @@ namespace { - void * load_plugin_fct(const std::string& file, void* handle, const std::string plugin_fct_name) + void* load_plugin_fct(const std::string& file, void* handle, + const std::string plugin_fct_name) { - void * plugin_fct = dlsym(handle, plugin_fct_name.c_str()); + void* plugin_fct = dlsym(handle, plugin_fct_name.c_str()); if (!plugin_fct) { - std::cerr << "ERROR: ignoring Output plugin: " << file - << ": missing " << plugin_fct_name << std::endl; + std::cerr << "ERROR: ignoring Output plugin: " << file + << ": missing " << plugin_fct_name << std::endl; } return plugin_fct; } -} - -namespace TwkApp { +} // namespace -OutputPlugin::~OutputPlugin() +namespace TwkApp { - unloadPlugin(); -} -std::shared_ptr -OutputPlugin::loadPlugin(const std::string& file) -{ - if (void *handle = dlopen(file.c_str(), RTLD_LAZY)) + OutputPlugin::~OutputPlugin() { unloadPlugin(); } + + std::shared_ptr + OutputPlugin::loadPlugin(const std::string& file) { - output_module_create_t* plugCreate = reinterpret_cast(load_plugin_fct(file, handle, "output_module_create")); - output_module_destroy_t* plugDestroy = reinterpret_cast(load_plugin_fct(file, handle, "output_module_destroy")); - if (!plugCreate || !plugDestroy) + if (void* handle = dlopen(file.c_str(), RTLD_LAZY)) { - dlclose( handle ); - return nullptr; + output_module_create_t* plugCreate = + reinterpret_cast( + load_plugin_fct(file, handle, "output_module_create")); + output_module_destroy_t* plugDestroy = + reinterpret_cast( + load_plugin_fct(file, handle, "output_module_destroy")); + if (!plugCreate || !plugDestroy) + { + dlclose(handle); + return nullptr; + } + + return std::make_shared( + file, handle, plugCreate, plugDestroy); + } + else + { + std::cerr << "ERROR: cannot open Output plugin " << file << ": " + << dlerror() << std::endl; } - return std::make_shared(file, handle, plugCreate, plugDestroy); - } - else - { - std::cerr << "ERROR: cannot open Output plugin " - << file - << ": " - << dlerror() << std::endl; + return nullptr; } - return nullptr; -} - -void -OutputPlugin::unloadPlugin() -{ - if (m_handle) + void OutputPlugin::unloadPlugin() { - dlclose(m_handle); - m_handle = nullptr; + if (m_handle) + { + dlclose(m_handle); + m_handle = nullptr; + } } -} - -TwkApp::VideoModule* -OutputPlugin::output_module_create(float output_plugin_version, int output_module_index) -{ - TwkApp::VideoModule* outputModule = nullptr; - if (m_output_module_create) + TwkApp::VideoModule* + OutputPlugin::output_module_create(float output_plugin_version, + int output_module_index) { - outputModule = m_output_module_create(output_plugin_version, output_module_index); - } + TwkApp::VideoModule* outputModule = nullptr; - return outputModule; -} + if (m_output_module_create) + { + outputModule = m_output_module_create(output_plugin_version, + output_module_index); + } + return outputModule; + } -void -OutputPlugin::output_module_destroy(TwkApp::VideoModule* output_module) -{ - if (m_output_module_destroy) + void OutputPlugin::output_module_destroy(TwkApp::VideoModule* output_module) { - m_output_module_destroy(output_module); + if (m_output_module_destroy) + { + m_output_module_destroy(output_module); + } } -} -} // TwkApp +} // namespace TwkApp diff --git a/src/lib/app/TwkApp/OutputPlugins.cpp b/src/lib/app/TwkApp/OutputPlugins.cpp index 2d5678fa5..553ec39f3 100644 --- a/src/lib/app/TwkApp/OutputPlugins.cpp +++ b/src/lib/app/TwkApp/OutputPlugins.cpp @@ -1,7 +1,7 @@ // -// Copyright (C) 2023 Autodesk, Inc. All Rights Reserved. -// -// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2023 Autodesk, Inc. All Rights Reserved. +// +// SPDX-License-Identifier: Apache-2.0 // #include @@ -12,8 +12,7 @@ namespace { - std::vector - getPluginFileList(const std::string& pathVar) + std::vector getPluginFileList(const std::string& pathVar) { std::string pluginPath; @@ -26,82 +25,78 @@ namespace pluginPath = "."; } - #ifdef PLATFORM_LINUX - return TwkUtil::findInPath(".*\\.so", pluginPath); - #endif +#ifdef PLATFORM_LINUX + return TwkUtil::findInPath(".*\\.so", pluginPath); +#endif - #ifdef PLATFORM_WINDOWS - return TwkUtil::findInPath(".*\\.dll", pluginPath); - #endif +#ifdef PLATFORM_WINDOWS + return TwkUtil::findInPath(".*\\.dll", pluginPath); +#endif - #ifdef PLATFORM_APPLE_MACH_BSD - return TwkUtil::findInPath(".*\\.dylib", pluginPath); - #endif +#ifdef PLATFORM_APPLE_MACH_BSD + return TwkUtil::findInPath(".*\\.dylib", pluginPath); +#endif } -} +} // namespace -namespace TwkApp { +namespace TwkApp +{ -bool OutputPlugins::m_loadedAll = false; -OutputPlugins::Plugins* OutputPlugins::m_plugins = nullptr; + bool OutputPlugins::m_loadedAll = false; + OutputPlugins::Plugins* OutputPlugins::m_plugins = nullptr; -OutputPlugins::OutputPlugins() -{ -} + OutputPlugins::OutputPlugins() {} -OutputPlugins::~OutputPlugins() -{ - unloadPlugins(); -} + OutputPlugins::~OutputPlugins() { unloadPlugins(); } -void -OutputPlugins::loadPlugins(const std::string& envVar) -{ - if (!m_loadedAll) + void OutputPlugins::loadPlugins(const std::string& envVar) { - std::vector pluginFiles = getPluginFileList(envVar); - - if (pluginFiles.empty()) + if (!m_loadedAll) { - std::cout << "INFO: no output plugins found in " << getenv(envVar.c_str()) << std::endl; - } + std::vector pluginFiles = getPluginFileList(envVar); - for (int i = 0; i < pluginFiles.size(); i++) - { - std::cout << "INFO: loading plugin " << pluginFiles[i] << std::endl; + if (pluginFiles.empty()) + { + std::cout << "INFO: no output plugins found in " + << getenv(envVar.c_str()) << std::endl; + } - if (TwkApp::OutputPluginPtr plugin = TwkApp::OutputPlugin::loadPlugin(pluginFiles[i])) + for (int i = 0; i < pluginFiles.size(); i++) { - addPlugin(plugin); + std::cout << "INFO: loading plugin " << pluginFiles[i] + << std::endl; + + if (TwkApp::OutputPluginPtr plugin = + TwkApp::OutputPlugin::loadPlugin(pluginFiles[i])) + { + addPlugin(plugin); + } } - } - m_loadedAll = true; + m_loadedAll = true; + } } -} -void -OutputPlugins::unloadPlugins() -{ - if (m_plugins) + void OutputPlugins::unloadPlugins() { - m_plugins->clear(); - delete m_plugins; - m_plugins = nullptr; + if (m_plugins) + { + m_plugins->clear(); + delete m_plugins; + m_plugins = nullptr; + } } -} -OutputPlugins::Plugins& -OutputPlugins::plugins() -{ - if (!m_plugins) m_plugins = new Plugins; - return *m_plugins; -} + OutputPlugins::Plugins& OutputPlugins::plugins() + { + if (!m_plugins) + m_plugins = new Plugins; + return *m_plugins; + } -void -OutputPlugins::addPlugin(const TwkApp::OutputPluginPtr& plugin) -{ - plugins().insert(plugin); -} + void OutputPlugins::addPlugin(const TwkApp::OutputPluginPtr& plugin) + { + plugins().insert(plugin); + } -} // TwkApp +} // namespace TwkApp diff --git a/src/lib/app/TwkApp/Selection.cpp b/src/lib/app/TwkApp/Selection.cpp index abd2109be..8415bada3 100644 --- a/src/lib/app/TwkApp/Selection.cpp +++ b/src/lib/app/TwkApp/Selection.cpp @@ -1,20 +1,19 @@ //****************************************************************************** -// Copyright (c) 2002 Tweak Inc. +// Copyright (c) 2002 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #include -namespace TwkApp { - -Selection::~Selection() +namespace TwkApp { - // nothing -} - -} // TwkApp + Selection::~Selection() + { + // nothing + } +} // namespace TwkApp diff --git a/src/lib/app/TwkApp/SelectionState.cpp b/src/lib/app/TwkApp/SelectionState.cpp index 49f8c0b62..cebb89e04 100644 --- a/src/lib/app/TwkApp/SelectionState.cpp +++ b/src/lib/app/TwkApp/SelectionState.cpp @@ -1,109 +1,105 @@ //****************************************************************************** -// Copyright (c) 2002 Tweak Inc. +// Copyright (c) 2002 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #include #include -namespace TwkApp { - -SelectionState::SelectionState() +namespace TwkApp { -} -SelectionState::~SelectionState() -{ - stl_ext::delete_contents(m_selections); -} + SelectionState::SelectionState() {} -SelectionState::SelectionState(const SelectionState &state) -{ - (*this) = state; -} - -SelectionState& -SelectionState::operator= (const SelectionState& state) -{ - stl_ext::delete_contents(m_selections); - m_selections.clear(); - - for (int i=0; i < state.m_selections.size(); i++) + SelectionState::~SelectionState() { - m_selections.push_back( state.m_selections[i]->copy() ); + stl_ext::delete_contents(m_selections); } - return *this; -} + SelectionState::SelectionState(const SelectionState& state) + { + (*this) = state; + } -Selection* -SelectionState::selection(const std::string &name, bool createIfNotThere) -{ - for (int i=0; i < m_selections.size(); i++) + SelectionState& SelectionState::operator=(const SelectionState& state) { - if (m_selections[i]->type()->name() == name) + stl_ext::delete_contents(m_selections); + m_selections.clear(); + + for (int i = 0; i < state.m_selections.size(); i++) { - return m_selections[i]; + m_selections.push_back(state.m_selections[i]->copy()); } + + return *this; } - if (createIfNotThere) + Selection* SelectionState::selection(const std::string& name, + bool createIfNotThere) { - if (SelectionType *type = SelectionType::findByName(name)) + for (int i = 0; i < m_selections.size(); i++) { - m_selections.push_back(type->newSelection()); - return m_selections.back(); + if (m_selections[i]->type()->name() == name) + { + return m_selections[i]; + } } - } - return 0; -} + if (createIfNotThere) + { + if (SelectionType* type = SelectionType::findByName(name)) + { + m_selections.push_back(type->newSelection()); + return m_selections.back(); + } + } -Selection* -SelectionState::selection(const SelectionType *t, bool createIfNotThere) -{ - for (int i=0; i < m_selections.size(); i++) + return 0; + } + + Selection* SelectionState::selection(const SelectionType* t, + bool createIfNotThere) { - if (m_selections[i]->type() == t) + for (int i = 0; i < m_selections.size(); i++) { - return m_selections[i]; + if (m_selections[i]->type() == t) + { + return m_selections[i]; + } } + + if (createIfNotThere) + { + m_selections.push_back(t->newSelection()); + return m_selections.back(); + } + + return 0; } - if (createIfNotThere) + const Selection* SelectionState::selection(const std::string& name) const { - m_selections.push_back(t->newSelection()); - return m_selections.back(); + return const_cast(this)->selection(name); } - return 0; -} - -const Selection* -SelectionState::selection(const std::string &name) const -{ - return const_cast(this)->selection(name); -} - -void -SelectionState::set(Selection *sel) -{ - if (sel) + void SelectionState::set(Selection* sel) { - for (int i=0; i < m_selections.size(); i++) + if (sel) { - if (m_selections[i]->type() == sel->type()) + for (int i = 0; i < m_selections.size(); i++) { - delete m_selections[i]; - m_selections[i] = sel; - return; + if (m_selections[i]->type() == sel->type()) + { + delete m_selections[i]; + m_selections[i] = sel; + return; + } } - } - m_selections.push_back(sel); + m_selections.push_back(sel); + } } -} -} // TwkApp +} // namespace TwkApp diff --git a/src/lib/app/TwkApp/SelectionType.cpp b/src/lib/app/TwkApp/SelectionType.cpp index b8a913540..404c7c640 100644 --- a/src/lib/app/TwkApp/SelectionType.cpp +++ b/src/lib/app/TwkApp/SelectionType.cpp @@ -1,42 +1,39 @@ //****************************************************************************** // Copyright (c) 2002 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #include #include -namespace TwkApp { -using namespace std; - -SelectionType::TypeVector SelectionType::m_allTypes; - -SelectionType::SelectionType(const string &name) : m_name(name) +namespace TwkApp { - m_allTypes.push_back(this); -} + using namespace std; -SelectionType::~SelectionType() -{ - stl_ext::remove(m_allTypes, this); -} + SelectionType::TypeVector SelectionType::m_allTypes; + SelectionType::SelectionType(const string& name) + : m_name(name) + { + m_allTypes.push_back(this); + } -SelectionType* -SelectionType::findByName(const std::string &name) -{ - for (int i=0; i < m_allTypes.size(); i++) + SelectionType::~SelectionType() { stl_ext::remove(m_allTypes, this); } + + SelectionType* SelectionType::findByName(const std::string& name) { - if (m_allTypes[i]->name() == name) + for (int i = 0; i < m_allTypes.size(); i++) { - return m_allTypes[i]; + if (m_allTypes[i]->name() == name) + { + return m_allTypes[i]; + } } - } - return 0; -} + return 0; + } -} // TwkApp +} // namespace TwkApp diff --git a/src/lib/app/TwkApp/TwkApp/Action.h b/src/lib/app/TwkApp/TwkApp/Action.h index 676ea788b..c497a59ea 100644 --- a/src/lib/app/TwkApp/TwkApp/Action.h +++ b/src/lib/app/TwkApp/TwkApp/Action.h @@ -1,60 +1,64 @@ //****************************************************************************** -// Copyright (c) 2002 Tweak Inc. +// Copyright (c) 2002 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #ifndef __TwkApp__Action__h__ #define __TwkApp__Action__h__ #include -namespace TwkApp { -class Event; -class Document; - -/// -/// class Action -/// -/// This is a base class for actions which can be bound to menu items -/// or event table entries. The base class does nothing. In order to -/// use an action there needs to be a sub-class of Action which does -/// something specific. -/// -/// For example, you could have something like this for a Python -/// action: -/// -/// class PythonAction : public Action -/// { -/// public: -/// PythonAction(string& pythonCommand); -/// virtual void execute(const Event&); -/// } -/// -/// In this case, execute() would be implemented to evaluate the -/// pythonCommand argument using the python interpreter. -/// -/// You must override the copy() function! -/// - -class Action +namespace TwkApp { - public: - Action() {} - Action(const std::string& help) : m_docstring(help) {} + class Event; + class Document; - virtual ~Action(); - virtual void execute(Document*, const Event&) const; - virtual Action* copy() const = 0; - virtual bool error() const = 0; + /// + /// class Action + /// + /// This is a base class for actions which can be bound to menu items + /// or event table entries. The base class does nothing. In order to + /// use an action there needs to be a sub-class of Action which does + /// something specific. + /// + /// For example, you could have something like this for a Python + /// action: + /// + /// class PythonAction : public Action + /// { + /// public: + /// PythonAction(string& pythonCommand); + /// virtual void execute(const Event&); + /// } + /// + /// In this case, execute() would be implemented to evaluate the + /// pythonCommand argument using the python interpreter. + /// + /// You must override the copy() function! + /// - const std::string& docString() const { return m_docstring; } + class Action + { + public: + Action() {} - private: - std::string m_docstring; -}; + Action(const std::string& help) + : m_docstring(help) + { + } + virtual ~Action(); + virtual void execute(Document*, const Event&) const; + virtual Action* copy() const = 0; + virtual bool error() const = 0; -} // TwkApp + const std::string& docString() const { return m_docstring; } + + private: + std::string m_docstring; + }; + +} // namespace TwkApp #endif // __TwkApp__Action__h__ diff --git a/src/lib/app/TwkApp/TwkApp/Application.h b/src/lib/app/TwkApp/TwkApp/Application.h index ed3b147ae..12d048aa7 100644 --- a/src/lib/app/TwkApp/TwkApp/Application.h +++ b/src/lib/app/TwkApp/TwkApp/Application.h @@ -1,9 +1,9 @@ //****************************************************************************** -// Copyright (c) 2005 Tweak Inc. +// Copyright (c) 2005 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #ifndef __TwkApp__Application__h__ #define __TwkApp__Application__h__ @@ -12,81 +12,84 @@ #include #include -namespace TwkApp { - -// -// class Application -// -// Application class (only a single instance allowed). The class instance -// should be accessed through like this: -// -// TwkApp::App() -// -// of just -// -// App() -// -// if using namespace TwkApp. -// - - -class Application : public TwkUtil::Notifier +namespace TwkApp { - public: + // - // Types + // class Application // - - typedef std::vector Documents; - typedef std::vector> VideoModules; - typedef TwkUtil::Notifier Notifier; - + // Application class (only a single instance allowed). The class instance + // should be accessed through like this: // - // Access + // TwkApp::App() // - - static Application* instance() { return m_app; } - + // of just + // + // App() // - // Documents + // if using namespace TwkApp. // - const Documents& documents() const { return m_documents; } + class Application : public TwkUtil::Notifier + { + public: + // + // Types + // - // - // Video Device Modules - // + typedef std::vector Documents; + typedef std::vector> VideoModules; + typedef TwkUtil::Notifier Notifier; + + // + // Access + // + + static Application* instance() { return m_app; } + + // + // Documents + // + + const Documents& documents() const { return m_documents; } + + // + // Video Device Modules + // + + void loadOutputPlugins(const std::string& envvar); + void unloadOutputPlugins(); + + void addVideoModule(VideoModule* m) + { + m_videoModules.push_back(std::shared_ptr(m)); + } - void loadOutputPlugins(const std::string& envvar); - void unloadOutputPlugins(); - void addVideoModule(VideoModule* m) { m_videoModules.push_back(std::shared_ptr(m)); } - virtual VideoModule* primaryVideoModule() const; - const VideoModules& videoModules() const { return m_videoModules; } + virtual VideoModule* primaryVideoModule() const; - protected: - virtual bool receive(Notifier*, - Notifier*, - Notifier::MessageId, - Notifier::MessageData*); + const VideoModules& videoModules() const { return m_videoModules; } - protected: - Application(); - virtual ~Application(); + protected: + virtual bool receive(Notifier*, Notifier*, Notifier::MessageId, + Notifier::MessageData*); - virtual void add(Document*); - virtual void remove(Document*); + protected: + Application(); + virtual ~Application(); - private: - Documents m_documents; - VideoModules m_videoModules; - OutputPlugins m_outputPlugins; - static Application* m_app; - friend class Document; -}; + virtual void add(Document*); + virtual void remove(Document*); + private: + Documents m_documents; + VideoModules m_videoModules; + OutputPlugins m_outputPlugins; + static Application* m_app; + friend class Document; + }; -inline Application* App() { return Application::instance(); } + inline Application* App() { return Application::instance(); } -} // TwkApp +} // namespace TwkApp #endif // __TwkApp__Application__h__ diff --git a/src/lib/app/TwkApp/TwkApp/Bundle.h b/src/lib/app/TwkApp/TwkApp/Bundle.h index eaab4cfce..4498962b1 100644 --- a/src/lib/app/TwkApp/TwkApp/Bundle.h +++ b/src/lib/app/TwkApp/TwkApp/Bundle.h @@ -1,231 +1,237 @@ //****************************************************************************** -// Copyright (c) 2007 Tweak Inc. +// Copyright (c) 2007 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #ifndef __TwkApp__Bundle__h__ #define __TwkApp__Bundle__h__ #include #include -namespace TwkApp { - -// -// class Bundle -// -// This is an interface to Application files outside of the binary. -// An instance of this must be passed to the Application class. This -// is usually instantiated as either a DarwinBundle, UnixBundle, or -// WindowsBundle depending on the OS. -// -// For our purposes, search paths to plugins, or paths to files are -// placed in environment variables. These are then searched by -// individual components (like image plugins for example) that know -// where and how to look for what they want. -// - -class Bundle +namespace TwkApp { -public: + // - // These could change to wstring or ustring + // class Bundle // - - typedef std::string Path; - typedef std::string FileName; - typedef std::string CacheItemName; - typedef std::string DirName; - typedef std::string EnvVar; - typedef std::vector PathVector; - typedef unsigned char Byte; - typedef std::string FileAccessPermission; - typedef void* AccessObject; - - class CacheArena - { - public: - CacheArena(const std::string& name) - : m_name(name) {} - virtual ~CacheArena(); - - const std::string& name() const { return m_name; } - - private: - std::string m_name; - }; - + // This is an interface to Application files outside of the binary. + // An instance of this must be passed to the Application class. This + // is usually instantiated as either a DarwinBundle, UnixBundle, or + // WindowsBundle depending on the OS. // - // + // For our purposes, search paths to plugins, or paths to files are + // placed in environment variables. These are then searched by + // individual components (like image plugins for example) that know + // where and how to look for what they want. // - Bundle(const std::string& appName, - size_t major_version, - size_t minor_version, - size_t revision_number, - bool sandboxed = false, - bool inheritedSandbox = false); + class Bundle + { + public: + // + // These could change to wstring or ustring + // - virtual ~Bundle(); + typedef std::string Path; + typedef std::string FileName; + typedef std::string CacheItemName; + typedef std::string DirName; + typedef std::string EnvVar; + typedef std::vector PathVector; + typedef unsigned char Byte; + typedef std::string FileAccessPermission; + typedef void* AccessObject; - static Bundle* mainBundle() { return m_mainBundle; } + class CacheArena + { + public: + CacheArena(const std::string& name) + : m_name(name) + { + } - const std::string& applicationName() const { return m_applicationName; } + virtual ~CacheArena(); - bool isSandboxed() const { return m_sandboxed; } - bool isInheritedSandbox() const { return m_inheritedSandbox; } + const std::string& name() const { return m_name; } - // - // Application root. This is not where the binary lives: its the - // topmost directory that holds the whole app. - // + private: + std::string m_name; + }; - virtual Path top() = 0; + // + // + // - // - // - - const std::string& majorVersionDir() const { return m_majorVersionDir; } - const std::string& versionDir() const { return m_versionDir; } + Bundle(const std::string& appName, size_t major_version, + size_t minor_version, size_t revision_number, + bool sandboxed = false, bool inheritedSandbox = false); - // - // Find a particular binary, or application - // + virtual ~Bundle(); - virtual Path executableFile(const FileName& name) = 0; - virtual Path application(const FileName& name) = 0; + static Bundle* mainBundle() { return m_mainBundle; } - // - // The user support root path (~/Library/Application Support/APP) - // + const std::string& applicationName() const { return m_applicationName; } - virtual PathVector supportPath() = 0; + bool isSandboxed() const { return m_sandboxed; } - // - // Looks for: - // rcenv - // .rcfileName in home dir - // rcfileName in bundle - // - // type is the extension, so .rvrc.mu which could be overriden by - // RV_INIT env var would look like: - // - // rcfile("rvrc", "mu", "RV_INIT") - // + bool isInheritedSandbox() const { return m_inheritedSandbox; } - virtual Path rcfile(const FileName& rcfileName, - const FileName& type, - const EnvVar& rcenv) = 0; + // + // Application root. This is not where the binary lives: its the + // topmost directory that holds the whole app. + // - // - // Find a seach path for types of plugins, or scripts. The app - // versions will find the path associated with the application - // directory only. - // + virtual Path top() = 0; - virtual PathVector pluginPath(const DirName& pluginType) = 0; - virtual PathVector scriptPath(const DirName& scriptType) = 0; - virtual Path appPluginPath(const DirName& pluginType) = 0; - virtual Path appScriptPath(const DirName& pluginType) = 0; - virtual Path userPluginPath(const DirName& pluginType) = 0; - virtual Path userCacheDir() = 0; + // + // - // - // For example: resource("rv_manual", "pdf"); - // + const std::string& majorVersionDir() const { return m_majorVersionDir; } - virtual Path resource(const FileName& name, const FileName& type) = 0; - - // - // Find all the license files in the usual system locations - // + const std::string& versionDir() const { return m_versionDir; } - virtual PathVector licenseFiles(const FileName& licFileName, - const FileName& type) = 0; + // + // Find a particular binary, or application + // - // - // Location of default license (may not exist) - // + virtual Path executableFile(const FileName& name) = 0; + virtual Path application(const FileName& name) = 0; - virtual Path defaultLicense(const FileName& licFileName, - const FileName& type) = 0; + // + // The user support root path (~/Library/Application Support/APP) + // - // - // Get/Set environment variables - // The version that takes a vector creates a path value - // if force is false, and the env var exists, it will not be touched. - // + virtual PathVector supportPath() = 0; - virtual std::string getEnvVar(const EnvVar& name, - const std::string& defaultValue = ""); + // + // Looks for: + // rcenv + // .rcfileName in home dir + // rcfileName in bundle + // + // type is the extension, so .rvrc.mu which could be overriden by + // RV_INIT env var would look like: + // + // rcfile("rvrc", "mu", "RV_INIT") + // - virtual void setEnvVar(const EnvVar& name, - const Path& value, - bool force=false) = 0; + virtual Path rcfile(const FileName& rcfileName, const FileName& type, + const EnvVar& rcenv) = 0; - virtual void addPathToEnvVar(const EnvVar& name, - const PathVector& value) = 0; + // + // Find a seach path for types of plugins, or scripts. The app + // versions will find the path associated with the application + // directory only. + // - // - // User directories. These don't necessarily exist. - // + virtual PathVector pluginPath(const DirName& pluginType) = 0; + virtual PathVector scriptPath(const DirName& scriptType) = 0; + virtual Path appPluginPath(const DirName& pluginType) = 0; + virtual Path appScriptPath(const DirName& pluginType) = 0; + virtual Path userPluginPath(const DirName& pluginType) = 0; + virtual Path userCacheDir() = 0; - virtual Path userHome(); - virtual Path userMovies(); - virtual Path userMusic(); - virtual Path userPictures(); + // + // For example: resource("rv_manual", "pdf"); + // - // - // Crash Log - // + virtual Path resource(const FileName& name, const FileName& type) = 0; - virtual FileName crashLogFile() = 0; - virtual Path crashLogDirectory() = 0; + // + // Find all the license files in the usual system locations + // - // - // Cache File Management - // - // This API manages cache files which are allowed to be removed - // at any time. - // - // userCacheDir() is the location of the main cache dir. - // rescanCache() will update internal cache lookups (cache cache) - // cacheItemPath() will return a path to the item name IFF it - // already exists in the cache. If not it returns - // a blank path - // - // addCacheItem() will cause a stat on the file unless you give it - // the size in bytes of the cache item you - // created - // + virtual PathVector licenseFiles(const FileName& licFileName, + const FileName& type) = 0; - virtual void rescanCache(const std::string& cacheName); - virtual bool hasCacheItem(const std::string& cacheName, const CacheItemName&); - virtual Path cacheItemPath(const std::string& cacheName, const CacheItemName&); - virtual void addCacheItem(const std::string& cacheName, const CacheItemName&, size_t size=0); + // + // Location of default license (may not exist) + // - // - // Security API for external filesystem resources - // This is chiefly here to support sandboxing - // + virtual Path defaultLicense(const FileName& licFileName, + const FileName& type) = 0; + + // + // Get/Set environment variables + // The version that takes a vector creates a path value + // if force is false, and the env var exists, it will not be touched. + // + + virtual std::string getEnvVar(const EnvVar& name, + const std::string& defaultValue = ""); + + virtual void setEnvVar(const EnvVar& name, const Path& value, + bool force = false) = 0; + + virtual void addPathToEnvVar(const EnvVar& name, + const PathVector& value) = 0; + + // + // User directories. These don't necessarily exist. + // + + virtual Path userHome(); + virtual Path userMovies(); + virtual Path userMusic(); + virtual Path userPictures(); + + // + // Crash Log + // + + virtual FileName crashLogFile() = 0; + virtual Path crashLogDirectory() = 0; + + // + // Cache File Management + // + // This API manages cache files which are allowed to be removed + // at any time. + // + // userCacheDir() is the location of the main cache dir. + // rescanCache() will update internal cache lookups (cache cache) + // cacheItemPath() will return a path to the item name IFF it + // already exists in the cache. If not it returns + // a blank path + // + // addCacheItem() will cause a stat on the file unless you give it + // the size in bytes of the cache item you + // created + // + + virtual void rescanCache(const std::string& cacheName); + virtual bool hasCacheItem(const std::string& cacheName, + const CacheItemName&); + virtual Path cacheItemPath(const std::string& cacheName, + const CacheItemName&); + virtual void addCacheItem(const std::string& cacheName, + const CacheItemName&, size_t size = 0); + + // + // Security API for external filesystem resources + // This is chiefly here to support sandboxing + // + + virtual FileAccessPermission + permissionForFileAccess(const Path&, bool readonly) const; + virtual AccessObject + beginFileAccessWithPermission(const FileAccessPermission&) const; + virtual void endFileAccessWithPermission(AccessObject) const; + + private: + std::string m_applicationName; + size_t m_majorVersion; + size_t m_minorVersion; + size_t m_revisionNumber; + std::string m_majorVersionDir; + std::string m_versionDir; + bool m_sandboxed; + bool m_inheritedSandbox; + static Bundle* m_mainBundle; + }; - virtual FileAccessPermission permissionForFileAccess(const Path&, bool readonly) const; - virtual AccessObject beginFileAccessWithPermission(const FileAccessPermission&) const; - virtual void endFileAccessWithPermission(AccessObject) const; - - private: - std::string m_applicationName; - size_t m_majorVersion; - size_t m_minorVersion; - size_t m_revisionNumber; - std::string m_majorVersionDir; - std::string m_versionDir; - bool m_sandboxed; - bool m_inheritedSandbox; - static Bundle* m_mainBundle; -}; - -} // TwkApp +} // namespace TwkApp #endif // __TwkApp__Bundle__h__ diff --git a/src/lib/app/TwkApp/TwkApp/Command.h b/src/lib/app/TwkApp/TwkApp/Command.h index a8c99ee44..1b0cfe925 100644 --- a/src/lib/app/TwkApp/TwkApp/Command.h +++ b/src/lib/app/TwkApp/TwkApp/Command.h @@ -1,9 +1,9 @@ //****************************************************************************** -// Copyright (c) 2002 Tweak Inc. +// Copyright (c) 2002 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #ifndef __TwkApp__Command__h__ #define __TwkApp__Command__h__ @@ -13,385 +13,400 @@ #include #include -namespace TwkApp { -class Command; - -// -// class CommandInfo -// -// Describes a command. Used to create instances of a particular type -// of command. In particular indicates the UndoType of the command: -// -// * Undoable: after doit() is called the command will be entered -// into the redo/undo history and may have its undo() and redo() -// functions called sometime later if the user chooses. -// -// * NotUndoable: the command changes state in some way. After doit() -// is called the command is deleted and does not go into the -// history. In addition, the history itself is cleared since the -// command made a state change that cannot be tracked. -// -// * EditOnly: the command makes a state change which may not be -// necessary for the operation of undo/redo. The command is deleted -// after doit() is called and is not entered into the -// history. Unlike NotUndoable, the history is left untouched after -// doit() is called. -// -// * Marker: the command marks a point in the application's -// state. The most useful case might be indicating when the state -// was saved to the filesystem. If the user calls undo() and the -// marker is on the top of the history stack, that means that the -// current state of the application is *also* represented as a file -// that was previously saved. In that case the application could -// exit safetly without asking for permission. A marker command -// does not have its doit(), undo(), or redo() commands called; it -// merely exists in the history and is shuffled from the redo to -// the undo (and back) stacks along with other commands. -// - -class CommandInfo +namespace TwkApp { -public: - typedef std::map CommandInfos; + class Command; - enum UndoType + // + // class CommandInfo + // + // Describes a command. Used to create instances of a particular type + // of command. In particular indicates the UndoType of the command: + // + // * Undoable: after doit() is called the command will be entered + // into the redo/undo history and may have its undo() and redo() + // functions called sometime later if the user chooses. + // + // * NotUndoable: the command changes state in some way. After doit() + // is called the command is deleted and does not go into the + // history. In addition, the history itself is cleared since the + // command made a state change that cannot be tracked. + // + // * EditOnly: the command makes a state change which may not be + // necessary for the operation of undo/redo. The command is deleted + // after doit() is called and is not entered into the + // history. Unlike NotUndoable, the history is left untouched after + // doit() is called. + // + // * Marker: the command marks a point in the application's + // state. The most useful case might be indicating when the state + // was saved to the filesystem. If the user calls undo() and the + // marker is on the top of the history stack, that means that the + // current state of the application is *also* represented as a file + // that was previously saved. In that case the application could + // exit safetly without asking for permission. A marker command + // does not have its doit(), undo(), or redo() commands called; it + // merely exists in the history and is shuffled from the redo to + // the undo (and back) stacks along with other commands. + // + + class CommandInfo { - Undoable, - NotUndoable, - EditOnly, - Marker - }; - - CommandInfo(const std::string& name, UndoType type = Undoable); - virtual ~CommandInfo(); + public: + typedef std::map CommandInfos; - static const CommandInfo* findByName(const std::string&); + enum UndoType + { + Undoable, + NotUndoable, + EditOnly, + Marker + }; - const std::string& name() const { return m_name; } + CommandInfo(const std::string& name, UndoType type = Undoable); + virtual ~CommandInfo(); - // - // Create a command object for execution - // + static const CommandInfo* findByName(const std::string&); - virtual Command* newCommand() const = 0; + const std::string& name() const { return m_name; } - bool isUndoable() const { return m_type == Undoable; } - bool isEditOnly() const { return m_type == EditOnly; } - bool isMarker() const { return m_type == Marker; } + // + // Create a command object for execution + // -private: - UndoType m_type; - std::string m_name; - static CommandInfos m_commands; -}; + virtual Command* newCommand() const = 0; -//---------------------------------------------------------------------- -// -// class Command -// -// Subclass from this class creates a command. The doit() method is -// required. If the command has undo, it may also need to implement -// undo() and/or redo(). By default undo() and redo() call doit(), so -// if doit for example does a state swap (toggling the state) than -// you only need to implement that. -// -// Limitations on what commands are allowed to do: -// -// 1. You cannot call queueCommand() on the CommandHistory from -// within a command. -// -// 2. You cannot touch the CommandHistory in any way from a command -// *unless* your command is EditOnly (not undoable, but queuable). -// -// 3. Commands are allowed to stash data between undo/redos, but -// should avoid stashing pointers at all costs. Objects may change -// identities between undo/redo invocations. -// + bool isUndoable() const { return m_type == Undoable; } -class Command -{ -public: - Command(const CommandInfo*); - virtual ~Command(); + bool isEditOnly() const { return m_type == EditOnly; } - const CommandInfo* info() const { return m_commandInfo; } + bool isMarker() const { return m_type == Marker; } - virtual void doit() = 0; - virtual void undo(); - virtual void redo(); + private: + UndoType m_type; + std::string m_name; + static CommandInfos m_commands; + }; - virtual std::string name() const; + //---------------------------------------------------------------------- + // + // class Command + // + // Subclass from this class creates a command. The doit() method is + // required. If the command has undo, it may also need to implement + // undo() and/or redo(). By default undo() and redo() call doit(), so + // if doit for example does a state swap (toggling the state) than + // you only need to implement that. + // + // Limitations on what commands are allowed to do: + // + // 1. You cannot call queueCommand() on the CommandHistory from + // within a command. + // + // 2. You cannot touch the CommandHistory in any way from a command + // *unless* your command is EditOnly (not undoable, but queuable). + // + // 3. Commands are allowed to stash data between undo/redos, but + // should avoid stashing pointers at all costs. Objects may change + // identities between undo/redo invocations. + // - bool isUndoable() const { return info()->isUndoable(); } - bool isEditOnly() const { return info()->isEditOnly(); } - bool isMarker() const { return info()->isMarker(); } + class Command + { + public: + Command(const CommandInfo*); + virtual ~Command(); - void setDescription(const std::string& d) { m_description = d; } - std::string description() const { return m_description; } + const CommandInfo* info() const { return m_commandInfo; } -private: - const CommandInfo* m_commandInfo; - std::string m_description; -}; + virtual void doit() = 0; + virtual void undo(); + virtual void redo(); -//---------------------------------------------------------------------- -// -// class CommandHistory -// -// An undo and redo stack as well as a facility to handle compound -// commands. -// -// The CommandQueue makes it possible for the applciation to queue up -// commands without having them executed. This is useful in -// multithreaded sitations where you want all state changes to occur -// at one time in a controlled manner (e.g. you want a particular -// thread to do all the state changes). The CommandQueue is -// internally protected with a mutex but its advisable to allow only -// a single thread to fill it and the same or another to flush it. -// + virtual std::string name() const; -class CompoundCommand; -class CompoundCommandInfo; -typedef std::deque CommandStack; -typedef CommandStack CommandQueue; + bool isUndoable() const { return info()->isUndoable(); } -class CommandHistory -{ - public: - typedef boost::signals2::signal VoidSignal; - typedef boost::mutex Mutex; - typedef boost::mutex::scoped_lock ScopedLock; + bool isEditOnly() const { return info()->isEditOnly(); } - enum HistoryState - { - EditingState, - UndoState, - RedoState - }; + bool isMarker() const { return info()->isMarker(); } - CommandHistory(); - ~CommandHistory(); + void setDescription(const std::string& d) { m_description = d; } + std::string description() const { return m_description; } + + private: + const CommandInfo* m_commandInfo; + std::string m_description; + }; + + //---------------------------------------------------------------------- + // + // class CommandHistory + // + // An undo and redo stack as well as a facility to handle compound + // commands. // - // Each beginCompoundCommand() must be bracketed by a corresponding - // endCompoundCommand(). Compound command trees can be created and are - // allowed. + // The CommandQueue makes it possible for the applciation to queue up + // commands without having them executed. This is useful in + // multithreaded sitations where you want all state changes to occur + // at one time in a controlled manner (e.g. you want a particular + // thread to do all the state changes). The CommandQueue is + // internally protected with a mutex but its advisable to allow only + // a single thread to fill it and the same or another to flush it. // - void beginCompoundCommand(const std::string&); - void endCompoundCommand(); - bool compoundActive() const { return m_compound != 0; } + class CompoundCommand; + class CompoundCommandInfo; + typedef std::deque CommandStack; + typedef CommandStack CommandQueue; - void clearUndoHistory(); - void clearRedoHistory(); - void clearHistory() { clearUndoHistory(); clearRedoHistory(); } + class CommandHistory + { + public: + typedef boost::signals2::signal VoidSignal; + typedef boost::mutex Mutex; + typedef boost::mutex::scoped_lock ScopedLock; - // - // This is the main method of creating a command by its type - // name. This should be only way an application creates command - // instances. - // + enum HistoryState + { + EditingState, + UndoState, + RedoState + }; - template - T* newCommand(const std::string&); + CommandHistory(); + ~CommandHistory(); - // - // Causes immediate call to doit(), undo(), or redo() on the command - // + // + // Each beginCompoundCommand() must be bracketed by a corresponding + // endCompoundCommand(). Compound command trees can be created and are + // allowed. + // - virtual void doCommand(Command*); - virtual void undoCommand(); - virtual void redoCommand(); + void beginCompoundCommand(const std::string&); + void endCompoundCommand(); - void undoAllCommands(); - void redoAllCommands(); + bool compoundActive() const { return m_compound != 0; } - // - // These two are protected by a mutex internally. Queuing a command - // does not result in a call to doit(). Flushing the command queue - // will causes repeated calls to doCommand() above on the queued - // commands and the queue will be empty after returning. - // + void clearUndoHistory(); + void clearRedoHistory(); - virtual void queueCommand(Command*); - virtual void flushCommandQueue(); + void clearHistory() + { + clearUndoHistory(); + clearRedoHistory(); + } - // - // Direct access to the undo/redo stacks - // + // + // This is the main method of creating a command by its type + // name. This should be only way an application creates command + // instances. + // - const CommandStack& undoStack() const { return m_undoStack; } - const CommandStack& redoStack() const { return m_redoStack; } + template T* newCommand(const std::string&); - static std::string topOfStackDescription(const CommandStack&); + // + // Causes immediate call to doit(), undo(), or redo() on the command + // - bool hasMarkerCommand(const std::string& name) const; - bool isMarkerCommandRecent(const std::string& name) const; + virtual void doCommand(Command*); + virtual void undoCommand(); + virtual void redoCommand(); - // - // Signals - // - - VoidSignal& undoSizeChangedSignal() { return m_undoSizeChangedSignal; } - VoidSignal& redoSizeChangedSignal() { return m_redoSizeChangedSignal; } + void undoAllCommands(); + void redoAllCommands(); - protected: - virtual void doCommandInternal(Command*); + // + // These two are protected by a mutex internally. Queuing a command + // does not result in a call to doit(). Flushing the command queue + // will causes repeated calls to doCommand() above on the queued + // commands and the queue will be empty after returning. + // - private: - void undoCommandInternal(); - void redoCommandInternal(); - void flushCommandQueueInternal(); + virtual void queueCommand(Command*); + virtual void flushCommandQueue(); - protected: - CompoundCommand* m_compound; - CommandStack m_undoStack; - CommandStack m_redoStack; - VoidSignal m_undoSizeChangedSignal; - VoidSignal m_redoSizeChangedSignal; - HistoryState m_historyState; - CommandQueue m_commandQueue; - Mutex m_commandQueueMutex; - static CompoundCommandInfo* m_ccinfo; -}; + // + // Direct access to the undo/redo stacks + // -template -T* -CommandHistory::newCommand(const std::string& n) -{ - const CommandInfo* i = CommandInfo::findByName(n); - return i ? dynamic_cast(i->newCommand()) : 0; -} + const CommandStack& undoStack() const { return m_undoStack; } -//---------------------------------------------------------------------- -// -// class CompoundCommandInfo -// + const CommandStack& redoStack() const { return m_redoStack; } + static std::string topOfStackDescription(const CommandStack&); -class CompoundCommandInfo : public CommandInfo -{ -public: - CompoundCommandInfo(); - virtual ~CompoundCommandInfo(); - virtual Command* newCommand() const; -}; + bool hasMarkerCommand(const std::string& name) const; + bool isMarkerCommandRecent(const std::string& name) const; + // + // Signals + // -//---------------------------------------------------------------------- -// -// class CompoundCommand -// -// Is its self a CommandHistory so that it can recursively hold -// commands for undo. When a compound command is undone, all of its -// children are undone. Redo is the same. -// + VoidSignal& undoSizeChangedSignal() { return m_undoSizeChangedSignal; } -class CompoundCommand : public Command, public CommandHistory -{ -public: - CompoundCommand(const CompoundCommandInfo*); - virtual ~CompoundCommand(); - virtual void doit(); - virtual void undo(); - virtual void redo(); - virtual std::string name() const; - void setName(const std::string& n) { m_name = n; } - -private: - std::string m_name; -}; - -//---------------------------------------------------------------------- -// -// class MarkerCommandInfo -// + VoidSignal& redoSizeChangedSignal() { return m_redoSizeChangedSignal; } + protected: + virtual void doCommandInternal(Command*); -class MarkerCommandInfo : public CommandInfo -{ -public: - MarkerCommandInfo(); - virtual ~MarkerCommandInfo(); - virtual Command* newCommand() const; -}; + private: + void undoCommandInternal(); + void redoCommandInternal(); + void flushCommandQueueInternal(); -//---------------------------------------------------------------------- -// -// class MarkerCommand -// -// + protected: + CompoundCommand* m_compound; + CommandStack m_undoStack; + CommandStack m_redoStack; + VoidSignal m_undoSizeChangedSignal; + VoidSignal m_redoSizeChangedSignal; + HistoryState m_historyState; + CommandQueue m_commandQueue; + Mutex m_commandQueueMutex; + static CompoundCommandInfo* m_ccinfo; + }; -class MarkerCommand : public Command -{ -public: - MarkerCommand(const MarkerCommandInfo*); - virtual ~MarkerCommand(); - virtual void doit(); - virtual void undo(); - virtual void redo(); - virtual std::string name() const; - bool isUnique() const { return m_unique; } - void setArgs(const std::string& n, bool unique=true) { m_name = n; m_unique = unique; } - -private: - std::string m_name; - bool m_unique; -}; - - -//---------------------------------------------------------------------- -// -// class HistoryCommandInfo -// + template T* CommandHistory::newCommand(const std::string& n) + { + const CommandInfo* i = CommandInfo::findByName(n); + return i ? dynamic_cast(i->newCommand()) : 0; + } + //---------------------------------------------------------------------- + // + // class CompoundCommandInfo + // -class HistoryCommandInfo : public CommandInfo -{ -public: - HistoryCommandInfo(); - virtual ~HistoryCommandInfo(); - virtual Command* newCommand() const; -}; + class CompoundCommandInfo : public CommandInfo + { + public: + CompoundCommandInfo(); + virtual ~CompoundCommandInfo(); + virtual Command* newCommand() const; + }; + + //---------------------------------------------------------------------- + // + // class CompoundCommand + // + // Is its self a CommandHistory so that it can recursively hold + // commands for undo. When a compound command is undone, all of its + // children are undone. Redo is the same. + // + class CompoundCommand + : public Command + , public CommandHistory + { + public: + CompoundCommand(const CompoundCommandInfo*); + virtual ~CompoundCommand(); + virtual void doit(); + virtual void undo(); + virtual void redo(); + virtual std::string name() const; + + void setName(const std::string& n) { m_name = n; } + + private: + std::string m_name; + }; -//---------------------------------------------------------------------- -// -// class HistoryCommand -// -// This command operates on the history itself. This makes it -// possible to queue history commands like any other state change (so -// they occur interleaved with others). HistoryCommands are not -// themselves stored in the history since they are declared as -// EditOnly commands. -// + //---------------------------------------------------------------------- + // + // class MarkerCommandInfo + // -class HistoryCommand : public Command -{ - public: - enum CommandType + class MarkerCommandInfo : public CommandInfo { - NoOpCommandType, - UndoCommandType, - RedoCommandType, - ClearCommandType, - BeginCompoundCommandType, - EndCompoundCommandType + public: + MarkerCommandInfo(); + virtual ~MarkerCommandInfo(); + virtual Command* newCommand() const; }; - HistoryCommand(const HistoryCommandInfo*); - virtual ~HistoryCommand(); - virtual void doit(); - virtual void undo(); - virtual void redo(); - void setArgs(CommandHistory* h, CommandType t, const std::string& name = ""); + //---------------------------------------------------------------------- + // + // class MarkerCommand + // + // - private: - CommandHistory* m_history; - CommandType m_commandType; - std::string m_name; -}; + class MarkerCommand : public Command + { + public: + MarkerCommand(const MarkerCommandInfo*); + virtual ~MarkerCommand(); + virtual void doit(); + virtual void undo(); + virtual void redo(); + virtual std::string name() const; + + bool isUnique() const { return m_unique; } + + void setArgs(const std::string& n, bool unique = true) + { + m_name = n; + m_unique = unique; + } + + private: + std::string m_name; + bool m_unique; + }; + + //---------------------------------------------------------------------- + // + // class HistoryCommandInfo + // + + class HistoryCommandInfo : public CommandInfo + { + public: + HistoryCommandInfo(); + virtual ~HistoryCommandInfo(); + virtual Command* newCommand() const; + }; + + //---------------------------------------------------------------------- + // + // class HistoryCommand + // + // This command operates on the history itself. This makes it + // possible to queue history commands like any other state change (so + // they occur interleaved with others). HistoryCommands are not + // themselves stored in the history since they are declared as + // EditOnly commands. + // + + class HistoryCommand : public Command + { + public: + enum CommandType + { + NoOpCommandType, + UndoCommandType, + RedoCommandType, + ClearCommandType, + BeginCompoundCommandType, + EndCompoundCommandType + }; + + HistoryCommand(const HistoryCommandInfo*); + virtual ~HistoryCommand(); + virtual void doit(); + virtual void undo(); + virtual void redo(); + void setArgs(CommandHistory* h, CommandType t, + const std::string& name = ""); + + private: + CommandHistory* m_history; + CommandType m_commandType; + std::string m_name; + }; -} // TwkApp +} // namespace TwkApp #endif // __TwkApp__Command__h__ diff --git a/src/lib/app/TwkApp/TwkApp/Document.h b/src/lib/app/TwkApp/TwkApp/Document.h index e93db1b5f..8744c4524 100644 --- a/src/lib/app/TwkApp/TwkApp/Document.h +++ b/src/lib/app/TwkApp/TwkApp/Document.h @@ -1,9 +1,9 @@ //***************************************************************************** // Copyright (c) 2002 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //***************************************************************************** #ifndef __TwkApp__Document__h__ #define __TwkApp__Document__h__ @@ -21,337 +21,370 @@ #include #include -namespace TwkApp { -class Menu; -class EventTable; - -// -// class Document -// -// Borrowing from the ideas in Cocoa, this is a base class for a -// thing being edited by the app. An example is the TwkModel::Scene -// object which is a document. This class provides API for reading -// and writing files, etc. The Application classes can work with this -// class without knowing about the implementation. Unlike Cocoa, you -// should certinaly inherit from this class and make your own -// document type. -// -// The Document manages editing modes (Mode.h) and selection -// (SelectionState.h). Its assumed that most things you're likely to be -// editing need these operations. -// - -class Document : public EventNode, - public TwkUtil::Notifier, - public CommandHistory +namespace TwkApp { -public: + class Menu; + class EventTable; + // - // Types + // class Document + // + // Borrowing from the ideas in Cocoa, this is a base class for a + // thing being edited by the app. An example is the TwkModel::Scene + // object which is a document. This class provides API for reading + // and writing files, etc. The Application classes can work with this + // class without knowing about the implementation. Unlike Cocoa, you + // should certinaly inherit from this class and make your own + // document type. + // + // The Document manages editing modes (Mode.h) and selection + // (SelectionState.h). Its assumed that most things you're likely to be + // editing need these operations. // - typedef std::map OptionMap; - typedef boost::signals2::signal VoidSignal; - typedef boost::signals2::signal DocumentSignal; - typedef boost::signals2::signal StringSignal; - typedef std::vector CommandQueue; - - struct FileIORequest + class Document + : public EventNode + , public TwkUtil::Notifier + , public CommandHistory { - FileIORequest() {} - + public: // - // request.setOption("flag", true); - // request.setOption("foo", string("string value")); - // request.setOption("bar", int(123)); - // request.setOption("baz", float(123.321)); + // Types // - void setOption(const std::string& name, const boost::any& value) { options[name] = value; } + typedef std::map OptionMap; + typedef boost::signals2::signal VoidSignal; + typedef boost::signals2::signal DocumentSignal; + typedef boost::signals2::signal StringSignal; + typedef std::vector CommandQueue; + + struct FileIORequest + { + FileIORequest() {} + + // + // request.setOption("flag", true); + // request.setOption("foo", string("string value")); + // request.setOption("bar", int(123)); + // request.setOption("baz", float(123.321)); + // + + void setOption(const std::string& name, const boost::any& value) + { + options[name] = value; + } + + // + // const bool b = request.optionValue("flag", false); + // const string foo = request.optionValue("foo", + // "defaultValue"); const int bar = + // request.optionValue("bar", 0); const float baz = + // request.optionValue("baz", 0.0f); + // + + template + T optionValue(const std::string& name, + const T& defaultValue = T()) const + { + OptionMap::const_iterator i = options.find(name); + if (i != options.end()) + return boost::any_cast(i->second); + return defaultValue; + } + + OptionMap options; + }; + + typedef FileIORequest ReadRequest; + typedef FileIORequest WriteRequest; + + struct MinorModeComp + { + bool operator()(MinorMode* a, MinorMode* b) const + { + return a->order() != b->order() ? a->order() < b->order() + : a->sortKey() != b->sortKey() + ? a->sortKey() < b->sortKey() + : a < b; + } + }; + + typedef std::map Modes; + typedef std::set MinorModes; + typedef std::map EventTables; + typedef EventTables::value_type EventTableEntry; + typedef std::vector EventTableStack; + typedef std::vector EventTableNameStack; + typedef std::vector Documents; + typedef std::pair ActionTablePair; + + typedef bool (*TablePredicate)(const Document&, const EventTable&, + const Event&); // - // const bool b = request.optionValue("flag", false); - // const string foo = request.optionValue("foo", "defaultValue"); - // const int bar = request.optionValue("bar", 0); - // const float baz = request.optionValue("baz", 0.0f); + // Signals // - template - T optionValue(const std::string& name, const T& defaultValue = T()) const + DocumentSignal& documentDeleteSignal() { return m_deleteSignal; } + + DocumentSignal& documentActiveSignal() { return m_activeSignal; } + + DocumentSignal& fileNameChangedSignal() { - OptionMap::const_iterator i = options.find(name); - if (i != options.end()) return boost::any_cast(i->second); - return defaultValue; + return m_fileNameChangedSignal; } - OptionMap options; - }; + DocumentSignal& historyChangedSignal() + { + return m_historyChangedSignal; + } - typedef FileIORequest ReadRequest; - typedef FileIORequest WriteRequest; + DocumentSignal& modeChangedSignal() { return m_modeChangedSignal; } - struct MinorModeComp - { - bool operator() (MinorMode* a, MinorMode* b) const + DocumentSignal& menuChangedSignal() { return m_menuChangedSignal; } + + DocumentSignal& selectionChangedSignal() { - return a->order() != b->order() ? - a->order() < b->order() : a->sortKey() != b->sortKey() ? - a->sortKey() < b->sortKey() : - a < b; + return m_selectionChangedSignal; } - }; - typedef std::map Modes; - typedef std::set MinorModes; - typedef std::map EventTables; - typedef EventTables::value_type EventTableEntry; - typedef std::vector EventTableStack; - typedef std::vector EventTableNameStack; - typedef std::vector Documents; - typedef std::pair ActionTablePair; + DocumentSignal& bindingsChangedSignal() + { + return m_bindingsChangedSignal; + } - typedef bool (*TablePredicate)(const Document&, - const EventTable&, - const Event&); + DocumentSignal& modeAddedSignal() { return m_modeAddedSignal; } - // - // Signals - // + // + // Messages + // - DocumentSignal& documentDeleteSignal() { return m_deleteSignal; } - DocumentSignal& documentActiveSignal() { return m_activeSignal; } - DocumentSignal& fileNameChangedSignal() { return m_fileNameChangedSignal; } - DocumentSignal& historyChangedSignal() { return m_historyChangedSignal; } - DocumentSignal& modeChangedSignal() { return m_modeChangedSignal; } - DocumentSignal& menuChangedSignal() { return m_menuChangedSignal; } - DocumentSignal& selectionChangedSignal() { return m_selectionChangedSignal; } - DocumentSignal& bindingsChangedSignal() { return m_bindingsChangedSignal; } - DocumentSignal& modeAddedSignal() { return m_modeAddedSignal; } + NOTIFIER_MESSAGE(modeChangedMessage); + NOTIFIER_MESSAGE(menuChangedMessage); + NOTIFIER_MESSAGE(selectionChangedMessage); + NOTIFIER_MESSAGE(activeMessage); + NOTIFIER_MESSAGE(bindingsChangedMessage); + NOTIFIER_MESSAGE(modeAddedMessage); + NOTIFIER_MESSAGE(historyChangedMessage); + NOTIFIER_MESSAGE(deleteMessage); + NOTIFIER_MESSAGE(filenameChangedMessage); - // - // Messages - // + // + // Constructor/Destructor + // - NOTIFIER_MESSAGE(modeChangedMessage); - NOTIFIER_MESSAGE(menuChangedMessage); - NOTIFIER_MESSAGE(selectionChangedMessage); - NOTIFIER_MESSAGE(activeMessage); - NOTIFIER_MESSAGE(bindingsChangedMessage); - NOTIFIER_MESSAGE(modeAddedMessage); - NOTIFIER_MESSAGE(historyChangedMessage); - NOTIFIER_MESSAGE(deleteMessage); - NOTIFIER_MESSAGE(filenameChangedMessage); + Document(); + virtual ~Document(); - // - // Constructor/Destructor - // + // + // Active / All documents + // - Document(); - virtual ~Document(); + static Document* activeDocument() + { + return m_documents.empty() ? 0 : m_documents.front(); + } - // - // Active / All documents - // + static const Documents& documents() { return m_documents; } - static Document* activeDocument() - { return m_documents.empty() ? 0 : m_documents.front(); } + static Document* eventDocument() { return m_eventDocument; } - static const Documents& documents() { return m_documents; } + // + // You must call the base class makeActive() if you override + // - static Document* eventDocument() { return m_eventDocument; } + virtual void makeActive(); - // - // You must call the base class makeActive() if you override - // + // + // Full path to file represented by document (Deprecated) + // - virtual void makeActive(); + virtual std::string filePath() const; - // - // Full path to file represented by document (Deprecated) - // + // + // Change the current filename. Note: This API supersedes the + // filePath() API. + // - virtual std::string filePath() const; + virtual void setFileName(const std::string& newName); + virtual const std::string& fileName() const; - // - // Change the current filename. Note: This API supersedes the - // filePath() API. - // + // + // Replaces contents with filename or if addContents==true then + // add the contents of the file instead of replacing. You should + // throw out of here if the read failed. + // + // The tags can be used for any purpose. In RV, this is used to + // indicate the circumstances under which the file is being + // read. For example, choosing a single file of a sequence in the + // media browser means "exclusively that file". + // - virtual void setFileName(const std::string& newName); - virtual const std::string& fileName() const; + virtual void read(const std::string& filename, const ReadRequest&); - // - // Replaces contents with filename or if addContents==true then - // add the contents of the file instead of replacing. You should - // throw out of here if the read failed. - // - // The tags can be used for any purpose. In RV, this is used to - // indicate the circumstances under which the file is being - // read. For example, choosing a single file of a sequence in the - // media browser means "exclusively that file". - // + // + // Write contents to filename or if partial==true, then write + // only some of the data. (This is interpreted by the document + // sub-class.) Normally this would mean: write selection + // only. you should throw out of here if the write fails. + // + // The tag can be used for any purpose. + // - virtual void read(const std::string& filename, const ReadRequest&); + virtual void write(const std::string& filename, const WriteRequest&); - // - // Write contents to filename or if partial==true, then write - // only some of the data. (This is interpreted by the document - // sub-class.) Normally this would mean: write selection - // only. you should throw out of here if the write fails. - // - // The tag can be used for any purpose. - // + // + // Deletes the contents of the document. + // - virtual void write(const std::string& filename, const WriteRequest&); + virtual void clear(); - // - // Deletes the contents of the document. - // + // + // Deltes all modes in the document + // - virtual void clear(); + virtual void deleteModes(); - // - // Deltes all modes in the document - // + // + // Command History + // --------------- + // - virtual void deleteModes(); + virtual void doCommand(Command*); + virtual void undoCommand(); + virtual void redoCommand(); - // - // Command History - // --------------- - // + // + // Editing modes. + // -------------- + // + // There is one MajorMode active at a time. There may be many + // MinorModes active at the same time. + // + // activateMode() will turn a mode on. If the mode is a major + // mode, it will deactivate the current MajorMode and then active + // the specified mode which will become the current MajorMode. If + // the mode is a MinorMode it will make it active. If the mode is + // already active, it will do nothing. + // + // deactivateMode() will turn a mode off. If the mode is a major + // mode, it will do nothing (there should always be an active + // major mode). if the mode is minor it will deactivate it unless + // its already inactive in which case it will do nothing. + // - virtual void doCommand(Command*); - virtual void undoCommand(); - virtual void redoCommand(); + virtual void addMode(Mode*); - // - // Editing modes. - // -------------- - // - // There is one MajorMode active at a time. There may be many - // MinorModes active at the same time. - // - // activateMode() will turn a mode on. If the mode is a major - // mode, it will deactivate the current MajorMode and then active - // the specified mode which will become the current MajorMode. If - // the mode is a MinorMode it will make it active. If the mode is - // already active, it will do nothing. - // - // deactivateMode() will turn a mode off. If the mode is a major - // mode, it will do nothing (there should always be an active - // major mode). if the mode is minor it will deactivate it unless - // its already inactive in which case it will do nothing. - // + const Modes& modes() const { return m_modes; } - virtual void addMode(Mode*); - const Modes& modes() const { return m_modes; } + MajorMode* majorMode() const { return m_majorMode; } - MajorMode* majorMode() const { return m_majorMode; } - const MinorModes& minorModes() const { return m_minorModes; } - Mode *findModeByName(const std::string& name) const; + const MinorModes& minorModes() const { return m_minorModes; } - virtual void activateMode(Mode*); - virtual void deactivateMode(Mode*); - bool isModeActive(Mode*); + Mode* findModeByName(const std::string& name) const; - void activateMode(const std::string& name); - void deactivateMode(const std::string& name); - bool isModeActive(const std::string& name); + virtual void activateMode(Mode*); + virtual void deactivateMode(Mode*); + bool isModeActive(Mode*); - // - // Query event finds the first action corresponding to the - // event. If after is non-nil queryEvent() will look for the - // first action *after* the passed in action. - // + void activateMode(const std::string& name); + void deactivateMode(const std::string& name); + bool isModeActive(const std::string& name); - ActionTablePair queryEvent(const Event& event, const Action* after=0); + // + // Query event finds the first action corresponding to the + // event. If after is non-nil queryEvent() will look for the + // first action *after* the passed in action. + // - void executeAction(const Event&); + ActionTablePair queryEvent(const Event& event, const Action* after = 0); - void pushTable(const std::string&); - void popTable(); - void popTable(const std::string&); + void executeAction(const Event&); - void invalidateEventTables(); + void pushTable(const std::string&); + void popTable(); + void popTable(const std::string&); - const Event* currentEvent() const { return m_event; } + void invalidateEventTables(); - static void debugEvents(); + const Event* currentEvent() const { return m_event; } - const EventTableStack& eventTableStack() const; + static void debugEvents(); - // - // EventNode API - // + const EventTableStack& eventTableStack() const; - virtual Result receiveEvent(const Event&); + // + // EventNode API + // - // - // The Document menu: the base class will construct a menu from - // the currently active modes and cache it. When modes change, - // the menu is invalidated and reconstructed upon request. You - // can modify the menu by overriding this function. - // - // invalidateMenu() will send a menuChangedMessage() as well as - // deleting the current m_menu -- this will force the menu to be - // rebuilt by the menu() function. This function is *NOT* called - // by activateMenu() and deactivateMenu() in order to prevent a - // race condition with order that modeChangedMessage() and - // menuChangedMessage() are received from some objects. - // + virtual Result receiveEvent(const Event&); + + // + // The Document menu: the base class will construct a menu from + // the currently active modes and cache it. When modes change, + // the menu is invalidated and reconstructed upon request. You + // can modify the menu by overriding this function. + // + // invalidateMenu() will send a menuChangedMessage() as well as + // deleting the current m_menu -- this will force the menu to be + // rebuilt by the menu() function. This function is *NOT* called + // by activateMenu() and deactivateMenu() in order to prevent a + // race condition with order that modeChangedMessage() and + // menuChangedMessage() are received from some objects. + // - virtual Menu* menu(); - virtual void invalidateMenu(); + virtual Menu* menu(); + virtual void invalidateMenu(); - // - // Get/Set selection - // + // + // Get/Set selection + // - const SelectionState& selection() const { return m_selectionState; } - virtual void setSelection(const SelectionState&); + const SelectionState& selection() const { return m_selectionState; } - // - // Opaque pointer - // + virtual void setSelection(const SelectionState&); + + // + // Opaque pointer + // + + void* opaquePointer() const { return m_opaquePointer; } + + void setOpaquePointer(void* p) { m_opaquePointer = p; } + + protected: + void buildEventTables(); + + private: + void setFocusTable(const EventTable*); + + private: + SelectionState m_selectionState; + Menu* m_menu; + MajorMode* m_majorMode; + MinorModes m_minorModes; + Modes m_modes; + EventTableStack m_eventTableStack; + EventTableNameStack m_eventTableNameStack; + const EventTable* m_focusTable; + bool m_eventTableDirty; + const Event* m_event; + CommandHistory m_commandHistory; + void* m_opaquePointer; + std::string m_fileName; + DocumentSignal m_deleteSignal; + DocumentSignal m_activeSignal; + DocumentSignal m_historyChangedSignal; + DocumentSignal m_fileNameChangedSignal; + DocumentSignal m_modeChangedSignal; + DocumentSignal m_menuChangedSignal; + DocumentSignal m_selectionChangedSignal; + DocumentSignal m_bindingsChangedSignal; + DocumentSignal m_modeAddedSignal; + static Documents m_documents; + static Document* m_eventDocument; + }; - void* opaquePointer() const { return m_opaquePointer; } - void setOpaquePointer(void* p) { m_opaquePointer = p; } - -protected: - void buildEventTables(); - -private: - void setFocusTable(const EventTable*); - -private: - SelectionState m_selectionState; - Menu* m_menu; - MajorMode* m_majorMode; - MinorModes m_minorModes; - Modes m_modes; - EventTableStack m_eventTableStack; - EventTableNameStack m_eventTableNameStack; - const EventTable* m_focusTable; - bool m_eventTableDirty; - const Event* m_event; - CommandHistory m_commandHistory; - void* m_opaquePointer; - std::string m_fileName; - DocumentSignal m_deleteSignal; - DocumentSignal m_activeSignal; - DocumentSignal m_historyChangedSignal; - DocumentSignal m_fileNameChangedSignal; - DocumentSignal m_modeChangedSignal; - DocumentSignal m_menuChangedSignal; - DocumentSignal m_selectionChangedSignal; - DocumentSignal m_bindingsChangedSignal; - DocumentSignal m_modeAddedSignal; - static Documents m_documents; - static Document* m_eventDocument; -}; - - -} // TwkApp +} // namespace TwkApp #endif // __TwkApp__Document__h__ diff --git a/src/lib/app/TwkApp/TwkApp/Event.h b/src/lib/app/TwkApp/TwkApp/Event.h index 6ec59e315..ce83cd430 100644 --- a/src/lib/app/TwkApp/TwkApp/Event.h +++ b/src/lib/app/TwkApp/TwkApp/Event.h @@ -1,9 +1,9 @@ //****************************************************************************** -// Copyright (c) 2002 Tweak Inc. +// Copyright (c) 2002 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #ifndef __TwkApp__Event__h__ #define __TwkApp__Event__h__ @@ -11,697 +11,756 @@ #include #include -namespace TwkApp { -class VideoDevice; -class EventNode; -class EventTable; - -/// -/// class Event -/// -/// This is a base class. To actually create an event, you'll probably -/// use a sub-class of the Event class. The most obvious uses are the -/// KeyEvent and PointerEvent (mouse) classes. -/// -/// Special events like RedrawEvent are also sub-classed from this -/// event. -/// - -class Event +namespace TwkApp { - public: - typedef std::vector StringVector; + class VideoDevice; + class EventNode; + class EventTable; + + /// + /// class Event + /// + /// This is a base class. To actually create an event, you'll probably + /// use a sub-class of the Event class. The most obvious uses are the + /// KeyEvent and PointerEvent (mouse) classes. + /// + /// Special events like RedrawEvent are also sub-classed from this + /// event. + /// + + class Event + { + public: + typedef std::vector StringVector; + + // + // It seems dangerous to allow events with no sender and blank name + // (caused a crash in one corner case), so for now we disallow all such + // events. + // + // Event() : m_name(""), m_sender(0) {} + + Event(const std::string& name, const EventNode* sender, void* data = 0) + : m_name(name) + , m_sender(sender) + , m_data(data) + , m_table(0) + , handled(false) + { + } + + const std::string& name() const { return m_name; } + + const EventNode* sender() const { return m_sender; } + + const EventTable* eventTable() const { return m_table; } + + virtual void output(std::ostream&) const; + + void* data() const { return m_data; } + + double timeStamp() const { return m_timeStamp; } + + mutable bool handled; + + private: + std::string m_name; + const EventNode* m_sender; + void* m_data; + mutable const EventTable* m_table; + mutable double m_timeStamp; + + friend class EventNode; + friend class Document; + }; // - // It seems dangerous to allow events with no sender and blank name - // (caused a crash in one corner case), so for now we disallow all such - // events. + // For debugging purposes. // - //Event() : m_name(""), m_sender(0) {} - Event(const std::string& name, const EventNode *sender, void* data = 0) - : m_name(name), - m_sender(sender), - m_data(data), - m_table(0), - handled(false) {} + inline std::ostream& operator<<(std::ostream& o, const Event& e) + { + e.output(o); + return o; + } + + //---------------------------------------------------------------------- + /// + /// RenderEvent + /// + /// A RenderEvent does not necessarily correspond to a device, but + /// can be generated in order to allow binding a function for + /// rendering. + /// + /// The additional string field is meant to provide context if any is + /// needed. + /// + + class RenderEvent : public Event + { + public: + // RenderEvent() : Event() {} + RenderEvent(const std::string& name, const EventNode* sender, int w, + int h, void* data = 0) + : m_w(w) + , m_h(h) + , m_device(0) + , Event(name, sender, data) + { + } + + RenderEvent(const std::string& name, const EventNode* sender, int w, + int h, const std::string& contents, void* data = 0) + : m_w(w) + , m_h(h) + , m_device(0) + , m_stringContent(contents) + , Event(name, sender, data) + { + } + + RenderEvent(const std::string& name, const EventNode* sender, + const VideoDevice* device, int w, int h, void* data = 0) + : m_w(w) + , m_h(h) + , m_device(device) + , Event(name, sender, data) + { + } + + RenderEvent(const std::string& name, const EventNode* sender, + const VideoDevice* device, int w, int h, + const std::string& contents, void* data = 0) + : m_w(w) + , m_h(h) + , m_device(device) + , m_stringContent(contents) + , Event(name, sender, data) + { + } + + int w() const { return m_w; } + + int h() const { return m_h; } + + const VideoDevice* device() const { return m_device; } + + const std::string& stringContent() const { return m_stringContent; } + + private: + int m_w; + int m_h; + std::string m_stringContent; + const VideoDevice* m_device; + }; - const std::string& name() const { return m_name; } - const EventNode* sender() const { return m_sender; } - const EventTable* eventTable() const { return m_table; } - - virtual void output(std::ostream&) const; - void* data() const { return m_data; } + //---------------------------------------------------------------------- + /// + /// RenderContextChangeEvent + /// + /// Sent if a render context is about to change. + /// - double timeStamp() const { return m_timeStamp; } + class RenderContextChangeEvent : public Event + { + public: + // RenderContextChangeEvent() : Event() {} + RenderContextChangeEvent(const std::string& name, + const EventNode* sender, void* data = 0) + : Event(name, sender, data) + { + } + }; - mutable bool handled; + //---------------------------------------------------------------------- + /// + /// VideoDeviceContextChangeEvent + /// + /// Sent if a physical device associated with another device + /// changes. E.g. if a GL video device (window) is moved from one + /// monitor (physical device) to another. + /// - private: - std::string m_name; - const EventNode* m_sender; - void* m_data; - mutable const EventTable* m_table; - mutable double m_timeStamp; + class VideoDeviceContextChangeEvent : public Event + { + public: + // VideoDeviceContextChangeEvent() : Event() {} + VideoDeviceContextChangeEvent(const std::string& name, + const EventNode* sender, + const VideoDevice* device, + const VideoDevice* physicalDevice, + void* data = 0) + : Event(name, sender, data) + , m_device(device) + , m_physicalDevice(physicalDevice) + { + } + + const VideoDevice* m_device; + const VideoDevice* m_physicalDevice; + }; - friend class EventNode; - friend class Document; -}; + //---------------------------------------------------------------------- + /// + /// ActivityChangeEvent + /// + /// User activity level changed + /// -// -// For debugging purposes. -// + class ActivityChangeEvent : public Event + { + public: + // ActivityChangeEvent() : Event() {} + ActivityChangeEvent(const std::string& name, const EventNode* sender, + void* data = 0) + : Event(name, sender, data) + { + } + }; -inline std::ostream& operator << (std::ostream& o, const Event& e) -{ - e.output(o); - return o; -} - - -//---------------------------------------------------------------------- -/// -/// RenderEvent -/// -/// A RenderEvent does not necessarily correspond to a device, but -/// can be generated in order to allow binding a function for -/// rendering. -/// -/// The additional string field is meant to provide context if any is -/// needed. -/// - -class RenderEvent : public Event -{ - public: - //RenderEvent() : Event() {} - RenderEvent(const std::string& name, - const EventNode* sender, - int w, - int h, - void* data=0) - : m_w(w), - m_h(h), - m_device(0), - Event(name, sender, data) {} - - RenderEvent(const std::string& name, - const EventNode* sender, - int w, - int h, - const std::string& contents, - void* data=0) - : m_w(w), - m_h(h), - m_device(0), - m_stringContent(contents), - Event(name, sender, data) {} - - RenderEvent(const std::string& name, - const EventNode* sender, - const VideoDevice* device, - int w, - int h, - void* data=0) - : m_w(w), - m_h(h), - m_device(device), - Event(name, sender, data) {} - - RenderEvent(const std::string& name, - const EventNode* sender, - const VideoDevice* device, - int w, - int h, - const std::string& contents, - void* data=0) - : m_w(w), - m_h(h), - m_device(device), - m_stringContent(contents), - Event(name, sender, data) {} - - int w() const { return m_w; } - int h() const { return m_h; } - const VideoDevice* device() const { return m_device; } - - const std::string& stringContent() const { return m_stringContent; } - - private: - int m_w; - int m_h; - std::string m_stringContent; - const VideoDevice* m_device; -}; - - -//---------------------------------------------------------------------- -/// -/// RenderContextChangeEvent -/// -/// Sent if a render context is about to change. -/// - -class RenderContextChangeEvent : public Event -{ - public: - //RenderContextChangeEvent() : Event() {} - RenderContextChangeEvent(const std::string& name, - const EventNode* sender, - void* data=0) - : Event(name, sender, data) {} -}; - -//---------------------------------------------------------------------- -/// -/// VideoDeviceContextChangeEvent -/// -/// Sent if a physical device associated with another device -/// changes. E.g. if a GL video device (window) is moved from one -/// monitor (physical device) to another. -/// - -class VideoDeviceContextChangeEvent : public Event -{ - public: - //VideoDeviceContextChangeEvent() : Event() {} - VideoDeviceContextChangeEvent(const std::string& name, - const EventNode* sender, - const VideoDevice* device, - const VideoDevice* physicalDevice, - void* data=0) - : Event(name, sender, data), - m_device(device), - m_physicalDevice(physicalDevice) {} - - const VideoDevice* m_device; - const VideoDevice* m_physicalDevice; -}; - -//---------------------------------------------------------------------- -/// -/// ActivityChangeEvent -/// -/// User activity level changed -/// - -class ActivityChangeEvent : public Event -{ - public: - //ActivityChangeEvent() : Event() {} - ActivityChangeEvent(const std::string& name, - const EventNode* sender, - void* data=0) - : Event(name, sender, data) {} -}; - - -//---------------------------------------------------------------------- -/// -/// ModifierEvent -/// -/// A ModifierEvent is a base class which holds the state of modifers -/// for Key and Mouse events (amoung others). -/// - -class ModifierEvent : public Event -{ - public: + //---------------------------------------------------------------------- + /// + /// ModifierEvent + /// + /// A ModifierEvent is a base class which holds the state of modifers + /// for Key and Mouse events (amoung others). + /// - enum Modifier + class ModifierEvent : public Event { - None = 0, - Shift = 1 << 0, - Control = 1 << 1, - Alt = 1 << 2, - Meta = 1 << 3, - Super = 1 << 4, - CapLock = 1 << 5, - NumLock = 1 << 6, - ScrollLock = 1 << 7 + public: + enum Modifier + { + None = 0, + Shift = 1 << 0, + Control = 1 << 1, + Alt = 1 << 2, + Meta = 1 << 3, + Super = 1 << 4, + CapLock = 1 << 5, + NumLock = 1 << 6, + ScrollLock = 1 << 7 + }; + + // ModifierEvent() : Event(), m_modifiers(0) {} + + ModifierEvent(const std::string& name, const EventNode* sender, + unsigned int modifiers, void* data = 0) + : Event(name, sender, data) + , m_modifiers(modifiers) + { + } + + bool modifierState(Modifier m) const + { + return (unsigned int)m & m_modifiers; + } + + unsigned int modifiers() const { return m_modifiers; } + + virtual void output(std::ostream&) const; + + private: + unsigned int m_modifiers; }; - //ModifierEvent() : Event(), m_modifiers(0) {} + //---------------------------------------------------------------------- + /// + /// KeyEvent is a base class for Key press and release events. + /// - ModifierEvent(const std::string& name, - const EventNode* sender, - unsigned int modifiers, - void* data=0) - : Event(name, sender, data), m_modifiers(modifiers) {} + class KeyEvent : public ModifierEvent + { + public: + KeyEvent(const std::string& name, const EventNode* sender, + unsigned int key, unsigned int modifiers, void* data = 0) + : ModifierEvent(name, sender, modifiers, data) + , m_key(key) + { + } - bool modifierState(Modifier m) const - { return (unsigned int)m & m_modifiers; } + unsigned int key() const { return m_key; } - unsigned int modifiers() const { return m_modifiers; } + virtual void output(std::ostream&) const; - virtual void output(std::ostream&) const; + private: + unsigned int m_key; + }; - private: - unsigned int m_modifiers; -}; + //---------------------------------------------------------------------- + /// + /// KeyPressEvent / KeyReleaseEvent + /// + /// These events correspond to the press and release of a key. The + /// information returned is the same for each. Note that the modifiers + /// can change between KeyPress and KeyRelease. + /// -//---------------------------------------------------------------------- -/// -/// KeyEvent is a base class for Key press and release events. -/// + class KeyPressEvent : public KeyEvent + { + public: + KeyPressEvent(const std::string& name, const EventNode* sender, + unsigned int key, unsigned int modifiers, void* data = 0) + : KeyEvent(name, sender, key, modifiers, data) + { + } + }; -class KeyEvent : public ModifierEvent -{ - public: - KeyEvent(const std::string& name, const EventNode *sender, - unsigned int key, unsigned int modifiers, void* data=0) - : ModifierEvent(name, sender, modifiers, data), m_key(key) {} + class KeyReleaseEvent : public KeyEvent + { + public: + KeyReleaseEvent(const std::string& name, const EventNode* sender, + unsigned int key, unsigned int modifiers, + void* data = 0) + : KeyEvent(name, sender, key, modifiers, data) + { + } + }; - unsigned int key() const { return m_key; } + //---------------------------------------------------------------------- + /// + /// PointerEvent + /// + /// Your basic mouse/touchpad/trackball event. The event includes the + /// domain -- the values which the pointer can legally have. The event + /// will be sent anytime the pointer position changes. When a button + /// press/release event occurs the sub-class PointerButtonPressEvent + /// and PointerButtonReleaseEvent will be sent instead. Note that this + /// even has the button state information already present. + /// + + class PointerEvent : public ModifierEvent + { + public: + // PointerEvent() : ModifierEvent(), + // m_x(0), m_y(0), m_w(0), m_h(0), m_px(0), m_py(0), + // m_buttonStates(0) {} + + PointerEvent(const std::string& name, const EventNode* sender, + unsigned int modifiers, int x, int y, /// position + int w, int h, /// size of domain + int ox, int oy, /// "push" values + unsigned int buttonStates, void* data = 0) + : ModifierEvent(name, sender, modifiers, data) + , m_x(x) + , m_y(y) + , m_w(w) + , m_h(h) + , m_px(ox) + , m_py(oy) + , m_buttonStates(buttonStates) + { + } + + int x() const { return m_x; } + + int y() const { return m_y; } + + int w() const { return m_w; } + + int h() const { return m_h; } + + int startX() const { return m_px; } + + int startY() const { return m_py; } + + unsigned int buttonStates() const { return m_buttonStates; } + + virtual void output(std::ostream&) const; + + private: + int m_x; + int m_y; + int m_w; + int m_h; + int m_px; + int m_py; + unsigned int m_buttonStates; + }; - virtual void output(std::ostream&) const; + //---------------------------------------------------------------------- + /// + /// PointerButtonPressEvent + /// + /// This event corresponds to a button on a mouse-like device being + /// pressed. + /// - private: - unsigned int m_key; -}; + class PointerButtonPressEvent : public PointerEvent + { + public: + PointerButtonPressEvent(const std::string& name, + const EventNode* sender, unsigned int modifiers, + int x, int y, int w, int h, int ox, int oy, + unsigned int buttonStates, void* data = 0, + float aTime = 0.0) + : PointerEvent(name, sender, modifiers, x, y, w, h, ox, oy, + buttonStates, data) + , m_activationTime(aTime) + { + } + + float activationTime() const { return m_activationTime; } + + private: + float m_activationTime; + }; -//---------------------------------------------------------------------- -/// -/// KeyPressEvent / KeyReleaseEvent -/// -/// These events correspond to the press and release of a key. The -/// information returned is the same for each. Note that the modifiers -/// can change between KeyPress and KeyRelease. -/// + //---------------------------------------------------------------------- + /// + /// PointerButtonReleaseEvent + /// + /// This event corresponds to a button on a mouse-like device being + /// released. + /// -class KeyPressEvent : public KeyEvent -{ - public: - KeyPressEvent(const std::string& name, const EventNode* sender, - unsigned int key, unsigned int modifiers, void* data=0) - : KeyEvent(name,sender,key,modifiers,data) {} -}; + class PointerButtonReleaseEvent : public PointerEvent + { + public: + PointerButtonReleaseEvent(const std::string& name, + const EventNode* sender, + unsigned int modifiers, int x, int y, int w, + int h, int ox, int oy, + unsigned int buttonStates, void* data = 0) + : PointerEvent(name, sender, modifiers, x, y, w, h, ox, oy, + buttonStates, data) + { + } + }; -class KeyReleaseEvent : public KeyEvent -{ - public: - KeyReleaseEvent(const std::string& name, const EventNode* sender, - unsigned int key, unsigned int modifiers, void* data=0) - : KeyEvent(name,sender,key,modifiers,data) {} -}; - -//---------------------------------------------------------------------- -/// -/// PointerEvent -/// -/// Your basic mouse/touchpad/trackball event. The event includes the -/// domain -- the values which the pointer can legally have. The event -/// will be sent anytime the pointer position changes. When a button -/// press/release event occurs the sub-class PointerButtonPressEvent -/// and PointerButtonReleaseEvent will be sent instead. Note that this -/// even has the button state information already present. -/// - -class PointerEvent : public ModifierEvent -{ - public: - //PointerEvent() : ModifierEvent(), - // m_x(0), m_y(0), m_w(0), m_h(0), m_px(0), m_py(0), - // m_buttonStates(0) {} - - PointerEvent(const std::string& name, - const EventNode* sender, - unsigned int modifiers, - int x, int y, /// position - int w, int h, /// size of domain - int ox, int oy, /// "push" values - unsigned int buttonStates, - void* data=0) - : ModifierEvent(name, sender, modifiers, data), - m_x(x), m_y(y), m_w(w), m_h(h), m_px(ox), m_py(oy), - m_buttonStates(buttonStates) {} - - int x() const { return m_x; } - int y() const { return m_y; } - int w() const { return m_w; } - int h() const { return m_h; } - int startX() const { return m_px; } - int startY() const { return m_py; } - unsigned int buttonStates() const { return m_buttonStates; } - - virtual void output(std::ostream&) const; - - private: - int m_x; - int m_y; - int m_w; - int m_h; - int m_px; - int m_py; - unsigned int m_buttonStates; -}; - -//---------------------------------------------------------------------- -/// -/// PointerButtonPressEvent -/// -/// This event corresponds to a button on a mouse-like device being -/// pressed. -/// - -class PointerButtonPressEvent : public PointerEvent -{ - public: - PointerButtonPressEvent(const std::string& name, - const EventNode *sender, - unsigned int modifiers, - int x, int y, - int w, int h, - int ox, int oy, - unsigned int buttonStates, - void* data=0, - float aTime=0.0) - : PointerEvent(name, sender, modifiers, - x, y, w, h, ox, oy, - buttonStates, data), m_activationTime(aTime) {} - - float activationTime() const { return m_activationTime; } - - private: - float m_activationTime; -}; - -//---------------------------------------------------------------------- -/// -/// PointerButtonReleaseEvent -/// -/// This event corresponds to a button on a mouse-like device being -/// released. -/// - -class PointerButtonReleaseEvent : public PointerEvent -{ - public: - PointerButtonReleaseEvent(const std::string& name, - const EventNode *sender, - unsigned int modifiers, - int x, int y, - int w, int h, - int ox, int oy, - unsigned int buttonStates, - void* data=0) - : PointerEvent(name, sender, modifiers, - x, y, w, h, ox, oy, - buttonStates, data) {} -}; - - -//---------------------------------------------------------------------- -/// -/// DragAndDropEvent -/// -/// This event series is sent when a drag 'n drop is occuring. Its -/// similar to a PointerEvent. The contents are currently limited to a -/// string because of FLTK's limited ability to deal with the XDnD -/// protocol. On the Mac, filename's etc may appear as contents. -/// - -class DragDropEvent : public PointerEvent -{ - public: - - enum Type { Enter, Leave, Move, Release }; - enum ContentType { File, URL, Text }; - - //DragDropEvent() : PointerEvent() {} - - DragDropEvent(const std::string& name, - const EventNode* sender, - Type type, - ContentType ctype, - const std::string& content, - unsigned int modifiers, - int x, int y, /// position - int w, int h, /// size of domain - int ox=-1, int oy=-1, - void* data=0) /// "push" values if any - : PointerEvent(name, sender, modifiers, - x, y, w, h, ox, oy, 0, data), - m_type(type), - m_contentType(ctype), - m_stringContent(content) {} - - DragDropEvent(const std::string& name, - const EventNode* sender, - Type type, - ContentType ctype, - unsigned int modifiers, - int x, int y, /// position - int w, int h, /// size of domain - int ox=-1, int oy=-1, - void* data=0) /// "push" values if any - : PointerEvent(name, sender, modifiers, - x, y, w, h, ox, oy, 0, data), - m_type(type), - m_contentType(ctype) {} - - Type type() const { return m_type; } - ContentType contentType() const { return m_contentType; } - - void setStringContent(const std::string& s) { m_stringContent = s; } - const std::string& stringContent() const { return m_stringContent; } - - private: - Type m_type; - ContentType m_contentType; - std::string m_stringContent; -}; - - -//---------------------------------------------------------------------- -/// -/// GenericStringEvent -/// -/// A way to send a single string as an event. This event can also have a -/// return string value. -/// -/// The stringContentVector() was added later to add additional -/// information without causing existing code to break. If you set -/// the contents vector, the first argument should be the same value -/// as the stringContent(). -/// - -class GenericStringEvent : public Event -{ - public: - //GenericStringEvent() : Event() {} - - GenericStringEvent(const std::string& name, - const EventNode* sender, - const std::string& content, - void* data=0) - : Event(name, sender, data), - m_stringContent(content) {} - - GenericStringEvent(const std::string& name, - const EventNode* sender, - const std::string& content, - const std::string& senderName, - void* data=0) - : Event(name, sender, data), - m_stringContent(content), - m_senderName(senderName) {} - - void setStringContent(const std::string& s) { m_stringContent = s; } - const std::string& stringContent() const { return m_stringContent; } - - void setStringContentVector(const StringVector& sv) { m_stringContentVector = sv; } - const StringVector& stringContentVector() const { return m_stringContentVector; } - - void setReturnContent(const std::string& s) const { m_returnContent = s; } - const std::string& returnContent() const { return m_returnContent; } - - void setSenderName(const std::string& s) { m_senderName = s; } - const std::string& senderName() const { return m_senderName; } - - private: - std::string m_stringContent; - std::string m_senderName; - StringVector m_stringContentVector; - mutable std::string m_returnContent; -}; - -///---------------------------------------------------------------------- -/// -/// PixelBlockTransferEvent -/// -/// Sends a block of pixels (which may be a whole image). Information -/// about the rest of the image (its actual size, channels, etc) -/// should already be known by the receiver. -/// - -class PixelBlockTransferEvent : public Event -{ - public: - //PixelBlockTransferEvent() : Event() {} - - PixelBlockTransferEvent(const std::string& name, - const EventNode* sender, - const std::string& media, - const std::string& layer, - const std::string& view, - int frame, - int x, int y, size_t w, size_t h, - const void* pixels, - size_t size, - void* data) - : Event(name, sender, data), - m_media(media), m_layer(layer), m_view(view), - m_x(x), m_y(y), m_w(w), m_h(h), - m_frame(frame), - m_pixels(pixels), - m_size(size) {} - - int x() const { return m_x; } - int y() const { return m_y; } - size_t width() const { return m_w; } - size_t height() const { return m_h; } - int frame() const { return m_frame; } - const std::string& media() const { return m_media; } - const std::string& layer() const { return m_layer; } - const std::string& view() const { return m_view; } - const void* pixels() const { return m_pixels; } - size_t size() const { return m_size; } - - private: - std::string m_media; - std::string m_layer; - std::string m_view; - const void* m_pixels; - size_t m_size; - int m_x; - int m_y; - size_t m_w; - size_t m_h; - int m_frame; -}; - -//---------------------------------------------------------------------- -/// -/// RawDataEvent -/// -/// An event holding -/// - -class RawDataEvent : public Event -{ - public: - //RawDataEvent() : Event() {} - - RawDataEvent(const std::string& name, - const EventNode* sender, - const std::string& contentType, - const char* rawData, - size_t size, - const char* utf8=0, - void* data=0, // this is the base class "data" - const std::string& senderName="") - : Event(name, sender, data), - m_type(contentType), - m_rawData(rawData), - m_size(size), - m_utf8(utf8), - m_senderName(senderName) {} - - const char* rawData() const { return m_rawData; } - size_t rawDataSize() const { return m_size; } - const char* utf8() const { return m_utf8; } - const std::string& contentType() const { return m_type; } - - void setSenderName(const std::string& s) { m_senderName = s; } - const std::string& senderName() const { return m_senderName; } - - void setReturnContent(const std::string& s) const { m_returnContent = s; } - const std::string& returnContent() const { return m_returnContent; } - - - private: - const char* m_utf8; - const char* m_rawData; - size_t m_size; - std::string m_type; - std::string m_senderName; - mutable std::string m_returnContent; -}; - -///---------------------------------------------------------------------- -/// -/// Tablet Event -/// - -class TabletEvent : public PointerEvent -{ - public: + //---------------------------------------------------------------------- + /// + /// DragAndDropEvent + /// + /// This event series is sent when a drag 'n drop is occuring. Its + /// similar to a PointerEvent. The contents are currently limited to a + /// string because of FLTK's limited ability to deal with the XDnD + /// protocol. On the Mac, filename's etc may appear as contents. + /// + + class DragDropEvent : public PointerEvent + { + public: + enum Type + { + Enter, + Leave, + Move, + Release + }; + + enum ContentType + { + File, + URL, + Text + }; + + // DragDropEvent() : PointerEvent() {} + + DragDropEvent(const std::string& name, const EventNode* sender, + Type type, ContentType ctype, const std::string& content, + unsigned int modifiers, int x, int y, /// position + int w, int h, /// size of domain + int ox = -1, int oy = -1, + void* data = 0) /// "push" values if any + : PointerEvent(name, sender, modifiers, x, y, w, h, ox, oy, 0, data) + , m_type(type) + , m_contentType(ctype) + , m_stringContent(content) + { + } + + DragDropEvent(const std::string& name, const EventNode* sender, + Type type, ContentType ctype, unsigned int modifiers, + int x, int y, /// position + int w, int h, /// size of domain + int ox = -1, int oy = -1, + void* data = 0) /// "push" values if any + : PointerEvent(name, sender, modifiers, x, y, w, h, ox, oy, 0, data) + , m_type(type) + , m_contentType(ctype) + { + } + + Type type() const { return m_type; } + + ContentType contentType() const { return m_contentType; } + + void setStringContent(const std::string& s) { m_stringContent = s; } + + const std::string& stringContent() const { return m_stringContent; } + + private: + Type m_type; + ContentType m_contentType; + std::string m_stringContent; + }; - enum TabletKind + //---------------------------------------------------------------------- + /// + /// GenericStringEvent + /// + /// A way to send a single string as an event. This event can also have a + /// return string value. + /// + /// The stringContentVector() was added later to add additional + /// information without causing existing code to break. If you set + /// the contents vector, the first argument should be the same value + /// as the stringContent(). + /// + + class GenericStringEvent : public Event { - UnknownTabletKind, - PenKind, - CursorKind, - EraserKind + public: + // GenericStringEvent() : Event() {} + + GenericStringEvent(const std::string& name, const EventNode* sender, + const std::string& content, void* data = 0) + : Event(name, sender, data) + , m_stringContent(content) + { + } + + GenericStringEvent(const std::string& name, const EventNode* sender, + const std::string& content, + const std::string& senderName, void* data = 0) + : Event(name, sender, data) + , m_stringContent(content) + , m_senderName(senderName) + { + } + + void setStringContent(const std::string& s) { m_stringContent = s; } + + const std::string& stringContent() const { return m_stringContent; } + + void setStringContentVector(const StringVector& sv) + { + m_stringContentVector = sv; + } + + const StringVector& stringContentVector() const + { + return m_stringContentVector; + } + + void setReturnContent(const std::string& s) const + { + m_returnContent = s; + } + + const std::string& returnContent() const { return m_returnContent; } + + void setSenderName(const std::string& s) { m_senderName = s; } + + const std::string& senderName() const { return m_senderName; } + + private: + std::string m_stringContent; + std::string m_senderName; + StringVector m_stringContentVector; + mutable std::string m_returnContent; }; - enum TabletDevice + ///---------------------------------------------------------------------- + /// + /// PixelBlockTransferEvent + /// + /// Sends a block of pixels (which may be a whole image). Information + /// about the rest of the image (its actual size, channels, etc) + /// should already be known by the receiver. + /// + + class PixelBlockTransferEvent : public Event + { + public: + // PixelBlockTransferEvent() : Event() {} + + PixelBlockTransferEvent(const std::string& name, + const EventNode* sender, + const std::string& media, + const std::string& layer, + const std::string& view, int frame, int x, + int y, size_t w, size_t h, const void* pixels, + size_t size, void* data) + : Event(name, sender, data) + , m_media(media) + , m_layer(layer) + , m_view(view) + , m_x(x) + , m_y(y) + , m_w(w) + , m_h(h) + , m_frame(frame) + , m_pixels(pixels) + , m_size(size) + { + } + + int x() const { return m_x; } + + int y() const { return m_y; } + + size_t width() const { return m_w; } + + size_t height() const { return m_h; } + + int frame() const { return m_frame; } + + const std::string& media() const { return m_media; } + + const std::string& layer() const { return m_layer; } + + const std::string& view() const { return m_view; } + + const void* pixels() const { return m_pixels; } + + size_t size() const { return m_size; } + + private: + std::string m_media; + std::string m_layer; + std::string m_view; + const void* m_pixels; + size_t m_size; + int m_x; + int m_y; + size_t m_w; + size_t m_h; + int m_frame; + }; + + //---------------------------------------------------------------------- + /// + /// RawDataEvent + /// + /// An event holding + /// + + class RawDataEvent : public Event + { + public: + // RawDataEvent() : Event() {} + + RawDataEvent(const std::string& name, const EventNode* sender, + const std::string& contentType, const char* rawData, + size_t size, const char* utf8 = 0, + void* data = 0, // this is the base class "data" + const std::string& senderName = "") + : Event(name, sender, data) + , m_type(contentType) + , m_rawData(rawData) + , m_size(size) + , m_utf8(utf8) + , m_senderName(senderName) + { + } + + const char* rawData() const { return m_rawData; } + + size_t rawDataSize() const { return m_size; } + + const char* utf8() const { return m_utf8; } + + const std::string& contentType() const { return m_type; } + + void setSenderName(const std::string& s) { m_senderName = s; } + + const std::string& senderName() const { return m_senderName; } + + void setReturnContent(const std::string& s) const + { + m_returnContent = s; + } + + const std::string& returnContent() const { return m_returnContent; } + + private: + const char* m_utf8; + const char* m_rawData; + size_t m_size; + std::string m_type; + std::string m_senderName; + mutable std::string m_returnContent; + }; + + ///---------------------------------------------------------------------- + /// + /// Tablet Event + /// + + class TabletEvent : public PointerEvent { - NoTableDevice, - PuckDevice, - StylusDevice, - AirBrushDevice, - FourDMouseDevice, - RotationStylusDevice + public: + enum TabletKind + { + UnknownTabletKind, + PenKind, + CursorKind, + EraserKind + }; + + enum TabletDevice + { + NoTableDevice, + PuckDevice, + StylusDevice, + AirBrushDevice, + FourDMouseDevice, + RotationStylusDevice + }; + + TabletEvent(const std::string& name, const EventNode* sender, + unsigned int modifiers, int x, int y, int w, int h, int ox, + int oy, unsigned int buttonStates, TabletKind kind, + TabletDevice device, double gx, double gy, double pres, + double tpres, double rot, int xtilt, int ytilt, int z = 0, + void* data = 0) + : PointerEvent(name, sender, modifiers, x, y, w, h, ox, oy, + buttonStates, data) + , _kind(kind) + , _device(device) + , _xFloat(gx) + , _yFloat(gy) + , _pressure(pres) + , _tangentialPressure(tpres) + , _rotation(rot) + , _xTilt(xtilt) + , _yTilt(ytilt) + , _z(z) + { + } + + double gx() const { return _xFloat; } + + double gy() const { return _yFloat; } + + double pressure() const { return _pressure; } + + double tangentialPressure() const { return _tangentialPressure; } + + double rotation() const { return _rotation; } + + int xTilt() const { return _xTilt; } + + int yTilt() const { return _yTilt; } + + int z() const { return _z; } + + private: + TabletKind _kind; + TabletDevice _device; + double _xFloat; + double _yFloat; + double _pressure; + double _rotation; + double _tangentialPressure; + int _xTilt; + int _yTilt; + int _z; }; - TabletEvent(const std::string& name, - const EventNode *sender, - unsigned int modifiers, - int x, int y, - int w, int h, - int ox, int oy, - unsigned int buttonStates, - TabletKind kind, - TabletDevice device, - double gx, double gy, - double pres, double tpres, - double rot, - int xtilt, int ytilt, - int z = 0, - void* data=0) - : PointerEvent(name, sender, modifiers, - x, y, w, h, ox, oy, - buttonStates, data), - _kind(kind), _device(device), - _xFloat(gx), _yFloat(gy), - _pressure(pres), _tangentialPressure(tpres), - _rotation(rot), _xTilt(xtilt), _yTilt(ytilt), - _z(z) {} - - double gx() const { return _xFloat; } - double gy() const { return _yFloat; } - double pressure() const { return _pressure; } - double tangentialPressure() const { return _tangentialPressure; } - double rotation() const { return _rotation; } - int xTilt() const { return _xTilt; } - int yTilt() const { return _yTilt; } - int z() const { return _z; } - - private: - TabletKind _kind; - TabletDevice _device; - double _xFloat; - double _yFloat; - double _pressure; - double _rotation; - double _tangentialPressure; - int _xTilt; - int _yTilt; - int _z; -}; - -} // TwkApp +} // namespace TwkApp #endif // __TwkApp__Event__h__ diff --git a/src/lib/app/TwkApp/TwkApp/EventNode.h b/src/lib/app/TwkApp/TwkApp/EventNode.h index a70dc7d7e..8f4927433 100644 --- a/src/lib/app/TwkApp/TwkApp/EventNode.h +++ b/src/lib/app/TwkApp/TwkApp/EventNode.h @@ -1,9 +1,9 @@ //****************************************************************************** -// Copyright (c) 2002 Tweak Inc. +// Copyright (c) 2002 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #ifndef __TwkApp__EventNode__h__ #define __TwkApp__EventNode__h__ @@ -12,89 +12,90 @@ #include #include -namespace TwkApp { - -/// -/// class EventNode -/// -/// This class holds an EventTable object in which events can be bound. -/// - -class EventNode +namespace TwkApp { -public: - typedef std::vector EventNodes; - typedef TwkUtil::Timer Timer; - enum Result + /// + /// class EventNode + /// + /// This class holds an EventTable object in which events can be bound. + /// + + class EventNode { - EventAccept, - EventAcceptAndContinue, - EventIgnored, - Error - }; + public: + typedef std::vector EventNodes; + typedef TwkUtil::Timer Timer; + + enum Result + { + EventAccept, + EventAcceptAndContinue, + EventIgnored, + Error + }; - EventNode(const char* name); - virtual ~EventNode(); + EventNode(const char* name); + virtual ~EventNode(); - const std::string& name() const { return m_name; } - void setEventNodeName(std::string n) { m_name = n; } + const std::string& name() const { return m_name; } - // - // The event propagation tree is constructed by listening to - // events from another EventNode. - // + void setEventNodeName(std::string n) { m_name = n; } - virtual void listenTo(EventNode*); + // + // The event propagation tree is constructed by listening to + // events from another EventNode. + // - // - // Events are propagated along the EventNode tree. The entry - // point is sendEvent(). Typically, the Event object will be - // created on the stack and passed to sendEvent(). You should - // call this function around a try{} block. - // + virtual void listenTo(EventNode*); - virtual Result sendEvent(const Event&); + // + // Events are propagated along the EventNode tree. The entry + // point is sendEvent(). Typically, the Event object will be + // created on the stack and passed to sendEvent(). You should + // call this function around a try{} block. + // - // - // If your node wishes to receive an events, override this - // function. This function should return true if the event - // propagation along the tree should be terminated (eaten) by - // receiver. Its ok to throw out of here. - // + virtual Result sendEvent(const Event&); - virtual Result receiveEvent(const Event&); + // + // If your node wishes to receive an events, override this + // function. This function should return true if the event + // propagation along the tree should be terminated (eaten) by + // receiver. Its ok to throw out of here. + // - // - // Breaks all connections with the node - // + virtual Result receiveEvent(const Event&); - virtual void breakConnection(EventNode*); + // + // Breaks all connections with the node + // - // - // Each EventNode has a timer. When events are sent from an - // EventNode, they receive a time stamp indicating when the - // event was sent relative to the creation of the EventNode - // + virtual void breakConnection(EventNode*); - const Timer& timer() const { return m_timer; } + // + // Each EventNode has a timer. When events are sent from an + // EventNode, they receive a time stamp indicating when the + // event was sent relative to the creation of the EventNode + // -protected: + const Timer& timer() const { return m_timer; } - // - // Event propagation occurs via propogateEvent(). This function - // is called by sendEvent() at the event source. - // + protected: + // + // Event propagation occurs via propogateEvent(). This function + // is called by sendEvent() at the event source. + // - virtual Result propagateEvent(const Event&); + virtual Result propagateEvent(const Event&); -private: - std::string m_name; - EventNodes m_listeners; - EventNodes m_senders; - static Timer m_timer; -}; + private: + std::string m_name; + EventNodes m_listeners; + EventNodes m_senders; + static Timer m_timer; + }; -} // TwkApp +} // namespace TwkApp #endif // __TwkApp__EventNode__h__ diff --git a/src/lib/app/TwkApp/TwkApp/EventTable.h b/src/lib/app/TwkApp/TwkApp/EventTable.h index 9a8657454..f90e0e561 100644 --- a/src/lib/app/TwkApp/TwkApp/EventTable.h +++ b/src/lib/app/TwkApp/TwkApp/EventTable.h @@ -1,9 +1,9 @@ //****************************************************************************** -// Copyright (c) 2002 Tweak Inc. +// Copyright (c) 2002 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #ifndef __TwkApp__EventTable__h__ #define __TwkApp__EventTable__h__ @@ -15,106 +15,116 @@ #include #include -namespace TwkApp { -class Mode; +namespace TwkApp +{ + class Mode; -/// -/// class EventTable -/// -/// Maps string event names with actions. -/// + /// + /// class EventTable + /// + /// Maps string event names with actions. + /// -class EventTable -{ -public: - // - // Types - // - - typedef std::map BindingMap; - typedef BindingMap::value_type Binding; - typedef TwkUtil::RegEx RegEx; - typedef std::pair RegExBinding; - typedef std::vector RegExBindings; - typedef TwkMath::Vec2i Vec2i; - typedef TwkMath::Box2i Box2i; - - // - // Constructors - // - - EventTable(const std::string&); - EventTable(const char *name); - ~EventTable(); - - const std::string& name() const { return m_name; } - - // - // Bind an event name to an action. Once you bind the action, it - // is owned by the EventTable. If the binding conflicts with an - // existing binding, it will replace it. - // - // While you can use regular expressions with bindRegex(), it can - // become a performance impairment if too many of them are - // needed. In addition, the order in which the regular - // expressions are added is the order in which they are matched; so - // - - void bind(const std::string& event, Action* action); - void bindRegex(const std::string& eventRegex, Action* action); - - // - // Completely remove the binding for event -- deletes the actions - // - - void unbind(const std::string& event); - void unbindRegex(const std::string& eventRegex); - - // - // ROI - // - - void setBBox(const Box2i& box) { m_bbox = box; } - const Box2i& bbox() const { return m_bbox; } - - // - // Unbinds all events -- deleting the actions - // - - void clear(); - - // - // Find the action for the event (if it exists) - // - - const Action* query(const std::string&) const; - - // - // Iterators - // - - BindingMap::const_iterator begin() const { return m_map.begin(); } - BindingMap::const_iterator end() const { return m_map.end(); } - - RegExBindings::const_iterator beginRegex() const {return m_reBindings.begin();} - RegExBindings::const_iterator endRegex() const { return m_reBindings.end(); } - - // - // Mode access - // - - const Mode* mode() const { return m_mode; } - -private: - std::string m_name; - BindingMap m_map; - RegExBindings m_reBindings; - Box2i m_bbox; - Mode* m_mode; - - friend class Mode; -}; - -} // TwkApp + class EventTable + { + public: + // + // Types + // + + typedef std::map BindingMap; + typedef BindingMap::value_type Binding; + typedef TwkUtil::RegEx RegEx; + typedef std::pair RegExBinding; + typedef std::vector RegExBindings; + typedef TwkMath::Vec2i Vec2i; + typedef TwkMath::Box2i Box2i; + + // + // Constructors + // + + EventTable(const std::string&); + EventTable(const char* name); + ~EventTable(); + + const std::string& name() const { return m_name; } + + // + // Bind an event name to an action. Once you bind the action, it + // is owned by the EventTable. If the binding conflicts with an + // existing binding, it will replace it. + // + // While you can use regular expressions with bindRegex(), it can + // become a performance impairment if too many of them are + // needed. In addition, the order in which the regular + // expressions are added is the order in which they are matched; so + // + + void bind(const std::string& event, Action* action); + void bindRegex(const std::string& eventRegex, Action* action); + + // + // Completely remove the binding for event -- deletes the actions + // + + void unbind(const std::string& event); + void unbindRegex(const std::string& eventRegex); + + // + // ROI + // + + void setBBox(const Box2i& box) { m_bbox = box; } + + const Box2i& bbox() const { return m_bbox; } + + // + // Unbinds all events -- deleting the actions + // + + void clear(); + + // + // Find the action for the event (if it exists) + // + + const Action* query(const std::string&) const; + + // + // Iterators + // + + BindingMap::const_iterator begin() const { return m_map.begin(); } + + BindingMap::const_iterator end() const { return m_map.end(); } + + RegExBindings::const_iterator beginRegex() const + { + return m_reBindings.begin(); + } + + RegExBindings::const_iterator endRegex() const + { + return m_reBindings.end(); + } + + // + // Mode access + // + + const Mode* mode() const { return m_mode; } + + private: + std::string m_name; + BindingMap m_map; + RegExBindings m_reBindings; + Box2i m_bbox; + Mode* m_mode; + + friend class Mode; + }; + +} // namespace TwkApp #endif // __TwkApp__EventTable__h__ diff --git a/src/lib/app/TwkApp/TwkApp/Exception.h b/src/lib/app/TwkApp/TwkApp/Exception.h index cc1dd9276..0790ce18c 100644 --- a/src/lib/app/TwkApp/TwkApp/Exception.h +++ b/src/lib/app/TwkApp/TwkApp/Exception.h @@ -1,19 +1,19 @@ //****************************************************************************** -// Copyright (c) 2005 Tweak Inc. +// Copyright (c) 2005 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #ifndef __TwkApp__Exception__h__ #define __TwkApp__Exception__h__ #include -namespace TwkApp { +namespace TwkApp +{ -TWK_DERIVED_EXCEPTION(DocumentException) + TWK_DERIVED_EXCEPTION(DocumentException) - -} // TwkApp +} // namespace TwkApp #endif // __TwkApp__Exception__h__ diff --git a/src/lib/app/TwkApp/TwkApp/Menu.h b/src/lib/app/TwkApp/TwkApp/Menu.h index e1395c4c3..98268c86c 100644 --- a/src/lib/app/TwkApp/TwkApp/Menu.h +++ b/src/lib/app/TwkApp/TwkApp/Menu.h @@ -1,9 +1,9 @@ //****************************************************************************** // Copyright (c) 2002 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #ifndef __TwkApp__Menu__h__ #define __TwkApp__Menu__h__ @@ -11,117 +11,128 @@ #include #include -namespace TwkApp { - -// -// class Menu -// -// Menu and Menu::Item are abstactions of some unknown UI toolkit -// menu. You can use a menu tree to represent things like the -// application menu in cocoa or a pop-up menu. In the Documnet class, -// for example, a document menu is defined. Its up to the UI toolkit -// implementation to make this menu and keep it working correctly. -// - -class Menu +namespace TwkApp { -public: // - // A Menu item + // class Menu + // + // Menu and Menu::Item are abstactions of some unknown UI toolkit + // menu. You can use a menu tree to represent things like the + // application menu in cocoa or a pop-up menu. In the Documnet class, + // for example, a document menu is defined. Its up to the UI toolkit + // implementation to make this menu and keep it working correctly. // - class Item; - - class StateFunc + class Menu { public: - StateFunc(); - virtual ~StateFunc(); - virtual int state() = 0; - virtual StateFunc* copy() const = 0; - virtual bool error() const = 0; - }; + // + // A Menu item + // - class Item - { - public: - Item(const std::string& title, - Action* action, - const std::string& key = "", - StateFunc* stateFunc = 0, - Menu* subMenu=0) - : m_title(title), - m_action(action), - m_key(key), - m_stateFunc(stateFunc), - m_subMenu(subMenu) {} - - Item(const std::string& title, - Action* action, - Menu* subMenu) - : m_title(title), - m_action(action), - m_key(""), - m_stateFunc(0), - m_subMenu(subMenu) {} - - ~Item() { delete m_action; delete m_subMenu; delete m_stateFunc; } - - Item(const Item* i) { copyFrom(i); } - Item(const Item& i) { copyFrom(&i); } - - - const std::string& title() const { return m_title; } - std::string& title() { return m_title; } - - const Action* action() const { return m_action; } - Action* action() { return m_action; } - - const std::string& key() const { return m_key; } - std::string& key() { return m_key; } - - const StateFunc* stateFunc() const { return m_stateFunc; } - StateFunc* stateFunc() { return m_stateFunc; } - - const Menu* subMenu() const { return m_subMenu; } - Menu* subMenu() { return m_subMenu; } - void subMenu(Menu *m) { m_subMenu = m; } - - void copyFrom(const Item*); + class Item; - private: - std::string m_title; - Action* m_action; - std::string m_key; - StateFunc* m_stateFunc; - Menu* m_subMenu; - }; + class StateFunc + { + public: + StateFunc(); + virtual ~StateFunc(); + virtual int state() = 0; + virtual StateFunc* copy() const = 0; + virtual bool error() const = 0; + }; + + class Item + { + public: + Item(const std::string& title, Action* action, + const std::string& key = "", StateFunc* stateFunc = 0, + Menu* subMenu = 0) + : m_title(title) + , m_action(action) + , m_key(key) + , m_stateFunc(stateFunc) + , m_subMenu(subMenu) + { + } + + Item(const std::string& title, Action* action, Menu* subMenu) + : m_title(title) + , m_action(action) + , m_key("") + , m_stateFunc(0) + , m_subMenu(subMenu) + { + } + + ~Item() + { + delete m_action; + delete m_subMenu; + delete m_stateFunc; + } + + Item(const Item* i) { copyFrom(i); } - typedef std::vector Items; + Item(const Item& i) { copyFrom(&i); } - Menu(const std::string &name); - Menu(const Menu*); - ~Menu(); + const std::string& title() const { return m_title; } - const std::string& name() const { return m_name; } + std::string& title() { return m_title; } - const Items& items() const { return m_items; } + const Action* action() const { return m_action; } - void addItem(Item *i) { m_items.push_back(i); } + Action* action() { return m_action; } - void merge(const Menu*); + const std::string& key() const { return m_key; } - void clear(); + std::string& key() { return m_key; } -private: - Item* matchingItem(const Item *); + const StateFunc* stateFunc() const { return m_stateFunc; } -private: - std::string m_name; - Items m_items; -}; + StateFunc* stateFunc() { return m_stateFunc; } + + const Menu* subMenu() const { return m_subMenu; } + + Menu* subMenu() { return m_subMenu; } + + void subMenu(Menu* m) { m_subMenu = m; } + + void copyFrom(const Item*); + + private: + std::string m_title; + Action* m_action; + std::string m_key; + StateFunc* m_stateFunc; + Menu* m_subMenu; + }; + + typedef std::vector Items; + + Menu(const std::string& name); + Menu(const Menu*); + ~Menu(); + + const std::string& name() const { return m_name; } + + const Items& items() const { return m_items; } + + void addItem(Item* i) { m_items.push_back(i); } + + void merge(const Menu*); + + void clear(); + + private: + Item* matchingItem(const Item*); + + private: + std::string m_name; + Items m_items; + }; -} // TwkApp +} // namespace TwkApp #endif // __TwkApp__Menu__h__ diff --git a/src/lib/app/TwkApp/TwkApp/Mode.h b/src/lib/app/TwkApp/TwkApp/Mode.h index c28a5a1f8..497817755 100644 --- a/src/lib/app/TwkApp/TwkApp/Mode.h +++ b/src/lib/app/TwkApp/TwkApp/Mode.h @@ -1,9 +1,9 @@ //****************************************************************************** -// Copyright (c) 2002 Tweak Inc. +// Copyright (c) 2002 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #ifndef __TwkApp__Mode__h__ #define __TwkApp__Mode__h__ @@ -13,129 +13,132 @@ #include #include -namespace TwkApp { -class Document; -class EventTable; +namespace TwkApp +{ + class Document; + class EventTable; -/// A feature "unit" in an Document/Application + /// A feature "unit" in an Document/Application -/// -/// An application mode. You should sub-class from MajorMode and Minor -/// Mode -- not the base class. -/// + /// + /// An application mode. You should sub-class from MajorMode and Minor + /// Mode -- not the base class. + /// -class Mode -{ - public: + class Mode + { + public: + // + // Types + // - // - // Types - // + typedef std::map EventTables; + typedef EventTables::value_type EventTableEntry; - typedef std::map EventTables; - typedef EventTables::value_type EventTableEntry; + // + // Constructors + // - // - // Constructors - // + virtual ~Mode(); - virtual ~Mode(); + // + // Given name + // - // - // Given name - // + const std::string& name() const { return m_name; } - const std::string& name() const { return m_name; } + // + // By default the sortKey() is the name() + // - // - // By default the sortKey() is the name() - // + virtual std::string sortKey() const; - virtual std::string sortKey() const; - - // - // Menu structure. Note: after a merge, the mode owns the passed - // in menu. - // + // + // Menu structure. Note: after a merge, the mode owns the passed + // in menu. + // - virtual Menu* menu(); - virtual void merge(Menu*); - virtual void setMenu(Menu*); + virtual Menu* menu(); + virtual void merge(Menu*); + virtual void setMenu(Menu*); - // - // Event Table(s). Derived classes should add event tables to the - // base class. Once you add an event table, its owned by the base - // class. - // + // + // Event Table(s). Derived classes should add event tables to the + // base class. Once you add an event table, its owned by the base + // class. + // - void addEventTable(EventTable*); - void removeEventTable(const std::string&); - void clearEventTables(); - EventTable* findTableByName(const std::string&); + void addEventTable(EventTable*); + void removeEventTable(const std::string&); + void clearEventTables(); + EventTable* findTableByName(const std::string&); - const EventTables& eventTables() { return m_eventTables; } + const EventTables& eventTables() { return m_eventTables; } - // - // Called before mode is activated or before it is deactivated. - // + // + // Called before mode is activated or before it is deactivated. + // - virtual void activate(); - virtual void deactivate(); + virtual void activate(); + virtual void deactivate(); - // - // SelectionMask - // + // + // SelectionMask + // - SelectionMask& selectionMask() { return m_selectionMask; } - const SelectionMask& selectionMask() const { return m_selectionMask; } + SelectionMask& selectionMask() { return m_selectionMask; } - Document* document() const { return m_document; } + const SelectionMask& selectionMask() const { return m_selectionMask; } - protected: - Mode(const char *name, Document *doc); + Document* document() const { return m_document; } - private: - std::string m_name; - SelectionMask m_selectionMask; - EventTables m_eventTables; - Document* m_document; - Menu* m_defaultMenu; -}; + protected: + Mode(const char* name, Document* doc); -/// There is only one active MajorMode in a document. + private: + std::string m_name; + SelectionMask m_selectionMask; + EventTables m_eventTables; + Document* m_document; + Menu* m_defaultMenu; + }; -class MajorMode : public Mode -{ - public: - MajorMode(const char *name, Document *doc); - virtual ~MajorMode(); -}; + /// There is only one active MajorMode in a document. -/// There can be many minor modes active in a document. + class MajorMode : public Mode + { + public: + MajorMode(const char* name, Document* doc); + virtual ~MajorMode(); + }; -/// -/// The order() function can be overloaded to allow the mode to move -/// its position in the list of minor modes. By default the order is -/// 0 in which case the sortkey is used to determine ordering. -/// + /// There can be many minor modes active in a document. -class MinorMode : public Mode -{ - public: - MinorMode(const char *name, Document *doc); - virtual ~MinorMode(); + /// + /// The order() function can be overloaded to allow the mode to move + /// its position in the list of minor modes. By default the order is + /// 0 in which case the sortkey is used to determine ordering. + /// + + class MinorMode : public Mode + { + public: + MinorMode(const char* name, Document* doc); + virtual ~MinorMode(); + + int order() const { return m_order; } + + virtual std::string sortKey() const; - int order() const { return m_order; } - virtual std::string sortKey() const; + void setOrder(int o) { m_order = o; } - void setOrder(int o) { m_order = o; } - void setSortKey(const std::string& s) { m_sortkey = s; } + void setSortKey(const std::string& s) { m_sortkey = s; } - protected: - std::string m_sortkey; - int m_order; -}; + protected: + std::string m_sortkey; + int m_order; + }; -} // TwkApp +} // namespace TwkApp #endif // __TwkApp__Mode__h__ diff --git a/src/lib/app/TwkApp/TwkApp/OutputPlugin.h b/src/lib/app/TwkApp/TwkApp/OutputPlugin.h index 99b64ff88..3eafbece5 100644 --- a/src/lib/app/TwkApp/TwkApp/OutputPlugin.h +++ b/src/lib/app/TwkApp/TwkApp/OutputPlugin.h @@ -1,7 +1,7 @@ // -// Copyright (C) 2023 Autodesk, Inc. All Rights Reserved. -// -// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2023 Autodesk, Inc. All Rights Reserved. +// +// SPDX-License-Identifier: Apache-2.0 // #pragma once @@ -9,63 +9,65 @@ #include #include -namespace TwkApp { +namespace TwkApp +{ -// -// Prototypes for the output plugin interface -// ------------------------------------------ -// -// If you implement an output plugin, you will need to have a function called -// "output_module_create" which is extern "C" and has the signature: -// -// extern "C" TwkApp::VideoModule* output_module_create(float output_plugin_version, int output_module_index); -// -// You will also need a function "output_module_destroy" of type: -// -// extern "C" void output_module_destroy(TwkApp::VideoModule*); -// -// + // + // Prototypes for the output plugin interface + // ------------------------------------------ + // + // If you implement an output plugin, you will need to have a function + // called "output_module_create" which is extern "C" and has the signature: + // + // extern "C" TwkApp::VideoModule* output_module_create(float + // output_plugin_version, int output_module_index); + // + // You will also need a function "output_module_destroy" of type: + // + // extern "C" void output_module_destroy(TwkApp::VideoModule*); + // + // #define OUTPUT_PLUGIN_VERSION 1.0 -class VideoModule; -typedef TwkApp::VideoModule* output_module_create_t(float, int); -typedef void output_module_destroy_t(TwkApp::VideoModule*); + class VideoModule; + typedef TwkApp::VideoModule* output_module_create_t(float, int); + typedef void output_module_destroy_t(TwkApp::VideoModule*); -// -// OutputPlugin -// -// Output plugin file and functions' entries info -// - -class OutputPlugin -{ - public: + // + // OutputPlugin + // + // Output plugin file and functions' entries info + // - OutputPlugin(const std::string& file, - void* handle, - output_module_create_t* create_fct, - output_module_destroy_t* destroy_fct) : - m_file(file), - m_handle(handle), - m_output_module_create(create_fct), - m_output_module_destroy(destroy_fct) {}; - virtual ~OutputPlugin(); + class OutputPlugin + { + public: + OutputPlugin(const std::string& file, void* handle, + output_module_create_t* create_fct, + output_module_destroy_t* destroy_fct) + : m_file(file) + , m_handle(handle) + , m_output_module_create(create_fct) + , m_output_module_destroy(destroy_fct) {}; + virtual ~OutputPlugin(); - static std::shared_ptr loadPlugin(const std::string& pathToPlugin); + static std::shared_ptr + loadPlugin(const std::string& pathToPlugin); - void unloadPlugin(); + void unloadPlugin(); - const std::string& filename() const { return m_file; } - TwkApp::VideoModule* output_module_create(float output_plugin_version, int output_module_index); - void output_module_destroy(TwkApp::VideoModule* output_module); + const std::string& filename() const { return m_file; } -private: + TwkApp::VideoModule* output_module_create(float output_plugin_version, + int output_module_index); + void output_module_destroy(TwkApp::VideoModule* output_module); - std::string m_file; - void *m_handle = nullptr; - output_module_create_t* m_output_module_create = nullptr; - output_module_destroy_t* m_output_module_destroy = nullptr; -}; + private: + std::string m_file; + void* m_handle = nullptr; + output_module_create_t* m_output_module_create = nullptr; + output_module_destroy_t* m_output_module_destroy = nullptr; + }; -} // TwkApp +} // namespace TwkApp diff --git a/src/lib/app/TwkApp/TwkApp/OutputPlugins.h b/src/lib/app/TwkApp/TwkApp/OutputPlugins.h index 2b94b9fd5..04cf490b2 100644 --- a/src/lib/app/TwkApp/TwkApp/OutputPlugins.h +++ b/src/lib/app/TwkApp/TwkApp/OutputPlugins.h @@ -1,7 +1,7 @@ // -// Copyright (C) 2023 Autodesk, Inc. All Rights Reserved. -// -// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2023 Autodesk, Inc. All Rights Reserved. +// +// SPDX-License-Identifier: Apache-2.0 // #pragma once @@ -10,50 +10,49 @@ #include #include -namespace TwkApp { - -class OutputPlugin; -using OutputPluginPtr = std::shared_ptr; - -// -// OutputPlugins -// -// Manages the audio/video output plugins -// - -class OutputPlugins +namespace TwkApp { - public: - - OutputPlugins(); - virtual ~OutputPlugins(); - using Plugins = std::unordered_set; + class OutputPlugin; + using OutputPluginPtr = std::shared_ptr; // - // Load all on-disk plugins + // OutputPlugins + // + // Manages the audio/video output plugins // - static void loadPlugins(const std::string& envVar); + class OutputPlugins + { + public: + OutputPlugins(); + virtual ~OutputPlugins(); - // - // Unload all on-disk plugins - // + using Plugins = std::unordered_set; - static void unloadPlugins(); + // + // Load all on-disk plugins + // - // - // Returns an unordered set of all the currently loaded plugins - // + static void loadPlugins(const std::string& envVar); + + // + // Unload all on-disk plugins + // + + static void unloadPlugins(); - static Plugins& plugins(); + // + // Returns an unordered set of all the currently loaded plugins + // - private: + static Plugins& plugins(); - static void addPlugin(const TwkApp::OutputPluginPtr&); + private: + static void addPlugin(const TwkApp::OutputPluginPtr&); - static bool m_loadedAll; - static Plugins* m_plugins; -}; + static bool m_loadedAll; + static Plugins* m_plugins; + }; -} // TwkApp +} // namespace TwkApp diff --git a/src/lib/app/TwkApp/TwkApp/Selection.h b/src/lib/app/TwkApp/TwkApp/Selection.h index cf84633df..2a732958b 100644 --- a/src/lib/app/TwkApp/TwkApp/Selection.h +++ b/src/lib/app/TwkApp/TwkApp/Selection.h @@ -1,81 +1,88 @@ //****************************************************************************** -// Copyright (c) 2002 Tweak Inc. +// Copyright (c) 2002 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #ifndef __TwkApp__Selection__h__ #define __TwkApp__Selection__h__ #include -namespace TwkApp { -class SelectionType; +namespace TwkApp +{ + class SelectionType; -// -// class Selection -// -// Holds a "selection" which is composed of some unknown -// objects. Information regarding the selection is held in the -// SelectionType class used to initialize it. -// + // + // class Selection + // + // Holds a "selection" which is composed of some unknown + // objects. Information regarding the selection is held in the + // SelectionType class used to initialize it. + // -class Selection -{ -public: - Selection(const SelectionType* type) : m_type(type) {} - virtual ~Selection(); + class Selection + { + public: + Selection(const SelectionType* type) + : m_type(type) + { + } - const SelectionType* type() const { return m_type; } - virtual Selection* copy() const = 0; + virtual ~Selection(); -private: - const SelectionType* m_type; -}; + const SelectionType* type() const { return m_type; } -// -// template class TypedSelection -// -// Convenience class which assembles a selection out of a vector of -// some type. -// + virtual Selection* copy() const = 0; -template -class TypedSelection : public Selection -{ -public: - typedef TContainer Container; + private: + const SelectionType* m_type; + }; - TypedSelection(const SelectionType *type) : Selection(type) {} - ~TypedSelection(); + // + // template class TypedSelection + // + // Convenience class which assembles a selection out of a vector of + // some type. + // - virtual Selection* copy() const; + template class TypedSelection : public Selection + { + public: + typedef TContainer Container; - Container& container() { return m_container; } - const Container& container() const { return m_container; } + TypedSelection(const SelectionType* type) + : Selection(type) + { + } -private: - Container m_container; -}; + ~TypedSelection(); -template -TypedSelection::~TypedSelection() -{ - // nothing -} + virtual Selection* copy() const; -template -Selection* -TypedSelection::copy() const -{ - typedef TypedSelection ThisType; - ThisType *c = new ThisType(type());; - c->container() = container(); - return c; -} + Container& container() { return m_container; } + const Container& container() const { return m_container; } -} // TwkApp + private: + Container m_container; + }; -#endif // __TwkApp__Selection__h__ + template TypedSelection::~TypedSelection() + { + // nothing + } + + template + Selection* TypedSelection::copy() const + { + typedef TypedSelection ThisType; + ThisType* c = new ThisType(type()); + ; + c->container() = container(); + return c; + } +} // namespace TwkApp + +#endif // __TwkApp__Selection__h__ diff --git a/src/lib/app/TwkApp/TwkApp/SelectionState.h b/src/lib/app/TwkApp/TwkApp/SelectionState.h index c98e6b81d..4d0e8b51d 100644 --- a/src/lib/app/TwkApp/TwkApp/SelectionState.h +++ b/src/lib/app/TwkApp/TwkApp/SelectionState.h @@ -1,88 +1,89 @@ //****************************************************************************** -// Copyright (c) 2002 Tweak Inc. +// Copyright (c) 2002 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #ifndef __TwkApp__SelectionState__h__ #define __TwkApp__SelectionState__h__ #include -namespace TwkApp { - -// -// class SelectionState -// -// Holds a bunch of selection objects. - -class SelectionState +namespace TwkApp { -public: - - typedef std::vector SelectionVector; // - // The SelectionState can be copied in which case a deep copy occurs. + // class SelectionState // + // Holds a bunch of selection objects. - SelectionState(); - SelectionState(const SelectionState&); - ~SelectionState(); + class SelectionState + { + public: + typedef std::vector SelectionVector; - SelectionState& operator=(const SelectionState&); + // + // The SelectionState can be copied in which case a deep copy occurs. + // - // - // Returns a selection of the type named (it may create one if it - // does not yet exist. - // + SelectionState(); + SelectionState(const SelectionState&); + ~SelectionState(); - Selection* selection(const std::string &name, bool createIfNotThere=true); - Selection* selection(const SelectionType *, bool createIfNotThere=true); - const Selection* selection(const std::string &name) const; + SelectionState& operator=(const SelectionState&); - // - // Set a particular selection. The passed in pointer will be - // owned by the SelectionState. - // + // + // Returns a selection of the type named (it may create one if it + // does not yet exist. + // - void set(Selection*); + Selection* selection(const std::string& name, + bool createIfNotThere = true); + Selection* selection(const SelectionType*, + bool createIfNotThere = true); + const Selection* selection(const std::string& name) const; - // - // Convenience: returns a pointer to a cast things. - // + // + // Set a particular selection. The passed in pointer will be + // owned by the SelectionState. + // - template T* selectionOfType(const std::string &name); - template const T* selectionOfType(const std::string &name) const; + void set(Selection*); - // - // All of the selection objects - // + // + // Convenience: returns a pointer to a cast things. + // - const SelectionVector& selections() const { return m_selections; } + template T* selectionOfType(const std::string& name); + template + const T* selectionOfType(const std::string& name) const; -private: - SelectionVector m_selections; -}; + // + // All of the selection objects + // -// -// Convenient member template -// + const SelectionVector& selections() const { return m_selections; } -template -T* -SelectionState::selectionOfType(const std::string &name) -{ - return dynamic_cast(selection(name)); -} + private: + SelectionVector m_selections; + }; -template -const T* -SelectionState::selectionOfType(const std::string &name) const -{ - return dynamic_cast(selection(name)); -} + // + // Convenient member template + // + + template + T* SelectionState::selectionOfType(const std::string& name) + { + return dynamic_cast(selection(name)); + } + + template + const T* SelectionState::selectionOfType(const std::string& name) const + { + return dynamic_cast(selection(name)); + } -} // TwkApp +} // namespace TwkApp #endif // __TwkApp__SelectionState__h__ diff --git a/src/lib/app/TwkApp/TwkApp/SelectionType.h b/src/lib/app/TwkApp/TwkApp/SelectionType.h index f4e0d44a3..bd93f6d1a 100644 --- a/src/lib/app/TwkApp/TwkApp/SelectionType.h +++ b/src/lib/app/TwkApp/TwkApp/SelectionType.h @@ -1,76 +1,77 @@ //****************************************************************************** -// Copyright (c) 2002 Tweak Inc. +// Copyright (c) 2002 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #ifndef __TwkApp__SelectionType__h__ #define __TwkApp__SelectionType__h__ #include #include -namespace TwkApp { -class Selection; - -// -// class SelectionType -// -// SelectionType names a kind of selection and implements the actual -// selection method. Kinds of SelectionTypes are things like -// "objects" or "polygon edges" or "vertices", etc. -// -// It is necessary to sub-class from this class to implement a new -// SelectionType. There is no inherent method of selection, just that -// a new Selection object can be returned. -// - -class SelectionType +namespace TwkApp { -public: - typedef std::vector TypeVector; - - enum Modifier - { - Replace, - Add, - Subtract - }; + class Selection; // - // Constructors + // class SelectionType // + // SelectionType names a kind of selection and implements the actual + // selection method. Kinds of SelectionTypes are things like + // "objects" or "polygon edges" or "vertices", etc. + // + // It is necessary to sub-class from this class to implement a new + // SelectionType. There is no inherent method of selection, just that + // a new Selection object can be returned. + // + + class SelectionType + { + public: + typedef std::vector TypeVector; - SelectionType(const std::string &name); - virtual ~SelectionType(); + enum Modifier + { + Replace, + Add, + Subtract + }; - const std::string& name() const { return m_name; } + // + // Constructors + // - // - // Look up in the collection of all SelectionTypes. - // + SelectionType(const std::string& name); + virtual ~SelectionType(); - static const TypeVector& allTypes() { return m_allTypes; } - static SelectionType* findByName(const std::string &name); + const std::string& name() const { return m_name; } - // - // Return a selection object for this type - // + // + // Look up in the collection of all SelectionTypes. + // - virtual Selection* newSelection() const = 0; + static const TypeVector& allTypes() { return m_allTypes; } -private: - static TypeVector m_allTypes; - std::string m_name; -}; + static SelectionType* findByName(const std::string& name); -// -// A selection mask -// + // + // Return a selection object for this type + // -typedef std::vector SelectionMask; + virtual Selection* newSelection() const = 0; -} // TwkApp + private: + static TypeVector m_allTypes; + std::string m_name; + }; -#endif // __TwkApp__SelectionType__h__ + // + // A selection mask + // + typedef std::vector SelectionMask; + +} // namespace TwkApp + +#endif // __TwkApp__SelectionType__h__ diff --git a/src/lib/app/TwkApp/TwkApp/VideoDevice.h b/src/lib/app/TwkApp/TwkApp/VideoDevice.h index 3901e1f0c..70dbf9676 100644 --- a/src/lib/app/TwkApp/TwkApp/VideoDevice.h +++ b/src/lib/app/TwkApp/TwkApp/VideoDevice.h @@ -1,9 +1,9 @@ // -// Copyright (c) 2011 Tweak Software. +// Copyright (c) 2011 Tweak Software. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// // #ifndef __TwkApp__VideoDevice__h__ #define __TwkApp__VideoDevice__h__ @@ -12,562 +12,645 @@ #include #include -namespace TwkApp { -class VideoModule; - -// -// VideoDevice -// -// Wraps APIs necessary to output and/or capture from a video -// stream. Examples sub-classes: -// -// * GL window system default frame buffer(s) -// * SDI+GL output buffer for nvidia cards -// * SDI stand-alone -// * Slave GL window on multi-head machine -// - -class VideoDevice : public EventNode +namespace TwkApp { -public: - - typedef double Time; - typedef std::vector AudioFrameSizeVector; - typedef std::vector StringVector; - - enum Capabilities - { - NoCapabilities = 0, - ImageOutput = 1 << 0, // can display images/video - ImageCapture = 1 << 1, // can capture images/video - ProvidesSync = 1 << 2, // provides a (wait on) sync call - FixedResolution = 1 << 3, // limited set of fixed resolutions - SubWindow = 1 << 4, // device is a subwindow of something larger - Clock = 1 << 5, // has its own clock to sync to - AudioOutput = 1 << 6, // can output audio samples (with the video) - AudioCapture = 1 << 7, // can capture audio samples (with the video) - TimeCodeOutput = 1 << 8, // can output VITC timecode - BlockingTransfer = 1 << 9, // transfer functions may block - ASyncReadBack = 1 << 10, // will read frames back asynchronously - FlippedImage = 1 << 11, // image should be rendered flipped - NormalizedCoordinates = 1 << 12 // passed in FBO attachements - // are GL_TEXTURE_2D instead - // of GL_TEXTURE_RECTANGLE - }; - - enum DisplayMode - { - IndependentDisplayMode = 0, - MirrorDisplayMode = 1, - NotADisplayMode = 2 - }; + class VideoModule; // - // The InternalDataFormat is the final format that the renderer - // will produce before transfering to the video device. This is - // only meaningful for GLBindableVideoDevice currently, but could - // be extended to non-GL devices as well. + // VideoDevice + // + // Wraps APIs necessary to output and/or capture from a video + // stream. Examples sub-classes: + // + // * GL window system default frame buffer(s) + // * SDI+GL output buffer for nvidia cards + // * SDI stand-alone + // * Slave GL window on multi-head machine // - enum InternalDataFormat + class VideoDevice : public EventNode { - RGB8, - RGBA8, - BGRA8, - RGB16, - RGBA16, - RGB10X2, - RGB10X2Rev, - RGB16F, - RGBA16F, - RGB32F, - RGBA32F, - - // - // NOTE: currently the renderer will convert to YUV but will - // not do the subsampling. - // - - CbY0CrY1_8_422, // aka 2vuy or UYVY - Y0CbY1Cr_8_422, // aka yuvs or YUY2 - Y1CbY0Cr_8_422, - YCrCb_AJA_10_422, // v210 - YCrCb_BM_10_422, // - - YCbCr_P216_16_422 // Semi-Planar, 4:2:2, 16-bit per component. - // The first buffer is a 16bpp luminance buffer. - // Immediately after this is an interleaved buffer of 16bpp Cb, Cr pairs. - }; + public: + typedef double Time; + typedef std::vector AudioFrameSizeVector; + typedef std::vector StringVector; + + enum Capabilities + { + NoCapabilities = 0, + ImageOutput = 1 << 0, // can display images/video + ImageCapture = 1 << 1, // can capture images/video + ProvidesSync = 1 << 2, // provides a (wait on) sync call + FixedResolution = 1 << 3, // limited set of fixed resolutions + SubWindow = 1 << 4, // device is a subwindow of something larger + Clock = 1 << 5, // has its own clock to sync to + AudioOutput = 1 << 6, // can output audio samples (with the video) + AudioCapture = 1 << 7, // can capture audio samples (with the video) + TimeCodeOutput = 1 << 8, // can output VITC timecode + BlockingTransfer = 1 << 9, // transfer functions may block + ASyncReadBack = 1 << 10, // will read frames back asynchronously + FlippedImage = 1 << 11, // image should be rendered flipped + NormalizedCoordinates = 1 << 12 // passed in FBO attachements + // are GL_TEXTURE_2D instead + // of GL_TEXTURE_RECTANGLE + }; + + enum DisplayMode + { + IndependentDisplayMode = 0, + MirrorDisplayMode = 1, + NotADisplayMode = 2 + }; - struct Resolution - { - Resolution(size_t w, size_t h, float pa, float ps) - : width(w), height(h), pixelAspect(pa), pixelScale(ps) {} - size_t width; - size_t height; - float pixelAspect; - float pixelScale; // e.g. retina might have 2.0 here - }; + // + // The InternalDataFormat is the final format that the renderer + // will produce before transfering to the video device. This is + // only meaningful for GLBindableVideoDevice currently, but could + // be extended to non-GL devices as well. + // - struct Offset - { - Offset(int x_, int y_) : x(x_), y(y_) {} - int x; - int y; - }; + enum InternalDataFormat + { + RGB8, + RGBA8, + BGRA8, + RGB16, + RGBA16, + RGB10X2, + RGB10X2Rev, + RGB16F, + RGBA16F, + RGB32F, + RGBA32F, + + // + // NOTE: currently the renderer will convert to YUV but will + // not do the subsampling. + // + + CbY0CrY1_8_422, // aka 2vuy or UYVY + Y0CbY1Cr_8_422, // aka yuvs or YUY2 + Y1CbY0Cr_8_422, + YCrCb_AJA_10_422, // v210 + YCrCb_BM_10_422, // + + YCbCr_P216_16_422 // Semi-Planar, 4:2:2, 16-bit per component. + // The first buffer is a 16bpp luminance buffer. + // Immediately after this is an interleaved buffer + // of 16bpp Cb, Cr pairs. + }; + + struct Resolution + { + Resolution(size_t w, size_t h, float pa, float ps) + : width(w) + , height(h) + , pixelAspect(pa) + , pixelScale(ps) + { + } + + size_t width; + size_t height; + float pixelAspect; + float pixelScale; // e.g. retina might have 2.0 here + }; + + struct Offset + { + Offset(int x_, int y_) + : x(x_) + , y(y_) + { + } + + int x; + int y; + }; + + struct Timing + { + Timing(float h) + : hz(h) + { + } + + float hz; + }; + + struct VideoFormat + : public Resolution + , public Timing + { + VideoFormat() + : Resolution(0, 0, 0, 0) + , Timing(0) + { + } + + VideoFormat(size_t w, size_t h, float pa, float ps, float hertz, + const std::string& desc = "") + : Resolution(w, h, pa, ps) + , Timing(hertz) + , description(desc) + { + } + + std::string description; + }; + + struct DataFormat + { + DataFormat(InternalDataFormat f, const std::string& desc = "") + : iformat(f) + , description(desc) + { + } + + DataFormat(const std::string& desc = "") + : iformat(RGBA16F) + , description(desc) + { + } + + InternalDataFormat iformat; + std::string description; + }; + + struct SyncMode + { + SyncMode(const std::string& desc = "") + : description(desc) + { + } + + std::string description; + }; + + struct SyncSource + { + SyncSource(const std::string& desc = "") + : description(desc) + { + } + + std::string description; + }; + + struct Video4KTransport + { + Video4KTransport(const std::string& desc = "") + : description(desc) + { + } + + std::string description; + }; + + struct Margins + { + Margins() + : left(0) + , right(0) + , top(0) + , bottom(0) + { + } + + Margins(float l, float r, float t, float b) + : left(l) + , right(r) + , top(t) + , bottom(b) + { + } + + float left; + float right; + float top; + float bottom; + }; + + struct AudioFormat + { + AudioFormat() + : hz(Time(0)) + , format(TwkAudio::Float32Format) + , numChannels(0) + , layout(TwkAudio::UnknownLayout) + { + } + + AudioFormat(Time rate, TwkAudio::Format t, size_t n, + TwkAudio::Layout layout, const std::string& desc) + : hz(rate) + , format(t) + , description(desc) + , numChannels(n) + , layout(layout) + { + } + + Time hz; + TwkAudio::Format format; + size_t numChannels; + TwkAudio::Layout layout; + std::string description; + }; + + enum ColorProfileType + { + NoColorProfile, + ICCProfile + }; + + struct ColorProfile + { + ColorProfile(ColorProfileType t = NoColorProfile, + const std::string& desc = "", + const std::string& u = "") + : type(t) + , description(desc) + , url(u) + { + } + + ColorProfileType type; + std::string description; + std::string url; + }; + + class AudioInterface + { + public: + AudioInterface(); + virtual ~AudioInterface(); + + virtual size_t numChannels() const = 0; + virtual void audioFillChannel(size_t startSample, double rate, + size_t channel, float* buffer, + size_t numSamples); + }; + + VideoDevice(VideoModule*, const std::string& name, + unsigned int capabilities); + + virtual ~VideoDevice(); - struct Timing - { - Timing(float h) : hz(h) {} - float hz; - }; + // + // Query state + // - struct VideoFormat : public Resolution, public Timing - { - VideoFormat() : Resolution(0,0,0,0), Timing(0) {} - VideoFormat(size_t w, size_t h, float pa, float ps, - float hertz, - const std::string& desc = "") - : Resolution(w, h, pa, ps), - Timing(hertz), - description(desc) {} - - std::string description; - }; + const std::string& name() const { return m_name; } - struct DataFormat - { - DataFormat(InternalDataFormat f, const std::string& desc = "") - : iformat(f), - description(desc) {} - DataFormat(const std::string& desc = "") - : iformat(RGBA16F), - description(desc) {} - InternalDataFormat iformat; - std::string description; - }; + unsigned int capabilities() const { return m_capabilities; } - struct SyncMode - { - SyncMode(const std::string& desc = "") - : description(desc) {} - std::string description; - }; + const VideoModule* module() const { return m_module; } - struct SyncSource - { - SyncSource(const std::string& desc = "") - : description(desc) {} - std::string description; - }; + bool swapStereoEyes() const { return m_swapStereoEyes; } - struct Video4KTransport - { - Video4KTransport(const std::string& desc = "") - : description(desc) {} - std::string description; - }; + void setSwapStereoEyes(bool swap) { m_swapStereoEyes = swap; } - struct Margins - { - Margins() : left(0), right(0), top(0), bottom(0) {} - Margins(float l, float r, float t, float b) - : left(l), right(r), top(t), bottom(b) {} - float left; - float right; - float top; - float bottom; - }; + // + // Hash ID + // + // This is the device name current video and data formats hashed + // together or just a subset of that. Use this to match display + // profiles for devices. For example you can find a general + // device hash using NameHash or a specific one using + // VideoAndDataFormatHash + // - struct AudioFormat - { - AudioFormat() : hz(Time(0)), - format(TwkAudio::Float32Format), - numChannels(0), - layout(TwkAudio::UnknownLayout) {} - - AudioFormat(Time rate, - TwkAudio::Format t, - size_t n, - TwkAudio::Layout layout, - const std::string& desc) - : hz(rate), - format(t), - description(desc), - numChannels(n), - layout(layout) {} - - Time hz; - TwkAudio::Format format; - size_t numChannels; - TwkAudio::Layout layout; - std::string description; - }; + enum IDType + { + HostnameVideoAndDataFormatID, + VideoAndDataFormatID, + VideoFormatID, + DataFormatID, + DeviceNameID, + ModuleNameID + }; - enum ColorProfileType - { - NoColorProfile, - ICCProfile - }; + size_t hashID(IDType t = HostnameVideoAndDataFormatID) const; + std::string + humanReadableID(IDType t = HostnameVideoAndDataFormatID) const; - struct ColorProfile - { - ColorProfile(ColorProfileType t = NoColorProfile, - const std::string& desc = "", - const std::string& u = "") - : type(t), - description(desc), - url(u) {} - - ColorProfileType type; - std::string description; - std::string url; - }; + // + // Audio + // - class AudioInterface - { - public: - AudioInterface(); - virtual ~AudioInterface(); - - virtual size_t numChannels() const = 0; - virtual void audioFillChannel(size_t startSample, - double rate, - size_t channel, - float* buffer, - size_t numSamples); - }; + bool hasAudioOutput() const + { + return (m_capabilities & AudioOutput) != 0; + } - VideoDevice(VideoModule*, - const std::string& name, - unsigned int capabilities); + bool audioOutputEnabled() const + { + return hasAudioOutput() && m_useAudioOutput; + } - virtual ~VideoDevice(); + void setAudioOutputEnabled(bool b) { m_useAudioOutput = b; } - // - // Query state - // + bool useLatencyForAudio() const { return m_useLatencyForAudio; } - const std::string& name() const { return m_name; } - unsigned int capabilities() const { return m_capabilities; } - const VideoModule* module() const { return m_module; } - bool swapStereoEyes() const { return m_swapStereoEyes; } + void setUseLatencyForAudio(bool b) { m_useLatencyForAudio = b; } - void setSwapStereoEyes (bool swap) { m_swapStereoEyes = swap; } + virtual size_t numAudioFormats() const; + virtual AudioFormat audioFormatAtIndex(size_t) const; + virtual void setAudioFormat(size_t); + virtual size_t currentAudioFormat() const; - // - // Hash ID - // - // This is the device name current video and data formats hashed - // together or just a subset of that. Use this to match display - // profiles for devices. For example you can find a general - // device hash using NameHash or a specific one using - // VideoAndDataFormatHash - // + // + // Transfer begin/end These are called before a single frame of data + // is transfered. The transfer can occur as a number of API + // calls. Once endTransfer() is called you know no more transfer calls + // will occur. + // - enum IDType - { - HostnameVideoAndDataFormatID, - VideoAndDataFormatID, - VideoFormatID, - DataFormatID, - DeviceNameID, - ModuleNameID - }; + virtual void beginTransfer() const; + virtual void endTransfer() const; - size_t hashID(IDType t = HostnameVideoAndDataFormatID) const; - std::string humanReadableID(IDType t = HostnameVideoAndDataFormatID) const; + // + // Called after openning and probably after binding if result is + // empty vector then its not ready yet. The vector will have + // either a single element, meaning the audio frame packet size + // is the same for every frame, or it will have a pattern which + // should be used for successive frames. + // + // So for example, it might have: + // + // 801 800 801 800 801 + // + // for 59.94Hz playback since at 48khz its not divisible. This + // means you output audio like this: + // + // 1 2 3 4 5 6 7 8 9 10 .... + // 801 800 801 800 801 801 800 801 800 801 .... + // + // - // - // Audio - // + virtual void audioFrameSizeSequence(AudioFrameSizeVector&) const; - bool hasAudioOutput() const { return (m_capabilities & AudioOutput) != 0; } - bool audioOutputEnabled() const { return hasAudioOutput() && m_useAudioOutput; } - void setAudioOutputEnabled(bool b) { m_useAudioOutput = b; } + // + // Return the audio frame size for the upcoming output frame + // - bool useLatencyForAudio() const { return m_useLatencyForAudio; } - void setUseLatencyForAudio(bool b) { m_useLatencyForAudio = b; } + virtual size_t currentAudioFrameSize() const; - virtual size_t numAudioFormats() const; - virtual AudioFormat audioFormatAtIndex(size_t) const; - virtual void setAudioFormat(size_t); - virtual size_t currentAudioFormat() const; + // + // Return the current audio frame size index into the array + // return by audioFrameSizeSequence(). + // - // - // Transfer begin/end These are called before a single frame of data - // is transfered. The transfer can occur as a number of API - // calls. Once endTransfer() is called you know no more transfer calls - // will occur. - // + virtual size_t currentAudioFrameSizeIndex() const; - virtual void beginTransfer() const; - virtual void endTransfer() const; - - // - // Called after openning and probably after binding if result is - // empty vector then its not ready yet. The vector will have - // either a single element, meaning the audio frame packet size - // is the same for every frame, or it will have a pattern which - // should be used for successive frames. - // - // So for example, it might have: - // - // 801 800 801 800 801 - // - // for 59.94Hz playback since at 48khz its not divisible. This - // means you output audio like this: - // - // 1 2 3 4 5 6 7 8 9 10 .... - // 801 800 801 800 801 801 800 801 800 801 .... - // - // + // + // Send audio to device. The number of samples will be initially + // decided by the result of audioFrameSizeSequence(). + // - virtual void audioFrameSizeSequence(AudioFrameSizeVector&) const; + virtual void transferAudio(void* interleavedData, size_t n) const; - // - // Return the audio frame size for the upcoming output frame - // + // + // Timecode + // - virtual size_t currentAudioFrameSize() const; + bool hasTimecodeOutput() const + { + return (m_capabilities & TimeCodeOutput) != 0; + } - // - // Return the current audio frame size index into the array - // return by audioFrameSizeSequence(). - // + bool timecodeOutputEnabled() const + { + return hasTimecodeOutput() && m_useTimecodeOutput; + } - virtual size_t currentAudioFrameSizeIndex() const; + void setTimecodeOutputEnabled(bool b) { m_useTimecodeOutput = b; } - // - // Send audio to device. The number of samples will be initially - // decided by the result of audioFrameSizeSequence(). - // + // + // Clock(s). If it has the capability these should return the + // global time of the current output and the time of the expected + // input. These can differ if the devices buffers frames before + // output. In that case + // - virtual void transferAudio(void* interleavedData, size_t n) const; + bool hasClock() const { return (m_capabilities & Clock) != 0; } - // - // Timecode - // + virtual Time outputTime() const; + virtual Time inputTime() const; - bool hasTimecodeOutput() const { return (m_capabilities & TimeCodeOutput) != 0; } - bool timecodeOutputEnabled() const { return hasTimecodeOutput() && m_useTimecodeOutput; } - void setTimecodeOutputEnabled(bool b) { m_useTimecodeOutput = b; } + virtual void resetClock() const; + virtual Time nextFrameTime() const; + virtual size_t nextFrame() const; - // - // Clock(s). If it has the capability these should return the - // global time of the current output and the time of the expected - // input. These can differ if the devices buffers frames before - // output. In that case - // + virtual bool willBlockOnTransfer() const; - bool hasClock() const { return (m_capabilities & Clock) != 0; } + // + // If ASyncReadBack is a capability than this function should + // return the number of internal buffers the renderer should + // allocate (FBOs in this case). I.e. the maximum number of + // mapped buffers required. + // - virtual Time outputTime() const; - virtual Time inputTime() const; + virtual size_t asyncMaxMappedBuffers() const; - virtual void resetClock() const; - virtual Time nextFrameTime() const; - virtual size_t nextFrame() const; + // + // The human identifiable name of the device: E.g. "DELL U2410" or + // "NVidia SDI" . Defaults to the device name. + // - virtual bool willBlockOnTransfer() const; + virtual std::string hardwareIdentification() const; - // - // If ASyncReadBack is a capability than this function should - // return the number of internal buffers the renderer should - // allocate (FBOs in this case). I.e. the maximum number of - // mapped buffers required. - // + // + // Configurations + // - virtual size_t asyncMaxMappedBuffers() const; + virtual size_t numVideoFormats() const; + virtual VideoFormat videoFormatAtIndex(size_t) const; + virtual void setVideoFormat(size_t); + virtual size_t currentVideoFormat() const; - // - // The human identifiable name of the device: E.g. "DELL U2410" or - // "NVidia SDI" . Defaults to the device name. - // + virtual size_t numDataFormats() const; + virtual DataFormat dataFormatAtIndex(size_t) const; + virtual void setDataFormat(size_t); + virtual size_t currentDataFormat() const; - virtual std::string hardwareIdentification() const; + virtual size_t numSyncModes() const; + virtual SyncMode syncModeAtIndex(size_t) const; + virtual void setSyncMode(size_t); + virtual size_t currentSyncMode() const; - // - // Configurations - // + virtual size_t numSyncSources() const; + virtual SyncSource syncSourceAtIndex(size_t) const; + virtual void setSyncSource(size_t); + virtual size_t currentSyncSource() const; - virtual size_t numVideoFormats() const; - virtual VideoFormat videoFormatAtIndex(size_t) const; - virtual void setVideoFormat(size_t); - virtual size_t currentVideoFormat() const; + virtual size_t numVideo4KTransports() const; + virtual Video4KTransport video4KTransportAtIndex(size_t) const; + virtual void setVideo4KTransport(size_t); + virtual size_t currentVideo4KTransport() const; - virtual size_t numDataFormats() const; - virtual DataFormat dataFormatAtIndex(size_t) const; - virtual void setDataFormat(size_t); - virtual size_t currentDataFormat() const; + // + // These are three independent video latencies. The first is + // computed by the device (if it can). + // + // The fixedLatency() is in seconds and does not vary with the + // video format. + // + // The frameLatency() is measured in frames (not seconds) and + // varies with the video frame rate. + // + // The totalLatencyInSeconds() is the sum of all three in seconds + // and can be used to offset audio in order to achieve some + // semblance of sync + // - virtual size_t numSyncModes() const; - virtual SyncMode syncModeAtIndex(size_t) const; - virtual void setSyncMode(size_t); - virtual size_t currentSyncMode() const; + virtual Time deviceLatency() const; - virtual size_t numSyncSources() const; - virtual SyncSource syncSourceAtIndex(size_t) const; - virtual void setSyncSource(size_t); - virtual size_t currentSyncSource() const; + Time fixedLatency() const; + void setFixedLatency(Time); - virtual size_t numVideo4KTransports() const; - virtual Video4KTransport video4KTransportAtIndex(size_t) const; - virtual void setVideo4KTransport(size_t); - virtual size_t currentVideo4KTransport() const; + Time frameLatencyInFrames() const; + Time frameLatencyInSeconds() const; + void setFrameLatency(Time frames); - // - // These are three independent video latencies. The first is - // computed by the device (if it can). - // - // The fixedLatency() is in seconds and does not vary with the - // video format. - // - // The frameLatency() is measured in frames (not seconds) and - // varies with the video frame rate. - // - // The totalLatencyInSeconds() is the sum of all three in seconds - // and can be used to offset audio in order to achieve some - // semblance of sync - // + Time totalLatencyInSeconds() const; - virtual Time deviceLatency() const; + // + // Current Format + // + // NOTE: internalWidth() and internalHeight() can differ from + // width() and height() in some cases. Renderers should use + // internalWidth() and internalHeight() to determine actual + // render buffer sizes. E.g. frame packed resolutions like: + // + // 1920 x (1080*2 + padding) + // + // would have an internal size of 1920 x 1080. + // - Time fixedLatency() const; - void setFixedLatency(Time); + virtual Resolution resolution() const = 0; + virtual Offset offset() const; // defaults to 0,0 + virtual Timing timing() const = 0; + virtual VideoFormat format() const = 0; - Time frameLatencyInFrames() const; - Time frameLatencyInSeconds() const; - void setFrameLatency(Time frames); + virtual size_t width() const = 0; + virtual size_t height() const = 0; + virtual float pixelScale() const; + virtual float pixelAspect() const; - Time totalLatencyInSeconds() const; + virtual Resolution internalResolution() const; + virtual Offset internalOffset() const; + virtual Timing internalTiming() const; + virtual VideoFormat internalFormat() const; + virtual size_t internalWidth() const; + virtual size_t internalHeight() const; - // - // Current Format - // - // NOTE: internalWidth() and internalHeight() can differ from - // width() and height() in some cases. Renderers should use - // internalWidth() and internalHeight() to determine actual - // render buffer sizes. E.g. frame packed resolutions like: - // - // 1920 x (1080*2 + padding) - // - // would have an internal size of 1920 x 1080. - // + virtual bool isStereo() const; + virtual bool isDualStereo() const; - virtual Resolution resolution() const = 0; - virtual Offset offset() const; // defaults to 0,0 - virtual Timing timing() const = 0; - virtual VideoFormat format() const = 0; + // + // Display Mode + // - virtual size_t width() const = 0; - virtual size_t height() const = 0; - virtual float pixelScale() const; - virtual float pixelAspect() const; + void setDisplayMode(DisplayMode m) { m_displayMode = m; } - virtual Resolution internalResolution() const; - virtual Offset internalOffset() const; - virtual Timing internalTiming() const; - virtual VideoFormat internalFormat() const; - virtual size_t internalWidth() const; - virtual size_t internalHeight() const; + DisplayMode displayMode() const { return m_displayMode; } - virtual bool isStereo() const; - virtual bool isDualStereo() const; + // + // Open the device for use. Video devices are not opened by + // default. The args are video device specific arguments (like + // command line arguments). + // - // - // Display Mode - // + virtual void open(const StringVector& args) = 0; + virtual void close() = 0; - void setDisplayMode(DisplayMode m) { m_displayMode = m; } - DisplayMode displayMode() const { return m_displayMode; } + virtual bool isOpen() const = 0; - // - // Open the device for use. Video devices are not opened by - // default. The args are video device specific arguments (like - // command line arguments). - // + // + // Clear any state caching + // - virtual void open(const StringVector& args) = 0; - virtual void close() = 0; + virtual void clearCaches() const = 0; - virtual bool isOpen() const = 0; + // + // Sync + // + // isSyncing() should return true if the device is currently + // blocked in syncBuffers in another thread. + // + // blockUntilSyncComplete() called from a thread different than + // the one that called syncBuffers() should cause the calling + // thread to block until syncBuffers() returns to its caller. + // - // - // Clear any state caching - // + virtual void syncBuffers() const; + virtual bool isSyncing() const; + virtual void blockUntilSyncComplete() const; - virtual void clearCaches() const = 0; + // + // Margins + // - // - // Sync - // - // isSyncing() should return true if the device is currently - // blocked in syncBuffers in another thread. - // - // blockUntilSyncComplete() called from a thread different than - // the one that called syncBuffers() should cause the calling - // thread to block until syncBuffers() returns to its caller. - // + void setMargins(float l, float r, float t, float b) const + { + m_margins = Margins(l, r, t, b); + } - virtual void syncBuffers() const; - virtual bool isSyncing() const; - virtual void blockUntilSyncComplete() const; + void setMargins(const Margins& m) const { m_margins = m; } - // - // Margins - // + const Margins& margins() const { return m_margins; } - void setMargins(float l, float r, float t, float b) const { m_margins = Margins(l, r, t, b); } - void setMargins(const Margins& m) const { m_margins = m; } - const Margins& margins() const { return m_margins; } + // + // Other + // - // - // Other - // + static size_t pixelSizeInBytes(InternalDataFormat); - static size_t pixelSizeInBytes(InternalDataFormat); + // + // Device Color Profile + // - // - // Device Color Profile - // + virtual ColorProfile colorProfile() const; - virtual ColorProfile colorProfile() const; + // virtual int qtScreen() const { return -1; } - //virtual int qtScreen() const { return -1; } + // + // Physical device. By default, this device _is_ this physical device, + // but from some devices (where the underlying physical screen can + // change), the physical device will be the "real" one. + // - // - // Physical device. By default, this device _is_ this physical device, - // but from some devices (where the underlying physical screen can - // change), the physical device will be the "real" one. - // + VideoDevice* physicalDevice() { return m_physicalDevice; } + + const VideoDevice* physicalDevice() const { return m_physicalDevice; } + + virtual void setPhysicalDevice(VideoDevice* d) { m_physicalDevice = d; } + + protected: + void setCapabilities(unsigned int caps) { m_capabilities = caps; } + + void incrementClock() const; + + protected: + std::string m_name; + unsigned int m_capabilities; + VideoModule* m_module; + DisplayMode m_displayMode; + bool m_useAudioOutput; + bool m_useTimecodeOutput; + bool m_useLatencyForAudio; + bool m_swapStereoEyes; + Time m_fixedLatency; + Time m_frameLatency; + VideoDevice* m_physicalDevice; + mutable AudioFrameSizeVector m_audioFrameSizes; + mutable size_t m_frameCount; + mutable Time m_currentTime; + mutable Margins m_margins; + }; - VideoDevice* physicalDevice() { return m_physicalDevice; } - const VideoDevice* physicalDevice() const { return m_physicalDevice; } - virtual void setPhysicalDevice (VideoDevice *d) { m_physicalDevice = d; } - -protected: - void setCapabilities(unsigned int caps) { m_capabilities = caps; } - void incrementClock() const; - -protected: - std::string m_name; - unsigned int m_capabilities; - VideoModule* m_module; - DisplayMode m_displayMode; - bool m_useAudioOutput; - bool m_useTimecodeOutput; - bool m_useLatencyForAudio; - bool m_swapStereoEyes; - Time m_fixedLatency; - Time m_frameLatency; - VideoDevice* m_physicalDevice; - mutable AudioFrameSizeVector m_audioFrameSizes; - mutable size_t m_frameCount; - mutable Time m_currentTime; - mutable Margins m_margins; -}; - -} // TwkApp +} // namespace TwkApp #endif // __TwkApp__VideoDevice__h__ diff --git a/src/lib/app/TwkApp/TwkApp/VideoModule.h b/src/lib/app/TwkApp/TwkApp/VideoModule.h index 2129337f4..b0ec303d4 100644 --- a/src/lib/app/TwkApp/TwkApp/VideoModule.h +++ b/src/lib/app/TwkApp/TwkApp/VideoModule.h @@ -1,9 +1,9 @@ // -// Copyright (c) 2011 Tweak Software. +// Copyright (c) 2011 Tweak Software. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// // #ifndef __TwkApp__VideoModule__h__ #define __TwkApp__VideoModule__h__ @@ -11,65 +11,66 @@ #include #include -namespace TwkApp { -class VideoDevice; - -// -// VideoModule -// -// This is basically a factory for VideoDevice objects. -// - -class VideoModule +namespace TwkApp { - public: - typedef std::vector VideoDevices; - typedef std::vector StringVector; - typedef void* NativeDisplayPtr; - - VideoModule(NativeDisplayPtr p = NULL); - virtual ~VideoModule(); - - virtual std::string name() const; + class VideoDevice; // - // SDKIdentifier: report a version string for any underlying SDK - // if there is any. For example "ACME SDK 12.2.1 2015-06-30". This - // should use whatever version macros are available from the SDK - // to automatically report -- don't hardcode this stuff. + // VideoModule // - // SDKInfo: additional info like "Recommended ACME driver: 12.2" - // - // Either one of these can return "" which is the default + // This is basically a factory for VideoDevice objects. // - virtual std::string SDKIdentifier() const; - virtual std::string SDKInfo() const; + class VideoModule + { + public: + typedef std::vector VideoDevices; + typedef std::vector StringVector; + typedef void* NativeDisplayPtr; - // - // Before calling anything below this comment, you need to call - // open() on the module. Its expected that open() will fill - // m_devices with whatever devices are available from this - // module. - // + VideoModule(NativeDisplayPtr p = NULL); + virtual ~VideoModule(); - virtual void open(); - virtual void close(); - virtual bool isOpen() const; - virtual const VideoDevices& devices() const; + virtual std::string name() const; - // - // Find the device at the absolute position. This is used by - // DesktopVideoModules when multiple screens are treated as one - // desktop. - // + // + // SDKIdentifier: report a version string for any underlying SDK + // if there is any. For example "ACME SDK 12.2.1 2015-06-30". This + // should use whatever version macros are available from the SDK + // to automatically report -- don't hardcode this stuff. + // + // SDKInfo: additional info like "Recommended ACME driver: 12.2" + // + // Either one of these can return "" which is the default + // + + virtual std::string SDKIdentifier() const; + virtual std::string SDKInfo() const; + + // + // Before calling anything below this comment, you need to call + // open() on the module. Its expected that open() will fill + // m_devices with whatever devices are available from this + // module. + // + + virtual void open(); + virtual void close(); + virtual bool isOpen() const; + virtual const VideoDevices& devices() const; + + // + // Find the device at the absolute position. This is used by + // DesktopVideoModules when multiple screens are treated as one + // desktop. + // - virtual VideoDevice* deviceFromPosition(int x, int y) const; + virtual VideoDevice* deviceFromPosition(int x, int y) const; - protected: - VideoDevices m_devices; -}; + protected: + VideoDevices m_devices; + }; -} // TwkApp +} // namespace TwkApp #endif // __TwkApp__VideoModule__h__ diff --git a/src/lib/app/TwkApp/VideoDevice.cpp b/src/lib/app/TwkApp/VideoDevice.cpp index 0649f4cf4..af1e89746 100644 --- a/src/lib/app/TwkApp/VideoDevice.cpp +++ b/src/lib/app/TwkApp/VideoDevice.cpp @@ -1,9 +1,9 @@ // -// Copyright (c) 2011 Tweak Software. +// Copyright (c) 2011 Tweak Software. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// // #include #include @@ -14,472 +14,316 @@ #include #include -namespace TwkApp { -using namespace std; -using namespace boost; - -VideoDevice::VideoDevice(VideoModule* module, const string& name, unsigned int caps) - : EventNode(name.c_str()), - m_module(module), - m_name(name), - m_capabilities(caps), - m_displayMode(IndependentDisplayMode), - m_useAudioOutput(false), - m_useTimecodeOutput(false), - m_useLatencyForAudio(false), - m_swapStereoEyes(false), - m_fixedLatency(0), - m_frameLatency(0), - m_frameCount(0), - m_currentTime(0) -{ - m_physicalDevice = this; -} +namespace TwkApp +{ + using namespace std; + using namespace boost; + + VideoDevice::VideoDevice(VideoModule* module, const string& name, + unsigned int caps) + : EventNode(name.c_str()) + , m_module(module) + , m_name(name) + , m_capabilities(caps) + , m_displayMode(IndependentDisplayMode) + , m_useAudioOutput(false) + , m_useTimecodeOutput(false) + , m_useLatencyForAudio(false) + , m_swapStereoEyes(false) + , m_fixedLatency(0) + , m_frameLatency(0) + , m_frameCount(0) + , m_currentTime(0) + { + m_physicalDevice = this; + } -VideoDevice::~VideoDevice() -{ -} + VideoDevice::~VideoDevice() {} -VideoDevice::Offset -VideoDevice::offset() const -{ - return Offset(0,0); -} + VideoDevice::Offset VideoDevice::offset() const { return Offset(0, 0); } -bool -VideoDevice::isStereo() const -{ - return false; -} + bool VideoDevice::isStereo() const { return false; } -bool -VideoDevice::isDualStereo() const -{ - return false; -} + bool VideoDevice::isDualStereo() const { return false; } -string -VideoDevice::hardwareIdentification() const -{ - return name(); -} + string VideoDevice::hardwareIdentification() const { return name(); } -float VideoDevice::pixelScale() const { return 1.0f; } -float VideoDevice::pixelAspect() const { return 1.0f; } + float VideoDevice::pixelScale() const { return 1.0f; } -void -VideoDevice::syncBuffers() const -{ -} + float VideoDevice::pixelAspect() const { return 1.0f; } -bool -VideoDevice::isSyncing() const -{ - return false; -} + void VideoDevice::syncBuffers() const {} -void -VideoDevice::blockUntilSyncComplete() const -{ -} + bool VideoDevice::isSyncing() const { return false; } -size_t -VideoDevice::asyncMaxMappedBuffers() const -{ - return 1; -} + void VideoDevice::blockUntilSyncComplete() const {} -void -VideoDevice::audioFrameSizeSequence(AudioFrameSizeVector&) const -{ -} + size_t VideoDevice::asyncMaxMappedBuffers() const { return 1; } -size_t -VideoDevice::currentAudioFrameSize() const -{ - if (m_audioFrameSizes.empty()) + void VideoDevice::audioFrameSizeSequence(AudioFrameSizeVector&) const {} + + size_t VideoDevice::currentAudioFrameSize() const { - audioFrameSizeSequence(m_audioFrameSizes); - } + if (m_audioFrameSizes.empty()) + { + audioFrameSizeSequence(m_audioFrameSizes); + } - return m_audioFrameSizes[currentAudioFrameSizeIndex()]; -} + return m_audioFrameSizes[currentAudioFrameSizeIndex()]; + } -size_t -VideoDevice::currentAudioFrameSizeIndex() const -{ - if (m_audioFrameSizes.empty()) + size_t VideoDevice::currentAudioFrameSizeIndex() const { - audioFrameSizeSequence(m_audioFrameSizes); + if (m_audioFrameSizes.empty()) + { + audioFrameSizeSequence(m_audioFrameSizes); + } + + return m_frameCount % m_audioFrameSizes.size(); } - return m_frameCount % m_audioFrameSizes.size(); -} + void VideoDevice::transferAudio(void* interleavedData, size_t n) const {} -void -VideoDevice::transferAudio(void* interleavedData, size_t n) const -{ -} + size_t VideoDevice::numAudioFormats() const { return 0; } -size_t -VideoDevice::numAudioFormats() const -{ - return 0; -} + VideoDevice::AudioFormat VideoDevice::audioFormatAtIndex(size_t) const + { + return AudioFormat(); + } -VideoDevice::AudioFormat -VideoDevice::audioFormatAtIndex(size_t) const -{ - return AudioFormat(); -} + void VideoDevice::setAudioFormat(size_t) { m_audioFrameSizes.clear(); } -void -VideoDevice::setAudioFormat(size_t) -{ - m_audioFrameSizes.clear(); -} + size_t VideoDevice::currentAudioFormat() const { return 0; } -size_t -VideoDevice::currentAudioFormat() const -{ - return 0; -} + size_t VideoDevice::numVideoFormats() const { return 0; } -size_t -VideoDevice::numVideoFormats() const -{ - return 0; -} + VideoDevice::VideoFormat VideoDevice::videoFormatAtIndex(size_t) const + { + return VideoFormat(); + } -VideoDevice::VideoFormat -VideoDevice::videoFormatAtIndex(size_t) const -{ - return VideoFormat(); -} + void VideoDevice::setVideoFormat(size_t) { m_audioFrameSizes.clear(); } -void -VideoDevice::setVideoFormat(size_t) -{ - m_audioFrameSizes.clear(); -} + size_t VideoDevice::currentVideoFormat() const { return 0; } -size_t -VideoDevice::currentVideoFormat() const -{ - return 0; -} + size_t VideoDevice::numDataFormats() const { return 0; } -size_t -VideoDevice::numDataFormats() const -{ - return 0; -} + VideoDevice::DataFormat VideoDevice::dataFormatAtIndex(size_t) const + { + return DataFormat(); + } -VideoDevice::DataFormat -VideoDevice::dataFormatAtIndex(size_t) const -{ - return DataFormat(); -} + void VideoDevice::setDataFormat(size_t) {} -void -VideoDevice::setDataFormat(size_t) -{ -} + size_t VideoDevice::currentDataFormat() const { return 0; } -size_t -VideoDevice::currentDataFormat() const -{ - return 0; -} + size_t VideoDevice::numSyncModes() const { return 0; } -size_t -VideoDevice::numSyncModes() const -{ - return 0; -} + VideoDevice::SyncMode VideoDevice::syncModeAtIndex(size_t) const + { + return SyncMode(); + } -VideoDevice::SyncMode -VideoDevice::syncModeAtIndex(size_t) const -{ - return SyncMode(); -} + void VideoDevice::setSyncMode(size_t) {} -void -VideoDevice::setSyncMode(size_t) -{ -} + size_t VideoDevice::currentSyncMode() const { return 0; } -size_t -VideoDevice::currentSyncMode() const -{ - return 0; -} + size_t VideoDevice::numSyncSources() const { return 0; } -size_t -VideoDevice::numSyncSources() const -{ - return 0; -} + VideoDevice::SyncSource VideoDevice::syncSourceAtIndex(size_t) const + { + return SyncSource(); + } -VideoDevice::SyncSource -VideoDevice::syncSourceAtIndex(size_t) const -{ - return SyncSource(); -} + void VideoDevice::setSyncSource(size_t) {} -void -VideoDevice::setSyncSource(size_t) -{ -} + size_t VideoDevice::currentSyncSource() const { return 0; } -size_t -VideoDevice::currentSyncSource() const -{ - return 0; -} + size_t VideoDevice::numVideo4KTransports() const { return 0; } -size_t -VideoDevice::numVideo4KTransports() const -{ - return 0; -} + VideoDevice::Video4KTransport + VideoDevice::video4KTransportAtIndex(size_t) const + { + return Video4KTransport(); + } -VideoDevice::Video4KTransport -VideoDevice::video4KTransportAtIndex(size_t) const -{ - return Video4KTransport(); -} + void VideoDevice::setVideo4KTransport(size_t) {} -void -VideoDevice::setVideo4KTransport(size_t) -{ -} + size_t VideoDevice::currentVideo4KTransport() const { return 0; } -size_t -VideoDevice::currentVideo4KTransport() const -{ - return 0; -} + VideoDevice::Time VideoDevice::outputTime() const + { + return Time(m_currentTime); + } -VideoDevice::Time -VideoDevice::outputTime() const -{ - return Time(m_currentTime); -} + VideoDevice::Time VideoDevice::inputTime() const { return Time(0); } -VideoDevice::Time -VideoDevice::inputTime() const -{ - return Time(0); -} + void VideoDevice::resetClock() const + { + m_frameCount = 0; + m_currentTime = 0; + } -void -VideoDevice::resetClock() const -{ - m_frameCount = 0; - m_currentTime = 0; -} + void VideoDevice::incrementClock() const + { + // + // Do the clock by incrementing a frame count and then using + // division on that to reduce floating point precision loss + // + + m_frameCount++; + const Time hz = videoFormatAtIndex(currentVideoFormat()).hz; + m_currentTime = Time(m_frameCount) / hz; + } -void -VideoDevice::incrementClock() const -{ - // - // Do the clock by incrementing a frame count and then using - // division on that to reduce floating point precision loss - // - - m_frameCount++; - const Time hz = videoFormatAtIndex(currentVideoFormat()).hz; - m_currentTime = Time(m_frameCount) / hz; -} - -VideoDevice::Time -VideoDevice::nextFrameTime() const -{ - return m_currentTime; -} + VideoDevice::Time VideoDevice::nextFrameTime() const + { + return m_currentTime; + } -size_t -VideoDevice::nextFrame() const -{ - return m_frameCount; -} + size_t VideoDevice::nextFrame() const { return m_frameCount; } -bool -VideoDevice::willBlockOnTransfer() const -{ - return false; -} + bool VideoDevice::willBlockOnTransfer() const { return false; } -VideoDevice::Time -VideoDevice::deviceLatency() const -{ - return Time(0); -} + VideoDevice::Time VideoDevice::deviceLatency() const { return Time(0); } -VideoDevice::Time -VideoDevice::fixedLatency() const -{ - return m_fixedLatency; -} + VideoDevice::Time VideoDevice::fixedLatency() const + { + return m_fixedLatency; + } -void -VideoDevice::setFixedLatency(Time l) -{ - m_fixedLatency = l; -} + void VideoDevice::setFixedLatency(Time l) { m_fixedLatency = l; } -VideoDevice::Time -VideoDevice::frameLatencyInFrames() const -{ - return m_frameLatency; -} + VideoDevice::Time VideoDevice::frameLatencyInFrames() const + { + return m_frameLatency; + } -VideoDevice::Time -VideoDevice::frameLatencyInSeconds() const -{ - return m_frameLatency / videoFormatAtIndex(currentVideoFormat()).hz; -} + VideoDevice::Time VideoDevice::frameLatencyInSeconds() const + { + return m_frameLatency / videoFormatAtIndex(currentVideoFormat()).hz; + } -void -VideoDevice::setFrameLatency(Time frames) -{ - m_frameLatency = frames; -} + void VideoDevice::setFrameLatency(Time frames) { m_frameLatency = frames; } -VideoDevice::Time -VideoDevice::totalLatencyInSeconds() const -{ - return deviceLatency() + frameLatencyInSeconds() + fixedLatency(); -} + VideoDevice::Time VideoDevice::totalLatencyInSeconds() const + { + return deviceLatency() + frameLatencyInSeconds() + fixedLatency(); + } -VideoDevice::Resolution -VideoDevice::internalResolution() const -{ - return resolution(); -} + VideoDevice::Resolution VideoDevice::internalResolution() const + { + return resolution(); + } -VideoDevice::Offset -VideoDevice::internalOffset() const -{ - return offset(); -} + VideoDevice::Offset VideoDevice::internalOffset() const { return offset(); } -VideoDevice::Timing -VideoDevice::internalTiming() const -{ - return timing(); -} + VideoDevice::Timing VideoDevice::internalTiming() const { return timing(); } -VideoDevice::VideoFormat -VideoDevice::internalFormat() const -{ - return format(); -} + VideoDevice::VideoFormat VideoDevice::internalFormat() const + { + return format(); + } -size_t -VideoDevice::internalWidth() const -{ - return width(); -} + size_t VideoDevice::internalWidth() const { return width(); } -size_t -VideoDevice::internalHeight() const -{ - return height(); -} + size_t VideoDevice::internalHeight() const { return height(); } -size_t -VideoDevice::pixelSizeInBytes(InternalDataFormat f) -{ - switch (f) + size_t VideoDevice::pixelSizeInBytes(InternalDataFormat f) { - case RGB8: return sizeof(unsigned char) * 3; - case RGBA8: - case BGRA8: return sizeof(unsigned char) * 4; - case RGB16: return sizeof(unsigned short) * 3; - case RGBA16: return sizeof(unsigned short) * 4; - case RGB10X2: return sizeof(unsigned int); - case RGB10X2Rev: return sizeof(unsigned int); - case RGB16F: return sizeof(unsigned short) * 3; - case RGBA16F: return sizeof(unsigned short) * 4; - case RGB32F: return sizeof(float) * 3; - case RGBA32F: return sizeof(float) * 4; - case CbY0CrY1_8_422: - case Y0CbY1Cr_8_422: - case Y1CbY0Cr_8_422: return sizeof(unsigned char) * 3; - case YCrCb_AJA_10_422: - case YCrCb_BM_10_422: return sizeof(unsigned int); - case YCbCr_P216_16_422: return sizeof(unsigned short) * 2; - default: - abort(); - } - - return 0; -} - -void -VideoDevice::beginTransfer() const -{ -} + switch (f) + { + case RGB8: + return sizeof(unsigned char) * 3; + case RGBA8: + case BGRA8: + return sizeof(unsigned char) * 4; + case RGB16: + return sizeof(unsigned short) * 3; + case RGBA16: + return sizeof(unsigned short) * 4; + case RGB10X2: + return sizeof(unsigned int); + case RGB10X2Rev: + return sizeof(unsigned int); + case RGB16F: + return sizeof(unsigned short) * 3; + case RGBA16F: + return sizeof(unsigned short) * 4; + case RGB32F: + return sizeof(float) * 3; + case RGBA32F: + return sizeof(float) * 4; + case CbY0CrY1_8_422: + case Y0CbY1Cr_8_422: + case Y1CbY0Cr_8_422: + return sizeof(unsigned char) * 3; + case YCrCb_AJA_10_422: + case YCrCb_BM_10_422: + return sizeof(unsigned int); + case YCbCr_P216_16_422: + return sizeof(unsigned short) * 2; + default: + abort(); + } + + return 0; + } -void -VideoDevice::endTransfer() const -{ -} + void VideoDevice::beginTransfer() const {} -size_t -VideoDevice::hashID(IDType t) const -{ - string idstr = humanReadableID(t); + void VideoDevice::endTransfer() const {} - // - // remove all whitespace to make it robust against against any - // whitespace changes or leading/trailing whitespace. - // + size_t VideoDevice::hashID(IDType t) const + { + string idstr = humanReadableID(t); - boost::hash string_hash; - string noWhiteSpace = algorithm::replace_all_copy(idstr, " ", ""); - return string_hash(noWhiteSpace); -} + // + // remove all whitespace to make it robust against against any + // whitespace changes or leading/trailing whitespace. + // -string -VideoDevice::humanReadableID(IDType t) const -{ - ostringstream str; - const string& vd = videoFormatAtIndex(currentVideoFormat()).description; - const string& dd = dataFormatAtIndex(currentDataFormat()).description; - const string& moduleName = module()->name(); + boost::hash string_hash; + string noWhiteSpace = algorithm::replace_all_copy(idstr, " ", ""); + return string_hash(noWhiteSpace); + } - switch (t) + string VideoDevice::humanReadableID(IDType t) const { - case HostnameVideoAndDataFormatID: - str << asio::ip::host_name() << "/" << moduleName << "/" << name() << "/" << vd << "/" << dd; - break; - case VideoAndDataFormatID: - str << moduleName << "/" << name() << "/" << vd << "/" << dd; - break; - case VideoFormatID: - str << moduleName << "/" << name() << "/" << vd; - break; - case DataFormatID: - str << moduleName << "/" << name() << "/" << dd; - break; - case DeviceNameID: - str << moduleName << "/" << name(); - break; - case ModuleNameID: - str << moduleName; - break; + ostringstream str; + const string& vd = videoFormatAtIndex(currentVideoFormat()).description; + const string& dd = dataFormatAtIndex(currentDataFormat()).description; + const string& moduleName = module()->name(); + + switch (t) + { + case HostnameVideoAndDataFormatID: + str << asio::ip::host_name() << "/" << moduleName << "/" << name() + << "/" << vd << "/" << dd; + break; + case VideoAndDataFormatID: + str << moduleName << "/" << name() << "/" << vd << "/" << dd; + break; + case VideoFormatID: + str << moduleName << "/" << name() << "/" << vd; + break; + case DataFormatID: + str << moduleName << "/" << name() << "/" << dd; + break; + case DeviceNameID: + str << moduleName << "/" << name(); + break; + case ModuleNameID: + str << moduleName; + break; + } + + return str.str(); } - return str.str(); -} - -VideoDevice::ColorProfile -VideoDevice::colorProfile() const -{ - return ColorProfile(); -} + VideoDevice::ColorProfile VideoDevice::colorProfile() const + { + return ColorProfile(); + } -} // TwkApp +} // namespace TwkApp diff --git a/src/lib/app/TwkApp/VideoModule.cpp b/src/lib/app/TwkApp/VideoModule.cpp index 723360b0c..8b43b7b99 100644 --- a/src/lib/app/TwkApp/VideoModule.cpp +++ b/src/lib/app/TwkApp/VideoModule.cpp @@ -1,67 +1,40 @@ // -// Copyright (c) 2011 Tweak Software. +// Copyright (c) 2011 Tweak Software. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// // #include -namespace TwkApp { -using namespace std; - -VideoModule::VideoModule(NativeDisplayPtr) +namespace TwkApp { -} + using namespace std; -VideoModule::~VideoModule() -{ -} + VideoModule::VideoModule(NativeDisplayPtr) {} -std::string -VideoModule::name() const -{ - return "UNNAMED"; -} + VideoModule::~VideoModule() {} -string -VideoModule::SDKIdentifier() const -{ - return ""; -} + std::string VideoModule::name() const { return "UNNAMED"; } -string -VideoModule::SDKInfo() const -{ - return ""; -} + string VideoModule::SDKIdentifier() const { return ""; } -void -VideoModule::open() -{ -} + string VideoModule::SDKInfo() const { return ""; } -void -VideoModule::close() -{ -} + void VideoModule::open() {} -bool -VideoModule::isOpen() const -{ - return false; -} + void VideoModule::close() {} -const VideoModule::VideoDevices& -VideoModule::devices() const -{ - return m_devices; -} + bool VideoModule::isOpen() const { return false; } -VideoDevice* -VideoModule::deviceFromPosition(int x, int y) const -{ - return 0; -} + const VideoModule::VideoDevices& VideoModule::devices() const + { + return m_devices; + } + + VideoDevice* VideoModule::deviceFromPosition(int x, int y) const + { + return 0; + } -} // TwkApp +} // namespace TwkApp diff --git a/src/lib/app/TwkMediaLibrary/Library.cpp b/src/lib/app/TwkMediaLibrary/Library.cpp index 1b28897e4..64ce7ad23 100644 --- a/src/lib/app/TwkMediaLibrary/Library.cpp +++ b/src/lib/app/TwkMediaLibrary/Library.cpp @@ -1,9 +1,9 @@ // -// Copyright (c) 2015 Tweak Software. +// Copyright (c) 2015 Tweak Software. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// // #include #include @@ -24,747 +24,873 @@ // type -- the other option would be cpp-netlib // -namespace TwkMediaLibrary { -using namespace std; -using namespace boost; - -namespace { -LibraryMap globalLibraryMap; -} - -Task::~Task() {} - -Node::Node(Library* lib) : m_library(lib) { } -Node::~Node() { } - -bool Node::isValid() const { return true; } -string Node::typeName() const { return ""; } -string Node::description() const { return ""; } -std::string Node::name() const { return ""; } -const Node* Node::parent() const { return 0; } -size_t Node::numChildren() const { return 0; } -const Node* Node::child(size_t index) const { return 0; } -void Node::setName(const std::string&) {} -void Node::setParent(const Node*) {} -InternalPath Node::path() const { return InternalPath(); } -InternalPath Node::mediaPath() const { return InternalPath(); } -LibraryURL Node::url() const { return LibraryURL(); } -LibraryURL Node::persistentURL() const { return LibraryURL(); } -URL Node::thumbnailImageURL() const { return URL(); } -MimeType Node::mediaMimeType() const { return MimeType(); } -URL Node::mediaURL() const { return URL(); } -size_t Node::numKeys() const { return 0; } -PropertyKey Node::key(size_t index) const { return PropertyKey(); } -bool Node::hasProperty(const PropertyKey&) const { return false; } -PropertyValue Node::propertyValue(const PropertyKey&) const { return PropertyValue(); } -bool Node::deleteProperty(const PropertyKey&) { return true; } -void Node::setProperty(const PropertyKey&, PropertyType type, const PropertyValue& value) { } -void Node::setPropertyFromString(const PropertyKey&, PropertyType type, const string& value) { } -PropertyType Node::propertyType(const PropertyKey&) const { return StringType; } -size_t Node::numMetaKeys(const PropertyKey&) const { return 0; } -PropertyKey Node::metaKey(const PropertyKey&, size_t index) const { return 0; } -PropertyValue Node::metaValue(const PropertyKey&, const PropertyKey& metaKey) const { return PropertyValue(); } -PropertyType Node::metaType(const PropertyKey&, const PropertyKey& metaKey) const { return StringType; } - -size_t -Node::index() const +namespace TwkMediaLibrary { - // - // Not ideal implementation, but its prob better not to cache the - // index value. - // + using namespace std; + using namespace boost; - if (const Node* p = parent()) + namespace { - for (size_t i = 0, s = p->numChildren(); i < s; i++) - { - if (p->child(i) == this) return i; - } + LibraryMap globalLibraryMap; } - return size_t(-1); -} + Task::~Task() {} + Node::Node(Library* lib) + : m_library(lib) + { + } -PropertyKeyVector -Node::keys() const -{ - // - // Use the API to provide a default implementation for this - // + Node::~Node() {} - size_t s = numKeys(); - PropertyKeyVector vec(s); - for (size_t i = 0; i < s; i++) vec[i] = key(i); - return vec; -} + bool Node::isValid() const { return true; } + string Node::typeName() const { return ""; } -PropertyKeyVector -Node::metaKeys(const PropertyKey& key) const -{ - // - // Use the API to provide a default implementation for this - // + string Node::description() const { return ""; } - size_t s = numMetaKeys(key); - PropertyKeyVector vec(s); - for (size_t i = 0; i < s; i++) vec[i] = metaKey(key, i); - return vec; -} + std::string Node::name() const { return ""; } -bool -Node::hasMeta(const PropertyKey& key, const PropertyKey& meta) const -{ - size_t s = numMetaKeys(key); - for (size_t i = 0; i < s; i++) if (metaKey(key, i) == meta) return true; - return false; -} + const Node* Node::parent() const { return 0; } -string -Node::propertyValueAsString(const PropertyKey& key) const -{ - ostringstream str; - PropertyValue value = propertyValue(key); - - switch (propertyType(key)) - { - case UnknownType: str << "Unknown"; break; - case IntType: str << any_cast(value); break; - case BoolType: str << any_cast(value); break; - case FloatType: str << any_cast(value); break; - default: - case DateAndTimeType: - case ReferenceType: - case URLType: - case StringType: str << any_cast(value); break; - case URLListType: - case StringListType: - case ReferenceListType: - { - StringVector v = any_cast(value); - for (size_t i = 0; i < v.size(); i++) str << (i?", ":"") << v[i]; - break; - } - case IntListType: - { - IntVector v = any_cast(value); - for (size_t i = 0; i < v.size(); i++) str << (i?", ":"") << v[i]; - break; - } - } - - return str.str(); -} - -string -Node::metaValueAsString(const PropertyKey& key, const PropertyKey& metaKey) const -{ - ostringstream str; - PropertyValue value = metaValue(key, metaKey); - - switch (metaType(key, metaKey)) - { - case UnknownType: str << "Unknown"; break; - case IntType: str << any_cast(value); break; - case BoolType: str << any_cast(value); break; - case FloatType: str << any_cast(value); break; - default: - case DateAndTimeType: - case ReferenceType: - case URLType: - case StringType: str << any_cast(value); break; - case URLListType: - case StringListType: - case ReferenceListType: - { - StringVector v = any_cast(value); - for (size_t i = 0; i < v.size(); i++) str << (i?", ":"") << v[i]; - break; - } - case IntListType: - { - IntVector v = any_cast(value); - for (size_t i = 0; i < v.size(); i++) str << (i?", ":"") << v[i]; - break; - } - } - - return str.str(); -} - -bool -Node::hasAncestor(const Node* node) const -{ - for (const Node* p = parent(); p; p = p->parent()) + size_t Node::numChildren() const { return 0; } + + const Node* Node::child(size_t index) const { return 0; } + + void Node::setName(const std::string&) {} + + void Node::setParent(const Node*) {} + + InternalPath Node::path() const { return InternalPath(); } + + InternalPath Node::mediaPath() const { return InternalPath(); } + + LibraryURL Node::url() const { return LibraryURL(); } + + LibraryURL Node::persistentURL() const { return LibraryURL(); } + + URL Node::thumbnailImageURL() const { return URL(); } + + MimeType Node::mediaMimeType() const { return MimeType(); } + + URL Node::mediaURL() const { return URL(); } + + size_t Node::numKeys() const { return 0; } + + PropertyKey Node::key(size_t index) const { return PropertyKey(); } + + bool Node::hasProperty(const PropertyKey&) const { return false; } + + PropertyValue Node::propertyValue(const PropertyKey&) const { - if (p == node) return true; + return PropertyValue(); } - return false; -} + bool Node::deleteProperty(const PropertyKey&) { return true; } -const Node* -Node::findChildByName(const string& name) const -{ - for (size_t i = 0, s = numChildren(); i < s; i++) + void Node::setProperty(const PropertyKey&, PropertyType type, + const PropertyValue& value) { - const Node* node = child(i); - if (node->name() == name) return node; } - return 0; -} + void Node::setPropertyFromString(const PropertyKey&, PropertyType type, + const string& value) + { + } -ostream& -Node::output(ostream& out) const -{ - StringPairVector pairs; + PropertyType Node::propertyType(const PropertyKey&) const + { + return StringType; + } + + size_t Node::numMetaKeys(const PropertyKey&) const { return 0; } - pairs.push_back( StringPair("Name", name()) ); - pairs.push_back( StringPair("Type", typeName()) ); - pairs.push_back( StringPair("URL", url()) ); - pairs.push_back( StringPair("persistentURL", persistentURL()) ); - pairs.push_back( StringPair("MediaURL", mediaURL()) ); - pairs.push_back( StringPair("ThumbnailImageURL", thumbnailImageURL()) ); - pairs.push_back( StringPair("InteralPath", path()) ); - pairs.push_back( StringPair("InternalMediaPath", mediaPath()) ); - pairs.push_back( StringPair("-", "") ); + PropertyKey Node::metaKey(const PropertyKey&, size_t index) const + { + return 0; + } - for (size_t i = 0, s = numKeys(); i < s; i++) + PropertyValue Node::metaValue(const PropertyKey&, + const PropertyKey& metaKey) const { - PropertyKey k = key(i); - pairs.push_back( StringPair(k, propertyValueAsString(k)) ); + return PropertyValue(); } - size_t keySize = 0; + PropertyType Node::metaType(const PropertyKey&, + const PropertyKey& metaKey) const + { + return StringType; + } - for (size_t i = 0; i < pairs.size(); i++) + size_t Node::index() const { - keySize = std::max(keySize, pairs[i].first.size()); - string::size_type p; + // + // Not ideal implementation, but its prob better not to cache the + // index value. + // - if ( (p = pairs[i].second.find('\n')) != string::npos ) + if (const Node* p = parent()) { - pairs[i].second[p] = ' '; + for (size_t i = 0, s = p->numChildren(); i < s; i++) + { + if (p->child(i) == this) + return i; + } } + + return size_t(-1); } - for (size_t i = 0; i < pairs.size(); i++) + PropertyKeyVector Node::keys() const + { + // + // Use the API to provide a default implementation for this + // + + size_t s = numKeys(); + PropertyKeyVector vec(s); + for (size_t i = 0; i < s; i++) + vec[i] = key(i); + return vec; + } + + PropertyKeyVector Node::metaKeys(const PropertyKey& key) const + { + // + // Use the API to provide a default implementation for this + // + + size_t s = numMetaKeys(key); + PropertyKeyVector vec(s); + for (size_t i = 0; i < s; i++) + vec[i] = metaKey(key, i); + return vec; + } + + bool Node::hasMeta(const PropertyKey& key, const PropertyKey& meta) const + { + size_t s = numMetaKeys(key); + for (size_t i = 0; i < s; i++) + if (metaKey(key, i) == meta) + return true; + return false; + } + + string Node::propertyValueAsString(const PropertyKey& key) const { ostringstream str; - const string& key = pairs[i].first; - const string& value = pairs[i].second; - str << setfill(key == "-" ? '-' : ' ') << setw(keySize + 1) << key; - out << str.str() << " = " << value << endl; - } - - return out; -} - -//---------------------------------------------------------------------- - -NodeAPI::~NodeAPI() {} -CapabilityAPI::~CapabilityAPI() {} -UserAPI::~UserAPI() {} -OrganizationAPI::~OrganizationAPI() {} -WatermarkAPI::~WatermarkAPI() {} -CutAPI::~CutAPI() {} -NoteAPI::~NoteAPI() {} -MediaAPI::~MediaAPI() {} -HTTPCookieVector MediaAPI::httpCookies() const { return HTTPCookieVector(); } -HTTPHeaderVector MediaAPI::httpHeaders() const { return HTTPHeaderVector(); } -URL MediaAPI::httpRedirection() const { return URL(); } - -//---------------------------------------------------------------------- - -Library::Library(const string& typeName, const string& appName) - : m_typeName(typeName), - m_appName(appName), - m_name(typeName), - m_taskStop(false), - m_taskThread(threadTrampoline, this) -{ - // globalLibraryMap[typeName] = this; -} + PropertyValue value = propertyValue(key); -Library::~Library() -{ + switch (propertyType(key)) + { + case UnknownType: + str << "Unknown"; + break; + case IntType: + str << any_cast(value); + break; + case BoolType: + str << any_cast(value); + break; + case FloatType: + str << any_cast(value); + break; + default: + case DateAndTimeType: + case ReferenceType: + case URLType: + case StringType: + str << any_cast(value); + break; + case URLListType: + case StringListType: + case ReferenceListType: + { + StringVector v = any_cast(value); + for (size_t i = 0; i < v.size(); i++) + str << (i ? ", " : "") << v[i]; + break; + } + case IntListType: + { + IntVector v = any_cast(value); + for (size_t i = 0; i < v.size(); i++) + str << (i ? ", " : "") << v[i]; + break; + } + } + + return str.str(); + } + + string Node::metaValueAsString(const PropertyKey& key, + const PropertyKey& metaKey) const { - ScopedLock lock(m_taskMutex); - m_taskStop = true; - m_taskCond.notify_one(); + ostringstream str; + PropertyValue value = metaValue(key, metaKey); + + switch (metaType(key, metaKey)) + { + case UnknownType: + str << "Unknown"; + break; + case IntType: + str << any_cast(value); + break; + case BoolType: + str << any_cast(value); + break; + case FloatType: + str << any_cast(value); + break; + default: + case DateAndTimeType: + case ReferenceType: + case URLType: + case StringType: + str << any_cast(value); + break; + case URLListType: + case StringListType: + case ReferenceListType: + { + StringVector v = any_cast(value); + for (size_t i = 0; i < v.size(); i++) + str << (i ? ", " : "") << v[i]; + break; + } + case IntListType: + { + IntVector v = any_cast(value); + for (size_t i = 0; i < v.size(); i++) + str << (i ? ", " : "") << v[i]; + break; + } + } + + return str.str(); } - m_taskThread.join(); + bool Node::hasAncestor(const Node* node) const + { + for (const Node* p = parent(); p; p = p->parent()) + { + if (p == node) + return true; + } - // - // willDeleteSignal() should be sent by derived classes. Its sent - // here as a stop-gap but if this is used is almost certain going - // to be a core dump. - // - // In other words: if you see this comment on the stack of a core - // dump where willDeleteSignal() is being sent you now know why. - // + return false; + } - willDeleteSignal()(); - globalLibraryMap.erase(name()); -} + const Node* Node::findChildByName(const string& name) const + { + for (size_t i = 0, s = numChildren(); i < s; i++) + { + const Node* node = child(i); + if (node->name() == name) + return node; + } -const LibraryMap& allLibraries() { return globalLibraryMap; } + return 0; + } -void -Library::setName(const string& name) -{ - // THIS IS AWFUL AND WE NEED TO CHANGE IT. + ostream& Node::output(ostream& out) const + { + StringPairVector pairs; + + pairs.push_back(StringPair("Name", name())); + pairs.push_back(StringPair("Type", typeName())); + pairs.push_back(StringPair("URL", url())); + pairs.push_back(StringPair("persistentURL", persistentURL())); + pairs.push_back(StringPair("MediaURL", mediaURL())); + pairs.push_back(StringPair("ThumbnailImageURL", thumbnailImageURL())); + pairs.push_back(StringPair("InteralPath", path())); + pairs.push_back(StringPair("InternalMediaPath", mediaPath())); + pairs.push_back(StringPair("-", "")); + + for (size_t i = 0, s = numKeys(); i < s; i++) + { + PropertyKey k = key(i); + pairs.push_back(StringPair(k, propertyValueAsString(k))); + } - // because the library initially sets itself to the typeName, it will - // continually re-write over "local". So instead I'm hacking this to - // do it when you set the name. I'm putting it outside the if because - // other wise "local" won't get registered and I'm too tired to think of - // the right way to do it now. sorry future person. - LibraryMap::const_iterator i = globalLibraryMap.find(name); - if (i != globalLibraryMap.end()) globalLibraryMap.erase(name); + size_t keySize = 0; - if (m_name != name) + for (size_t i = 0; i < pairs.size(); i++) + { + keySize = std::max(keySize, pairs[i].first.size()); + string::size_type p; + + if ((p = pairs[i].second.find('\n')) != string::npos) + { + pairs[i].second[p] = ' '; + } + } + + for (size_t i = 0; i < pairs.size(); i++) + { + ostringstream str; + const string& key = pairs[i].first; + const string& value = pairs[i].second; + str << setfill(key == "-" ? '-' : ' ') << setw(keySize + 1) << key; + out << str.str() << " = " << value << endl; + } + + return out; + } + + //---------------------------------------------------------------------- + + NodeAPI::~NodeAPI() {} + + CapabilityAPI::~CapabilityAPI() {} + + UserAPI::~UserAPI() {} + + OrganizationAPI::~OrganizationAPI() {} + + WatermarkAPI::~WatermarkAPI() {} + + CutAPI::~CutAPI() {} + + NoteAPI::~NoteAPI() {} + + MediaAPI::~MediaAPI() {} + + HTTPCookieVector MediaAPI::httpCookies() const { - m_name = name; - m_nameChangedSignal(m_name); + return HTTPCookieVector(); + } + HTTPHeaderVector MediaAPI::httpHeaders() const + { + return HTTPHeaderVector(); } - globalLibraryMap[m_name] = this; -} + URL MediaAPI::httpRedirection() const { return URL(); } -// -// These all return error or default values -// + //---------------------------------------------------------------------- -bool Library::isReadable() const { return true; } -bool Library::isWriteable() const { return false; } -bool Library::hasWritableProperties() const { return false; } -bool Library::hasImport() const { return false; } -bool Library::hasExport() const { return false; } -URL Library::url() const { return URL(); } -size_t Library::numNodeTypeNames() const { return 0; } -string Library::nodeTypeName(size_t) const { return ""; } -const Node* Library::rootNode() const { return 0; } -const Node* Library::nodeFromLibraryURL(const URL&) const { return 0; } -const Node* Library::nodeFromInternalPath(const InternalPath&) const { return 0; } -void Library::deleteNode(const Node*) { } -bool Library::isolateNode(const Node*) { return false; } -void Library::restoreIsolatedNode(const Node*) { } -void Library::reorderNode(const Node*, size_t newIndex) { } -void Library::moveNode(const Node*, const Node*, size_t newIndex) { } -const Node* Library::newNode(const std::string& nodeTypeName) { return 0; } -const Node* Library::newNodeFromMediaURL(const URL& url) { return 0; } -const Node* Library::newNodeFromCutURL(const URL& url) { return 0; } -URL Library::exportMedia(const Node*) const { return URL(); } -void Library::setNodeName(const Node*, const string&) {} -void Library::setNodeParent(const Node*, const Node*) {} -bool Library::isMediaSupported(const URL& url) const { return false; } -string Library::nodeTypeForMedia(const URL& url) const { return ""; } -bool Library::copyToLibrary(const Node*, const PropertyKey&) { return false; } -bool Library::isAuthenticated() const { return false; } -bool Library::authenticate(const std::string& userName, const std::string& password) const { return false; } -const CapabilityAPI* Library::authenticatedCapabilityAPI() const { return NULL; } -const CapabilityAPI* Library::owner() const { return NULL; } -UserAPIVector Library::userNodeAPIs() const { return UserAPIVector(); } -OrganizationAPIVector Library::organizationNodeAPIs() const { return OrganizationAPIVector(); } -WatermarkAPIVector Library::watermarkNodeAPIs() const { return WatermarkAPIVector(); } -const NodeAPI* Library::nodeAPI(const Node*) const { return NULL; } - -URL -libraryURLtoMediaURL(const URL& inURL) -{ - if (const Node* node = nodeOfURL(inURL)) + Library::Library(const string& typeName, const string& appName) + : m_typeName(typeName) + , m_appName(appName) + , m_name(typeName) + , m_taskStop(false) + , m_taskThread(threadTrampoline, this) { - return node->mediaURL(); + // globalLibraryMap[typeName] = this; } - return "nothing"; -} + Library::~Library() + { + { + ScopedLock lock(m_taskMutex); + m_taskStop = true; + m_taskCond.notify_one(); + } -bool -isLibraryURL(const URL& inURL) -{ - return libraryOfURL(inURL) != NULL; -} + m_taskThread.join(); -bool -isNodeURL(const URL& inURL) -{ - if (Library* l = libraryOfURL(inURL)) + // + // willDeleteSignal() should be sent by derived classes. Its sent + // here as a stop-gap but if this is used is almost certain going + // to be a core dump. + // + // In other words: if you see this comment on the stack of a core + // dump where willDeleteSignal() is being sent you now know why. + // + + willDeleteSignal()(); + globalLibraryMap.erase(name()); + } + + const LibraryMap& allLibraries() { return globalLibraryMap; } + + void Library::setName(const string& name) { - QUrl url(inURL.c_str()); - return url.fragment() == ""; + // THIS IS AWFUL AND WE NEED TO CHANGE IT. + + // because the library initially sets itself to the typeName, it will + // continually re-write over "local". So instead I'm hacking this to + // do it when you set the name. I'm putting it outside the if because + // other wise "local" won't get registered and I'm too tired to think of + // the right way to do it now. sorry future person. + LibraryMap::const_iterator i = globalLibraryMap.find(name); + if (i != globalLibraryMap.end()) + globalLibraryMap.erase(name); + + if (m_name != name) + { + m_name = name; + m_nameChangedSignal(m_name); + } + + globalLibraryMap[m_name] = this; } - return false; -} + // + // These all return error or default values + // + + bool Library::isReadable() const { return true; } -bool -isPropertyURL(const URL& inURL) -{ - if (Library* l = libraryOfURL(inURL)) + bool Library::isWriteable() const { return false; } + + bool Library::hasWritableProperties() const { return false; } + + bool Library::hasImport() const { return false; } + + bool Library::hasExport() const { return false; } + + URL Library::url() const { return URL(); } + + size_t Library::numNodeTypeNames() const { return 0; } + + string Library::nodeTypeName(size_t) const { return ""; } + + const Node* Library::rootNode() const { return 0; } + + const Node* Library::nodeFromLibraryURL(const URL&) const { return 0; } + + const Node* Library::nodeFromInternalPath(const InternalPath&) const { - QUrl url(inURL.c_str()); - return url.fragment() != ""; + return 0; } - return false; -} + void Library::deleteNode(const Node*) {} -string -Library::nameFromMedia(const URL& inURL) -{ - QUrl url(inURL.c_str()); - QFileInfo info(url.path()); - return info.completeBaseName().toUtf8().constData(); -} + bool Library::isolateNode(const Node*) { return false; } -string -Library::filenameOfMedia(const URL& inURL) -{ - QUrl url(inURL.c_str()); - QFileInfo info(url.path()); - return info.fileName().toUtf8().constData(); -} + void Library::restoreIsolatedNode(const Node*) {} -MediaFileInfo -Library::computeMediaFileInfo(const URL& mediaURL) -{ - string mediaFile = mediaURL.substr(7, string::npos); + void Library::reorderNode(const Node*, size_t newIndex) {} - TwkUtil::Timer timer; - timer.start(); - TwkUtil::FileStream fileStream(mediaFile, TwkUtil::FileStream::MemoryMap); - size_t hashid = TwkUtil::FNV1a64(fileStream.data(), fileStream.size()); - timer.stop(); + void Library::moveNode(const Node*, const Node*, size_t newIndex) {} - ostringstream dataIDstr; - dataIDstr << "FNV1a/" << hex << hashid; + const Node* Library::newNode(const std::string& nodeTypeName) { return 0; } - MediaFileInfo info; - info.hashValue = dataIDstr.str(); - info.hashTimeInSeconds = float(timer.elapsed()); - info.fileSize = fileStream.size(); + const Node* Library::newNodeFromMediaURL(const URL& url) { return 0; } - return info; -} + const Node* Library::newNodeFromCutURL(const URL& url) { return 0; } -namespace { + URL Library::exportMedia(const Node*) const { return URL(); } -void -recursiveFindReferences(const string& refNodeURL, const Node* node, Library::NodePropertyResult& result) -{ - Library::NodePropertyKeyVectorPair propPair; - PropertyKeyVector keys = node->keys(); + void Library::setNodeName(const Node*, const string&) {} + + void Library::setNodeParent(const Node*, const Node*) {} + + bool Library::isMediaSupported(const URL& url) const { return false; } + + string Library::nodeTypeForMedia(const URL& url) const { return ""; } + + bool Library::copyToLibrary(const Node*, const PropertyKey&) + { + return false; + } + + bool Library::isAuthenticated() const { return false; } - for (size_t i = 0, s = keys.size(); i < s; i++) + bool Library::authenticate(const std::string& userName, + const std::string& password) const { - PropertyKey key = keys[i]; - PropertyType t = node->propertyType(key); + return false; + } - if (t == ReferenceType) + const CapabilityAPI* Library::authenticatedCapabilityAPI() const + { + return NULL; + } + + const CapabilityAPI* Library::owner() const { return NULL; } + + UserAPIVector Library::userNodeAPIs() const { return UserAPIVector(); } + + OrganizationAPIVector Library::organizationNodeAPIs() const + { + return OrganizationAPIVector(); + } + + WatermarkAPIVector Library::watermarkNodeAPIs() const + { + return WatermarkAPIVector(); + } + + const NodeAPI* Library::nodeAPI(const Node*) const { return NULL; } + + URL libraryURLtoMediaURL(const URL& inURL) + { + if (const Node* node = nodeOfURL(inURL)) { - URL url = any_cast(node->propertyValue(key)); + return node->mediaURL(); + } - if (url == refNodeURL) - { - propPair.second.push_back(key); - propPair.first = node; - } + return "nothing"; + } + + bool isLibraryURL(const URL& inURL) { return libraryOfURL(inURL) != NULL; } + + bool isNodeURL(const URL& inURL) + { + if (Library* l = libraryOfURL(inURL)) + { + QUrl url(inURL.c_str()); + return url.fragment() == ""; } - else if (t == ReferenceListType) + + return false; + } + + bool isPropertyURL(const URL& inURL) + { + if (Library* l = libraryOfURL(inURL)) { - vector v = any_cast< vector >(node->propertyValue(key)); - - for (size_t q = 0; q < v.size(); q++) - { - if (v[q] == refNodeURL) - { - propPair.second.push_back(key); - propPair.first = node; - break; - } - } + QUrl url(inURL.c_str()); + return url.fragment() != ""; } + + return false; } - if (propPair.first) result.push_back(propPair); + string Library::nameFromMedia(const URL& inURL) + { + QUrl url(inURL.c_str()); + QFileInfo info(url.path()); + return info.completeBaseName().toUtf8().constData(); + } - for (size_t i = 0, s = node->numChildren(); i < s; i++) + string Library::filenameOfMedia(const URL& inURL) { - recursiveFindReferences(refNodeURL, node->child(i), result); + QUrl url(inURL.c_str()); + QFileInfo info(url.path()); + return info.fileName().toUtf8().constData(); } -} -} + MediaFileInfo Library::computeMediaFileInfo(const URL& mediaURL) + { + string mediaFile = mediaURL.substr(7, string::npos); -const Node* -Library::nodeOfMedia(const URL& url) const -{ - return NULL; -} + TwkUtil::Timer timer; + timer.start(); + TwkUtil::FileStream fileStream(mediaFile, + TwkUtil::FileStream::MemoryMap); + size_t hashid = TwkUtil::FNV1a64(fileStream.data(), fileStream.size()); + timer.stop(); -bool -Library::isLibraryMediaURL(const URL& inURL) const -{ - // - // This is intended to be a fast test. The default case does a full look up. - // + ostringstream dataIDstr; + dataIDstr << "FNV1a/" << hex << hashid; - return nodeOfMedia(inURL) != NULL; -} + MediaFileInfo info; + info.hashValue = dataIDstr.str(); + info.hashTimeInSeconds = float(timer.elapsed()); + info.fileSize = fileStream.size(); -NodeVector -Library::associatedNodes(const URL& inURL) const -{ - QUrl url(inURL.c_str()); - const Node* node = url.scheme() == "file" ? nodeOfMedia(inURL) : nodeOfURL(inURL); - NodeVector nodes; + return info; + } - if (node) + namespace { - set nodeSet; - NodePropertyResult result = referencesToNode(node); - for (size_t i = 0; i < result.size(); i++) nodeSet.insert(result[i].first); - std::copy(nodeSet.begin(), nodeSet.end(), back_inserter(nodes)); - } + void recursiveFindReferences(const string& refNodeURL, const Node* node, + Library::NodePropertyResult& result) + { + Library::NodePropertyKeyVectorPair propPair; + PropertyKeyVector keys = node->keys(); - return nodes; -} + for (size_t i = 0, s = keys.size(); i < s; i++) + { + PropertyKey key = keys[i]; + PropertyType t = node->propertyType(key); -const Task* -Library::nodeOfMediaASync(const URL&, NodeQueryResultFunction) const -{ - return 0; -} + if (t == ReferenceType) + { + URL url = any_cast(node->propertyValue(key)); -Library::NodePropertyResult -Library::referencesToNode(const Node* node) const -{ - // - // NOTE: this is a *terrible* way to do this. Each library - // implementation would presumably have a much more efficient way of - // doing this querry. The default implementation (scan every node in - // the library) works only as a stand in. - // + if (url == refNodeURL) + { + propPair.second.push_back(key); + propPair.first = node; + } + } + else if (t == ReferenceListType) + { + vector v = + any_cast>(node->propertyValue(key)); + + for (size_t q = 0; q < v.size(); q++) + { + if (v[q] == refNodeURL) + { + propPair.second.push_back(key); + propPair.first = node; + break; + } + } + } + } - NodePropertyResult result; - recursiveFindReferences(node->url(), rootNode(), result); - return result; -} + if (propPair.first) + result.push_back(propPair); -const Task* -Library::referencesToNodeASync(const Node*, PropertyQueryResultFunction) const -{ - return 0; -} + for (size_t i = 0, s = node->numChildren(); i < s; i++) + { + recursiveFindReferences(refNodeURL, node->child(i), result); + } + } -void -Library::threadTrampoline(Library* library) -{ - library->threadMain(); -} + } // namespace -void -Library::addTask(Task* item) const -{ - ScopedLock lock(m_taskMutex); - m_taskQueue.push_back(item); - m_taskCond.notify_one(); -} + const Node* Library::nodeOfMedia(const URL& url) const { return NULL; } -void -Library::cancelTask(const Task* item) const -{ - if (item && item->library() == this) + bool Library::isLibraryMediaURL(const URL& inURL) const { - ScopedLock lock(m_taskMutex); + // + // This is intended to be a fast test. The default case does a full + // look up. + // + + return nodeOfMedia(inURL) != NULL; + } - TaskDeque::iterator i = find(m_taskQueue.begin(), m_taskQueue.end(), item); + NodeVector Library::associatedNodes(const URL& inURL) const + { + QUrl url(inURL.c_str()); + const Node* node = + url.scheme() == "file" ? nodeOfMedia(inURL) : nodeOfURL(inURL); + NodeVector nodes; - if (i != m_taskQueue.end()) + if (node) { - delete *i; - m_taskQueue.erase(i); + set nodeSet; + + NodePropertyResult result = referencesToNode(node); + for (size_t i = 0; i < result.size(); i++) + nodeSet.insert(result[i].first); + std::copy(nodeSet.begin(), nodeSet.end(), back_inserter(nodes)); } - m_taskCond.notify_one(); + return nodes; } -} -void -Library::cancelTasks(const TaskVector& tasks) const -{ - if (!tasks.empty()) + const Task* Library::nodeOfMediaASync(const URL&, + NodeQueryResultFunction) const + { + return 0; + } + + Library::NodePropertyResult + Library::referencesToNode(const Node* node) const { // - // One lock many cancels + // NOTE: this is a *terrible* way to do this. Each library + // implementation would presumably have a much more efficient way of + // doing this querry. The default implementation (scan every node in + // the library) works only as a stand in. // + NodePropertyResult result; + recursiveFindReferences(node->url(), rootNode(), result); + return result; + } + + const Task* + Library::referencesToNodeASync(const Node*, + PropertyQueryResultFunction) const + { + return 0; + } + + void Library::threadTrampoline(Library* library) { library->threadMain(); } + + void Library::addTask(Task* item) const + { ScopedLock lock(m_taskMutex); + m_taskQueue.push_back(item); + m_taskCond.notify_one(); + } - for (size_t q = 0; q < tasks.size(); q++) + void Library::cancelTask(const Task* item) const + { + if (item && item->library() == this) { - const Task* item = tasks[q]; + ScopedLock lock(m_taskMutex); - if (item && item->library() == this) + TaskDeque::iterator i = + find(m_taskQueue.begin(), m_taskQueue.end(), item); + + if (i != m_taskQueue.end()) { - TaskDeque::iterator i = find(m_taskQueue.begin(), m_taskQueue.end(), item); - - if (i != m_taskQueue.end()) - { - delete *i; - m_taskQueue.erase(i); - } + delete *i; + m_taskQueue.erase(i); } + + m_taskCond.notify_one(); } - - m_taskCond.notify_one(); } -} -void -Library::threadMain() -{ - // - // Worker thread parks in here - // + void Library::cancelTasks(const TaskVector& tasks) const + { + if (!tasks.empty()) + { + // + // One lock many cancels + // - TwkUtil::setThreadName("Library Task Thread"); + ScopedLock lock(m_taskMutex); - ScopedLock lock(m_taskMutex); - m_taskStop = false; + for (size_t q = 0; q < tasks.size(); q++) + { + const Task* item = tasks[q]; + + if (item && item->library() == this) + { + TaskDeque::iterator i = + find(m_taskQueue.begin(), m_taskQueue.end(), item); + + if (i != m_taskQueue.end()) + { + delete *i; + m_taskQueue.erase(i); + } + } + } - while (!m_taskStop) + m_taskCond.notify_one(); + } + } + + void Library::threadMain() { - while (!m_taskStop && m_taskQueue.empty()) m_taskCond.wait(lock); + // + // Worker thread parks in here + // - if (!m_taskStop && !m_taskQueue.empty()) + TwkUtil::setThreadName("Library Task Thread"); + + ScopedLock lock(m_taskMutex); + m_taskStop = false; + + while (!m_taskStop) { - Task* item = m_taskQueue.front(); - m_taskQueue.pop_front(); - lock.unlock(); + while (!m_taskStop && m_taskQueue.empty()) + m_taskCond.wait(lock); - try - { - item->execute(); - } - catch (const std::exception& exc) + if (!m_taskStop && !m_taskQueue.empty()) { - cout << "ERROR: Library worker thread caught: " << exc.what() << endl; - } - catch (...) - { - cout << "ERROR: Library worker thread uncaught exception" << endl; + Task* item = m_taskQueue.front(); + m_taskQueue.pop_front(); + lock.unlock(); + + try + { + item->execute(); + } + catch (const std::exception& exc) + { + cout << "ERROR: Library worker thread caught: " + << exc.what() << endl; + } + catch (...) + { + cout << "ERROR: Library worker thread uncaught exception" + << endl; + } + + delete item; + lock.lock(); } - - delete item; - lock.lock(); } } -} -Library* -libraryOfURL(const URL& inURL) -{ - QUrl url(inURL.c_str()); - - if (url.scheme() == "sglib") + Library* libraryOfURL(const URL& inURL) { - string libname = url.host().toUtf8().constData(); - LibraryMap::const_iterator i = globalLibraryMap.find(libname); - if (i != globalLibraryMap.end()) return i->second; - } - - return 0; -} + QUrl url(inURL.c_str()); -const Node* -nodeOfURL(const URL& inURL) -{ - if (Library* l = libraryOfURL(inURL)) - { - if (const Node* node = l->nodeFromLibraryURL(inURL)) + if (url.scheme() == "sglib") { - return node; - } - else - { - QUrl url(inURL.c_str()); - if (url.path() == "") return l->rootNode(); + string libname = url.host().toUtf8().constData(); + LibraryMap::const_iterator i = globalLibraryMap.find(libname); + if (i != globalLibraryMap.end()) + return i->second; } + + return 0; } - return 0; -} + const Node* nodeOfURL(const URL& inURL) + { + if (Library* l = libraryOfURL(inURL)) + { + if (const Node* node = l->nodeFromLibraryURL(inURL)) + { + return node; + } + else + { + QUrl url(inURL.c_str()); + if (url.path() == "") + return l->rootNode(); + } + } -NodeVector -libraryNodesAssociatedWithURL(const URL& inURL) -{ - NodeVector nodes; + return 0; + } - for (LibraryMap::const_iterator i = globalLibraryMap.begin(); - i != globalLibraryMap.end(); - ++i) + NodeVector libraryNodesAssociatedWithURL(const URL& inURL) { - NodeVector n = i->second->associatedNodes(inURL); - std::copy(n.begin(), n.end(), back_inserter(nodes)); - } + NodeVector nodes; - return nodes; -} + for (LibraryMap::const_iterator i = globalLibraryMap.begin(); + i != globalLibraryMap.end(); ++i) + { + NodeVector n = i->second->associatedNodes(inURL); + std::copy(n.begin(), n.end(), back_inserter(nodes)); + } -URLVector -libraryURLsAssociatedWithURL(const URL& inURL) -{ - URLVector urls; + return nodes; + } - for (LibraryMap::const_iterator i = globalLibraryMap.begin(); - i != globalLibraryMap.end(); - ++i) + URLVector libraryURLsAssociatedWithURL(const URL& inURL) { - NodeVector n = i->second->associatedNodes(inURL); + URLVector urls; - for (size_t q = 0; q < n.size(); q++) urls.push_back(n[q]->persistentURL()); - } + for (LibraryMap::const_iterator i = globalLibraryMap.begin(); + i != globalLibraryMap.end(); ++i) + { + NodeVector n = i->second->associatedNodes(inURL); - return urls; -} + for (size_t q = 0; q < n.size(); q++) + urls.push_back(n[q]->persistentURL()); + } -URLVector -libraryURLsOfMedia(const URL& mediaURL) -{ - URLVector urls; + return urls; + } - for (LibraryMap::const_iterator i = globalLibraryMap.begin(); - i != globalLibraryMap.end(); - ++i) + URLVector libraryURLsOfMedia(const URL& mediaURL) { - if (const Node* node = i->second->nodeOfMedia(mediaURL)) + URLVector urls; + + for (LibraryMap::const_iterator i = globalLibraryMap.begin(); + i != globalLibraryMap.end(); ++i) { - urls.push_back(node->persistentURL()); + if (const Node* node = i->second->nodeOfMedia(mediaURL)) + { + urls.push_back(node->persistentURL()); + } } - } - return urls; -} + return urls; + } -bool -isLibraryMediaURL(const URL& mediaURL) -{ - for (LibraryMap::const_iterator i = globalLibraryMap.begin(); - i != globalLibraryMap.end(); - ++i) + bool isLibraryMediaURL(const URL& mediaURL) { - if (i->second->isLibraryMediaURL(mediaURL)) return true; - } + for (LibraryMap::const_iterator i = globalLibraryMap.begin(); + i != globalLibraryMap.end(); ++i) + { + if (i->second->isLibraryMediaURL(mediaURL)) + return true; + } - return false; -} + return false; + } -} // TwkMediaLibrary +} // namespace TwkMediaLibrary diff --git a/src/lib/app/TwkMediaLibrary/TwkMediaLibrary/Library.h b/src/lib/app/TwkMediaLibrary/TwkMediaLibrary/Library.h index 5808cfad5..ee14b4956 100644 --- a/src/lib/app/TwkMediaLibrary/TwkMediaLibrary/Library.h +++ b/src/lib/app/TwkMediaLibrary/TwkMediaLibrary/Library.h @@ -1,9 +1,9 @@ // -// Copyright (c) 2015 Tweak Software. +// Copyright (c) 2015 Tweak Software. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// // #ifndef __TwkMediaLibrary__Library__h__ #define __TwkMediaLibrary__Library__h__ @@ -16,821 +16,947 @@ #include #include -namespace TwkMediaLibrary { - -/// Module Types - -// -// URL : Any scheme -// LibraryURL : Library scheme -// InternalPath : UNIX style path relative to library root -- -// may or may not correspond to equivalent -// LibraryURL -// - - -struct HTTPCookie -{ - HTTPCookie(const std::string& d, - const std::string& p, - const std::string& n, - const std::string& v) - : domain(d), - path(p), - name(n), - value(v) {} - - std::string domain; - std::string path; - std::string name; - std::string value; -}; - -struct HTTPHeader -{ - HTTPHeader(std::string n, - std::string v) - : name(std::move(n)), - value(std::move(v)) {} - - std::string name; - std::string value; -}; - -// -// All std::strings are assumed to be UTF-8 encoded *except* for URLs. -// These should be the subset of UTF-8 strings producing valid URLs. -// - -typedef std::string URL; -typedef std::string LibraryURL; -typedef std::string InternalPath; -typedef std::string FileSystemPath; -typedef std::string MimeType; -typedef boost::any PropertyValue; -typedef std::vector PropertyValueVector; -typedef std::string PropertyKey; -typedef std::vector PropertyKeyVector; -typedef std::vector URLVector; -typedef std::vector StringVector; -typedef std::vector IntVector; -typedef std::pair StringPair; -typedef std::vector StringPairVector; -typedef std::vector HTTPCookieVector; -typedef std::vector HTTPHeaderVector; - -enum PropertyType -{ - UnknownType, - - FloatType, - IntType, - StringType, - BoolType, - ReferenceType, - URLType, - DateType, - DateAndTimeType, - - IntListType, - StringListType, - ReferenceListType, - URLListType, - - FirstListType = IntListType - - // FIELD TYPES (shotgun) - // --------------------- - // DateType, - // DateAndTime, - // Duration, - // Entity, - // Multi-Entity, - // File/Link - // Footage - // List (enum) - // Number (???) - // Percent - // Query - // Status List - // Text - // Timecode - // URL Template - - // ATTRIBUTES (mac media libs) - // --------------------------- -}; - -enum PropertyFlags -{ - ReadFlag = 1 << 0, - WriteFlag = 1 << 1, - HiddenFlag = 1 << 2, -}; - - -struct MediaFileInfo -{ - std::string hashValue; - float hashTimeInSeconds; - size_t fileSize; -}; - - -enum UserCapabilityFlags -{ - AdministratorCapabilityFlag = 1 << 0, - NoWatermarkCapabilityFlag = 1 << 1, // no watermarks while viewing media - ExportCapabilityFlag = 1 << 2, // can export to movie/audio files - RawExportCapabilityFlag = 1 << 3, // can export raw media files - EditCapabilityFlag = 1 << 4, // can edit library - - DefaultCapabiliesFlag = AdministratorCapabilityFlag - | NoWatermarkCapabilityFlag - | ExportCapabilityFlag - | RawExportCapabilityFlag - | EditCapabilityFlag -}; - -enum TaskType +namespace TwkMediaLibrary { - QueryTaskType, - EditingTaskType -}; -class Library; + /// Module Types -/// class Node is a handle to an object in the library - -/// -/// class Node -/// - -class Node -{ - public: - // - // Status - // - - virtual bool isValid() const; - virtual std::string name() const; - virtual std::string typeName() const; - virtual std::string description() const; - - // - // Hierarchy - // - - virtual const Node* parent() const; - virtual size_t numChildren() const; - virtual const Node* child(size_t index) const; - virtual const Library* library() const { return m_library; } - virtual size_t index() const; - virtual const Node* findChildByName(const std::string&) const; - virtual bool hasAncestor(const Node*) const; - - // - // InternalPaths to the node and related media. These are paths - // relative to the library in the hierarchy space. - // - // Internal Paths look like: - // - // /root/path/to/the/node - // - // they are abstract and don't necessarily correspond to real - // file system paths. They may or may not be valid Library URLs - // if prefixed by the sglib:// scheme. That's up to the library - // implementation. - // - // PropertyValues that cross reference nodes may use InternalPath - // - // path() : the path to this node - // mediaPath() : path to the "current" media node (could be path()) - // - - virtual InternalPath path() const; - virtual InternalPath mediaPath() const; - - // - // Globally accessible locations. Only url() will return a library - // URL. The other return a "browsable" URL. An actual object should - // exist at the URL. // - // Some examples of url() might be: + // URL : Any scheme + // LibraryURL : Library scheme + // InternalPath : UNIX style path relative to library root -- + // may or may not correspond to equivalent + // LibraryURL // - // ShotGrid Server : sglib://shotgun/server.shotgridsoftware.com/path/to/a/node - // Local : sglib://local/path/to/a/node - // - // Some examples of mediaURL() or thumbnailImageURL() might be: - // - // ShotGrid Server : http://server.shotgridsoftware.com/path/to/a/node?media - // Local : file:///Users/name/Movies/mylibrary.sglib/node21/hires.mov - // Local : file:///Users/name/Movies/mylibrary.sglib/node32131/thumbnail.jpg - // - - virtual LibraryURL url() const; - virtual LibraryURL persistentURL() const; - virtual URL mediaURL() const; - virtual URL thumbnailImageURL() const; - - // - // MimeType is a two-part identifier for file formats and format - // contents (from Wikipedia). - // - - virtual MimeType mediaMimeType() const; - - // - // Properties - // Property Paths: sglib://path/to/node#propertykey - // - // The schema used by a node to hold its state should not be assumed - // by code using the MediaLibrary API. To get semantic information - // from a node without needing to know about the schema use one of the - // API objects below. E.g. the UserAPI will give you the name of a - // user without needing to know which property or properties store - // that information. - // - - virtual size_t numKeys() const; - virtual PropertyKey key(size_t index) const; - virtual PropertyKeyVector keys() const; - virtual bool hasProperty(const PropertyKey&) const; - virtual PropertyValue propertyValue(const PropertyKey&) const; - virtual PropertyType propertyType(const PropertyKey&) const; - std::string propertyValueAsString(const PropertyKey&) const; - - // - // Metaproperties - // - // These are properties *of* properties. They are assumed to be - // constant and vary with node type. An example use might be to - // provide a specific default value or a list of enum values for the - // UI, etc, etc. - // - - virtual size_t numMetaKeys(const PropertyKey&) const; - virtual PropertyKey metaKey(const PropertyKey&, size_t index) const; - virtual PropertyKeyVector metaKeys(const PropertyKey&) const; - virtual bool hasMeta(const PropertyKey&, const PropertyKey&) const; - virtual PropertyValue metaValue(const PropertyKey&, const PropertyKey& metaKey) const; - virtual PropertyType metaType(const PropertyKey&, const PropertyKey& metaKey) const; - std::string metaValueAsString(const PropertyKey&, const PropertyKey&) const; - - // - // Utilities - // - - std::ostream& output(std::ostream&) const; - - protected: - Node(Library*); - virtual ~Node(); - - // - // Mutating functions. These should only be called through the edit - // object - // - - virtual bool deleteProperty(const PropertyKey&); - virtual void setProperty(const PropertyKey&, PropertyType type, const PropertyValue& value); - virtual void setPropertyFromString(const PropertyKey&, PropertyType type, const std::string& value); - virtual void setName(const std::string&); - virtual void setParent(const Node*); - - friend class Library; - friend class NodeEdit; - - protected: - Library* m_library; -}; - -typedef std::vector NodeVector; - - -/// NodeAPI adds specific API to Node via a separate object - -class NodeAPI -{ - public: - virtual const Node* node() const = 0; - - protected: - NodeAPI() {} - virtual ~NodeAPI(); -}; - -/// CapabilityAPI makes - -/// -/// class CapabilityAPI -/// -/// Nodes which can be used to authenticate are CapabilityNodes. Right now -/// that's just UserNode and OrganizationNode. -/// - -class CapabilityAPI; -class UserAPI; -class OrganizationAPI; -class WatermarkAPI; - -typedef std::vector UserAPIVector; -typedef std::vector OrganizationAPIVector; -typedef std::vector WatermarkAPIVector; - -class CapabilityAPI : public NodeAPI -{ - public: - virtual std::string loginName() const = 0; - virtual bool passwordMatches(const std::string& plainTextUTF8) const = 0; - virtual UserCapabilityFlags capabilities() const = 0; - - protected: - CapabilityAPI() : NodeAPI() {} - virtual ~CapabilityAPI(); -}; -class UserAPI : public CapabilityAPI -{ - public: - virtual const OrganizationAPI* organization() const = 0; - - protected: - UserAPI() : CapabilityAPI() {} - virtual ~UserAPI(); -}; - -class OrganizationAPI : public CapabilityAPI -{ - public: - virtual UserAPIVector users() const = 0; - - protected: - OrganizationAPI() : CapabilityAPI() {} - virtual ~OrganizationAPI(); -}; - -class WatermarkAPI : public NodeAPI -{ - public: - virtual std::string text() const = 0; - - protected: - WatermarkAPI() : NodeAPI() {} - virtual ~WatermarkAPI(); -}; - -class CutAPI : public NodeAPI -{ - public: - virtual int cutStart() const = 0; - virtual int cutEnd() const = 0; - virtual float cutFPS() const = 0; - virtual size_t numClips() const = 0; - virtual std::string clipMedia(size_t) const = 0; - virtual const Node* clipNode(size_t) const = 0; - virtual float clipFPS(size_t) const = 0; - virtual int clipIn(size_t) const = 0; - virtual int clipOut(size_t) const = 0; - virtual int cutIn(size_t) const = 0; - virtual int cutOut(size_t) const = 0; - - protected: - CutAPI() : NodeAPI() {} - virtual ~CutAPI(); -}; - -class NoteAPI : public NodeAPI -{ - public: - virtual std::string content() const = 0; - virtual const Node* toUser() const = 0; - virtual NodeVector ccUsers() const = 0; - virtual URLVector attachments() const = 0; - virtual NodeVector objectsOfNote() const = 0; - - protected: - NoteAPI() : NodeAPI() {} - virtual ~NoteAPI(); -}; - -class MediaAPI : public NodeAPI -{ - public: - virtual bool isStreaming() const = 0; - virtual bool isRedirecting() const = 0; - virtual const Node* baseMediaNode() const = 0; // iff isProxy() == true - virtual HTTPCookieVector httpCookies() const; - virtual HTTPHeaderVector httpHeaders() const; - virtual URL httpRedirection() const; - - protected: - MediaAPI() : NodeAPI() {} - virtual ~MediaAPI(); -}; - -/// class NodeEdit is used on the stack to make mutating changes to a Node - -/// -/// class NodeEdit -/// -/// Usage: -/// -/// { -/// const Node* node = ...; -/// NodeEdit edit(node); -/// edit.setName("foo"); -/// } -/// - -class NodeEdit -{ - public: - NodeEdit(const Node* n) - : m_node(const_cast(n)), - m_library(n->m_library) {} - ~NodeEdit() {} - - bool deleteProperty(const PropertyKey& k) { bool b = n()->deleteProperty(k); return b; } - void setProperty(const PropertyKey& k, PropertyType t, const PropertyValue& v) { n()->setProperty(k,t,v); } - void setPropertyFromString(const PropertyKey& k, PropertyType t, const std::string& v) { n()->setPropertyFromString(k,t,v); } - void setName(const std::string& name) { n()->setName(name); } - void setParent(const Node* p) { n()->setParent(p); } - - protected: - Node* n() { return m_node; } - - private: - Node* m_node; - Library* m_library; -}; - -/// Task - an asynchronous parallel task - -/// -/// This class does *not* manage its own thread. The execute function -/// should be blocking. Task to thread assignment is handled elsewhere. -/// - -class Task -{ - public: - Task(const std::string& name, Library* l, TaskType t) - : m_name(name), m_library(l), m_type(t) {} - virtual ~Task(); - - Library* library() const { return m_library; } - TaskType type() const { return m_type; } - const std::string& name() const { return m_name; } - virtual void execute() = 0; - - private: - Library* m_library; - TaskType m_type; - std::string m_name; -}; - -typedef std::vector TaskVector; - -/// class Library is the base API for a media library + struct HTTPCookie + { + HTTPCookie(const std::string& d, const std::string& p, + const std::string& n, const std::string& v) + : domain(d) + , path(p) + , name(n) + , value(v) + { + } + + std::string domain; + std::string path; + std::string name; + std::string value; + }; + + struct HTTPHeader + { + HTTPHeader(std::string n, std::string v) + : name(std::move(n)) + , value(std::move(v)) + { + } + + std::string name; + std::string value; + }; + + // + // All std::strings are assumed to be UTF-8 encoded *except* for URLs. + // These should be the subset of UTF-8 strings producing valid URLs. + // + + typedef std::string URL; + typedef std::string LibraryURL; + typedef std::string InternalPath; + typedef std::string FileSystemPath; + typedef std::string MimeType; + typedef boost::any PropertyValue; + typedef std::vector PropertyValueVector; + typedef std::string PropertyKey; + typedef std::vector PropertyKeyVector; + typedef std::vector URLVector; + typedef std::vector StringVector; + typedef std::vector IntVector; + typedef std::pair StringPair; + typedef std::vector StringPairVector; + typedef std::vector HTTPCookieVector; + typedef std::vector HTTPHeaderVector; + + enum PropertyType + { + UnknownType, + + FloatType, + IntType, + StringType, + BoolType, + ReferenceType, + URLType, + DateType, + DateAndTimeType, + + IntListType, + StringListType, + ReferenceListType, + URLListType, + + FirstListType = IntListType + + // FIELD TYPES (shotgun) + // --------------------- + // DateType, + // DateAndTime, + // Duration, + // Entity, + // Multi-Entity, + // File/Link + // Footage + // List (enum) + // Number (???) + // Percent + // Query + // Status List + // Text + // Timecode + // URL Template + + // ATTRIBUTES (mac media libs) + // --------------------------- + }; + + enum PropertyFlags + { + ReadFlag = 1 << 0, + WriteFlag = 1 << 1, + HiddenFlag = 1 << 2, + }; -/// -/// class Library -/// + struct MediaFileInfo + { + std::string hashValue; + float hashTimeInSeconds; + size_t fileSize; + }; -class Library -{ - public: - // - // Types - // + enum UserCapabilityFlags + { + AdministratorCapabilityFlag = 1 << 0, + NoWatermarkCapabilityFlag = 1 << 1, // no watermarks while viewing media + ExportCapabilityFlag = 1 << 2, // can export to movie/audio files + RawExportCapabilityFlag = 1 << 3, // can export raw media files + EditCapabilityFlag = 1 << 4, // can edit library + + DefaultCapabiliesFlag = AdministratorCapabilityFlag + | NoWatermarkCapabilityFlag + | ExportCapabilityFlag | RawExportCapabilityFlag + | EditCapabilityFlag + }; + + enum TaskType + { + QueryTaskType, + EditingTaskType + }; - typedef void (VoidFunc)(void); - typedef void (NodeFunc)(const Node*); - typedef void (NodePairFunc)(const Node*, const Node*); - typedef void (NodeStringFunc)(const Node*, const std::string&); - typedef void (NodeSizetFunc)(const Node*, size_t); - typedef void (StringFunc)(const std::string&); - typedef void (NodeMoveFunc)(const Node*, const Node*, size_t, const Node*, size_t); - - typedef boost::signals2::signal VoidSignal; - typedef boost::signals2::signal NodeSignal; - typedef boost::signals2::signal NodePairSignal; - typedef boost::signals2::signal NodePropertySignal; - typedef boost::signals2::signal NodeIndexSignal; - typedef boost::signals2::signal NodeMoveSignal; - typedef boost::signals2::signal StringSignal; - typedef std::pair NodePropertyKeyVectorPair; - typedef std::vector NodePropertyResult; - typedef boost::mutex Mutex; - typedef boost::mutex::scoped_lock ScopedLock; - typedef boost::thread Thread; - typedef boost::condition_variable Condition; - typedef std::deque TaskDeque; - - typedef void (NodePropertyResultFunc)(const Task*, const NodePropertyResult&); - typedef void (NodeTaskFunc)(const Task*, const Node*); - - typedef boost::function PropertyQueryResultFunction; - typedef boost::function NodeQueryResultFunction; + class Library; - // - // Constructors - // + /// class Node is a handle to an object in the library - explicit Library(const std::string& typeName, const std::string& appName); - virtual ~Library(); + /// + /// class Node + /// - // - // Capabilities - // + class Node + { + public: + // + // Status + // + + virtual bool isValid() const; + virtual std::string name() const; + virtual std::string typeName() const; + virtual std::string description() const; + + // + // Hierarchy + // + + virtual const Node* parent() const; + virtual size_t numChildren() const; + virtual const Node* child(size_t index) const; + + virtual const Library* library() const { return m_library; } + + virtual size_t index() const; + virtual const Node* findChildByName(const std::string&) const; + virtual bool hasAncestor(const Node*) const; + + // + // InternalPaths to the node and related media. These are paths + // relative to the library in the hierarchy space. + // + // Internal Paths look like: + // + // /root/path/to/the/node + // + // they are abstract and don't necessarily correspond to real + // file system paths. They may or may not be valid Library URLs + // if prefixed by the sglib:// scheme. That's up to the library + // implementation. + // + // PropertyValues that cross reference nodes may use InternalPath + // + // path() : the path to this node + // mediaPath() : path to the "current" media node (could be path()) + // + + virtual InternalPath path() const; + virtual InternalPath mediaPath() const; + + // + // Globally accessible locations. Only url() will return a library + // URL. The other return a "browsable" URL. An actual object should + // exist at the URL. + // + // Some examples of url() might be: + // + // ShotGrid Server : + // sglib://shotgun/server.shotgridsoftware.com/path/to/a/node Local : + // sglib://local/path/to/a/node + // + // Some examples of mediaURL() or thumbnailImageURL() might be: + // + // ShotGrid Server : + // http://server.shotgridsoftware.com/path/to/a/node?media Local : + // file:///Users/name/Movies/mylibrary.sglib/node21/hires.mov Local : + // file:///Users/name/Movies/mylibrary.sglib/node32131/thumbnail.jpg + // + + virtual LibraryURL url() const; + virtual LibraryURL persistentURL() const; + virtual URL mediaURL() const; + virtual URL thumbnailImageURL() const; + + // + // MimeType is a two-part identifier for file formats and format + // contents (from Wikipedia). + // + + virtual MimeType mediaMimeType() const; + + // + // Properties + // Property Paths: sglib://path/to/node#propertykey + // + // The schema used by a node to hold its state should not be assumed + // by code using the MediaLibrary API. To get semantic information + // from a node without needing to know about the schema use one of the + // API objects below. E.g. the UserAPI will give you the name of a + // user without needing to know which property or properties store + // that information. + // + + virtual size_t numKeys() const; + virtual PropertyKey key(size_t index) const; + virtual PropertyKeyVector keys() const; + virtual bool hasProperty(const PropertyKey&) const; + virtual PropertyValue propertyValue(const PropertyKey&) const; + virtual PropertyType propertyType(const PropertyKey&) const; + std::string propertyValueAsString(const PropertyKey&) const; + + // + // Metaproperties + // + // These are properties *of* properties. They are assumed to be + // constant and vary with node type. An example use might be to + // provide a specific default value or a list of enum values for the + // UI, etc, etc. + // + + virtual size_t numMetaKeys(const PropertyKey&) const; + virtual PropertyKey metaKey(const PropertyKey&, size_t index) const; + virtual PropertyKeyVector metaKeys(const PropertyKey&) const; + virtual bool hasMeta(const PropertyKey&, const PropertyKey&) const; + virtual PropertyValue metaValue(const PropertyKey&, + const PropertyKey& metaKey) const; + virtual PropertyType metaType(const PropertyKey&, + const PropertyKey& metaKey) const; + std::string metaValueAsString(const PropertyKey&, + const PropertyKey&) const; + + // + // Utilities + // + + std::ostream& output(std::ostream&) const; + + protected: + Node(Library*); + virtual ~Node(); + + // + // Mutating functions. These should only be called through the edit + // object + // + + virtual bool deleteProperty(const PropertyKey&); + virtual void setProperty(const PropertyKey&, PropertyType type, + const PropertyValue& value); + virtual void setPropertyFromString(const PropertyKey&, + PropertyType type, + const std::string& value); + virtual void setName(const std::string&); + virtual void setParent(const Node*); + + friend class Library; + friend class NodeEdit; + + protected: + Library* m_library; + }; + + typedef std::vector NodeVector; + + /// NodeAPI adds specific API to Node via a separate object + + class NodeAPI + { + public: + virtual const Node* node() const = 0; - virtual bool isReadable() const; - virtual bool isWriteable() const; - virtual bool hasWritableProperties() const; - virtual bool hasImport() const; - virtual bool hasExport() const; + protected: + NodeAPI() {} - // - // Signals - // - // NOTE: willDeleteSignal() should be sent by the most derived class' - // destructor before any state changes occur (even before that). The - // base class will also send it, but if its used that's almost a - // guaranteed core dump - // - // nodePropertiesWillBeAddedSignal() and nodePropertiesAddedSignal() - // should be sent when unique node properties are created on a single - // node. In the case that the schema changes use - // nodeSchemeChangedSignal() and nodeSchemeWillChangeSignal() in which - // case the node argument will be the scheme itself *not* a node in - // the library. - // + virtual ~NodeAPI(); + }; - VoidSignal& willDeleteSignal() { return m_willDeleteSignal; } - NodeSignal& nodeTreeWillDeleteSignal() { return m_nodeTreeWillDeleteSignal; } - NodeSignal& nodeTreeDidDeleteSignal() { return m_nodeTreeDidDeleteSignal; } - NodeSignal& nodeWillDeleteSignal() { return m_nodeWillDeleteSignal; } - NodeSignal& nodeDidDeleteSignal() { return m_nodeDidDeleteSignal; } - NodeIndexSignal& willCreateNodeSignal() { return m_willCreateNodeSignal; } - NodeSignal& newNodeSignal() { return m_newNodeSignal; } - NodePropertySignal& nodePropertyChangedSignal() { return m_nodePropertyChangedSignal; } - NodeSignal& nodePropertiesWillBeAddedSignal() { return m_nodePropertiesWillBeAddedSignal; } - NodeSignal& nodePropertiesAddedSignal() { return m_nodePropertiesAddedSignal; } - StringSignal& nameChangedSignal() { return m_nameChangedSignal; } - NodeSignal& nodeNameChangedSignal() { return m_nodeNameChangedSignal; } + /// CapabilityAPI makes - NodePairSignal& willChangeNodeParentSignal() { return m_willChangeNodeParentSignal; } - NodePairSignal& nodeParentChangedSignal() { return m_nodeParentChangedSignal; } + /// + /// class CapabilityAPI + /// + /// Nodes which can be used to authenticate are CapabilityNodes. Right now + /// that's just UserNode and OrganizationNode. + /// - NodeIndexSignal& willReorderNodeSignal() { return m_willReorderNodeSignal; } - NodeSignal& nodeReorderedSignal() { return m_nodeReorderedSignal; } + class CapabilityAPI; + class UserAPI; + class OrganizationAPI; + class WatermarkAPI; - NodeSignal& nodeSchemeWillChangeSignal() { return m_nodeShemeWillChangeSignal; } - NodeSignal& nodeSchemeChangedSignal() { return m_nodeShemeChangedSignal; } + typedef std::vector UserAPIVector; + typedef std::vector OrganizationAPIVector; + typedef std::vector WatermarkAPIVector; - NodeMoveSignal& willMoveNodeSignal() { return m_willMoveSignal; } - NodeSignal& nodeMovedSignal() { return m_movedSignal; } + class CapabilityAPI : public NodeAPI + { + public: + virtual std::string loginName() const = 0; + virtual bool + passwordMatches(const std::string& plainTextUTF8) const = 0; + virtual UserCapabilityFlags capabilities() const = 0; + + protected: + CapabilityAPI() + : NodeAPI() + { + } + + virtual ~CapabilityAPI(); + }; + + class UserAPI : public CapabilityAPI + { + public: + virtual const OrganizationAPI* organization() const = 0; - const std::string& typeName() const { return m_typeName; } - const std::string& appName() const { return m_appName; } - const std::string& name() const { return m_name; } + protected: + UserAPI() + : CapabilityAPI() + { + } - virtual URL url() const; + virtual ~UserAPI(); + }; - void setName(const std::string&); + class OrganizationAPI : public CapabilityAPI + { + public: + virtual UserAPIVector users() const = 0; - // - // Enumerate all node supported node types - // + protected: + OrganizationAPI() + : CapabilityAPI() + { + } - virtual size_t numNodeTypeNames() const; - virtual std::string nodeTypeName(size_t) const; + virtual ~OrganizationAPI(); + }; - // - // Authentication - // - // The user should match either the default user or one in the library - // itself. If isAuthenticated() is true than a user has been - // authenticated successfully. The authenticatedCapabilityNode() is - // the CapabilityNode of the authenticated user/organization. - // - // owner() will return the CapabilityNode of the owner of this library - // if there is one. - // - - virtual bool isAuthenticated() const; - virtual bool authenticate(const std::string& authenticationName, const std::string& password) const; - virtual const CapabilityAPI* authenticatedCapabilityAPI() const; - virtual const CapabilityAPI* owner() const; - - // - // Manage Nodes - // - // NOTE: deleteNode() should delete all its ancestors analogous - // to shell command: rm -rf. Child ordering should remain stable - // if a child is deleted (but obviously some children may have - // new child index numbers). - // + class WatermarkAPI : public NodeAPI + { + public: + virtual std::string text() const = 0; - virtual const Node* newNode(const std::string& nodeTypeName); - virtual void deleteNode(const Node*); - virtual void setNodeName(const Node*, const std::string&); - virtual void setNodeParent(const Node*, const Node*); - virtual void reorderNode(const Node*, size_t newIndex); - - virtual void moveNode(const Node* node, const Node* newParent, size_t newIndex); + protected: + WatermarkAPI() + : NodeAPI() + { + } - // - // Isolating a node does not delete the node but it does make it - // inaccessible to the outside world. After calling isolateNode() and - // if the function returns true, the pointer to the node is no longer - // valid, but has not been deleted; the only function which may be - // called with the pointer is restoreIsolatedNode(). If - // restoreIsolatedNode() is called the pointer becomes valid again. - // When the library is closed, nodes that have been isolated but not - // restored will be destroyed permanently. - // - // This mechanism exists to efficiently implement undo/redo. The - // default implementation does nothing -- isolateNode returns false - // indicating that it failed (and no changes have occured, the node is - // still valid). - // + virtual ~WatermarkAPI(); + }; - virtual bool isolateNode(const Node*); - virtual void restoreIsolatedNode(const Node*); + class CutAPI : public NodeAPI + { + public: + virtual int cutStart() const = 0; + virtual int cutEnd() const = 0; + virtual float cutFPS() const = 0; + virtual size_t numClips() const = 0; + virtual std::string clipMedia(size_t) const = 0; + virtual const Node* clipNode(size_t) const = 0; + virtual float clipFPS(size_t) const = 0; + virtual int clipIn(size_t) const = 0; + virtual int clipOut(size_t) const = 0; + virtual int cutIn(size_t) const = 0; + virtual int cutOut(size_t) const = 0; + + protected: + CutAPI() + : NodeAPI() + { + } + + virtual ~CutAPI(); + }; + + class NoteAPI : public NodeAPI + { + public: + virtual std::string content() const = 0; + virtual const Node* toUser() const = 0; + virtual NodeVector ccUsers() const = 0; + virtual URLVector attachments() const = 0; + virtual NodeVector objectsOfNote() const = 0; + + protected: + NoteAPI() + : NodeAPI() + { + } + + virtual ~NoteAPI(); + }; + + class MediaAPI : public NodeAPI + { + public: + virtual bool isStreaming() const = 0; + virtual bool isRedirecting() const = 0; + virtual const Node* baseMediaNode() const = 0; // iff isProxy() == true + virtual HTTPCookieVector httpCookies() const; + virtual HTTPHeaderVector httpHeaders() const; + virtual URL httpRedirection() const; + + protected: + MediaAPI() + : NodeAPI() + { + } + + virtual ~MediaAPI(); + }; + + /// class NodeEdit is used on the stack to make mutating changes to a Node + + /// + /// class NodeEdit + /// + /// Usage: + /// + /// { + /// const Node* node = ...; + /// NodeEdit edit(node); + /// edit.setName("foo"); + /// } + /// + + class NodeEdit + { + public: + NodeEdit(const Node* n) + : m_node(const_cast(n)) + , m_library(n->m_library) + { + } - // - // Querries - // - // referencesToNode() blocks and returns a vector of property - // URLs. The default implemenation will almost certainly be too slow - // for release code (it recursively scans library node properties each - // time its called). Each implementation should override it. - // Similarily, referencesToNodeASync() is also slow and will consume - // too many resources. In the ASync case an internal thread will be - // calling the PropertyQueryFunc. - // - // nodeOfMedia() will locate a Media node corresponding to the given - // file URL. The default implementation is dog slow and a resource - // hog. - // + ~NodeEdit() {} - virtual const Node* rootNode() const; - virtual const Node* nodeFromInternalPath(const InternalPath&) const; - virtual const Node* nodeFromLibraryURL(const LibraryURL&) const; + bool deleteProperty(const PropertyKey& k) + { + bool b = n()->deleteProperty(k); + return b; + } - virtual NodePropertyResult referencesToNode(const Node*) const; - virtual const Node* nodeOfMedia(const URL& url) const; - virtual NodeVector associatedNodes(const URL& url) const; + void setProperty(const PropertyKey& k, PropertyType t, + const PropertyValue& v) + { + n()->setProperty(k, t, v); + } - virtual const Task* referencesToNodeASync(const Node*, PropertyQueryResultFunction) const; - virtual const Task* nodeOfMediaASync(const URL&, NodeQueryResultFunction) const; + void setPropertyFromString(const PropertyKey& k, PropertyType t, + const std::string& v) + { + n()->setPropertyFromString(k, t, v); + } - virtual bool isLibraryMediaURL(const URL&) const; + void setName(const std::string& name) { n()->setName(name); } - // - // Import (Ingest) Media - // - // This will almost certainly launch an external process to ingest the - // media. - // - // isMediaSupported() returns false if its not supported. - // nodeTypeForMedia() return the name of the node type that - // would be created by newNodeFromMediaURL() - // newNodeFromMediaURL() creates a node of the proper type (which is - // up to the underlying implementation) - // newNodeFromCutURL() creates structures associated with a "cut - // file" which could be an rv/sgr session, - // exchange EDL format, etc. - // + void setParent(const Node* p) { n()->setParent(p); } - virtual bool isMediaSupported(const URL& url) const; - virtual std::string nodeTypeForMedia(const URL& url) const; - virtual const Node* newNodeFromMediaURL(const URL& url); - virtual const Node* newNodeFromCutURL(const URL& url); + protected: + Node* n() { return m_node; } - // - // copyToLibrary() copy an extrenally referenced file into - // the library itself. The property key should - // point to a URLType property. - // + private: + Node* m_node; + Library* m_library; + }; - virtual bool copyToLibrary(const Node*, const PropertyKey&); + /// Task - an asynchronous parallel task - // - // NodeAPI access - // + /// + /// This class does *not* manage its own thread. The execute function + /// should be blocking. Task to thread assignment is handled elsewhere. + /// - virtual const NodeAPI* nodeAPI(const Node*) const; - virtual UserAPIVector userNodeAPIs() const; - virtual OrganizationAPIVector organizationNodeAPIs() const; - virtual WatermarkAPIVector watermarkNodeAPIs() const; + class Task + { + public: + Task(const std::string& name, Library* l, TaskType t) + : m_name(name) + , m_library(l) + , m_type(t) + { + } - // - // In order to do a reverse look-up the media needs identifying - // information. This function, given a file, will compute that - // information. It does not do anything with it other than return it. - // + virtual ~Task(); - static MediaFileInfo computeMediaFileInfo(const URL& mediaURL); + Library* library() const { return m_library; } - // - // Export Media - // + TaskType type() const { return m_type; } - virtual URL exportMedia(const Node*) const; + const std::string& name() const { return m_name; } - // - // Utility functions - // + virtual void execute() = 0; - static std::string nameFromMedia(const URL&); - static std::string filenameOfMedia(const URL&); + private: + Library* m_library; + TaskType m_type; + std::string m_name; + }; - // - // ASync/Parallel Task API - // + typedef std::vector TaskVector; - static void threadTrampoline(Library*); - void threadMain(); - - void addTask(Task*) const; - void cancelTask(const Task*) const; - void cancelTasks(const TaskVector&) const; - - protected: - Library() {} - - private: - const std::string m_typeName; - const std::string m_appName; - std::string m_name; - VoidSignal m_willDeleteSignal; - NodeIndexSignal m_willCreateNodeSignal; - NodeSignal m_newNodeSignal; - NodeSignal m_nodeTreeWillDeleteSignal; - NodeSignal m_nodeTreeDidDeleteSignal; - NodeSignal m_nodeWillDeleteSignal; - NodeSignal m_nodeDidDeleteSignal; - NodePropertySignal m_nodePropertyChangedSignal; - NodeSignal m_nodePropertiesWillBeAddedSignal; - NodeSignal m_nodePropertiesAddedSignal; - StringSignal m_nameChangedSignal; - NodeSignal m_nodeNameChangedSignal; - - NodePairSignal m_nodeParentChangedSignal; - NodePairSignal m_willChangeNodeParentSignal; - - NodeIndexSignal m_willReorderNodeSignal; - NodeSignal m_nodeReorderedSignal; - - NodeMoveSignal m_willMoveSignal;; - NodeSignal m_movedSignal; - - NodeSignal m_nodeShemeWillChangeSignal; - NodeSignal m_nodeShemeChangedSignal; - Thread m_taskThread; - mutable Condition m_taskCond; - mutable Mutex m_taskMutex; - mutable bool m_taskStop; - mutable TaskDeque m_taskQueue; -}; + /// class Library is the base API for a media library -// -// Global -// + /// + /// class Library + /// -typedef std::map LibraryMap; - -bool isLibraryURL(const URL&); -bool isNodeURL(const URL&); -bool isPropertyURL(const URL&); -Library* libraryOfURL(const URL&); -const Node* nodeOfURL(const URL&); -const LibraryMap& allLibraries(); -URL libraryURLtoMediaURL(const URL&); -bool isLibraryMediaURL(const URL&); -URLVector libraryURLsOfMedia(const URL&); -NodeVector libraryNodesAssociatedWithURL(const URL&); -URLVector libraryURLsAssociatedWithURL(const URL&); -inline bool isPropertyListType(PropertyType t) { return t >= FirstListType; } - -template -inline const T* api_cast(const Node* node) -{ - if (const NodeAPI* api = node->library()->nodeAPI(node)) + class Library { - return dynamic_cast(api); - } - else + public: + // + // Types + // + + typedef void(VoidFunc)(void); + typedef void(NodeFunc)(const Node*); + typedef void(NodePairFunc)(const Node*, const Node*); + typedef void(NodeStringFunc)(const Node*, const std::string&); + typedef void(NodeSizetFunc)(const Node*, size_t); + typedef void(StringFunc)(const std::string&); + typedef void(NodeMoveFunc)(const Node*, const Node*, size_t, + const Node*, size_t); + + typedef boost::signals2::signal VoidSignal; + typedef boost::signals2::signal NodeSignal; + typedef boost::signals2::signal NodePairSignal; + typedef boost::signals2::signal NodePropertySignal; + typedef boost::signals2::signal NodeIndexSignal; + typedef boost::signals2::signal NodeMoveSignal; + typedef boost::signals2::signal StringSignal; + typedef std::pair + NodePropertyKeyVectorPair; + typedef std::vector NodePropertyResult; + typedef boost::mutex Mutex; + typedef boost::mutex::scoped_lock ScopedLock; + typedef boost::thread Thread; + typedef boost::condition_variable Condition; + typedef std::deque TaskDeque; + + typedef void(NodePropertyResultFunc)(const Task*, + const NodePropertyResult&); + typedef void(NodeTaskFunc)(const Task*, const Node*); + + typedef boost::function + PropertyQueryResultFunction; + typedef boost::function NodeQueryResultFunction; + + // + // Constructors + // + + explicit Library(const std::string& typeName, + const std::string& appName); + virtual ~Library(); + + // + // Capabilities + // + + virtual bool isReadable() const; + virtual bool isWriteable() const; + virtual bool hasWritableProperties() const; + virtual bool hasImport() const; + virtual bool hasExport() const; + + // + // Signals + // + // NOTE: willDeleteSignal() should be sent by the most derived class' + // destructor before any state changes occur (even before that). The + // base class will also send it, but if its used that's almost a + // guaranteed core dump + // + // nodePropertiesWillBeAddedSignal() and nodePropertiesAddedSignal() + // should be sent when unique node properties are created on a single + // node. In the case that the schema changes use + // nodeSchemeChangedSignal() and nodeSchemeWillChangeSignal() in which + // case the node argument will be the scheme itself *not* a node in + // the library. + // + + VoidSignal& willDeleteSignal() { return m_willDeleteSignal; } + + NodeSignal& nodeTreeWillDeleteSignal() + { + return m_nodeTreeWillDeleteSignal; + } + + NodeSignal& nodeTreeDidDeleteSignal() + { + return m_nodeTreeDidDeleteSignal; + } + + NodeSignal& nodeWillDeleteSignal() { return m_nodeWillDeleteSignal; } + + NodeSignal& nodeDidDeleteSignal() { return m_nodeDidDeleteSignal; } + + NodeIndexSignal& willCreateNodeSignal() + { + return m_willCreateNodeSignal; + } + + NodeSignal& newNodeSignal() { return m_newNodeSignal; } + + NodePropertySignal& nodePropertyChangedSignal() + { + return m_nodePropertyChangedSignal; + } + + NodeSignal& nodePropertiesWillBeAddedSignal() + { + return m_nodePropertiesWillBeAddedSignal; + } + + NodeSignal& nodePropertiesAddedSignal() + { + return m_nodePropertiesAddedSignal; + } + + StringSignal& nameChangedSignal() { return m_nameChangedSignal; } + + NodeSignal& nodeNameChangedSignal() { return m_nodeNameChangedSignal; } + + NodePairSignal& willChangeNodeParentSignal() + { + return m_willChangeNodeParentSignal; + } + + NodePairSignal& nodeParentChangedSignal() + { + return m_nodeParentChangedSignal; + } + + NodeIndexSignal& willReorderNodeSignal() + { + return m_willReorderNodeSignal; + } + + NodeSignal& nodeReorderedSignal() { return m_nodeReorderedSignal; } + + NodeSignal& nodeSchemeWillChangeSignal() + { + return m_nodeShemeWillChangeSignal; + } + + NodeSignal& nodeSchemeChangedSignal() + { + return m_nodeShemeChangedSignal; + } + + NodeMoveSignal& willMoveNodeSignal() { return m_willMoveSignal; } + + NodeSignal& nodeMovedSignal() { return m_movedSignal; } + + const std::string& typeName() const { return m_typeName; } + + const std::string& appName() const { return m_appName; } + + const std::string& name() const { return m_name; } + + virtual URL url() const; + + void setName(const std::string&); + + // + // Enumerate all node supported node types + // + + virtual size_t numNodeTypeNames() const; + virtual std::string nodeTypeName(size_t) const; + + // + // Authentication + // + // The user should match either the default user or one in the library + // itself. If isAuthenticated() is true than a user has been + // authenticated successfully. The authenticatedCapabilityNode() is + // the CapabilityNode of the authenticated user/organization. + // + // owner() will return the CapabilityNode of the owner of this library + // if there is one. + // + + virtual bool isAuthenticated() const; + virtual bool authenticate(const std::string& authenticationName, + const std::string& password) const; + virtual const CapabilityAPI* authenticatedCapabilityAPI() const; + virtual const CapabilityAPI* owner() const; + + // + // Manage Nodes + // + // NOTE: deleteNode() should delete all its ancestors analogous + // to shell command: rm -rf. Child ordering should remain stable + // if a child is deleted (but obviously some children may have + // new child index numbers). + // + + virtual const Node* newNode(const std::string& nodeTypeName); + virtual void deleteNode(const Node*); + virtual void setNodeName(const Node*, const std::string&); + virtual void setNodeParent(const Node*, const Node*); + virtual void reorderNode(const Node*, size_t newIndex); + + virtual void moveNode(const Node* node, const Node* newParent, + size_t newIndex); + + // + // Isolating a node does not delete the node but it does make it + // inaccessible to the outside world. After calling isolateNode() and + // if the function returns true, the pointer to the node is no longer + // valid, but has not been deleted; the only function which may be + // called with the pointer is restoreIsolatedNode(). If + // restoreIsolatedNode() is called the pointer becomes valid again. + // When the library is closed, nodes that have been isolated but not + // restored will be destroyed permanently. + // + // This mechanism exists to efficiently implement undo/redo. The + // default implementation does nothing -- isolateNode returns false + // indicating that it failed (and no changes have occured, the node is + // still valid). + // + + virtual bool isolateNode(const Node*); + virtual void restoreIsolatedNode(const Node*); + + // + // Querries + // + // referencesToNode() blocks and returns a vector of property + // URLs. The default implemenation will almost certainly be too slow + // for release code (it recursively scans library node properties each + // time its called). Each implementation should override it. + // Similarily, referencesToNodeASync() is also slow and will consume + // too many resources. In the ASync case an internal thread will be + // calling the PropertyQueryFunc. + // + // nodeOfMedia() will locate a Media node corresponding to the given + // file URL. The default implementation is dog slow and a resource + // hog. + // + + virtual const Node* rootNode() const; + virtual const Node* nodeFromInternalPath(const InternalPath&) const; + virtual const Node* nodeFromLibraryURL(const LibraryURL&) const; + + virtual NodePropertyResult referencesToNode(const Node*) const; + virtual const Node* nodeOfMedia(const URL& url) const; + virtual NodeVector associatedNodes(const URL& url) const; + + virtual const Task* + referencesToNodeASync(const Node*, PropertyQueryResultFunction) const; + virtual const Task* nodeOfMediaASync(const URL&, + NodeQueryResultFunction) const; + + virtual bool isLibraryMediaURL(const URL&) const; + + // + // Import (Ingest) Media + // + // This will almost certainly launch an external process to ingest the + // media. + // + // isMediaSupported() returns false if its not supported. + // nodeTypeForMedia() return the name of the node type that + // would be created by newNodeFromMediaURL() + // newNodeFromMediaURL() creates a node of the proper type (which is + // up to the underlying implementation) + // newNodeFromCutURL() creates structures associated with a "cut + // file" which could be an rv/sgr session, + // exchange EDL format, etc. + // + + virtual bool isMediaSupported(const URL& url) const; + virtual std::string nodeTypeForMedia(const URL& url) const; + virtual const Node* newNodeFromMediaURL(const URL& url); + virtual const Node* newNodeFromCutURL(const URL& url); + + // + // copyToLibrary() copy an extrenally referenced file into + // the library itself. The property key should + // point to a URLType property. + // + + virtual bool copyToLibrary(const Node*, const PropertyKey&); + + // + // NodeAPI access + // + + virtual const NodeAPI* nodeAPI(const Node*) const; + virtual UserAPIVector userNodeAPIs() const; + virtual OrganizationAPIVector organizationNodeAPIs() const; + virtual WatermarkAPIVector watermarkNodeAPIs() const; + + // + // In order to do a reverse look-up the media needs identifying + // information. This function, given a file, will compute that + // information. It does not do anything with it other than return it. + // + + static MediaFileInfo computeMediaFileInfo(const URL& mediaURL); + + // + // Export Media + // + + virtual URL exportMedia(const Node*) const; + + // + // Utility functions + // + + static std::string nameFromMedia(const URL&); + static std::string filenameOfMedia(const URL&); + + // + // ASync/Parallel Task API + // + + static void threadTrampoline(Library*); + void threadMain(); + + void addTask(Task*) const; + void cancelTask(const Task*) const; + void cancelTasks(const TaskVector&) const; + + protected: + Library() {} + + private: + const std::string m_typeName; + const std::string m_appName; + std::string m_name; + VoidSignal m_willDeleteSignal; + NodeIndexSignal m_willCreateNodeSignal; + NodeSignal m_newNodeSignal; + NodeSignal m_nodeTreeWillDeleteSignal; + NodeSignal m_nodeTreeDidDeleteSignal; + NodeSignal m_nodeWillDeleteSignal; + NodeSignal m_nodeDidDeleteSignal; + NodePropertySignal m_nodePropertyChangedSignal; + NodeSignal m_nodePropertiesWillBeAddedSignal; + NodeSignal m_nodePropertiesAddedSignal; + StringSignal m_nameChangedSignal; + NodeSignal m_nodeNameChangedSignal; + + NodePairSignal m_nodeParentChangedSignal; + NodePairSignal m_willChangeNodeParentSignal; + + NodeIndexSignal m_willReorderNodeSignal; + NodeSignal m_nodeReorderedSignal; + + NodeMoveSignal m_willMoveSignal; + ; + NodeSignal m_movedSignal; + + NodeSignal m_nodeShemeWillChangeSignal; + NodeSignal m_nodeShemeChangedSignal; + Thread m_taskThread; + mutable Condition m_taskCond; + mutable Mutex m_taskMutex; + mutable bool m_taskStop; + mutable TaskDeque m_taskQueue; + }; + + // + // Global + // + + typedef std::map LibraryMap; + + bool isLibraryURL(const URL&); + bool isNodeURL(const URL&); + bool isPropertyURL(const URL&); + Library* libraryOfURL(const URL&); + const Node* nodeOfURL(const URL&); + const LibraryMap& allLibraries(); + URL libraryURLtoMediaURL(const URL&); + bool isLibraryMediaURL(const URL&); + URLVector libraryURLsOfMedia(const URL&); + NodeVector libraryNodesAssociatedWithURL(const URL&); + URLVector libraryURLsAssociatedWithURL(const URL&); + + inline bool isPropertyListType(PropertyType t) { - return NULL; + return t >= FirstListType; } -} + template inline const T* api_cast(const Node* node) + { + if (const NodeAPI* api = node->library()->nodeAPI(node)) + { + return dynamic_cast(api); + } + else + { + return NULL; + } + } -} // TwkMediaLibrary +} // namespace TwkMediaLibrary #endif // __TwkMediaLibrary__Library__h__ diff --git a/src/lib/app/TwkQtBase/QtUtil.cpp b/src/lib/app/TwkQtBase/QtUtil.cpp index 0ef6d4845..ee98df644 100644 --- a/src/lib/app/TwkQtBase/QtUtil.cpp +++ b/src/lib/app/TwkQtBase/QtUtil.cpp @@ -1,7 +1,7 @@ // -// Copyright (C) 2023 Autodesk, Inc. All Rights Reserved. -// -// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2023 Autodesk, Inc. All Rights Reserved. +// +// SPDX-License-Identifier: Apache-2.0 // #include @@ -10,132 +10,135 @@ #include #include - using namespace std; -namespace TwkQtBase { - -namespace { - -const char * -ky(int index) -{ - return (index == 0) ? - "StringType::String* url = NODE_ARG_OBJECT" : - "const StringType* stype = static_cast"; -} - -}; // anon namespace - -string -encode(string pass, int key) +namespace TwkQtBase { - static bool first = true; - QCryptographicHash qch(QCryptographicHash::Sha1); - string topSecretKey = ky(key); - string uidStr = TwkUtil::uidString(); - ostringstream text; - text << topSecretKey << "-" << uidStr; - string simpleKey = text.str(); - QString saltStr; - - if (first) + namespace { - time_t tt; - time(&tt); - srand((int) tt); - first = false; - } - saltStr.setNum(rand()); - text << "-" << saltStr.toUtf8().constData(); - - // - // First round - // - QByteArray textArray(text.str().c_str()); - QString qpass(pass.c_str());; - QString withoutSemis = qpass.replace(";", "###SEMICOLON###"); - - ostringstream passStr; - passStr << withoutSemis.toStdString() << ";" << "succeeded"; - QByteArray passArray(passStr.str().c_str()); - textArray = qch.hash(textArray, QCryptographicHash::Sha1); + const char* ky(int index) + { + return (index == 0) ? "StringType::String* url = NODE_ARG_OBJECT" + : "const StringType* stype = static_cast"; + } - for (int i = 0; i < passArray.size(); ++i) passArray[i] = passArray[i] ^ textArray[i % textArray.size()]; + }; // namespace - // - // Second round - // - passArray = saltStr.toUtf8() + ";" + passArray;; - - textArray = QByteArray(simpleKey.c_str()); - textArray = qch.hash(textArray, QCryptographicHash::Sha1); - - for (int i = 0; i < passArray.size(); ++i) + string encode(string pass, int key) { - passArray[i] = passArray[i] ^ textArray[i % textArray.size()]; + static bool first = true; + + QCryptographicHash qch(QCryptographicHash::Sha1); + string topSecretKey = ky(key); + string uidStr = TwkUtil::uidString(); + ostringstream text; + text << topSecretKey << "-" << uidStr; + string simpleKey = text.str(); + QString saltStr; + + if (first) + { + time_t tt; + time(&tt); + srand((int)tt); + first = false; + } + saltStr.setNum(rand()); + text << "-" << saltStr.toUtf8().constData(); + + // + // First round + // + QByteArray textArray(text.str().c_str()); + QString qpass(pass.c_str()); + ; + QString withoutSemis = qpass.replace(";", "###SEMICOLON###"); + + ostringstream passStr; + passStr << withoutSemis.toStdString() << ";" << "succeeded"; + QByteArray passArray(passStr.str().c_str()); + + textArray = qch.hash(textArray, QCryptographicHash::Sha1); + + for (int i = 0; i < passArray.size(); ++i) + passArray[i] = passArray[i] ^ textArray[i % textArray.size()]; + + // + // Second round + // + passArray = saltStr.toUtf8() + ";" + passArray; + ; + + textArray = QByteArray(simpleKey.c_str()); + textArray = qch.hash(textArray, QCryptographicHash::Sha1); + + for (int i = 0; i < passArray.size(); ++i) + { + passArray[i] = passArray[i] ^ textArray[i % textArray.size()]; + } + + passArray = passArray.toHex(); + QString qs(passArray); + + return (qs.toStdString()); } - passArray = passArray.toHex(); - QString qs(passArray); - - return (qs.toStdString()); -} - -string -decode(string pass, int key) -{ - QByteArray passArray(pass.c_str()); - passArray = QByteArray::fromHex(passArray); - - // - // Undo second round - // - - QCryptographicHash qch(QCryptographicHash::Sha1); - string topSecretKey = ky(key); - ostringstream text; - text << topSecretKey << "-" << TwkUtil::uidString(); - QByteArray textArray(text.str().c_str()); - - textArray = qch.hash(textArray, QCryptographicHash::Sha1); - for (int i = 0; i < passArray.size(); ++i) passArray[i] = passArray[i] ^ textArray[i % textArray.size()]; - - // - // Undo first round - // - - QStringList qsl = (QString(passArray).split(";")); - int breakPoint = passArray.indexOf(';'); - if (breakPoint == -1) return ""; - - QByteArray randomInt = passArray; - randomInt.chop(randomInt.size()-breakPoint); - passArray.remove(0, breakPoint+1); - text << "-" << randomInt.constData(); - textArray = QByteArray(text.str().c_str()); - - textArray = qch.hash(textArray, QCryptographicHash::Sha1); - - for (int i = 0; i < passArray.size(); ++i) passArray[i] = passArray[i] ^ textArray[i % textArray.size()]; - - // - // Check result - // - - QString qs(passArray); - qsl = (QString(passArray)).split(";"); - - if (qsl.size() == 2 && qsl[1] == "succeeded") + string decode(string pass, int key) { - QString withSemis = qsl[0].replace("###SEMICOLON###", ";"); - return withSemis.toStdString(); + QByteArray passArray(pass.c_str()); + passArray = QByteArray::fromHex(passArray); + + // + // Undo second round + // + + QCryptographicHash qch(QCryptographicHash::Sha1); + string topSecretKey = ky(key); + ostringstream text; + text << topSecretKey << "-" << TwkUtil::uidString(); + QByteArray textArray(text.str().c_str()); + + textArray = qch.hash(textArray, QCryptographicHash::Sha1); + for (int i = 0; i < passArray.size(); ++i) + passArray[i] = passArray[i] ^ textArray[i % textArray.size()]; + + // + // Undo first round + // + + QStringList qsl = (QString(passArray).split(";")); + int breakPoint = passArray.indexOf(';'); + if (breakPoint == -1) + return ""; + + QByteArray randomInt = passArray; + randomInt.chop(randomInt.size() - breakPoint); + passArray.remove(0, breakPoint + 1); + text << "-" << randomInt.constData(); + textArray = QByteArray(text.str().c_str()); + + textArray = qch.hash(textArray, QCryptographicHash::Sha1); + + for (int i = 0; i < passArray.size(); ++i) + passArray[i] = passArray[i] ^ textArray[i % textArray.size()]; + + // + // Check result + // + + QString qs(passArray); + qsl = (QString(passArray)).split(";"); + + if (qsl.size() == 2 && qsl[1] == "succeeded") + { + QString withSemis = qsl[0].replace("###SEMICOLON###", ";"); + return withSemis.toStdString(); + } + else + return ""; } - else return ""; -} }; // namespace TwkQtBase - - diff --git a/src/lib/app/TwkQtBase/TwkQtBase/QtUtil.h b/src/lib/app/TwkQtBase/TwkQtBase/QtUtil.h index 01e1b2945..1b1060d39 100644 --- a/src/lib/app/TwkQtBase/TwkQtBase/QtUtil.h +++ b/src/lib/app/TwkQtBase/TwkQtBase/QtUtil.h @@ -1,7 +1,7 @@ // -// Copyright (C) 2023 Autodesk, Inc. All Rights Reserved. -// -// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2023 Autodesk, Inc. All Rights Reserved. +// +// SPDX-License-Identifier: Apache-2.0 // #ifndef _TwkQtBaseQtUtil_h_ @@ -9,10 +9,11 @@ #include -namespace TwkQtBase { +namespace TwkQtBase +{ -std::string encode(std::string s, int key = 0); -std::string decode(std::string s, int key = 0); + std::string encode(std::string s, int key = 0); + std::string decode(std::string s, int key = 0); }; // namespace TwkQtBase diff --git a/src/lib/audio/ALSAAudioModule/ALSAAudioModule/ALSAAudioRenderer.h b/src/lib/audio/ALSAAudioModule/ALSAAudioModule/ALSAAudioRenderer.h index 2d0812430..d8334e3ce 100644 --- a/src/lib/audio/ALSAAudioModule/ALSAAudioModule/ALSAAudioRenderer.h +++ b/src/lib/audio/ALSAAudioModule/ALSAAudioModule/ALSAAudioRenderer.h @@ -1,9 +1,9 @@ //****************************************************************************** // Copyright (c) 2005 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #ifndef __IPCore__ALSAAudioRenderer__h__ #define __IPCore__ALSAAudioRenderer__h__ @@ -14,88 +14,87 @@ #include -namespace IPCore { - -/// Pure ALSA implementation of AudioRenderer - -/// -/// -/// - -class ALSAAudioRenderer : public AudioRenderer +namespace IPCore { -public: - // - // Types - // - - struct ALSADevice - { - std::string plug; - std::string card; - std::string name; - }; - - typedef std::vector ALSADeviceVector; - typedef TwkAudio::AudioBuffer AudioBuffer; - typedef stl_ext::thread_group ThreadGroup; - typedef std::vector OutputSampleBuffer; - typedef TwkUtil::Timer Timer; - ALSAAudioRenderer(const RendererParameters&); - ~ALSAAudioRenderer(); + /// Pure ALSA implementation of AudioRenderer - - /// - /// play() will return almost immediately -- a worker thread will - /// be released and start playing. /// - - virtual void play(); - virtual void play(Session*); - /// - /// stop() will cause the worker thread to wait until play. A - /// subsequent play should restart it. /// - virtual void stop(Session*); - - /// - /// Completely stop the audio hardware and the audio thread. You can't - /// call play() after you've called shutdown() - /// - - virtual void shutdown(); - - /// - /// These are currently ignored by ALSAAudioRenderer - /// - - virtual void availableLayouts(const Device&, LayoutsVector&); - virtual void availableFormats(const Device&, FormatVector&); - virtual void availableRates(const Device&, Format, RateVector&); - - void threadMain(); - void configureDevice(); - -protected: - virtual void createDeviceList(); - -private: - OutputSampleBuffer m_outBuffer; - ALSADeviceVector m_alsaDevices; - ThreadGroup m_threadGroup; - size_t m_startSample; - snd_pcm_t* m_pcm; - snd_pcm_uframes_t m_periodSize; - snd_pcm_uframes_t m_bufferSize; - pthread_t m_audioThread; - bool m_audioThreadRunning; - pthread_mutex_t m_runningLock; -}; - + class ALSAAudioRenderer : public AudioRenderer + { + public: + // + // Types + // + + struct ALSADevice + { + std::string plug; + std::string card; + std::string name; + }; + + typedef std::vector ALSADeviceVector; + typedef TwkAudio::AudioBuffer AudioBuffer; + typedef stl_ext::thread_group ThreadGroup; + typedef std::vector OutputSampleBuffer; + typedef TwkUtil::Timer Timer; + + ALSAAudioRenderer(const RendererParameters&); + ~ALSAAudioRenderer(); + + /// + /// play() will return almost immediately -- a worker thread will + /// be released and start playing. + /// + + virtual void play(); + virtual void play(Session*); + + /// + /// stop() will cause the worker thread to wait until play. A + /// subsequent play should restart it. + /// + + virtual void stop(Session*); + + /// + /// Completely stop the audio hardware and the audio thread. You can't + /// call play() after you've called shutdown() + /// + + virtual void shutdown(); + + /// + /// These are currently ignored by ALSAAudioRenderer + /// + + virtual void availableLayouts(const Device&, LayoutsVector&); + virtual void availableFormats(const Device&, FormatVector&); + virtual void availableRates(const Device&, Format, RateVector&); + + void threadMain(); + void configureDevice(); + + protected: + virtual void createDeviceList(); + + private: + OutputSampleBuffer m_outBuffer; + ALSADeviceVector m_alsaDevices; + ThreadGroup m_threadGroup; + size_t m_startSample; + snd_pcm_t* m_pcm; + snd_pcm_uframes_t m_periodSize; + snd_pcm_uframes_t m_bufferSize; + pthread_t m_audioThread; + bool m_audioThreadRunning; + pthread_mutex_t m_runningLock; + }; -} // Rv +} // namespace IPCore #endif // __IPCore__ALSAAudioRenderer__h__ diff --git a/src/lib/audio/ALSAAudioModule/ALSAAudioRenderer.cpp b/src/lib/audio/ALSAAudioModule/ALSAAudioRenderer.cpp index 04b7e4183..c80c5e8e2 100644 --- a/src/lib/audio/ALSAAudioModule/ALSAAudioRenderer.cpp +++ b/src/lib/audio/ALSAAudioModule/ALSAAudioRenderer.cpp @@ -1,9 +1,9 @@ //****************************************************************************** // Copyright (c) 2005 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #include #include @@ -168,7 +168,7 @@ // quickly. // -//#define USE_SAFE_ALSA +// #define USE_SAFE_ALSA #ifndef USE_SAFE_ALSA #define ALSA_PCM_NEW_HW_PARAMS_API @@ -177,46 +177,40 @@ #include -namespace IPCore { -using namespace std; -using namespace stl_ext; -using namespace TwkApp; -using namespace TwkAudio; - -static void -alsaErrorHandler (const char *file, - int line, - const char *function, - int err, - const char *fmt, - ...) +namespace IPCore { - // don't print out ALSA asserts -} - -static int -snd_pcm_open_real_hard(snd_pcm_t **pcm, - const char *name, - snd_pcm_stream_t stream, - int mode, - size_t iterations = 1) -{ - // - // Try REAL HARD to open the device. If it doesn't open right - // away. Wait a second and see if anything improves. There's - // probably a way to avoid this by waiting until the device is - // drained, but one might assume snd_pcm_drain() would do that - // wouldn't one? - // - // It seems like the device is still playing back accumulated - // samples and cannot be opened (e.g., switching to an exclusive - // hardware device from default). If you wait for the device to - // drain, it will eventually work. This technique (or a - // variation) is applied by a number of other programs on the - // net. - // - - int err = snd_pcm_open(pcm, name, stream, mode); + using namespace std; + using namespace stl_ext; + using namespace TwkApp; + using namespace TwkAudio; + + static void alsaErrorHandler(const char* file, int line, + const char* function, int err, const char* fmt, + ...) + { + // don't print out ALSA asserts + } + + static int snd_pcm_open_real_hard(snd_pcm_t** pcm, const char* name, + snd_pcm_stream_t stream, int mode, + size_t iterations = 1) + { + // + // Try REAL HARD to open the device. If it doesn't open right + // away. Wait a second and see if anything improves. There's + // probably a way to avoid this by waiting until the device is + // drained, but one might assume snd_pcm_drain() would do that + // wouldn't one? + // + // It seems like the device is still playing back accumulated + // samples and cannot be opened (e.g., switching to an exclusive + // hardware device from default). If you wait for the device to + // drain, it will eventually work. This technique (or a + // variation) is applied by a number of other programs on the + // net. + // + + int err = snd_pcm_open(pcm, name, stream, mode); #if 0 for (size_t i = 0; i < iterations && err == -EBUSY; i++) @@ -226,404 +220,433 @@ snd_pcm_open_real_hard(snd_pcm_t **pcm, } #endif - if (!err && *pcm) snd_pcm_nonblock(*pcm, 0); // 0 means block - return err; -} + if (!err && *pcm) + snd_pcm_nonblock(*pcm, 0); // 0 means block + return err; + } -ALSAAudioRenderer::ALSAAudioRenderer(const RendererParameters& p) - : AudioRenderer(p), - m_threadGroup(1,2), - m_pcm(0), - m_audioThread(pthread_self()), - m_audioThreadRunning(false) -{ - snd_lib_error_set_handler(alsaErrorHandler); - pthread_mutex_init(&m_runningLock, 0); + ALSAAudioRenderer::ALSAAudioRenderer(const RendererParameters& p) + : AudioRenderer(p) + , m_threadGroup(1, 2) + , m_pcm(0) + , m_audioThread(pthread_self()) + , m_audioThreadRunning(false) + { + snd_lib_error_set_handler(alsaErrorHandler); + pthread_mutex_init(&m_runningLock, 0); + + if (m_parameters.rate == 0) + m_parameters.rate = TWEAK_AUDIO_DEFAULT_SAMPLE_RATE; + if (m_parameters.framesPerBuffer == 0) + m_parameters.framesPerBuffer = 512; + if (m_parameters.device == "") + m_parameters.device = "default"; - if (m_parameters.rate == 0) m_parameters.rate = TWEAK_AUDIO_DEFAULT_SAMPLE_RATE; - if (m_parameters.framesPerBuffer == 0) m_parameters.framesPerBuffer = 512; - if (m_parameters.device == "") m_parameters.device = "default"; + createDeviceList(); - createDeviceList(); + if (debug) + outputParameters(m_parameters); - if (debug) outputParameters(m_parameters); +#ifndef PLATFORM_WINDOWS + /* + We used to initialize the device at this point, but if something + goes wrong, it means we can't even change the device in the + prefs, because audio is shutdown. If we skip this step, we'll + hold open the device after the first play(). + */ - #ifndef PLATFORM_WINDOWS - /* - We used to initialize the device at this point, but if something - goes wrong, it means we can't even change the device in the - prefs, because audio is shutdown. If we skip this step, we'll - hold open the device after the first play(). - */ + if (m_parameters.holdOpen) + { + play(); + AudioRenderer::stop(); + } +#endif + } - if (m_parameters.holdOpen) + ALSAAudioRenderer::~ALSAAudioRenderer() { - play(); AudioRenderer::stop(); + shutdown(); + pthread_mutex_destroy(&m_runningLock); } - #endif -} - -ALSAAudioRenderer::~ALSAAudioRenderer() -{ - AudioRenderer::stop(); - shutdown(); - pthread_mutex_destroy(&m_runningLock); -} - -void -ALSAAudioRenderer::createDeviceList() -{ - m_outputDevices.clear(); - m_alsaDevices.clear(); - -#ifdef USE_SAFE_ALSA - // - // use the snd_device_name_hint() function - // - void** deviceList = 0; - snd_device_name_hint(-1, "pcm", (void***)&deviceList); - - for (void** d = deviceList; *d; d++) + void ALSAAudioRenderer::createDeviceList() { - char* namep = snd_device_name_get_hint(*d, "NAME"); - char* descp = snd_device_name_get_hint(*d, "DESC"); - const string name = namep; - const string desc = descp; + m_outputDevices.clear(); + m_alsaDevices.clear(); +#ifdef USE_SAFE_ALSA // - // we only do stereo right now + // use the snd_device_name_hint() function // - if (name == "null" || name.find("surround") != string::npos) continue; - string::size_type n = desc.find('\n'); - const string desc0 = desc.substr(0, n); - const string desc1 = desc.substr(n+1, desc.size()); + void** deviceList = 0; + snd_device_name_hint(-1, "pcm", (void***)&deviceList); - free(namep); - free(descp); + for (void** d = deviceList; *d; d++) + { + char* namep = snd_device_name_get_hint(*d, "NAME"); + char* descp = snd_device_name_get_hint(*d, "DESC"); + const string name = namep; + const string desc = descp; - Device d(name); - d.layout = 0; - d.defaultRate = 0; - d.isDefaultDevice = false; - d.index = m_outputDevices.size(); + // + // we only do stereo right now + // + if (name == "null" || name.find("surround") != string::npos) + continue; - ALSADevice ad; - ad.plug = "plugIn"; - ad.name = name; - ad.card = ""; + string::size_type n = desc.find('\n'); + const string desc0 = desc.substr(0, n); + const string desc1 = desc.substr(n + 1, desc.size()); - m_outputDevices.push_back(d); - m_alsaDevices.push_back(ad); - } + free(namep); + free(descp); - snd_device_name_free_hint(deviceList); + Device d(name); + d.layout = 0; + d.defaultRate = 0; + d.isDefaultDevice = false; + d.index = m_outputDevices.size(); -#else + ALSADevice ad; + ad.plug = "plugIn"; + ad.name = name; + ad.card = ""; - for (int card = -1; snd_card_next(&card) >= 0 && card >= 0;) - { - // - // Find the card devices - // + m_outputDevices.push_back(d); + m_alsaDevices.push_back(ad); + } - snd_ctl_t* ctl = 0; - char* cardname = 0; - ostringstream hwcard; - hwcard << "hw:" << card; + snd_device_name_free_hint(deviceList); - snd_card_get_longname(card, &cardname); +#else - if (snd_ctl_open(&ctl, hwcard.str().c_str(), 0) == 0) + for (int card = -1; snd_card_next(&card) >= 0 && card >= 0;) { - snd_pcm_info_t* info = 0; - snd_pcm_info_alloca(&info); + // + // Find the card devices + // + + snd_ctl_t* ctl = 0; + char* cardname = 0; + ostringstream hwcard; + hwcard << "hw:" << card; - for (int device = -1; snd_ctl_pcm_next_device(ctl, &device) >= 0 && device >= 0;) + snd_card_get_longname(card, &cardname); + + if (snd_ctl_open(&ctl, hwcard.str().c_str(), 0) == 0) { - snd_pcm_info_set_device(info, device); - snd_pcm_info_set_subdevice(info, 0); - snd_pcm_info_set_stream(info, SND_PCM_STREAM_PLAYBACK); + snd_pcm_info_t* info = 0; + snd_pcm_info_alloca(&info); - if (snd_ctl_pcm_info(ctl, info) >= 0) + for (int device = -1; + snd_ctl_pcm_next_device(ctl, &device) >= 0 && device >= 0;) { - ostringstream fullname; - - fullname << cardname - << ": " << snd_pcm_info_get_name(info) - << " (" << hwcard.str() - << "," << device - << ")"; - - ostringstream dname; - dname << hwcard.str() << "," << device; - - Device d(fullname.str()); - d.layout = TwkAudio::UnknownLayout; - d.defaultRate = 0; - d.isDefaultDevice = false; - d.index = m_outputDevices.size(); - - char* c; - snd_card_get_name(card, &c); - - ALSADevice ad; - ad.plug = "hw"; - ad.name = dname.str(); - ad.card = c; - - m_outputDevices.push_back(d); - m_alsaDevices.push_back(ad); + snd_pcm_info_set_device(info, device); + snd_pcm_info_set_subdevice(info, 0); + snd_pcm_info_set_stream(info, SND_PCM_STREAM_PLAYBACK); + + if (snd_ctl_pcm_info(ctl, info) >= 0) + { + ostringstream fullname; + + fullname << cardname << ": " + << snd_pcm_info_get_name(info) << " (" + << hwcard.str() << "," << device << ")"; + + ostringstream dname; + dname << hwcard.str() << "," << device; + + Device d(fullname.str()); + d.layout = TwkAudio::UnknownLayout; + d.defaultRate = 0; + d.isDefaultDevice = false; + d.index = m_outputDevices.size(); + + char* c; + snd_card_get_name(card, &c); + + ALSADevice ad; + ad.plug = "hw"; + ad.name = dname.str(); + ad.card = c; + + m_outputDevices.push_back(d); + m_alsaDevices.push_back(ad); + } } - } - snd_ctl_close(ctl); + snd_ctl_close(ctl); + } } - } #endif - // - // See if RV_ALSA_EXTRA_DEVICES is set and if so scarf the - // devices out of there too. - // - - if (const char* xdevices = getenv("RV_ALSA_EXTRA_DEVICES")) - { - vector tokens; - stl_ext::tokenize(tokens, xdevices, "|"); + // + // See if RV_ALSA_EXTRA_DEVICES is set and if so scarf the + // devices out of there too. + // - for (size_t i = 0; i < tokens.size(); i++) + if (const char* xdevices = getenv("RV_ALSA_EXTRA_DEVICES")) { - vector dtokens; - stl_ext::tokenize(dtokens, tokens[i], "@"); + vector tokens; + stl_ext::tokenize(tokens, xdevices, "|"); - string name; - string alsaDevice; - - if (dtokens.size() == 1) - { - name = tokens[i]; - alsaDevice = name; - } - else if (dtokens.size() == 2) - { - name = dtokens[0]; - alsaDevice = dtokens[1]; - } - else + for (size_t i = 0; i < tokens.size(); i++) { - cerr << "ERROR: RV_ALSA_EXTRA_DEVICES env variable -- syntax error" << endl; - break; - } + vector dtokens; + stl_ext::tokenize(dtokens, tokens[i], "@"); - Device d(name); - d.layout = TwkAudio::Stereo_2; - d.defaultRate = TWEAK_AUDIO_DEFAULT_SAMPLE_RATE; - d.latencyLow = 0; - d.latencyHigh = 0; - d.isDefaultDevice = false; - d.index = m_outputDevices.size(); + string name; + string alsaDevice; - ALSADevice ad; - ad.plug = "plughw"; - ad.card = "PlugIn Module"; - ad.name = alsaDevice; + if (dtokens.size() == 1) + { + name = tokens[i]; + alsaDevice = name; + } + else if (dtokens.size() == 2) + { + name = dtokens[0]; + alsaDevice = dtokens[1]; + } + else + { + cerr << "ERROR: RV_ALSA_EXTRA_DEVICES env variable -- " + "syntax error" + << endl; + break; + } - m_outputDevices.push_back(d); - m_alsaDevices.push_back(ad); + Device d(name); + d.layout = TwkAudio::Stereo_2; + d.defaultRate = TWEAK_AUDIO_DEFAULT_SAMPLE_RATE; + d.latencyLow = 0; + d.latencyHigh = 0; + d.isDefaultDevice = false; + d.index = m_outputDevices.size(); + + ALSADevice ad; + ad.plug = "plughw"; + ad.card = "PlugIn Module"; + ad.name = alsaDevice; + + m_outputDevices.push_back(d); + m_alsaDevices.push_back(ad); + } } - } - // - // Add default - // - - Device d("default"); - d.layout = TwkAudio::Stereo_2; - d.defaultRate = TWEAK_AUDIO_DEFAULT_SAMPLE_RATE; - d.latencyLow = 0; - d.latencyHigh = 0; - d.isDefaultDevice = true; - d.index = m_outputDevices.size(); - - ALSADevice ad; - ad.plug = "plughw"; - ad.card = "PlugIn Module"; - ad.name = "default"; - - m_outputDevices.push_back(d); - m_alsaDevices.push_back(ad); - - // - // Copy the current state from the parameters - // - - DeviceState state; - state.device = m_parameters.device; - state.format = m_parameters.format; - state.rate = m_parameters.rate; - state.latency = m_parameters.latency; - state.layout = m_parameters.layout; - state.framesPerBuffer = m_parameters.framesPerBuffer; - setDeviceState(state); - - // - // Force allocation of memory now - // - - int channelsCount = TwkAudio::channelsCount(state.layout); - m_abuffer.reconfigure(state.framesPerBuffer, state.layout, Time(state.rate), 0, 0); - m_outBuffer.resize(m_abuffer.size() * channelsCount * formatSizeInBytes(state.format)); -} - - -void -ALSAAudioRenderer::availableLayouts(const Device& d, LayoutsVector& layouts) -{ - layouts.clear(); + // + // Add default + // - layouts.push_back(TwkAudio::Mono_1); - layouts.push_back(TwkAudio::Stereo_2); -} + Device d("default"); + d.layout = TwkAudio::Stereo_2; + d.defaultRate = TWEAK_AUDIO_DEFAULT_SAMPLE_RATE; + d.latencyLow = 0; + d.latencyHigh = 0; + d.isDefaultDevice = true; + d.index = m_outputDevices.size(); + ALSADevice ad; + ad.plug = "plughw"; + ad.card = "PlugIn Module"; + ad.name = "default"; -void -ALSAAudioRenderer::availableFormats(const Device& d, FormatVector& formats) -{ - // - // The base class ensures that this function is not called when a - // device is opened. - // + m_outputDevices.push_back(d); + m_alsaDevices.push_back(ad); + + // + // Copy the current state from the parameters + // + + DeviceState state; + state.device = m_parameters.device; + state.format = m_parameters.format; + state.rate = m_parameters.rate; + state.latency = m_parameters.latency; + state.layout = m_parameters.layout; + state.framesPerBuffer = m_parameters.framesPerBuffer; + setDeviceState(state); - formats.clear(); - static Format allformats[4] = { Float32Format, Int32Format, Int16Format, Int8Format }; + // + // Force allocation of memory now + // - const ALSADevice& ad = m_alsaDevices[d.index]; - const string& deviceName = ad.name; + int channelsCount = TwkAudio::channelsCount(state.layout); + m_abuffer.reconfigure(state.framesPerBuffer, state.layout, + Time(state.rate), 0, 0); + m_outBuffer.resize(m_abuffer.size() * channelsCount + * formatSizeInBytes(state.format)); + } - for (size_t i = 0; i < 3; i++) + void ALSAAudioRenderer::availableLayouts(const Device& d, + LayoutsVector& layouts) { - Format format = allformats[i]; + layouts.clear(); - snd_pcm_t* pcm; - int err; + layouts.push_back(TwkAudio::Mono_1); + layouts.push_back(TwkAudio::Stereo_2); + } - if ((err = snd_pcm_open_real_hard(&pcm, - deviceName.c_str(), - SND_PCM_STREAM_PLAYBACK, - SND_PCM_NONBLOCK, - 10)) == 0) - { - snd_pcm_hw_params_t* params; - snd_pcm_hw_params_alloca(¶ms); - snd_pcm_hw_params_any(pcm, params); + void ALSAAudioRenderer::availableFormats(const Device& d, + FormatVector& formats) + { + // + // The base class ensures that this function is not called when a + // device is opened. + // - unsigned int rrate = (unsigned int)m_parameters.rate; + formats.clear(); + static Format allformats[4] = {Float32Format, Int32Format, Int16Format, + Int8Format}; - snd_pcm_format_t alsaformat; + const ALSADevice& ad = m_alsaDevices[d.index]; + const string& deviceName = ad.name; - switch (format) - { - case Float32Format: alsaformat = SND_PCM_FORMAT_FLOAT_LE; break; - case Int32Format: alsaformat = SND_PCM_FORMAT_S32_LE; break; - case Int16Format: alsaformat = SND_PCM_FORMAT_S16_LE; break; - case Int8Format: alsaformat = SND_PCM_FORMAT_S8; break; - } + for (size_t i = 0; i < 3; i++) + { + Format format = allformats[i]; - int dir = 0; - snd_pcm_hw_params_set_access(pcm, params, SND_PCM_ACCESS_RW_INTERLEAVED); - bool ok = snd_pcm_hw_params_set_format(pcm, params, alsaformat) == 0; - snd_pcm_hw_params_set_channels(pcm, params, TwkAudio::channelsCount(m_parameters.layout)); - snd_pcm_hw_params_set_rate_near(pcm, params, &rrate, &dir); + snd_pcm_t* pcm; + int err; - if (ok && rrate == m_parameters.rate) + if ((err = snd_pcm_open_real_hard(&pcm, deviceName.c_str(), + SND_PCM_STREAM_PLAYBACK, + SND_PCM_NONBLOCK, 10)) + == 0) { - int periods = 2; - snd_pcm_uframes_t period_size = 8192; - snd_pcm_uframes_t buffer_size = 0; - - snd_pcm_hw_params_set_periods(pcm, params, periods, 0); - snd_pcm_hw_params_set_buffer_size(pcm, params, (period_size * periods) >> 2); - - if (snd_pcm_hw_params(pcm, params) >= 0) + snd_pcm_hw_params_t* params; + snd_pcm_hw_params_alloca(¶ms); + snd_pcm_hw_params_any(pcm, params); + + unsigned int rrate = (unsigned int)m_parameters.rate; + + snd_pcm_format_t alsaformat; + + switch (format) { - formats.push_back(format); + case Float32Format: + alsaformat = SND_PCM_FORMAT_FLOAT_LE; + break; + case Int32Format: + alsaformat = SND_PCM_FORMAT_S32_LE; + break; + case Int16Format: + alsaformat = SND_PCM_FORMAT_S16_LE; + break; + case Int8Format: + alsaformat = SND_PCM_FORMAT_S8; + break; } - } - snd_pcm_close(pcm); - } - else if (err == -EBUSY) - { - // - // The device isn't available - // + int dir = 0; + snd_pcm_hw_params_set_access(pcm, params, + SND_PCM_ACCESS_RW_INTERLEAVED); + bool ok = + snd_pcm_hw_params_set_format(pcm, params, alsaformat) == 0; + snd_pcm_hw_params_set_channels( + pcm, params, TwkAudio::channelsCount(m_parameters.layout)); + snd_pcm_hw_params_set_rate_near(pcm, params, &rrate, &dir); - break; - } - } -} + if (ok && rrate == m_parameters.rate) + { + int periods = 2; + snd_pcm_uframes_t period_size = 8192; + snd_pcm_uframes_t buffer_size = 0; -void -ALSAAudioRenderer::availableRates(const Device& device, Format format, RateVector& rates) -{ - // - // The base class ensures that this function is not called when a - // device is opened. - // + snd_pcm_hw_params_set_periods(pcm, params, periods, 0); + snd_pcm_hw_params_set_buffer_size( + pcm, params, (period_size * periods) >> 2); - rates.clear(); + if (snd_pcm_hw_params(pcm, params) >= 0) + { + formats.push_back(format); + } + } - static double standardSampleRates[] = { - 8000.0, 9600.0, 11025.0, 12000.0, 16000.0, 22050.0, 24000.0, 32000.0, - 44100.0, 48000.0, 88200.0, 96000.0, 192000.0, -1 /* negative terminated list */ - }; + snd_pcm_close(pcm); + } + else if (err == -EBUSY) + { + // + // The device isn't available + // - const ALSADevice& ad = m_alsaDevices[device.index]; - const string& deviceName = ad.name; + break; + } + } + } - for (size_t i = 0; standardSampleRates[i] > 0; i++) + void ALSAAudioRenderer::availableRates(const Device& device, Format format, + RateVector& rates) { - double rate = standardSampleRates[i]; - snd_pcm_t* pcm; - int err; + // + // The base class ensures that this function is not called when a + // device is opened. + // - if ((err = snd_pcm_open_real_hard(&pcm, - deviceName.c_str(), - SND_PCM_STREAM_PLAYBACK, - SND_PCM_NONBLOCK, - 10)) == 0) - { - snd_pcm_hw_params_t* params; - snd_pcm_hw_params_alloca(¶ms); - snd_pcm_hw_params_any(pcm, params); + rates.clear(); - unsigned int rrate = (unsigned int)rate; + static double standardSampleRates[] = { + 8000.0, 9600.0, 11025.0, 12000.0, 16000.0, + 22050.0, 24000.0, 32000.0, 44100.0, 48000.0, + 88200.0, 96000.0, 192000.0, -1 /* negative terminated list */ + }; - snd_pcm_format_t alsaformat; + const ALSADevice& ad = m_alsaDevices[device.index]; + const string& deviceName = ad.name; - switch (m_parameters.format) + for (size_t i = 0; standardSampleRates[i] > 0; i++) + { + double rate = standardSampleRates[i]; + snd_pcm_t* pcm; + int err; + + if ((err = snd_pcm_open_real_hard(&pcm, deviceName.c_str(), + SND_PCM_STREAM_PLAYBACK, + SND_PCM_NONBLOCK, 10)) + == 0) { - case Float32Format: alsaformat = SND_PCM_FORMAT_FLOAT_LE; break; - case Int32Format: alsaformat = SND_PCM_FORMAT_S32_LE; break; - case Int16Format: alsaformat = SND_PCM_FORMAT_S16_LE; break; - case Int8Format: alsaformat = SND_PCM_FORMAT_S8; break; - } + snd_pcm_hw_params_t* params; + snd_pcm_hw_params_alloca(¶ms); + snd_pcm_hw_params_any(pcm, params); - // - // This doesn't work -- why does ALSA say it does? - // + unsigned int rrate = (unsigned int)rate; - int dir = 0; - snd_pcm_hw_params_set_access(pcm, params, SND_PCM_ACCESS_RW_INTERLEAVED); - snd_pcm_hw_params_set_format(pcm, params, alsaformat); - snd_pcm_hw_params_set_channels(pcm, params, TwkAudio::channelsCount(m_parameters.layout)); - snd_pcm_hw_params_set_rate_near(pcm, params, &rrate, &dir); + snd_pcm_format_t alsaformat; + + switch (m_parameters.format) + { + case Float32Format: + alsaformat = SND_PCM_FORMAT_FLOAT_LE; + break; + case Int32Format: + alsaformat = SND_PCM_FORMAT_S32_LE; + break; + case Int16Format: + alsaformat = SND_PCM_FORMAT_S16_LE; + break; + case Int8Format: + alsaformat = SND_PCM_FORMAT_S8; + break; + } - if (rrate == rate) rates.push_back((unsigned int)rate); + // + // This doesn't work -- why does ALSA say it does? + // + + int dir = 0; + snd_pcm_hw_params_set_access(pcm, params, + SND_PCM_ACCESS_RW_INTERLEAVED); + snd_pcm_hw_params_set_format(pcm, params, alsaformat); + snd_pcm_hw_params_set_channels( + pcm, params, TwkAudio::channelsCount(m_parameters.layout)); + snd_pcm_hw_params_set_rate_near(pcm, params, &rrate, &dir); + + if (rrate == rate) + rates.push_back((unsigned int)rate); #if 0 int periods = 2; @@ -639,594 +662,628 @@ ALSAAudioRenderer::availableRates(const Device& device, Format format, RateVecto } #endif - snd_pcm_close(pcm); + snd_pcm_close(pcm); + } } } -} -static void -trampoline(void* data) -{ - ALSAAudioRenderer* a = (ALSAAudioRenderer*)data; - a->threadMain(); -} - -void -ALSAAudioRenderer::configureDevice() -{ - int err; + static void trampoline(void* data) + { + ALSAAudioRenderer* a = (ALSAAudioRenderer*)data; + a->threadMain(); + } - if (!m_pcm) + void ALSAAudioRenderer::configureDevice() { - string alsaDeviceName = "default"; - int dindex = findDeviceByName(m_parameters.device); + int err; - if (dindex >= 0 && dindex < m_alsaDevices.size()) + if (!m_pcm) { - const ALSADevice& ad = m_alsaDevices[dindex]; - alsaDeviceName = ad.name; - } + string alsaDeviceName = "default"; + int dindex = findDeviceByName(m_parameters.device); - if ((err = snd_pcm_open_real_hard(&m_pcm, - alsaDeviceName.c_str(), - SND_PCM_STREAM_PLAYBACK, - SND_PCM_NONBLOCK)) < 0) - { - cerr << "WARNING: ALSA: Playback open error (" - << err << "): " << snd_strerror(err) << endl; + if (dindex >= 0 && dindex < m_alsaDevices.size()) + { + const ALSADevice& ad = m_alsaDevices[dindex]; + alsaDeviceName = ad.name; + } - - if (alsaDeviceName != "default" && err != -16) /* busy */ + if ((err = snd_pcm_open_real_hard(&m_pcm, alsaDeviceName.c_str(), + SND_PCM_STREAM_PLAYBACK, + SND_PCM_NONBLOCK)) + < 0) { - cerr << "WARNING: ALSA: trying default instead of " - << alsaDeviceName - << endl; + cerr << "WARNING: ALSA: Playback open error (" << err + << "): " << snd_strerror(err) << endl; - if ((err = snd_pcm_open_real_hard(&m_pcm, - "default", - SND_PCM_STREAM_PLAYBACK, - SND_PCM_NONBLOCK)) < 0) + if (alsaDeviceName != "default" && err != -16) /* busy */ { - cerr << "WARNING: ALSA: no luck with default either" << endl; - setErrorCondition("Unable to open an audio device"); + cerr << "WARNING: ALSA: trying default instead of " + << alsaDeviceName << endl; + + if ((err = snd_pcm_open_real_hard(&m_pcm, "default", + SND_PCM_STREAM_PLAYBACK, + SND_PCM_NONBLOCK)) + < 0) + { + cerr << "WARNING: ALSA: no luck with default either" + << endl; + setErrorCondition("Unable to open an audio device"); + } + else + { + cerr << "WARNING: ALSA: using default device instead" + << endl; + m_deviceState.device = "default"; + alsaDeviceName = "default"; + } } else { - cerr << "WARNING: ALSA: using default device instead" << endl; - m_deviceState.device = "default"; - alsaDeviceName = "default"; + setErrorCondition("Unable to open an audio device"); } } - else + + snd_pcm_hw_params_t* params; + snd_pcm_hw_params_alloca(¶ms); + snd_pcm_hw_params_any(m_pcm, params); + + snd_pcm_format_t alsaformat; + size_t dataSize = 0; + + switch (m_parameters.format) { - setErrorCondition("Unable to open an audio device"); + case Float32Format: + alsaformat = SND_PCM_FORMAT_FLOAT_LE; + dataSize = sizeof(float); + break; + default: + case Int16Format: + alsaformat = SND_PCM_FORMAT_S16_LE; + dataSize = sizeof(short); + break; + case Int32Format: + alsaformat = SND_PCM_FORMAT_S32_LE; + dataSize = sizeof(signed int); + break; + case Int8Format: + alsaformat = SND_PCM_FORMAT_S8; + dataSize = sizeof(char); + break; } - } - snd_pcm_hw_params_t* params; - snd_pcm_hw_params_alloca(¶ms); - snd_pcm_hw_params_any(m_pcm, params); + unsigned int rrate = (unsigned int)m_parameters.rate; + int dir = 0; - snd_pcm_format_t alsaformat; - size_t dataSize = 0; - - switch (m_parameters.format) - { - case Float32Format: - alsaformat = SND_PCM_FORMAT_FLOAT_LE; - dataSize = sizeof(float); - break; - default: - case Int16Format: - alsaformat = SND_PCM_FORMAT_S16_LE; - dataSize = sizeof(short); - break; - case Int32Format: - alsaformat = SND_PCM_FORMAT_S32_LE; - dataSize = sizeof(signed int); - break; - case Int8Format: - alsaformat = SND_PCM_FORMAT_S8; - dataSize = sizeof(char); - break; - } + if (snd_pcm_hw_params_set_access(m_pcm, params, + SND_PCM_ACCESS_RW_INTERLEAVED) + < 0) + { + cerr << "ERROR: ALSA: access (interleaved) failed - can't " + "continue" + << endl; + outputParameters(m_parameters); + snd_pcm_close(m_pcm); + m_pcm = 0; + setErrorCondition("unable to configure audio device"); + } - unsigned int rrate = (unsigned int)m_parameters.rate; - int dir = 0; + if (snd_pcm_hw_params_set_format(m_pcm, params, alsaformat) < 0) + { + if (snd_pcm_hw_params_set_format(m_pcm, params, + SND_PCM_FORMAT_S16_LE) + >= 0) + { + if (debug) + cerr << "WARNING: ALSA: format falling back to Int16" + << endl; + m_parameters.format = Int16Format; + } + else + { + cerr << "ERROR: ALSA: format failed - can't continue" + << endl; + outputParameters(m_parameters); + snd_pcm_close(m_pcm); + m_pcm = 0; + setErrorCondition("unable to configure audio device"); + } + } - if (snd_pcm_hw_params_set_access(m_pcm, params, SND_PCM_ACCESS_RW_INTERLEAVED) < 0) - { - cerr << "ERROR: ALSA: access (interleaved) failed - can't continue" << endl; - outputParameters(m_parameters); - snd_pcm_close(m_pcm); - m_pcm = 0; - setErrorCondition("unable to configure audio device"); - } + int channelsCount = TwkAudio::channelsCount(m_parameters.layout); - if (snd_pcm_hw_params_set_format(m_pcm, params, alsaformat) < 0) - { - if (snd_pcm_hw_params_set_format(m_pcm, params, SND_PCM_FORMAT_S16_LE) >= 0) + if (snd_pcm_hw_params_set_channels(m_pcm, params, channelsCount) + < 0) { - if (debug) cerr << "WARNING: ALSA: format falling back to Int16" << endl; - m_parameters.format = Int16Format; + cerr << "ERROR: ALSA: can't use " << channelsCount + << " channels -- can't continue" << endl; + outputParameters(m_parameters); + snd_pcm_close(m_pcm); + m_pcm = 0; + setErrorCondition("unable to configure audio device"); } - else + + if (snd_pcm_hw_params_set_rate_near(m_pcm, params, &rrate, &dir) + < 0) { - cerr << "ERROR: ALSA: format failed - can't continue" << endl; + cerr << "ERROR: ALSA: unable to set rate near " << rrate + << " -- can't continue" << endl; outputParameters(m_parameters); snd_pcm_close(m_pcm); m_pcm = 0; setErrorCondition("unable to configure audio device"); } - } - int channelsCount = TwkAudio::channelsCount(m_parameters.layout); + snd_pcm_hw_params_set_periods_integer(m_pcm, params); - if (snd_pcm_hw_params_set_channels(m_pcm, params, channelsCount) < 0) - { - cerr << "ERROR: ALSA: can't use " << channelsCount - << " channels -- can't continue" << endl; - outputParameters(m_parameters); - snd_pcm_close(m_pcm); - m_pcm = 0; - setErrorCondition("unable to configure audio device"); - } - - if (snd_pcm_hw_params_set_rate_near(m_pcm, params, &rrate, &dir) < 0) - { - cerr << "ERROR: ALSA: unable to set rate near " << rrate - << " -- can't continue" << endl; - outputParameters(m_parameters); - snd_pcm_close(m_pcm); - m_pcm = 0; - setErrorCondition("unable to configure audio device"); - } + // + // Reasonably low latency + // - snd_pcm_hw_params_set_periods_integer(m_pcm, params); + unsigned int periods = 2; + m_periodSize = snd_pcm_uframes_t(double(512) / double(48000.0) + * double(m_parameters.rate)); + m_bufferSize = m_periodSize * periods * channelsCount * dataSize; + dir = 0; - // - // Reasonably low latency - // + snd_pcm_hw_params_set_periods(m_pcm, params, periods, 0); + snd_pcm_hw_params_set_period_size_near(m_pcm, params, &m_periodSize, + &dir); + snd_pcm_hw_params_set_buffer_size_near(m_pcm, params, + &m_bufferSize); - unsigned int periods = 2; - m_periodSize = snd_pcm_uframes_t(double(512) / double(48000.0) * double(m_parameters.rate)); - m_bufferSize = m_periodSize * periods * channelsCount * dataSize; - dir = 0; + if ((err = snd_pcm_hw_params(m_pcm, params)) < 0) + { + cerr << "ERROR: ALSA: params failed: " << snd_strerror(err) + << endl; + snd_pcm_close(m_pcm); + m_pcm = 0; + setErrorCondition("unable to configure audio device"); + } - snd_pcm_hw_params_set_periods(m_pcm, params, periods, 0); - snd_pcm_hw_params_set_period_size_near(m_pcm, params, &m_periodSize, &dir); - snd_pcm_hw_params_set_buffer_size_near(m_pcm, params, &m_bufferSize); + snd_pcm_hw_params_get_buffer_size(params, &m_bufferSize); + snd_pcm_hw_params_get_period_size(params, &m_periodSize, &dir); + periods = m_bufferSize / m_periodSize; - if ((err = snd_pcm_hw_params(m_pcm, params)) < 0) - { - cerr << "ERROR: ALSA: params failed: " << snd_strerror(err) << endl; - snd_pcm_close(m_pcm); - m_pcm = 0; - setErrorCondition("unable to configure audio device"); - } + // LATENCY: + // + // latency = periodsize * periods / (rate * bytes_per_frame) + // + // is this even correct? Some sources claim there are still + // other latencies beyond this. I really don't want to add an + // extra latency UI. + // - snd_pcm_hw_params_get_buffer_size(params, &m_bufferSize); - snd_pcm_hw_params_get_period_size(params, &m_periodSize, &dir); - periods = m_bufferSize / m_periodSize; + DeviceState nstate; + nstate.device = m_parameters.device; + nstate.format = m_parameters.format; + nstate.rate = rrate; + nstate.layout = m_parameters.layout; + nstate.latency = + m_parameters.latency + + m_periodSize * periods + / (nstate.rate * sizeof(short) * channelsCount); + // THIS WILL BLOW IT UP IF ITS NOT 512 + // nstate.framesPerBuffer = 2048; + nstate.framesPerBuffer = m_parameters.framesPerBuffer; + setDeviceState(nstate); + + if (debug) + { + cout << "DEBUG: alsa buffer_size = " << m_bufferSize << endl + << "DEBUG: alsa period_size = " << m_periodSize << endl + << "DEBUG: alsa periods = " << periods << endl + << "DEBUG: alsa device latency = " << nstate.latency + << endl; + } - // LATENCY: - // - // latency = periodsize * periods / (rate * bytes_per_frame) - // - // is this even correct? Some sources claim there are still - // other latencies beyond this. I really don't want to add an - // extra latency UI. - // + // + // Wait for the device to be ready + // - DeviceState nstate; - nstate.device = m_parameters.device; - nstate.format = m_parameters.format; - nstate.rate = rrate; - nstate.layout = m_parameters.layout; - nstate.latency = m_parameters.latency + m_periodSize * periods / (nstate.rate * sizeof(short) * channelsCount); - // THIS WILL BLOW IT UP IF ITS NOT 512 - //nstate.framesPerBuffer = 2048; - nstate.framesPerBuffer = m_parameters.framesPerBuffer; - setDeviceState(nstate); - - if (debug) - { - cout << "DEBUG: alsa buffer_size = " << m_bufferSize << endl - << "DEBUG: alsa period_size = " << m_periodSize << endl - << "DEBUG: alsa periods = " << periods << endl - << "DEBUG: alsa device latency = " << nstate.latency << endl; + snd_pcm_wait(m_pcm, -1); } + } + void ALSAAudioRenderer::threadMain() + { // - // Wait for the device to be ready + // Set the thread priority if asked to do so // - - snd_pcm_wait(m_pcm, -1); - } -} - - -void -ALSAAudioRenderer::threadMain() -{ - // - // Set the thread priority if asked to do so - // - - size_t sched_priority = Application::optionValue("displayPriority", size_t(-1)); - string schedulePolicy = Application::optionValue("schedulePolicy", ""); - - if (schedulePolicy != "") - { - sched_param sp; - memset(&sp, 0, sizeof(sched_param)); - //sp.sched_priority = opts.displayPriority; - sp.sched_priority = sched_priority; - - unsigned int policy = SCHED_OTHER; - if (schedulePolicy == "SCHED_RR") policy = SCHED_RR; - else if (schedulePolicy == "SCHED_FIFO") policy = SCHED_FIFO; + size_t sched_priority = + Application::optionValue("displayPriority", size_t(-1)); + string schedulePolicy = + Application::optionValue("schedulePolicy", ""); - if (policy != SCHED_OTHER) + if (schedulePolicy != "") { - if (sched_setscheduler(0, policy, &sp)) + sched_param sp; + memset(&sp, 0, sizeof(sched_param)); + // sp.sched_priority = opts.displayPriority; + sp.sched_priority = sched_priority; + + unsigned int policy = SCHED_OTHER; + + if (schedulePolicy == "SCHED_RR") + policy = SCHED_RR; + else if (schedulePolicy == "SCHED_FIFO") + policy = SCHED_FIFO; + + if (policy != SCHED_OTHER) { - cout << "ERROR: can't set thread priority" << endl; + if (sched_setscheduler(0, policy, &sp)) + { + cout << "ERROR: can't set thread priority" << endl; + } } - } - else - { - if (setpriority(PRIO_PROCESS, 0, sp.sched_priority)) + else { - cout << "ERROR: can't set thread priority" << endl; + if (setpriority(PRIO_PROCESS, 0, sp.sched_priority)) + { + cout << "ERROR: can't set thread priority" << endl; + } } } - } - - int err; - // - // NOTE: it's possible for this thread to continue on as a - // zombie (after the control thread tried to stop it). In that - // case m_pcm will be null, so check for that whenever we're - // going to use it. This should stop the "asset failed: pcm" - // crashes we get from alsa. - // - if (!m_pcm) return; + int err; + + // + // NOTE: it's possible for this thread to continue on as a + // zombie (after the control thread tried to stop it). In that + // case m_pcm will be null, so check for that whenever we're + // going to use it. This should stop the "asset failed: pcm" + // crashes we get from alsa. + // + if (!m_pcm) + return; - m_threadGroup.lock(m_runningLock); - m_audioThreadRunning = true; - m_audioThread = pthread_self(); - m_threadGroup.unlock(m_runningLock); + m_threadGroup.lock(m_runningLock); + m_audioThreadRunning = true; + m_audioThread = pthread_self(); + m_threadGroup.unlock(m_runningLock); - // - // Get the current state. (yeah, I know it was just set above) - // + // + // Get the current state. (yeah, I know it was just set above) + // - const DeviceState& state = deviceState(); + const DeviceState& state = deviceState(); - // - // Setup accumulation buffer - // + // + // Setup accumulation buffer + // - int channelsCount = TwkAudio::channelsCount(state.layout); + int channelsCount = TwkAudio::channelsCount(state.layout); - AudioBuffer buffer(state.framesPerBuffer, - state.layout, - state.rate); + AudioBuffer buffer(state.framesPerBuffer, state.layout, state.rate); - m_abuffer.reconfigure(state.framesPerBuffer, - state.layout, - Time(state.rate)); + m_abuffer.reconfigure(state.framesPerBuffer, state.layout, + Time(state.rate)); - const size_t formatSize = formatSizeInBytes(m_parameters.format); - m_outBuffer.resize(state.framesPerBuffer * channelsCount * formatSize); + const size_t formatSize = formatSizeInBytes(m_parameters.format); + m_outBuffer.resize(state.framesPerBuffer * channelsCount * formatSize); - // - // Allocate and initialize the "status" object for this pcm stream - // + // + // Allocate and initialize the "status" object for this pcm stream + // - snd_pcm_status_t* status; - snd_pcm_status_alloca(&status); - if (!m_pcm) return; - snd_pcm_status(m_pcm, status); + snd_pcm_status_t* status; + snd_pcm_status_alloca(&status); + if (!m_pcm) + return; + snd_pcm_status(m_pcm, status); - if (!m_pcm) return; - snd_pcm_state_t pcmState = snd_pcm_state(m_pcm); + if (!m_pcm) + return; + snd_pcm_state_t pcmState = snd_pcm_state(m_pcm); - if (pcmState == SND_PCM_STATE_SETUP) - { - if (!m_pcm) return; - if ((err = snd_pcm_prepare(m_pcm)) < 0) + if (pcmState == SND_PCM_STATE_SETUP) { - cerr << "ERROR: ASLA: " << snd_strerror(err) << endl; - return; - } + if (!m_pcm) + return; + if ((err = snd_pcm_prepare(m_pcm)) < 0) + { + cerr << "ERROR: ASLA: " << snd_strerror(err) << endl; + return; + } - if (!m_pcm) return; - pcmState = snd_pcm_state(m_pcm); - } - - m_startSample = 0; - - for (size_t count = 0; - pcmState != SND_PCM_STATE_DISCONNECTED && - pcmState != SND_PCM_STATE_XRUN && - (isPlaying() || - (m_startSample % m_periodSize != 0) || - m_parameters.holdOpen); - count++) - { - // - // Figure out the current latency by hook or by crook. - // + if (!m_pcm) + return; + pcmState = snd_pcm_state(m_pcm); + } - if (!m_pcm) return; - snd_pcm_status(m_pcm, status); - snd_pcm_sframes_t latencyFrames = snd_pcm_status_get_delay(status); + m_startSample = 0; - if ((!latencyFrames || state.latency == 0) && count > 0) + for (size_t count = 0; + pcmState != SND_PCM_STATE_DISCONNECTED + && pcmState != SND_PCM_STATE_XRUN + && (isPlaying() || (m_startSample % m_periodSize != 0) + || m_parameters.holdOpen); + count++) { // - // Update the latency using snd_pcm_delay because - // snd_pcm_status_get_delay() failed. This is common with - // the default device and/or dmix. + // Figure out the current latency by hook or by crook. // - - if (!m_pcm) return; - if (!snd_pcm_delay(m_pcm, &latencyFrames) && latencyFrames > 0) + + if (!m_pcm) + return; + snd_pcm_status(m_pcm, status); + snd_pcm_sframes_t latencyFrames = snd_pcm_status_get_delay(status); + + if ((!latencyFrames || state.latency == 0) && count > 0) { // - // Only if we think this actually worked - // (i.e. latencyFrames > 0) + // Update the latency using snd_pcm_delay because + // snd_pcm_status_get_delay() failed. This is common with + // the default device and/or dmix. // - m_deviceState.latency = m_parameters.latency + latencyFrames / double(state.rate); - } - else - { - m_deviceState.latency = m_parameters.latency; + if (!m_pcm) + return; + if (!snd_pcm_delay(m_pcm, &latencyFrames) && latencyFrames > 0) + { + // + // Only if we think this actually worked + // (i.e. latencyFrames > 0) + // + + m_deviceState.latency = + m_parameters.latency + + latencyFrames / double(state.rate); + } + else + { + m_deviceState.latency = m_parameters.latency; + } } - } - // - // Call the evaluation function - // + // + // Call the evaluation function + // - buffer.reconfigure(state.framesPerBuffer, - state.layout, - Time(state.rate), - samplesToTime(m_startSample, state.rate)); + buffer.reconfigure(state.framesPerBuffer, state.layout, + Time(state.rate), + samplesToTime(m_startSample, state.rate)); - buffer.zero(); + buffer.zero(); - // - // Fetch the samples - // + // + // Fetch the samples + // - audioFillBuffer(buffer); + audioFillBuffer(buffer); - // - // Convert to the correct output format - // + // + // Convert to the correct output format + // - unsigned char* out = &m_outBuffer.front(); + unsigned char* out = &m_outBuffer.front(); - switch (m_parameters.format) - { - case Float32Format: - memcpy(out, buffer.pointer(), buffer.sizeInBytes()); - break; - - case Int16Format: - transform(buffer.pointer(), - buffer.pointer() + buffer.sizeInFloats(), - (short*)out, - toType); - break; - - case Int32Format: - transform(buffer.pointer(), - buffer.pointer() + buffer.sizeInFloats(), - (signed int*)out, - toType); - break; - - case Int8Format: - transform(buffer.pointer(), - buffer.pointer() + buffer.sizeInFloats(), - (signed char*)out, - toType); - break; - } + switch (m_parameters.format) + { + case Float32Format: + memcpy(out, buffer.pointer(), buffer.sizeInBytes()); + break; - // - // Write it. This may block waiting for the device. I'm not - // sure why we have to account for chopping up the output: - // sometimes ALSA just doesn't write all the samples and you - // have to call write again. - // + case Int16Format: + transform(buffer.pointer(), + buffer.pointer() + buffer.sizeInFloats(), (short*)out, + toType); + break; - size_t total = 0; - snd_pcm_sframes_t frames = 0; + case Int32Format: + transform(buffer.pointer(), + buffer.pointer() + buffer.sizeInFloats(), + (signed int*)out, toType); + break; - if (!m_pcm) return; - pcmState = snd_pcm_state(m_pcm);; + case Int8Format: + transform(buffer.pointer(), + buffer.pointer() + buffer.sizeInFloats(), + (signed char*)out, toType); + break; + } - // - // Write the samples. - // - // NOTE: snd_pcm_writei() can BLOCK for an indefinite amount - // of time. - // + // + // Write it. This may block waiting for the device. I'm not + // sure why we have to account for chopping up the output: + // sometimes ALSA just doesn't write all the samples and you + // have to call write again. + // - for (size_t wcount = 0; - (pcmState == SND_PCM_STATE_RUNNING || - pcmState == SND_PCM_STATE_PREPARED) && - total < buffer.size()&& - frames >= 0 && - wcount < buffer.size(); - wcount++) - { - if (!m_pcm) return; - if (debug) - { - cerr << "INFO: pcm_writei: wcount " << wcount << - ", count " << count << - ", total " << total << - ", chan " << channelsCount << - ", formatSize " << formatSize << - ", bufferSize " << buffer.size() << endl; - } - frames = snd_pcm_writei(m_pcm, - out + (total * channelsCount * formatSize), - buffer.size() - total); - if (debug) cerr << "INFO: pcm_writei complete, frames " << frames << endl; - - if (frames >= 0) - { - total += frames; - } - else - { - // - // Possible underrun (in alsa parlance) - // + size_t total = 0; + snd_pcm_sframes_t frames = 0; - // too new to use + if (!m_pcm) + return; + pcmState = snd_pcm_state(m_pcm); + ; + // + // Write the samples. + // + // NOTE: snd_pcm_writei() can BLOCK for an indefinite amount + // of time. + // + + for (size_t wcount = 0; (pcmState == SND_PCM_STATE_RUNNING + || pcmState == SND_PCM_STATE_PREPARED) + && total < buffer.size() && frames >= 0 + && wcount < buffer.size(); + wcount++) + { + if (!m_pcm) + return; + if (debug) + { + cerr << "INFO: pcm_writei: wcount " << wcount << ", count " + << count << ", total " << total << ", chan " + << channelsCount << ", formatSize " << formatSize + << ", bufferSize " << buffer.size() << endl; + } + frames = snd_pcm_writei( + m_pcm, out + (total * channelsCount * formatSize), + buffer.size() - total); if (debug) + cerr << "INFO: pcm_writei complete, frames " << frames + << endl; + + if (frames >= 0) { - cerr << "ERROR: ASLA: write failed (" - << frames - << "): " << snd_strerror(frames) - << " -- "; + total += frames; + } + else + { + // + // Possible underrun (in alsa parlance) + // + + // too new to use - switch (frames) + if (debug) { - case -EBADFD: cerr << "bad pcm state"; break; - case -EPIPE: cerr << "underrun occured"; break; - case -ESTRPIPE: cerr << "suspend event occured"; break; + cerr << "ERROR: ASLA: write failed (" << frames + << "): " << snd_strerror(frames) << " -- "; + + switch (frames) + { + case -EBADFD: + cerr << "bad pcm state"; + break; + case -EPIPE: + cerr << "underrun occured"; + break; + case -ESTRPIPE: + cerr << "suspend event occured"; + break; + } + + cerr << endl; } - cerr << endl; - } - - if (!m_pcm) return; + if (!m_pcm) + return; #ifdef USE_SAFE_ALSA - frames = snd_pcm_recover(m_pcm, frames, 0); + frames = snd_pcm_recover(m_pcm, frames, 0); #else - frames = snd_pcm_prepare(m_pcm); + frames = snd_pcm_prepare(m_pcm); #endif - break; + break; + } + if (total < buffer.size()) + { + if (!m_pcm) + return; + pcmState = snd_pcm_state(m_pcm); + } } - if (total < buffer.size()) - { - if (!m_pcm) return; - pcmState = snd_pcm_state(m_pcm); - } - } - m_startSample += total; - if (!m_pcm) return; - pcmState = snd_pcm_state(m_pcm); + m_startSample += total; + if (!m_pcm) + return; + pcmState = snd_pcm_state(m_pcm); - if (pcmState == SND_PCM_STATE_XRUN) - { - if (!m_pcm) return; - if (snd_pcm_prepare(m_pcm) < 0) break; - if (!m_pcm) return; - if ((pcmState = snd_pcm_state(m_pcm)) == SND_PCM_STATE_XRUN) break; + if (pcmState == SND_PCM_STATE_XRUN) + { + if (!m_pcm) + return; + if (snd_pcm_prepare(m_pcm) < 0) + break; + if (!m_pcm) + return; + if ((pcmState = snd_pcm_state(m_pcm)) == SND_PCM_STATE_XRUN) + break; + } } - } - - if (!m_pcm) return; - if (pcmState == SND_PCM_STATE_RUNNING) snd_pcm_drop(m_pcm); - - m_threadGroup.lock(m_runningLock); - m_audioThreadRunning = false; - m_threadGroup.unlock(m_runningLock); - if (debug) cout << "DEBUG: audio thread exiting" << endl; -} - -void -ALSAAudioRenderer::play(Session* s) -{ - AudioRenderer::play(s); - - s->audioVarLock(); - s->setAudioTimeShift(numeric_limits::max()); - s->setAudioStartSample(0); - s->setAudioFirstPass(true); - s->audioVarUnLock(); - - s->audioConfigure(); + if (!m_pcm) + return; + if (pcmState == SND_PCM_STATE_RUNNING) + snd_pcm_drop(m_pcm); - if (!isPlaying()) play(); -} + m_threadGroup.lock(m_runningLock); + m_audioThreadRunning = false; + m_threadGroup.unlock(m_runningLock); -void -ALSAAudioRenderer::play() -{ - AudioRenderer::play(); + if (debug) + cout << "DEBUG: audio thread exiting" << endl; + } - bool notconfigured = m_pcm == 0; - configureDevice(); + void ALSAAudioRenderer::play(Session* s) + { + AudioRenderer::play(s); - // - // Dispatch the playback thread if its not running already. The - // last argument (async=false) indicates that we want to wait - // until the thread is running before the function returns. - // + s->audioVarLock(); + s->setAudioTimeShift(numeric_limits::max()); + s->setAudioStartSample(0); + s->setAudioFirstPass(true); + s->audioVarUnLock(); - if (notconfigured) m_threadGroup.dispatch(trampoline, this); -} + s->audioConfigure(); -void -ALSAAudioRenderer::stop(Session* s) -{ - AudioRenderer::stop(s); - s->setAudioTimeShift(numeric_limits::max()); - if (!m_parameters.holdOpen) shutdown(); -} + if (!isPlaying()) + play(); + } -void -ALSAAudioRenderer::shutdown() -{ - // - // Shut down the hardware - // + void ALSAAudioRenderer::play() + { + AudioRenderer::play(); - const bool holdOpen = m_parameters.holdOpen; - m_parameters.holdOpen = false; + bool notconfigured = m_pcm == 0; + configureDevice(); - AudioRenderer::stop(); + // + // Dispatch the playback thread if its not running already. The + // last argument (async=false) indicates that we want to wait + // until the thread is running before the function returns. + // - m_threadGroup.lock(m_runningLock); - bool isrunning = m_audioThreadRunning; - m_threadGroup.unlock(m_runningLock); + if (notconfigured) + m_threadGroup.dispatch(trampoline, this); + } - if (isrunning) m_threadGroup.control_wait(true, 1.0); + void ALSAAudioRenderer::stop(Session* s) + { + AudioRenderer::stop(s); + s->setAudioTimeShift(numeric_limits::max()); + if (!m_parameters.holdOpen) + shutdown(); + } - if (m_pcm) + void ALSAAudioRenderer::shutdown() { // - // Although we tried to stop the audio threads above, we - // may have failed (IE the control_wait may have timed out, - // so lock-bracket the m_pcm=0 statement, and don't close - // the audio device until after m_pcm has been zeroed. + // Shut down the hardware // - snd_pcm_t *tmp = m_pcm; + + const bool holdOpen = m_parameters.holdOpen; + m_parameters.holdOpen = false; + + AudioRenderer::stop(); + m_threadGroup.lock(m_runningLock); - m_pcm = 0; + bool isrunning = m_audioThreadRunning; m_threadGroup.unlock(m_runningLock); - snd_pcm_close(tmp); - } - m_parameters.holdOpen = holdOpen; -} + if (isrunning) + m_threadGroup.control_wait(true, 1.0); + + if (m_pcm) + { + // + // Although we tried to stop the audio threads above, we + // may have failed (IE the control_wait may have timed out, + // so lock-bracket the m_pcm=0 statement, and don't close + // the audio device until after m_pcm has been zeroed. + // + snd_pcm_t* tmp = m_pcm; + m_threadGroup.lock(m_runningLock); + m_pcm = 0; + m_threadGroup.unlock(m_runningLock); + snd_pcm_close(tmp); + } + m_parameters.holdOpen = holdOpen; + } -} // Rv +} // namespace IPCore diff --git a/src/lib/audio/ALSAAudioModule/init.cpp b/src/lib/audio/ALSAAudioModule/init.cpp index 03cc8e512..3dc017f6f 100644 --- a/src/lib/audio/ALSAAudioModule/init.cpp +++ b/src/lib/audio/ALSAAudioModule/init.cpp @@ -1,16 +1,16 @@ // -// Copyright (C) 2023 Autodesk, Inc. All Rights Reserved. -// -// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2023 Autodesk, Inc. All Rights Reserved. +// +// SPDX-License-Identifier: Apache-2.0 // #include -extern "C" { - -IPCore::AudioRenderer* -CreateAudioModule(const IPCore::AudioRenderer::RendererParameters& p) -{ - return new IPCore::ALSAAudioRenderer(p); -} +extern "C" +{ + IPCore::AudioRenderer* + CreateAudioModule(const IPCore::AudioRenderer::RendererParameters& p) + { + return new IPCore::ALSAAudioRenderer(p); + } } diff --git a/src/lib/audio/ALSASafeAudioModule/ALSASafeAudioModule/ALSASafeAudioRenderer.h b/src/lib/audio/ALSASafeAudioModule/ALSASafeAudioModule/ALSASafeAudioRenderer.h index 2db37e777..fde02710b 100644 --- a/src/lib/audio/ALSASafeAudioModule/ALSASafeAudioModule/ALSASafeAudioRenderer.h +++ b/src/lib/audio/ALSASafeAudioModule/ALSASafeAudioModule/ALSASafeAudioRenderer.h @@ -1,9 +1,9 @@ //****************************************************************************** // Copyright (c) 2005 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #ifndef __audio__ALSASafeAudioRenderer__h__ #define __audio__ALSASafeAudioRenderer__h__ @@ -14,88 +14,87 @@ #include -namespace IPCore { - -/// Pure ALSASafe implementation of AudioRenderer - -/// -/// -/// - -class ALSASafeAudioRenderer : public AudioRenderer +namespace IPCore { -public: - // - // Types - // - - struct ALSADevice - { - std::string plug; - std::string card; - std::string name; - }; - - typedef std::vector ALSADeviceVector; - typedef TwkAudio::AudioBuffer AudioBuffer; - typedef stl_ext::thread_group ThreadGroup; - typedef std::vector OutputSampleBuffer; - typedef TwkUtil::Timer Timer; - ALSASafeAudioRenderer(const RendererParameters&); - ~ALSASafeAudioRenderer(); + /// Pure ALSASafe implementation of AudioRenderer - - /// - /// play() will return almost immediately -- a worker thread will - /// be released and start playing. /// - - virtual void play(); - virtual void play(Session*); - /// - /// stop() will cause the worker thread to wait until play. A - /// subsequent play should restart it. /// - virtual void stop(Session*); - - /// - /// Completely stop the audio hardware and the audio thread. You can't - /// call play() after you've called shutdown() - /// - - virtual void shutdown(); - - /// - /// These are currently ignored by ALSAAudioRenderer - /// - - virtual void availableLayouts(const Device&, LayoutsVector&); - virtual void availableFormats(const Device&, FormatVector&); - virtual void availableRates(const Device&, Format, RateVector&); - - void threadMain(); - void configureDevice(); - -protected: - virtual void createDeviceList(); - -private: - OutputSampleBuffer m_outBuffer; - ALSADeviceVector m_alsaDevices; - ThreadGroup m_threadGroup; - size_t m_startSample; - snd_pcm_t* m_pcm; - snd_pcm_uframes_t m_periodSize; - snd_pcm_uframes_t m_bufferSize; - pthread_t m_audioThread; - bool m_audioThreadRunning; - pthread_mutex_t m_runningLock; -}; - + class ALSASafeAudioRenderer : public AudioRenderer + { + public: + // + // Types + // + + struct ALSADevice + { + std::string plug; + std::string card; + std::string name; + }; + + typedef std::vector ALSADeviceVector; + typedef TwkAudio::AudioBuffer AudioBuffer; + typedef stl_ext::thread_group ThreadGroup; + typedef std::vector OutputSampleBuffer; + typedef TwkUtil::Timer Timer; + + ALSASafeAudioRenderer(const RendererParameters&); + ~ALSASafeAudioRenderer(); + + /// + /// play() will return almost immediately -- a worker thread will + /// be released and start playing. + /// + + virtual void play(); + virtual void play(Session*); + + /// + /// stop() will cause the worker thread to wait until play. A + /// subsequent play should restart it. + /// + + virtual void stop(Session*); + + /// + /// Completely stop the audio hardware and the audio thread. You can't + /// call play() after you've called shutdown() + /// + + virtual void shutdown(); + + /// + /// These are currently ignored by ALSAAudioRenderer + /// + + virtual void availableLayouts(const Device&, LayoutsVector&); + virtual void availableFormats(const Device&, FormatVector&); + virtual void availableRates(const Device&, Format, RateVector&); + + void threadMain(); + void configureDevice(); + + protected: + virtual void createDeviceList(); + + private: + OutputSampleBuffer m_outBuffer; + ALSADeviceVector m_alsaDevices; + ThreadGroup m_threadGroup; + size_t m_startSample; + snd_pcm_t* m_pcm; + snd_pcm_uframes_t m_periodSize; + snd_pcm_uframes_t m_bufferSize; + pthread_t m_audioThread; + bool m_audioThreadRunning; + pthread_mutex_t m_runningLock; + }; -} // IPCore +} // namespace IPCore #endif // __audio__ALSASafeAudioRenderer__h__ diff --git a/src/lib/audio/ALSASafeAudioModule/ALSASafeAudioRenderer.cpp b/src/lib/audio/ALSASafeAudioModule/ALSASafeAudioRenderer.cpp index 5495d7c02..fea17505c 100644 --- a/src/lib/audio/ALSASafeAudioModule/ALSASafeAudioRenderer.cpp +++ b/src/lib/audio/ALSASafeAudioModule/ALSASafeAudioRenderer.cpp @@ -1,9 +1,9 @@ //****************************************************************************** // Copyright (c) 2005 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #include #include @@ -171,55 +171,50 @@ #include -namespace IPCore { -using namespace std; -using namespace stl_ext; -using namespace TwkApp; -using namespace TwkAudio; +namespace IPCore +{ + using namespace std; + using namespace stl_ext; + using namespace TwkApp; + using namespace TwkAudio; -namespace { + namespace + { -template T toType (float a) -{ - return T(double(a) * double(numeric_limits::max())); -} + template T toType(float a) + { + return T(double(a) * double(numeric_limits::max())); + } -} + } // namespace -static void -alsaErrorHandler (const char *file, - int line, - const char *function, - int err, - const char *fmt, - ...) -{ - // don't print out ALSA asserts -} - -static int -snd_pcm_open_real_hard(snd_pcm_t **pcm, - const char *name, - snd_pcm_stream_t stream, - int mode, - size_t iterations = 1) -{ - // - // Try REAL HARD to open the device. If it doesn't open right - // away. Wait a second and see if anything improves. There's - // probably a way to avoid this by waiting until the device is - // drained, but one might assume snd_pcm_drain() would do that - // wouldn't one? - // - // It seems like the device is still playing back accumulated - // samples and cannot be opened (e.g., switching to an exclusive - // hardware device from default). If you wait for the device to - // drain, it will eventually work. This technique (or a - // variation) is applied by a number of other programs on the - // net. - // - - int err = snd_pcm_open(pcm, name, stream, mode); + static void alsaErrorHandler(const char* file, int line, + const char* function, int err, const char* fmt, + ...) + { + // don't print out ALSA asserts + } + + static int snd_pcm_open_real_hard(snd_pcm_t** pcm, const char* name, + snd_pcm_stream_t stream, int mode, + size_t iterations = 1) + { + // + // Try REAL HARD to open the device. If it doesn't open right + // away. Wait a second and see if anything improves. There's + // probably a way to avoid this by waiting until the device is + // drained, but one might assume snd_pcm_drain() would do that + // wouldn't one? + // + // It seems like the device is still playing back accumulated + // samples and cannot be opened (e.g., switching to an exclusive + // hardware device from default). If you wait for the device to + // drain, it will eventually work. This technique (or a + // variation) is applied by a number of other programs on the + // net. + // + + int err = snd_pcm_open(pcm, name, stream, mode); #if 0 for (size_t i = 0; i < iterations && err == -EBUSY; i++) @@ -229,412 +224,442 @@ snd_pcm_open_real_hard(snd_pcm_t **pcm, } #endif - if (!err && *pcm) snd_pcm_nonblock(*pcm, 0); // 0 means block - return err; -} + if (!err && *pcm) + snd_pcm_nonblock(*pcm, 0); // 0 means block + return err; + } -ALSASafeAudioRenderer::ALSASafeAudioRenderer(const RendererParameters& p) - : AudioRenderer(p), - m_threadGroup(1,2), - m_pcm(0), - m_audioThread(pthread_self()), - m_audioThreadRunning(false) -{ - snd_lib_error_set_handler(alsaErrorHandler); - pthread_mutex_init(&m_runningLock, 0); + ALSASafeAudioRenderer::ALSASafeAudioRenderer(const RendererParameters& p) + : AudioRenderer(p) + , m_threadGroup(1, 2) + , m_pcm(0) + , m_audioThread(pthread_self()) + , m_audioThreadRunning(false) + { + snd_lib_error_set_handler(alsaErrorHandler); + pthread_mutex_init(&m_runningLock, 0); - if (m_parameters.rate == 0) m_parameters.rate = TWEAK_AUDIO_DEFAULT_SAMPLE_RATE; - if (m_parameters.framesPerBuffer == 0) m_parameters.framesPerBuffer = 512; - if (m_parameters.device == "") m_parameters.device = "default"; + if (m_parameters.rate == 0) + m_parameters.rate = TWEAK_AUDIO_DEFAULT_SAMPLE_RATE; + if (m_parameters.framesPerBuffer == 0) + m_parameters.framesPerBuffer = 512; + if (m_parameters.device == "") + m_parameters.device = "default"; - createDeviceList(); + createDeviceList(); - if (debug) outputParameters(m_parameters); + if (debug) + outputParameters(m_parameters); - #ifndef PLATFORM_WINDOWS - /* - We used to initialize the device at this point, but if something - goes wrong, it means we can't even change the device in the - prefs, because audio is shutdown. If we skip this step, we'll - hold open the device after the first play(). - */ +#ifndef PLATFORM_WINDOWS + /* + We used to initialize the device at this point, but if something + goes wrong, it means we can't even change the device in the + prefs, because audio is shutdown. If we skip this step, we'll + hold open the device after the first play(). + */ - if (m_parameters.holdOpen) + if (m_parameters.holdOpen) + { + play(); + AudioRenderer::stop(); + } +#endif + } + + ALSASafeAudioRenderer::~ALSASafeAudioRenderer() { - play(); AudioRenderer::stop(); + shutdown(); + pthread_mutex_destroy(&m_runningLock); } - #endif -} -ALSASafeAudioRenderer::~ALSASafeAudioRenderer() -{ - AudioRenderer::stop(); - shutdown(); - pthread_mutex_destroy(&m_runningLock); -} - -void -ALSASafeAudioRenderer::createDeviceList() -{ - m_outputDevices.clear(); - m_alsaDevices.clear(); + void ALSASafeAudioRenderer::createDeviceList() + { + m_outputDevices.clear(); + m_alsaDevices.clear(); #ifdef USE_SAFE_ALSA - // - // use the snd_device_name_hint() function - // - - void** deviceList = 0; - snd_device_name_hint(-1, "pcm", (void***)&deviceList); - - // - // For whatever reason ("pulseaudio sucks" ?) the list of devices returned - // here is sometimes incomplete (missing the "pusle" device). But calling - // the same call again seems to work around the problem ... - // - - snd_device_name_free_hint(deviceList); - snd_device_name_hint(-1, "pcm", (void***)&deviceList); - - for (void** dv = deviceList; *dv; dv++) - { - char* namep = snd_device_name_get_hint(*dv, "NAME"); - char* descp = snd_device_name_get_hint(*dv, "DESC"); - const string name = namep; - const string desc = descp; + // + // use the snd_device_name_hint() function + // + + void** deviceList = 0; + snd_device_name_hint(-1, "pcm", (void***)&deviceList); // - // we only do stereo right now + // For whatever reason ("pulseaudio sucks" ?) the list of devices + // returned here is sometimes incomplete (missing the "pusle" device). + // But calling the same call again seems to work around the problem ... // - if (name == "null" || name.find("surround") != string::npos) continue; - string::size_type n = desc.find('\n'); - const string desc0 = desc.substr(0, n); - const string desc1 = desc.substr(n+1, desc.size()); + snd_device_name_free_hint(deviceList); + snd_device_name_hint(-1, "pcm", (void***)&deviceList); - free(namep); - free(descp); + for (void** dv = deviceList; *dv; dv++) + { + char* namep = snd_device_name_get_hint(*dv, "NAME"); + char* descp = snd_device_name_get_hint(*dv, "DESC"); + const string name = namep; + const string desc = descp; - Device d(name); - d.layout = TwkAudio::UnknownLayout; - d.defaultRate = 0; - d.isDefaultDevice = false; - d.index = m_outputDevices.size(); + // + // we only do stereo right now + // + if (name == "null" || name.find("surround") != string::npos) + continue; - ALSADevice ad; - ad.plug = "plugIn"; - ad.name = name; - ad.card = ""; + string::size_type n = desc.find('\n'); + const string desc0 = desc.substr(0, n); + const string desc1 = desc.substr(n + 1, desc.size()); - m_outputDevices.push_back(d); - m_alsaDevices.push_back(ad); - } + free(namep); + free(descp); - snd_device_name_free_hint(deviceList); + Device d(name); + d.layout = TwkAudio::UnknownLayout; + d.defaultRate = 0; + d.isDefaultDevice = false; + d.index = m_outputDevices.size(); -#else + ALSADevice ad; + ad.plug = "plugIn"; + ad.name = name; + ad.card = ""; - for (int card = -1; snd_card_next(&card) >= 0 && card >= 0;) - { - // - // Find the card devices - // + m_outputDevices.push_back(d); + m_alsaDevices.push_back(ad); + } - snd_ctl_t* ctl = 0; - char* cardname = 0; - ostringstream hwcard; - hwcard << "hw:" << card; + snd_device_name_free_hint(deviceList); - snd_card_get_longname(card, &cardname); +#else - if (snd_ctl_open(&ctl, hwcard.str().c_str(), 0) == 0) + for (int card = -1; snd_card_next(&card) >= 0 && card >= 0;) { - snd_pcm_info_t* info = 0; - snd_pcm_info_alloca(&info); + // + // Find the card devices + // + + snd_ctl_t* ctl = 0; + char* cardname = 0; + ostringstream hwcard; + hwcard << "hw:" << card; - for (int device = -1; snd_ctl_pcm_next_device(ctl, &device) >= 0 && device >= 0;) + snd_card_get_longname(card, &cardname); + + if (snd_ctl_open(&ctl, hwcard.str().c_str(), 0) == 0) { - snd_pcm_info_set_device(info, device); - snd_pcm_info_set_subdevice(info, 0); - snd_pcm_info_set_stream(info, SND_PCM_STREAM_PLAYBACK); + snd_pcm_info_t* info = 0; + snd_pcm_info_alloca(&info); - if (snd_ctl_pcm_info(ctl, info) >= 0) + for (int device = -1; + snd_ctl_pcm_next_device(ctl, &device) >= 0 && device >= 0;) { - ostringstream fullname; - - fullname << cardname - << ": " << snd_pcm_info_get_name(info) - << " (" << hwcard.str() - << "," << device - << ")"; - - ostringstream dname; - dname << hwcard.str() << "," << device; - - Device d(fullname.str()); - d.layout = TwkAudio::UnknownLayout; - d.defaultRate = 0; - d.isDefaultDevice = false; - d.index = m_outputDevices.size(); - - char* c; - snd_card_get_name(card, &c); - - ALSADevice ad; - ad.plug = "hw"; - ad.name = dname.str(); - ad.card = c; - - m_outputDevices.push_back(d); - m_alsaDevices.push_back(ad); + snd_pcm_info_set_device(info, device); + snd_pcm_info_set_subdevice(info, 0); + snd_pcm_info_set_stream(info, SND_PCM_STREAM_PLAYBACK); + + if (snd_ctl_pcm_info(ctl, info) >= 0) + { + ostringstream fullname; + + fullname << cardname << ": " + << snd_pcm_info_get_name(info) << " (" + << hwcard.str() << "," << device << ")"; + + ostringstream dname; + dname << hwcard.str() << "," << device; + + Device d(fullname.str()); + d.layout = TwkAudio::UnknownLayout; + d.defaultRate = 0; + d.isDefaultDevice = false; + d.index = m_outputDevices.size(); + + char* c; + snd_card_get_name(card, &c); + + ALSADevice ad; + ad.plug = "hw"; + ad.name = dname.str(); + ad.card = c; + + m_outputDevices.push_back(d); + m_alsaDevices.push_back(ad); + } } - } - snd_ctl_close(ctl); + snd_ctl_close(ctl); + } } - } #endif - // - // See if RV_ALSA_EXTRA_DEVICES is set and if so scarf the - // devices out of there too. - // - - if (const char* xdevices = getenv("RV_ALSA_EXTRA_DEVICES")) - { - vector tokens; - stl_ext::tokenize(tokens, xdevices, "|"); + // + // See if RV_ALSA_EXTRA_DEVICES is set and if so scarf the + // devices out of there too. + // - for (size_t i = 0; i < tokens.size(); i++) + if (const char* xdevices = getenv("RV_ALSA_EXTRA_DEVICES")) { - vector dtokens; - stl_ext::tokenize(dtokens, tokens[i], "@"); - - string name; - string alsaDevice; + vector tokens; + stl_ext::tokenize(tokens, xdevices, "|"); - if (dtokens.size() == 1) + for (size_t i = 0; i < tokens.size(); i++) { - name = tokens[i]; - alsaDevice = name; - } - else if (dtokens.size() == 2) - { - name = dtokens[0]; - alsaDevice = dtokens[1]; - } - else - { - cerr << "ERROR: RV_ALSA_EXTRA_DEVICES env variable -- syntax error" << endl; - break; - } + vector dtokens; + stl_ext::tokenize(dtokens, tokens[i], "@"); - Device d(name); - d.layout = TwkAudio::Stereo_2; - d.defaultRate = TWEAK_AUDIO_DEFAULT_SAMPLE_RATE; - d.latencyLow = 0; - d.latencyHigh = 0; - d.isDefaultDevice = false; - d.index = m_outputDevices.size(); + string name; + string alsaDevice; - ALSADevice ad; - ad.plug = "plughw"; - ad.card = "PlugIn Module"; - ad.name = alsaDevice; + if (dtokens.size() == 1) + { + name = tokens[i]; + alsaDevice = name; + } + else if (dtokens.size() == 2) + { + name = dtokens[0]; + alsaDevice = dtokens[1]; + } + else + { + cerr << "ERROR: RV_ALSA_EXTRA_DEVICES env variable -- " + "syntax error" + << endl; + break; + } - m_outputDevices.push_back(d); - m_alsaDevices.push_back(ad); + Device d(name); + d.layout = TwkAudio::Stereo_2; + d.defaultRate = TWEAK_AUDIO_DEFAULT_SAMPLE_RATE; + d.latencyLow = 0; + d.latencyHigh = 0; + d.isDefaultDevice = false; + d.index = m_outputDevices.size(); + + ALSADevice ad; + ad.plug = "plughw"; + ad.card = "PlugIn Module"; + ad.name = alsaDevice; + + m_outputDevices.push_back(d); + m_alsaDevices.push_back(ad); + } } - } - // - // Add default - // - - Device d("default"); - d.layout = TwkAudio::Stereo_2; - d.defaultRate = TWEAK_AUDIO_DEFAULT_SAMPLE_RATE; - d.latencyLow = 0; - d.latencyHigh = 0; - d.isDefaultDevice = true; - d.index = m_outputDevices.size(); - - ALSADevice ad; - ad.plug = "plughw"; - ad.card = "PlugIn Module"; - ad.name = "default"; - - m_outputDevices.push_back(d); - m_alsaDevices.push_back(ad); - - // - // Copy the current state from the parameters - // - - DeviceState state; - state.device = m_parameters.device; - state.format = m_parameters.format; - state.rate = m_parameters.rate; - state.latency = m_parameters.latency; - state.layout = m_parameters.layout; - state.framesPerBuffer = m_parameters.framesPerBuffer; - setDeviceState(state); - - // - // Force allocation of memory now - // - - int channelsCount = TwkAudio::channelsCount(state.layout); - m_abuffer.reconfigure(state.framesPerBuffer, state.layout, Time(state.rate), 0, 0); - m_outBuffer.resize(m_abuffer.size() * channelsCount * formatSizeInBytes(state.format)); -} - - -void -ALSASafeAudioRenderer::availableLayouts(const Device& d, LayoutsVector& layouts) -{ - layouts.clear(); + // + // Add default + // - layouts.push_back(TwkAudio::Mono_1); - layouts.push_back(TwkAudio::Stereo_2); -} + Device d("default"); + d.layout = TwkAudio::Stereo_2; + d.defaultRate = TWEAK_AUDIO_DEFAULT_SAMPLE_RATE; + d.latencyLow = 0; + d.latencyHigh = 0; + d.isDefaultDevice = true; + d.index = m_outputDevices.size(); -void -ALSASafeAudioRenderer::availableFormats(const Device& d, FormatVector& formats) -{ - // - // The base class ensures that this function is not called when a - // device is opened. - // + ALSADevice ad; + ad.plug = "plughw"; + ad.card = "PlugIn Module"; + ad.name = "default"; - formats.clear(); - static Format allformats[4] = { Float32Format, Int32Format, Int16Format, Int8Format }; + m_outputDevices.push_back(d); + m_alsaDevices.push_back(ad); + + // + // Copy the current state from the parameters + // - const ALSADevice& ad = m_alsaDevices[d.index]; - const string& deviceName = ad.name; + DeviceState state; + state.device = m_parameters.device; + state.format = m_parameters.format; + state.rate = m_parameters.rate; + state.latency = m_parameters.latency; + state.layout = m_parameters.layout; + state.framesPerBuffer = m_parameters.framesPerBuffer; + setDeviceState(state); - for (size_t i = 0; i < 3; i++) + // + // Force allocation of memory now + // + + int channelsCount = TwkAudio::channelsCount(state.layout); + m_abuffer.reconfigure(state.framesPerBuffer, state.layout, + Time(state.rate), 0, 0); + m_outBuffer.resize(m_abuffer.size() * channelsCount + * formatSizeInBytes(state.format)); + } + + void ALSASafeAudioRenderer::availableLayouts(const Device& d, + LayoutsVector& layouts) { - Format format = allformats[i]; + layouts.clear(); - snd_pcm_t* pcm; - int err; + layouts.push_back(TwkAudio::Mono_1); + layouts.push_back(TwkAudio::Stereo_2); + } - if ((err = snd_pcm_open_real_hard(&pcm, - deviceName.c_str(), - SND_PCM_STREAM_PLAYBACK, - SND_PCM_NONBLOCK, - 10)) == 0) - { - snd_pcm_hw_params_t* params; - snd_pcm_hw_params_alloca(¶ms); - snd_pcm_hw_params_any(pcm, params); + void ALSASafeAudioRenderer::availableFormats(const Device& d, + FormatVector& formats) + { + // + // The base class ensures that this function is not called when a + // device is opened. + // - unsigned int rrate = (unsigned int)m_parameters.rate; + formats.clear(); + static Format allformats[4] = {Float32Format, Int32Format, Int16Format, + Int8Format}; - snd_pcm_format_t alsaformat; + const ALSADevice& ad = m_alsaDevices[d.index]; + const string& deviceName = ad.name; - switch (format) - { - case Float32Format: alsaformat = SND_PCM_FORMAT_FLOAT_LE; break; - case Int32Format: alsaformat = SND_PCM_FORMAT_S32_LE; break; - case Int16Format: alsaformat = SND_PCM_FORMAT_S16_LE; break; - case Int8Format: alsaformat = SND_PCM_FORMAT_S8; break; - } + for (size_t i = 0; i < 3; i++) + { + Format format = allformats[i]; - int dir = 0; - snd_pcm_hw_params_set_access(pcm, params, SND_PCM_ACCESS_RW_INTERLEAVED); - bool ok = snd_pcm_hw_params_set_format(pcm, params, alsaformat) == 0; - snd_pcm_hw_params_set_channels(pcm, params, TwkAudio::channelsCount(m_parameters.layout)); - snd_pcm_hw_params_set_rate_near(pcm, params, &rrate, &dir); + snd_pcm_t* pcm; + int err; - if (ok && rrate == m_parameters.rate) + if ((err = snd_pcm_open_real_hard(&pcm, deviceName.c_str(), + SND_PCM_STREAM_PLAYBACK, + SND_PCM_NONBLOCK, 10)) + == 0) { - int periods = 2; - snd_pcm_uframes_t period_size = 8192; - snd_pcm_uframes_t buffer_size = 0; - - snd_pcm_hw_params_set_periods(pcm, params, periods, 0); - snd_pcm_hw_params_set_buffer_size(pcm, params, (period_size * periods) >> 2); - - if (snd_pcm_hw_params(pcm, params) >= 0) + snd_pcm_hw_params_t* params; + snd_pcm_hw_params_alloca(¶ms); + snd_pcm_hw_params_any(pcm, params); + + unsigned int rrate = (unsigned int)m_parameters.rate; + + snd_pcm_format_t alsaformat; + + switch (format) { - formats.push_back(format); + case Float32Format: + alsaformat = SND_PCM_FORMAT_FLOAT_LE; + break; + case Int32Format: + alsaformat = SND_PCM_FORMAT_S32_LE; + break; + case Int16Format: + alsaformat = SND_PCM_FORMAT_S16_LE; + break; + case Int8Format: + alsaformat = SND_PCM_FORMAT_S8; + break; } - } - snd_pcm_close(pcm); - } - else if (err == -EBUSY) - { - // - // The device isn't available - // + int dir = 0; + snd_pcm_hw_params_set_access(pcm, params, + SND_PCM_ACCESS_RW_INTERLEAVED); + bool ok = + snd_pcm_hw_params_set_format(pcm, params, alsaformat) == 0; + snd_pcm_hw_params_set_channels( + pcm, params, TwkAudio::channelsCount(m_parameters.layout)); + snd_pcm_hw_params_set_rate_near(pcm, params, &rrate, &dir); - break; - } - } -} + if (ok && rrate == m_parameters.rate) + { + int periods = 2; + snd_pcm_uframes_t period_size = 8192; + snd_pcm_uframes_t buffer_size = 0; -void -ALSASafeAudioRenderer::availableRates(const Device& device, Format format, RateVector& rates) -{ - // - // The base class ensures that this function is not called when a - // device is opened. - // + snd_pcm_hw_params_set_periods(pcm, params, periods, 0); + snd_pcm_hw_params_set_buffer_size( + pcm, params, (period_size * periods) >> 2); - rates.clear(); + if (snd_pcm_hw_params(pcm, params) >= 0) + { + formats.push_back(format); + } + } - static double standardSampleRates[] = { - 8000.0, 9600.0, 11025.0, 12000.0, 16000.0, 22050.0, 24000.0, 32000.0, - 44100.0, 48000.0, 88200.0, 96000.0, 192000.0, -1 /* negative terminated list */ - }; + snd_pcm_close(pcm); + } + else if (err == -EBUSY) + { + // + // The device isn't available + // - const ALSADevice& ad = m_alsaDevices[device.index]; - const string& deviceName = ad.name; + break; + } + } + } - for (size_t i = 0; standardSampleRates[i] > 0; i++) + void ALSASafeAudioRenderer::availableRates(const Device& device, + Format format, RateVector& rates) { - double rate = standardSampleRates[i]; - snd_pcm_t* pcm; - int err; + // + // The base class ensures that this function is not called when a + // device is opened. + // - if ((err = snd_pcm_open_real_hard(&pcm, - deviceName.c_str(), - SND_PCM_STREAM_PLAYBACK, - SND_PCM_NONBLOCK, - 10)) == 0) - { - snd_pcm_hw_params_t* params; - snd_pcm_hw_params_alloca(¶ms); - snd_pcm_hw_params_any(pcm, params); + rates.clear(); - unsigned int rrate = (unsigned int)rate; + static double standardSampleRates[] = { + 8000.0, 9600.0, 11025.0, 12000.0, 16000.0, + 22050.0, 24000.0, 32000.0, 44100.0, 48000.0, + 88200.0, 96000.0, 192000.0, -1 /* negative terminated list */ + }; - snd_pcm_format_t alsaformat; + const ALSADevice& ad = m_alsaDevices[device.index]; + const string& deviceName = ad.name; - switch (m_parameters.format) + for (size_t i = 0; standardSampleRates[i] > 0; i++) + { + double rate = standardSampleRates[i]; + snd_pcm_t* pcm; + int err; + + if ((err = snd_pcm_open_real_hard(&pcm, deviceName.c_str(), + SND_PCM_STREAM_PLAYBACK, + SND_PCM_NONBLOCK, 10)) + == 0) { - case Float32Format: alsaformat = SND_PCM_FORMAT_FLOAT_LE; break; - case Int32Format: alsaformat = SND_PCM_FORMAT_S32_LE; break; - case Int16Format: alsaformat = SND_PCM_FORMAT_S16_LE; break; - case Int8Format: alsaformat = SND_PCM_FORMAT_S8; break; - } + snd_pcm_hw_params_t* params; + snd_pcm_hw_params_alloca(¶ms); + snd_pcm_hw_params_any(pcm, params); - // - // This doesn't work -- why does ALSA say it does? - // + unsigned int rrate = (unsigned int)rate; - int dir = 0; - snd_pcm_hw_params_set_access(pcm, params, SND_PCM_ACCESS_RW_INTERLEAVED); - snd_pcm_hw_params_set_format(pcm, params, alsaformat); - snd_pcm_hw_params_set_channels(pcm, params, TwkAudio::channelsCount(m_parameters.layout)); - snd_pcm_hw_params_set_rate_near(pcm, params, &rrate, &dir); + snd_pcm_format_t alsaformat; - if (rrate == rate) rates.push_back((unsigned int)rate); + switch (m_parameters.format) + { + case Float32Format: + alsaformat = SND_PCM_FORMAT_FLOAT_LE; + break; + case Int32Format: + alsaformat = SND_PCM_FORMAT_S32_LE; + break; + case Int16Format: + alsaformat = SND_PCM_FORMAT_S16_LE; + break; + case Int8Format: + alsaformat = SND_PCM_FORMAT_S8; + break; + } + + // + // This doesn't work -- why does ALSA say it does? + // + + int dir = 0; + snd_pcm_hw_params_set_access(pcm, params, + SND_PCM_ACCESS_RW_INTERLEAVED); + snd_pcm_hw_params_set_format(pcm, params, alsaformat); + snd_pcm_hw_params_set_channels( + pcm, params, TwkAudio::channelsCount(m_parameters.layout)); + snd_pcm_hw_params_set_rate_near(pcm, params, &rrate, &dir); + + if (rrate == rate) + rates.push_back((unsigned int)rate); #if 0 int periods = 2; @@ -650,592 +675,624 @@ ALSASafeAudioRenderer::availableRates(const Device& device, Format format, RateV } #endif - snd_pcm_close(pcm); + snd_pcm_close(pcm); + } } } -} - -static void -trampoline(void* data) -{ - ALSASafeAudioRenderer* a = (ALSASafeAudioRenderer*)data; - a->threadMain(); -} -void -ALSASafeAudioRenderer::configureDevice() -{ - int err; + static void trampoline(void* data) + { + ALSASafeAudioRenderer* a = (ALSASafeAudioRenderer*)data; + a->threadMain(); + } - if (!m_pcm) + void ALSASafeAudioRenderer::configureDevice() { - string alsaDeviceName = "default"; - int dindex = findDeviceByName(m_parameters.device); + int err; - if (dindex >= 0 && dindex < m_alsaDevices.size()) + if (!m_pcm) { - const ALSADevice& ad = m_alsaDevices[dindex]; - alsaDeviceName = ad.name; - } + string alsaDeviceName = "default"; + int dindex = findDeviceByName(m_parameters.device); - if ((err = snd_pcm_open_real_hard(&m_pcm, - alsaDeviceName.c_str(), - SND_PCM_STREAM_PLAYBACK, - SND_PCM_NONBLOCK)) < 0) - { - cerr << "WARNING: ALSA: Playback open error (" - << err << "): " << snd_strerror(err) << endl; + if (dindex >= 0 && dindex < m_alsaDevices.size()) + { + const ALSADevice& ad = m_alsaDevices[dindex]; + alsaDeviceName = ad.name; + } - - if (alsaDeviceName != "default" && err != -16) /* busy */ + if ((err = snd_pcm_open_real_hard(&m_pcm, alsaDeviceName.c_str(), + SND_PCM_STREAM_PLAYBACK, + SND_PCM_NONBLOCK)) + < 0) { - cerr << "WARNING: ALSA: trying default instead of " - << alsaDeviceName - << endl; + cerr << "WARNING: ALSA: Playback open error (" << err + << "): " << snd_strerror(err) << endl; - if ((err = snd_pcm_open_real_hard(&m_pcm, - "default", - SND_PCM_STREAM_PLAYBACK, - SND_PCM_NONBLOCK)) < 0) + if (alsaDeviceName != "default" && err != -16) /* busy */ { - cerr << "WARNING: ALSA: no luck with default either" << endl; - setErrorCondition("Unable to open an audio device"); + cerr << "WARNING: ALSA: trying default instead of " + << alsaDeviceName << endl; + + if ((err = snd_pcm_open_real_hard(&m_pcm, "default", + SND_PCM_STREAM_PLAYBACK, + SND_PCM_NONBLOCK)) + < 0) + { + cerr << "WARNING: ALSA: no luck with default either" + << endl; + setErrorCondition("Unable to open an audio device"); + } + else + { + cerr << "WARNING: ALSA: using default device instead" + << endl; + m_deviceState.device = "default"; + alsaDeviceName = "default"; + } } else { - cerr << "WARNING: ALSA: using default device instead" << endl; - m_deviceState.device = "default"; - alsaDeviceName = "default"; + setErrorCondition("Unable to open an audio device"); } } - else + + snd_pcm_hw_params_t* params; + snd_pcm_hw_params_alloca(¶ms); + snd_pcm_hw_params_any(m_pcm, params); + + snd_pcm_format_t alsaformat; + size_t dataSize = 0; + + switch (m_parameters.format) { - setErrorCondition("Unable to open an audio device"); + case Float32Format: + alsaformat = SND_PCM_FORMAT_FLOAT_LE; + dataSize = sizeof(float); + break; + default: + case Int16Format: + alsaformat = SND_PCM_FORMAT_S16_LE; + dataSize = sizeof(short); + break; + case Int32Format: + alsaformat = SND_PCM_FORMAT_S32_LE; + dataSize = sizeof(signed int); + break; + case Int8Format: + alsaformat = SND_PCM_FORMAT_S8; + dataSize = sizeof(char); + break; } - } - snd_pcm_hw_params_t* params; - snd_pcm_hw_params_alloca(¶ms); - snd_pcm_hw_params_any(m_pcm, params); + unsigned int rrate = (unsigned int)m_parameters.rate; + int dir = 0; - snd_pcm_format_t alsaformat; - size_t dataSize = 0; - - switch (m_parameters.format) - { - case Float32Format: - alsaformat = SND_PCM_FORMAT_FLOAT_LE; - dataSize = sizeof(float); - break; - default: - case Int16Format: - alsaformat = SND_PCM_FORMAT_S16_LE; - dataSize = sizeof(short); - break; - case Int32Format: - alsaformat = SND_PCM_FORMAT_S32_LE; - dataSize = sizeof(signed int); - break; - case Int8Format: - alsaformat = SND_PCM_FORMAT_S8; - dataSize = sizeof(char); - break; - } + if (snd_pcm_hw_params_set_access(m_pcm, params, + SND_PCM_ACCESS_RW_INTERLEAVED) + < 0) + { + cerr << "ERROR: ALSA: access (interleaved) failed - can't " + "continue" + << endl; + outputParameters(m_parameters); + snd_pcm_close(m_pcm); + m_pcm = 0; + setErrorCondition("unable to configure audio device"); + } - unsigned int rrate = (unsigned int)m_parameters.rate; - int dir = 0; + if (snd_pcm_hw_params_set_format(m_pcm, params, alsaformat) < 0) + { + if (snd_pcm_hw_params_set_format(m_pcm, params, + SND_PCM_FORMAT_S16_LE) + >= 0) + { + if (debug) + cerr << "WARNING: ALSA: format falling back to Int16" + << endl; + m_parameters.format = Int16Format; + } + else + { + cerr << "ERROR: ALSA: format failed - can't continue" + << endl; + outputParameters(m_parameters); + snd_pcm_close(m_pcm); + m_pcm = 0; + setErrorCondition("unable to configure audio device"); + } + } - if (snd_pcm_hw_params_set_access(m_pcm, params, SND_PCM_ACCESS_RW_INTERLEAVED) < 0) - { - cerr << "ERROR: ALSA: access (interleaved) failed - can't continue" << endl; - outputParameters(m_parameters); - snd_pcm_close(m_pcm); - m_pcm = 0; - setErrorCondition("unable to configure audio device"); - } + int channelsCount = TwkAudio::channelsCount(m_parameters.layout); - if (snd_pcm_hw_params_set_format(m_pcm, params, alsaformat) < 0) - { - if (snd_pcm_hw_params_set_format(m_pcm, params, SND_PCM_FORMAT_S16_LE) >= 0) + if (snd_pcm_hw_params_set_channels(m_pcm, params, channelsCount) + < 0) { - if (debug) cerr << "WARNING: ALSA: format falling back to Int16" << endl; - m_parameters.format = Int16Format; + cerr << "ERROR: ALSA: can't use " << channelsCount + << " channels -- can't continue" << endl; + outputParameters(m_parameters); + snd_pcm_close(m_pcm); + m_pcm = 0; + setErrorCondition("unable to configure audio device"); } - else + + if (snd_pcm_hw_params_set_rate_near(m_pcm, params, &rrate, &dir) + < 0) { - cerr << "ERROR: ALSA: format failed - can't continue" << endl; + cerr << "ERROR: ALSA: unable to set rate near " << rrate + << " -- can't continue" << endl; outputParameters(m_parameters); snd_pcm_close(m_pcm); m_pcm = 0; setErrorCondition("unable to configure audio device"); } - } - int channelsCount = TwkAudio::channelsCount(m_parameters.layout); + snd_pcm_hw_params_set_periods_integer(m_pcm, params); - if (snd_pcm_hw_params_set_channels(m_pcm, params, channelsCount) < 0) - { - cerr << "ERROR: ALSA: can't use " << channelsCount - << " channels -- can't continue" << endl; - outputParameters(m_parameters); - snd_pcm_close(m_pcm); - m_pcm = 0; - setErrorCondition("unable to configure audio device"); - } - - if (snd_pcm_hw_params_set_rate_near(m_pcm, params, &rrate, &dir) < 0) - { - cerr << "ERROR: ALSA: unable to set rate near " << rrate - << " -- can't continue" << endl; - outputParameters(m_parameters); - snd_pcm_close(m_pcm); - m_pcm = 0; - setErrorCondition("unable to configure audio device"); - } + // + // Reasonably low latency + // - snd_pcm_hw_params_set_periods_integer(m_pcm, params); + unsigned int periods = 2; + m_periodSize = snd_pcm_uframes_t(double(512) / double(48000.0) + * double(m_parameters.rate)); + m_bufferSize = m_periodSize * periods * channelsCount * dataSize; + dir = 0; - // - // Reasonably low latency - // + snd_pcm_hw_params_set_periods(m_pcm, params, periods, 0); + snd_pcm_hw_params_set_period_size_near(m_pcm, params, &m_periodSize, + &dir); + snd_pcm_hw_params_set_buffer_size_near(m_pcm, params, + &m_bufferSize); - unsigned int periods = 2; - m_periodSize = snd_pcm_uframes_t(double(512) / double(48000.0) * double(m_parameters.rate)); - m_bufferSize = m_periodSize * periods * channelsCount * dataSize; - dir = 0; + if ((err = snd_pcm_hw_params(m_pcm, params)) < 0) + { + cerr << "ERROR: ALSA: params failed: " << snd_strerror(err) + << endl; + snd_pcm_close(m_pcm); + m_pcm = 0; + setErrorCondition("unable to configure audio device"); + } - snd_pcm_hw_params_set_periods(m_pcm, params, periods, 0); - snd_pcm_hw_params_set_period_size_near(m_pcm, params, &m_periodSize, &dir); - snd_pcm_hw_params_set_buffer_size_near(m_pcm, params, &m_bufferSize); + snd_pcm_hw_params_get_buffer_size(params, &m_bufferSize); + snd_pcm_hw_params_get_period_size(params, &m_periodSize, &dir); + periods = m_bufferSize / m_periodSize; - if ((err = snd_pcm_hw_params(m_pcm, params)) < 0) - { - cerr << "ERROR: ALSA: params failed: " << snd_strerror(err) << endl; - snd_pcm_close(m_pcm); - m_pcm = 0; - setErrorCondition("unable to configure audio device"); - } + // LATENCY: + // + // latency = periodsize * periods / (rate * bytes_per_frame) + // + // is this even correct? Some sources claim there are still + // other latencies beyond this. I really don't want to add an + // extra latency UI. + // - snd_pcm_hw_params_get_buffer_size(params, &m_bufferSize); - snd_pcm_hw_params_get_period_size(params, &m_periodSize, &dir); - periods = m_bufferSize / m_periodSize; + DeviceState nstate; + nstate.device = m_parameters.device; + nstate.format = m_parameters.format; + nstate.rate = rrate; + nstate.layout = m_parameters.layout; + nstate.latency = + m_parameters.latency + + m_periodSize * periods + / (nstate.rate * sizeof(short) * channelsCount); + // THIS WILL BLOW IT UP IF ITS NOT 512 + // nstate.framesPerBuffer = 2048; + nstate.framesPerBuffer = m_parameters.framesPerBuffer; + setDeviceState(nstate); + + if (debug) + { + cout << "DEBUG: alsa buffer_size = " << m_bufferSize << endl + << "DEBUG: alsa period_size = " << m_periodSize << endl + << "DEBUG: alsa periods = " << periods << endl + << "DEBUG: alsa device latency = " << nstate.latency + << endl; + } - // LATENCY: - // - // latency = periodsize * periods / (rate * bytes_per_frame) - // - // is this even correct? Some sources claim there are still - // other latencies beyond this. I really don't want to add an - // extra latency UI. - // + // + // Wait for the device to be ready + // - DeviceState nstate; - nstate.device = m_parameters.device; - nstate.format = m_parameters.format; - nstate.rate = rrate; - nstate.layout = m_parameters.layout; - nstate.latency = m_parameters.latency + m_periodSize * periods / (nstate.rate * sizeof(short) * channelsCount); - // THIS WILL BLOW IT UP IF ITS NOT 512 - //nstate.framesPerBuffer = 2048; - nstate.framesPerBuffer = m_parameters.framesPerBuffer; - setDeviceState(nstate); - - if (debug) - { - cout << "DEBUG: alsa buffer_size = " << m_bufferSize << endl - << "DEBUG: alsa period_size = " << m_periodSize << endl - << "DEBUG: alsa periods = " << periods << endl - << "DEBUG: alsa device latency = " << nstate.latency << endl; + snd_pcm_wait(m_pcm, -1); } + } + void ALSASafeAudioRenderer::threadMain() + { // - // Wait for the device to be ready + // Set the thread priority if asked to do so // - - snd_pcm_wait(m_pcm, -1); - } -} - - -void -ALSASafeAudioRenderer::threadMain() -{ - // - // Set the thread priority if asked to do so - // - const Rv::Options& opts = Rv::Options::sharedOptions(); + const Rv::Options& opts = Rv::Options::sharedOptions(); - if (opts.schedulePolicy) - { - sched_param sp; - memset(&sp, 0, sizeof(sched_param)); - sp.sched_priority = opts.displayPriority; + if (opts.schedulePolicy) + { + sched_param sp; + memset(&sp, 0, sizeof(sched_param)); + sp.sched_priority = opts.displayPriority; - unsigned int policy = SCHED_OTHER; + unsigned int policy = SCHED_OTHER; - if (!strcmp(opts.schedulePolicy, "SCHED_RR")) policy = SCHED_RR; - else if (!strcmp(opts.schedulePolicy, "SCHED_FIFO")) policy = SCHED_FIFO; + if (!strcmp(opts.schedulePolicy, "SCHED_RR")) + policy = SCHED_RR; + else if (!strcmp(opts.schedulePolicy, "SCHED_FIFO")) + policy = SCHED_FIFO; - if (policy != SCHED_OTHER) - { - if (sched_setscheduler(0, policy, &sp)) + if (policy != SCHED_OTHER) { - cout << "ERROR: can't set thread priority" << endl; + if (sched_setscheduler(0, policy, &sp)) + { + cout << "ERROR: can't set thread priority" << endl; + } } - } - else - { - if (setpriority(PRIO_PROCESS, 0, opts.displayPriority)) + else { - cout << "ERROR: can't set thread priority" << endl; + if (setpriority(PRIO_PROCESS, 0, opts.displayPriority)) + { + cout << "ERROR: can't set thread priority" << endl; + } } } - } - - int err; - // - // NOTE: it's possible for this thread to continue on as a - // zombie (after the control thread tried to stop it). In that - // case m_pcm will be null, so check for that whenever we're - // going to use it. This should stop the "asset failed: pcm" - // crashes we get from alsa. - // - if (!m_pcm) return; + int err; + + // + // NOTE: it's possible for this thread to continue on as a + // zombie (after the control thread tried to stop it). In that + // case m_pcm will be null, so check for that whenever we're + // going to use it. This should stop the "asset failed: pcm" + // crashes we get from alsa. + // + if (!m_pcm) + return; - m_threadGroup.lock(m_runningLock); - m_audioThreadRunning = true; - m_audioThread = pthread_self(); - m_threadGroup.unlock(m_runningLock); + m_threadGroup.lock(m_runningLock); + m_audioThreadRunning = true; + m_audioThread = pthread_self(); + m_threadGroup.unlock(m_runningLock); - // - // Get the current state. (yeah, I know it was just set above) - // + // + // Get the current state. (yeah, I know it was just set above) + // - const DeviceState& state = deviceState(); + const DeviceState& state = deviceState(); - // - // Setup accumulation buffer - // + // + // Setup accumulation buffer + // - int channelsCount = TwkAudio::channelsCount(state.layout); + int channelsCount = TwkAudio::channelsCount(state.layout); - AudioBuffer buffer(state.framesPerBuffer, - state.layout, - state.rate); + AudioBuffer buffer(state.framesPerBuffer, state.layout, state.rate); - m_abuffer.reconfigure(state.framesPerBuffer, - state.layout, - Time(state.rate)); + m_abuffer.reconfigure(state.framesPerBuffer, state.layout, + Time(state.rate)); - const size_t formatSize = formatSizeInBytes(m_parameters.format); - m_outBuffer.resize(state.framesPerBuffer * channelsCount * formatSize); + const size_t formatSize = formatSizeInBytes(m_parameters.format); + m_outBuffer.resize(state.framesPerBuffer * channelsCount * formatSize); - // - // Allocate and initialize the "status" object for this pcm stream - // + // + // Allocate and initialize the "status" object for this pcm stream + // - snd_pcm_status_t* status; - snd_pcm_status_alloca(&status); - if (!m_pcm) return; - snd_pcm_status(m_pcm, status); + snd_pcm_status_t* status; + snd_pcm_status_alloca(&status); + if (!m_pcm) + return; + snd_pcm_status(m_pcm, status); - if (!m_pcm) return; - snd_pcm_state_t pcmState = snd_pcm_state(m_pcm); + if (!m_pcm) + return; + snd_pcm_state_t pcmState = snd_pcm_state(m_pcm); - if (pcmState == SND_PCM_STATE_SETUP) - { - if (!m_pcm) return; - if ((err = snd_pcm_prepare(m_pcm)) < 0) + if (pcmState == SND_PCM_STATE_SETUP) { - cerr << "ERROR: ASLA: " << snd_strerror(err) << endl; - return; - } + if (!m_pcm) + return; + if ((err = snd_pcm_prepare(m_pcm)) < 0) + { + cerr << "ERROR: ASLA: " << snd_strerror(err) << endl; + return; + } - if (!m_pcm) return; - pcmState = snd_pcm_state(m_pcm); - } - - m_startSample = 0; - - for (size_t count = 0; - pcmState != SND_PCM_STATE_DISCONNECTED && - pcmState != SND_PCM_STATE_XRUN && - (isPlaying() || - (m_startSample % m_periodSize != 0) || - m_parameters.holdOpen); - count++) - { - // - // Figure out the current latency by hook or by crook. - // + if (!m_pcm) + return; + pcmState = snd_pcm_state(m_pcm); + } - if (!m_pcm) return; - snd_pcm_status(m_pcm, status); - snd_pcm_sframes_t latencyFrames = snd_pcm_status_get_delay(status); + m_startSample = 0; - if ((!latencyFrames || state.latency == 0) && count > 0) + for (size_t count = 0; + pcmState != SND_PCM_STATE_DISCONNECTED + && pcmState != SND_PCM_STATE_XRUN + && (isPlaying() || (m_startSample % m_periodSize != 0) + || m_parameters.holdOpen); + count++) { // - // Update the latency using snd_pcm_delay because - // snd_pcm_status_get_delay() failed. This is common with - // the default device and/or dmix. + // Figure out the current latency by hook or by crook. // - - if (!m_pcm) return; - if (!snd_pcm_delay(m_pcm, &latencyFrames) && latencyFrames > 0) + + if (!m_pcm) + return; + snd_pcm_status(m_pcm, status); + snd_pcm_sframes_t latencyFrames = snd_pcm_status_get_delay(status); + + if ((!latencyFrames || state.latency == 0) && count > 0) { // - // Only if we think this actually worked - // (i.e. latencyFrames > 0) + // Update the latency using snd_pcm_delay because + // snd_pcm_status_get_delay() failed. This is common with + // the default device and/or dmix. // - m_deviceState.latency = m_parameters.latency + latencyFrames / double(state.rate); - } - else - { - m_deviceState.latency = m_parameters.latency; + if (!m_pcm) + return; + if (!snd_pcm_delay(m_pcm, &latencyFrames) && latencyFrames > 0) + { + // + // Only if we think this actually worked + // (i.e. latencyFrames > 0) + // + + m_deviceState.latency = + m_parameters.latency + + latencyFrames / double(state.rate); + } + else + { + m_deviceState.latency = m_parameters.latency; + } } - } - // - // Call the evaluation function - // + // + // Call the evaluation function + // - buffer.reconfigure(state.framesPerBuffer, - state.layout, - Time(state.rate), - samplesToTime(m_startSample, state.rate)); + buffer.reconfigure(state.framesPerBuffer, state.layout, + Time(state.rate), + samplesToTime(m_startSample, state.rate)); - buffer.zero(); + buffer.zero(); - // - // Fetch the samples - // + // + // Fetch the samples + // - audioFillBuffer(buffer); + audioFillBuffer(buffer); - // - // Convert to the correct output format - // + // + // Convert to the correct output format + // - unsigned char* out = &m_outBuffer.front(); + unsigned char* out = &m_outBuffer.front(); - switch (m_parameters.format) - { - case Float32Format: - memcpy(out, buffer.pointer(), buffer.sizeInBytes()); - break; - - case Int16Format: - transform(buffer.pointer(), - buffer.pointer() + buffer.sizeInFloats(), - (short*)out, - toType); - break; - - case Int32Format: - transform(buffer.pointer(), - buffer.pointer() + buffer.sizeInFloats(), - (signed int*)out, - toType); - break; - - case Int8Format: - transform(buffer.pointer(), - buffer.pointer() + buffer.sizeInFloats(), - (signed char*)out, - toType); - break; - } + switch (m_parameters.format) + { + case Float32Format: + memcpy(out, buffer.pointer(), buffer.sizeInBytes()); + break; - // - // Write it. This may block waiting for the device. I'm not - // sure why we have to account for chopping up the output: - // sometimes ALSA just doesn't write all the samples and you - // have to call write again. - // + case Int16Format: + transform(buffer.pointer(), + buffer.pointer() + buffer.sizeInFloats(), (short*)out, + toType); + break; - size_t total = 0; - snd_pcm_sframes_t frames = 0; + case Int32Format: + transform(buffer.pointer(), + buffer.pointer() + buffer.sizeInFloats(), + (signed int*)out, toType); + break; - if (!m_pcm) return; - pcmState = snd_pcm_state(m_pcm);; + case Int8Format: + transform(buffer.pointer(), + buffer.pointer() + buffer.sizeInFloats(), + (signed char*)out, toType); + break; + } - // - // Write the samples. - // - // NOTE: snd_pcm_writei() can BLOCK for an indefinite amount - // of time. - // + // + // Write it. This may block waiting for the device. I'm not + // sure why we have to account for chopping up the output: + // sometimes ALSA just doesn't write all the samples and you + // have to call write again. + // - for (size_t wcount = 0; - (pcmState == SND_PCM_STATE_RUNNING || - pcmState == SND_PCM_STATE_PREPARED) && - total < buffer.size()&& - frames >= 0 && - wcount < buffer.size(); - wcount++) - { - if (!m_pcm) return; - if (debug) - { - cerr << "INFO: pcm_writei: wcount " << wcount << - ", count " << count << - ", total " << total << - ", chan " << channelsCount << - ", formatSize " << formatSize << - ", bufferSize " << buffer.size() << endl; - } - frames = snd_pcm_writei(m_pcm, - out + (total * channelsCount * formatSize), - buffer.size() - total); - if (debug) cerr << "INFO: pcm_writei complete, frames " << frames << endl; - - if (frames >= 0) - { - total += frames; - } - else - { - // - // Possible underrun (in alsa parlance) - // + size_t total = 0; + snd_pcm_sframes_t frames = 0; - // too new to use + if (!m_pcm) + return; + pcmState = snd_pcm_state(m_pcm); + ; + // + // Write the samples. + // + // NOTE: snd_pcm_writei() can BLOCK for an indefinite amount + // of time. + // + + for (size_t wcount = 0; (pcmState == SND_PCM_STATE_RUNNING + || pcmState == SND_PCM_STATE_PREPARED) + && total < buffer.size() && frames >= 0 + && wcount < buffer.size(); + wcount++) + { + if (!m_pcm) + return; if (debug) { - cerr << "ERROR: ASLA: write failed (" - << frames - << "): " << snd_strerror(frames) - << " -- "; + cerr << "INFO: pcm_writei: wcount " << wcount << ", count " + << count << ", total " << total << ", chan " + << channelsCount << ", formatSize " << formatSize + << ", bufferSize " << buffer.size() << endl; + } + frames = snd_pcm_writei( + m_pcm, out + (total * channelsCount * formatSize), + buffer.size() - total); + if (debug) + cerr << "INFO: pcm_writei complete, frames " << frames + << endl; + + if (frames >= 0) + { + total += frames; + } + else + { + // + // Possible underrun (in alsa parlance) + // + + // too new to use - switch (frames) + if (debug) { - case -EBADFD: cerr << "bad pcm state"; break; - case -EPIPE: cerr << "underrun occured"; break; - case -ESTRPIPE: cerr << "suspend event occured"; break; + cerr << "ERROR: ASLA: write failed (" << frames + << "): " << snd_strerror(frames) << " -- "; + + switch (frames) + { + case -EBADFD: + cerr << "bad pcm state"; + break; + case -EPIPE: + cerr << "underrun occured"; + break; + case -ESTRPIPE: + cerr << "suspend event occured"; + break; + } + + cerr << endl; } - cerr << endl; - } - - if (!m_pcm) return; + if (!m_pcm) + return; #ifdef USE_SAFE_ALSA - frames = snd_pcm_recover(m_pcm, frames, 0); + frames = snd_pcm_recover(m_pcm, frames, 0); #else - frames = snd_pcm_prepare(m_pcm); + frames = snd_pcm_prepare(m_pcm); #endif - break; + break; + } + if (total < buffer.size()) + { + if (!m_pcm) + return; + pcmState = snd_pcm_state(m_pcm); + } } - if (total < buffer.size()) - { - if (!m_pcm) return; - pcmState = snd_pcm_state(m_pcm); - } - } - m_startSample += total; - if (!m_pcm) return; - pcmState = snd_pcm_state(m_pcm); + m_startSample += total; + if (!m_pcm) + return; + pcmState = snd_pcm_state(m_pcm); - if (pcmState == SND_PCM_STATE_XRUN) - { - if (!m_pcm) return; - if (snd_pcm_prepare(m_pcm) < 0) break; - if (!m_pcm) return; - if ((pcmState = snd_pcm_state(m_pcm)) == SND_PCM_STATE_XRUN) break; + if (pcmState == SND_PCM_STATE_XRUN) + { + if (!m_pcm) + return; + if (snd_pcm_prepare(m_pcm) < 0) + break; + if (!m_pcm) + return; + if ((pcmState = snd_pcm_state(m_pcm)) == SND_PCM_STATE_XRUN) + break; + } } - } - - if (!m_pcm) return; - if (pcmState == SND_PCM_STATE_RUNNING) snd_pcm_drop(m_pcm); - - m_threadGroup.lock(m_runningLock); - m_audioThreadRunning = false; - m_threadGroup.unlock(m_runningLock); - if (debug) cout << "DEBUG: audio thread exiting" << endl; -} - -void -ALSASafeAudioRenderer::play(Session* s) -{ - AudioRenderer::play(s); - - s->audioVarLock(); - s->setAudioTimeShift(numeric_limits::max()); - s->setAudioStartSample(0); - s->setAudioFirstPass(true); - s->audioVarUnLock(); - - s->audioConfigure(); + if (!m_pcm) + return; + if (pcmState == SND_PCM_STATE_RUNNING) + snd_pcm_drop(m_pcm); - if (!isPlaying()) play(); -} + m_threadGroup.lock(m_runningLock); + m_audioThreadRunning = false; + m_threadGroup.unlock(m_runningLock); -void -ALSASafeAudioRenderer::play() -{ - AudioRenderer::play(); + if (debug) + cout << "DEBUG: audio thread exiting" << endl; + } - bool notconfigured = m_pcm == 0; - configureDevice(); + void ALSASafeAudioRenderer::play(Session* s) + { + AudioRenderer::play(s); - // - // Dispatch the playback thread if its not running already. The - // last argument (async=false) indicates that we want to wait - // until the thread is running before the function returns. - // + s->audioVarLock(); + s->setAudioTimeShift(numeric_limits::max()); + s->setAudioStartSample(0); + s->setAudioFirstPass(true); + s->audioVarUnLock(); - if (notconfigured) m_threadGroup.dispatch(trampoline, this); -} + s->audioConfigure(); -void -ALSASafeAudioRenderer::stop(Session* s) -{ - AudioRenderer::stop(s); - s->setAudioTimeShift(numeric_limits::max()); - if (!m_parameters.holdOpen) shutdown(); -} + if (!isPlaying()) + play(); + } -void -ALSASafeAudioRenderer::shutdown() -{ - // - // Shut down the hardware - // + void ALSASafeAudioRenderer::play() + { + AudioRenderer::play(); - const bool holdOpen = m_parameters.holdOpen; - m_parameters.holdOpen = false; + bool notconfigured = m_pcm == 0; + configureDevice(); - AudioRenderer::stop(); + // + // Dispatch the playback thread if its not running already. The + // last argument (async=false) indicates that we want to wait + // until the thread is running before the function returns. + // - m_threadGroup.lock(m_runningLock); - bool isrunning = m_audioThreadRunning; - m_threadGroup.unlock(m_runningLock); + if (notconfigured) + m_threadGroup.dispatch(trampoline, this); + } - if (isrunning) m_threadGroup.control_wait(true, 1.0); + void ALSASafeAudioRenderer::stop(Session* s) + { + AudioRenderer::stop(s); + s->setAudioTimeShift(numeric_limits::max()); + if (!m_parameters.holdOpen) + shutdown(); + } - if (m_pcm) + void ALSASafeAudioRenderer::shutdown() { // - // Although we tried to stop the audio threads above, we - // may have failed (IE the control_wait may have timed out, - // so lock-bracket the m_pcm=0 statement, and don't close - // the audio device until after m_pcm has been zeroed. + // Shut down the hardware // - snd_pcm_t *tmp = m_pcm; + + const bool holdOpen = m_parameters.holdOpen; + m_parameters.holdOpen = false; + + AudioRenderer::stop(); + m_threadGroup.lock(m_runningLock); - m_pcm = 0; + bool isrunning = m_audioThreadRunning; m_threadGroup.unlock(m_runningLock); - snd_pcm_close(tmp); - } - m_parameters.holdOpen = holdOpen; -} + if (isrunning) + m_threadGroup.control_wait(true, 1.0); + + if (m_pcm) + { + // + // Although we tried to stop the audio threads above, we + // may have failed (IE the control_wait may have timed out, + // so lock-bracket the m_pcm=0 statement, and don't close + // the audio device until after m_pcm has been zeroed. + // + snd_pcm_t* tmp = m_pcm; + m_threadGroup.lock(m_runningLock); + m_pcm = 0; + m_threadGroup.unlock(m_runningLock); + snd_pcm_close(tmp); + } + m_parameters.holdOpen = holdOpen; + } -} // Rv +} // namespace IPCore diff --git a/src/lib/audio/ALSASafeAudioModule/init.cpp b/src/lib/audio/ALSASafeAudioModule/init.cpp index 0df8abd19..4b6e4b340 100644 --- a/src/lib/audio/ALSASafeAudioModule/init.cpp +++ b/src/lib/audio/ALSASafeAudioModule/init.cpp @@ -1,16 +1,16 @@ // -// Copyright (C) 2023 Autodesk, Inc. All Rights Reserved. -// -// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2023 Autodesk, Inc. All Rights Reserved. +// +// SPDX-License-Identifier: Apache-2.0 // #include -extern "C" { - -IPCore::AudioRenderer* -CreateAudioModule(const IPCore::AudioRenderer::RendererParameters& p) -{ - return new IPCore::ALSASafeAudioRenderer(p); -} +extern "C" +{ + IPCore::AudioRenderer* + CreateAudioModule(const IPCore::AudioRenderer::RendererParameters& p) + { + return new IPCore::ALSASafeAudioRenderer(p); + } } diff --git a/src/lib/audio/QTAudioRenderer/QTAudioRenderer.cpp b/src/lib/audio/QTAudioRenderer/QTAudioRenderer.cpp index db734330a..53cae4e78 100644 --- a/src/lib/audio/QTAudioRenderer/QTAudioRenderer.cpp +++ b/src/lib/audio/QTAudioRenderer/QTAudioRenderer.cpp @@ -1,9 +1,9 @@ /// // Copyright (c) 2013,2014 Tweak Software. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// // #include #include @@ -38,1088 +38,1079 @@ // reproducible under centos7 or my centos6 vm // (parallels 11). So commenting out RUN_IN_MAIN_THREAD_ON_NO_HOLDOPEN. // -// +// // #ifdef PLATFORM_LINUX -//#define RUN_IN_MAIN_THREAD_ON_NO_HOLDOPEN +// #define RUN_IN_MAIN_THREAD_ON_NO_HOLDOPEN #endif -namespace IPCore { -using namespace std; - +namespace IPCore +{ + using namespace std; #ifdef DEBUG_QTAUDIO -#define QTAUDIO_DEBUG(_f) \ - if (AudioRenderer::debugVerbose) TwkUtil::Log("AUDIO") << _f << " Qthread:" << QThread::currentThread(); +#define QTAUDIO_DEBUG(_f) \ + if (AudioRenderer::debugVerbose) \ + TwkUtil::Log("AUDIO") << _f << " Qthread:" << QThread::currentThread(); #else #define QTAUDIO_DEBUG(_f) #endif -static ENVVAR_BOOL( evApplyWasapiFix, "RV_AUDIO_APPLY_WASAPI_FIX", true ); + static ENVVAR_BOOL(evApplyWasapiFix, "RV_AUDIO_APPLY_WASAPI_FIX", true); -//---------------------------------------------------------------------- -// QTAudioThread -// -// This is the Qt thread class that lives -// with main/UI thread but holds the -// audio thread and has interThread "emit" methods to invoke methods -// in the audio thread which control -// the start/resume/stop/open behavior of -// the QAudioOutput and QIODevice running within it. -// -//---------------------------------------------------------------------- - -QTAudioThread::QTAudioThread(QTAudioRenderer &audioRenderer, - QObject* parent) : - QThread(parent) - , m_parent(parent) - , m_ioDevice(0) - , m_audioOutput(0) - , m_audioRenderer(audioRenderer) - , m_preRollSamples(0) - , m_processedSamples(0) - , m_startSample(0) - , m_preRollDisable(false) - , m_startOfInitialization(0) - , m_endOfInitialization(-1) - , m_lastDeviceLatency(0) - , m_patch9355Enabled(false) - -{ - QTAUDIO_DEBUG("QTAudioThread") - - // Cache some format related variables so we dont have to - // precompute them each time. - m_bytesPerSample = audioRenderer.m_format.channelCount() * audioRenderer.m_format.sampleSize() / 8; + //---------------------------------------------------------------------- + // QTAudioThread + // + // This is the Qt thread class that lives + // with main/UI thread but holds the + // audio thread and has interThread "emit" methods to invoke methods + // in the audio thread which control + // the start/resume/stop/open behavior of + // the QAudioOutput and QIODevice running within it. + // + //---------------------------------------------------------------------- + + QTAudioThread::QTAudioThread(QTAudioRenderer& audioRenderer, + QObject* parent) + : QThread(parent) + , m_parent(parent) + , m_ioDevice(0) + , m_audioOutput(0) + , m_audioRenderer(audioRenderer) + , m_preRollSamples(0) + , m_processedSamples(0) + , m_startSample(0) + , m_preRollDisable(false) + , m_startOfInitialization(0) + , m_endOfInitialization(-1) + , m_lastDeviceLatency(0) + , m_patch9355Enabled(false) - m_preRollMode = m_audioRenderer.m_parameters.preRoll; + { + QTAUDIO_DEBUG("QTAudioThread") - qRegisterMetaType("IPCore::Session*"); + // Cache some format related variables so we dont have to + // precompute them each time. + m_bytesPerSample = audioRenderer.m_format.channelCount() + * audioRenderer.m_format.sampleSize() / 8; - m_patch9355Enabled = (getenv("RV_AUDIO_AUTO_ADJUST") != NULL); -} + m_preRollMode = m_audioRenderer.m_parameters.preRoll; -QTAudioThread::~QTAudioThread() -{ - detachAudioOutputDevice(); - disconnect(m_parent); -} + qRegisterMetaType("IPCore::Session*"); + m_patch9355Enabled = (getenv("RV_AUDIO_AUTO_ADJUST") != NULL); + } -void -QTAudioThread::startMe() -{ -#ifdef RUN_IN_MAIN_THREAD_ON_NO_HOLDOPEN - if (!m_audioRenderer.m_parameters.holdOpen) + QTAudioThread::~QTAudioThread() { - if (!createAudioOutput()) return; - m_audioOutput->setAudioOutputBufferSize(); - return; + detachAudioOutputDevice(); + disconnect(m_parent); } -#endif - - start(); - unsigned long waitTime = 0; // in ms; - do { - wait(300); // in ms; - waitTime += 300; - QTAUDIO_DEBUG("QTAudioThread::startMe(): waiting for thread to start...") - } while (!isRunning() && waitTime < 1000); - QMetaObject::invokeMethod(m_audioOutput, "setAudioOutputBufferSize", Qt::QueuedConnection); -} - -size_t -QTAudioThread::processedSamples() const -{ - return m_processedSamples; -} + void QTAudioThread::startMe() + { +#ifdef RUN_IN_MAIN_THREAD_ON_NO_HOLDOPEN + if (!m_audioRenderer.m_parameters.holdOpen) + { + if (!createAudioOutput()) + return; + m_audioOutput->setAudioOutputBufferSize(); + return; + } +#endif -void -QTAudioThread::setProcessedSamples(size_t n) -{ - m_mutex.lock(); - m_processedSamples = n; - m_mutex.unlock(); -} + start(); + unsigned long waitTime = 0; // in ms; + do + { + wait(300); // in ms; + waitTime += 300; + QTAUDIO_DEBUG( + "QTAudioThread::startMe(): waiting for thread to start...") + } while (!isRunning() && waitTime < 1000); + QMetaObject::invokeMethod(m_audioOutput, "setAudioOutputBufferSize", + Qt::QueuedConnection); + } -size_t -QTAudioThread::startSample() const -{ - return m_startSample; -} + size_t QTAudioThread::processedSamples() const + { + return m_processedSamples; + } -void -QTAudioThread::setStartSample(size_t n) -{ - m_mutex.lock(); - m_startSample = n; - m_mutex.unlock(); -} + void QTAudioThread::setProcessedSamples(size_t n) + { + m_mutex.lock(); + m_processedSamples = n; + m_mutex.unlock(); + } -void -QTAudioThread::setDeviceLatency(double t) -{ - m_mutex.lock(); - m_audioRenderer.m_deviceState.latency = t + m_audioRenderer.m_parameters.latency; - m_mutex.unlock(); -} + size_t QTAudioThread::startSample() const { return m_startSample; } -bool -QTAudioThread::preRollDisable() const -{ - return m_preRollDisable; -} + void QTAudioThread::setStartSample(size_t n) + { + m_mutex.lock(); + m_startSample = n; + m_mutex.unlock(); + } -void -QTAudioThread::setPreRollDisable(bool disable) -{ - m_mutex.lock(); - m_preRollDisable = disable; - m_mutex.unlock(); -} + void QTAudioThread::setDeviceLatency(double t) + { + m_mutex.lock(); + m_audioRenderer.m_deviceState.latency = + t + m_audioRenderer.m_parameters.latency; + m_mutex.unlock(); + } + bool QTAudioThread::preRollDisable() const { return m_preRollDisable; } -void -QTAudioThread::setPreRollDelay(TwkAudio::Time t) -{ - m_mutex.lock(); - m_audioRenderer.setPreRollDelay(t); - if (t == 0 ) + void QTAudioThread::setPreRollDisable(bool disable) { - m_preRollDisable = false; - m_preRollSamples = 0; + m_mutex.lock(); + m_preRollDisable = disable; + m_mutex.unlock(); } - m_mutex.unlock(); -} - -int -QTAudioThread::bytesPerSample() const -{ - return m_bytesPerSample; -} -size_t -QTAudioThread::framesPerBuffer() const -{ - return m_audioRenderer.m_parameters.framesPerBuffer; -} + void QTAudioThread::setPreRollDelay(TwkAudio::Time t) + { + m_mutex.lock(); + m_audioRenderer.setPreRollDelay(t); + if (t == 0) + { + m_preRollDisable = false; + m_preRollSamples = 0; + } + m_mutex.unlock(); + } + int QTAudioThread::bytesPerSample() const { return m_bytesPerSample; } -bool -QTAudioThread::holdOpen() const -{ - return m_audioRenderer.m_parameters.holdOpen; -} + size_t QTAudioThread::framesPerBuffer() const + { + return m_audioRenderer.m_parameters.framesPerBuffer; + } + bool QTAudioThread::holdOpen() const + { + return m_audioRenderer.m_parameters.holdOpen; + } -void -QTAudioThread::emitStartAudio() -{ - QTAUDIO_DEBUG("QTAudioThread::emitStartAudio") + void QTAudioThread::emitStartAudio() + { + QTAUDIO_DEBUG("QTAudioThread::emitStartAudio") #ifdef RUN_IN_MAIN_THREAD_ON_NO_HOLDOPEN - if (!m_audioRenderer.m_parameters.holdOpen) - { - m_audioOutput->startAudio(); - return; - } + if (!m_audioRenderer.m_parameters.holdOpen) + { + m_audioOutput->startAudio(); + return; + } #endif - QMetaObject::invokeMethod(m_audioOutput, "startAudio", Qt::QueuedConnection); -} + QMetaObject::invokeMethod(m_audioOutput, "startAudio", + Qt::QueuedConnection); + } -const AudioRenderer::DeviceState& -QTAudioThread::deviceState() const -{ - return m_audioRenderer.deviceState(); -} + const AudioRenderer::DeviceState& QTAudioThread::deviceState() const + { + return m_audioRenderer.deviceState(); + } -void -QTAudioThread::setDeviceState(AudioRenderer::DeviceState &state) -{ - m_mutex.lock(); - m_audioRenderer.setDeviceState(state); - m_mutex.unlock(); -} + void QTAudioThread::setDeviceState(AudioRenderer::DeviceState& state) + { + m_mutex.lock(); + m_audioRenderer.setDeviceState(state); + m_mutex.unlock(); + } -void -QTAudioThread::emitResetAudio() -{ - QTAUDIO_DEBUG("QTAudioThread::emitResetAudio") + void QTAudioThread::emitResetAudio() + { + QTAUDIO_DEBUG("QTAudioThread::emitResetAudio") #ifdef RUN_IN_MAIN_THREAD_ON_NO_HOLDOPEN - if (!m_audioRenderer.m_parameters.holdOpen) - { - m_audioOutput->resetAudio(); - return; - } + if (!m_audioRenderer.m_parameters.holdOpen) + { + m_audioOutput->resetAudio(); + return; + } #endif - QMetaObject::invokeMethod(m_audioOutput, "resetAudio", Qt::QueuedConnection); -} + QMetaObject::invokeMethod(m_audioOutput, "resetAudio", + Qt::QueuedConnection); + } -void -QTAudioThread::emitStopAudio() -{ - QTAUDIO_DEBUG("QTAudioThread::emitStopAudio") + void QTAudioThread::emitStopAudio() + { + QTAUDIO_DEBUG("QTAudioThread::emitStopAudio") #ifdef RUN_IN_MAIN_THREAD_ON_NO_HOLDOPEN - if (!m_audioRenderer.m_parameters.holdOpen) - { - m_audioOutput->stopAudio(); - return; - } + if (!m_audioRenderer.m_parameters.holdOpen) + { + m_audioOutput->stopAudio(); + return; + } #endif - QMetaObject::invokeMethod(m_audioOutput, "stopAudio", Qt::BlockingQueuedConnection); -} - + QMetaObject::invokeMethod(m_audioOutput, "stopAudio", + Qt::BlockingQueuedConnection); + } -void -QTAudioThread::emitSuspendAudio() -{ - QTAUDIO_DEBUG("QTAudioThread::emitSuspendAudio") + void QTAudioThread::emitSuspendAudio() + { + QTAUDIO_DEBUG("QTAudioThread::emitSuspendAudio") #ifdef RUN_IN_MAIN_THREAD_ON_NO_HOLDOPEN - if (!m_audioRenderer.m_parameters.holdOpen) - { - m_audioOutput->suspendAudio(); - return; - } + if (!m_audioRenderer.m_parameters.holdOpen) + { + m_audioOutput->suspendAudio(); + return; + } #endif - QMetaObject::invokeMethod(m_audioOutput, "suspendAudio", Qt::BlockingQueuedConnection); -} - + QMetaObject::invokeMethod(m_audioOutput, "suspendAudio", + Qt::BlockingQueuedConnection); + } -void -QTAudioThread::emitSuspendAndResetAudio() -{ - QTAUDIO_DEBUG("QTAudioThread::emitSuspendAndResetAudio") + void QTAudioThread::emitSuspendAndResetAudio() + { + QTAUDIO_DEBUG("QTAudioThread::emitSuspendAndResetAudio") #ifdef RUN_IN_MAIN_THREAD_ON_NO_HOLDOPEN - if (!m_audioRenderer.m_parameters.holdOpen) - { - m_audioOutput->suspendAndResetAudio(); - return; - } + if (!m_audioRenderer.m_parameters.holdOpen) + { + m_audioOutput->suspendAndResetAudio(); + return; + } #endif - QMetaObject::invokeMethod(m_audioOutput, "suspendAndResetAudio", Qt::BlockingQueuedConnection); -} - + QMetaObject::invokeMethod(m_audioOutput, "suspendAndResetAudio", + Qt::BlockingQueuedConnection); + } -void -QTAudioThread::emitResetDevice() -{ - QTAUDIO_DEBUG("QTAudioThread::emitResetDevice") + void QTAudioThread::emitResetDevice() + { + QTAUDIO_DEBUG("QTAudioThread::emitResetDevice") #ifdef RUN_IN_MAIN_THREAD_ON_NO_HOLDOPEN - if (!m_audioRenderer.m_parameters.holdOpen) - { - m_ioDevice->resetDevice(); - return; - } + if (!m_audioRenderer.m_parameters.holdOpen) + { + m_ioDevice->resetDevice(); + return; + } #endif - QMetaObject::invokeMethod(m_ioDevice, "resetDevice", Qt::QueuedConnection); -} + QMetaObject::invokeMethod(m_ioDevice, "resetDevice", + Qt::QueuedConnection); + } -void -QTAudioThread::emitStopDevice() -{ - QTAUDIO_DEBUG("QTAudioThread::emitStopDevice") + void QTAudioThread::emitStopDevice() + { + QTAUDIO_DEBUG("QTAudioThread::emitStopDevice") #ifdef RUN_IN_MAIN_THREAD_ON_NO_HOLDOPEN - if (!m_audioRenderer.m_parameters.holdOpen) - { - m_ioDevice->stopDevice(); - return; - } + if (!m_audioRenderer.m_parameters.holdOpen) + { + m_ioDevice->stopDevice(); + return; + } #endif - QMetaObject::invokeMethod(m_ioDevice, "stopDevice", Qt::BlockingQueuedConnection); -} + QMetaObject::invokeMethod(m_ioDevice, "stopDevice", + Qt::BlockingQueuedConnection); + } -void -QTAudioThread::emitPlay(IPCore::Session *s) -{ - QTAUDIO_DEBUG("QTAudioThread::emitPlay") + void QTAudioThread::emitPlay(IPCore::Session* s) + { + QTAUDIO_DEBUG("QTAudioThread::emitPlay") #ifdef RUN_IN_MAIN_THREAD_ON_NO_HOLDOPEN - if (!m_audioRenderer.m_parameters.holdOpen) - { - m_audioOutput->play(s); - return; - } + if (!m_audioRenderer.m_parameters.holdOpen) + { + m_audioOutput->play(s); + return; + } #endif - // This needs to be a blocking connection to ensure play is as close to - // starting for real. This improves the av sync lag especially om Windows. - // - QMetaObject::invokeMethod(m_audioOutput, "play", Qt::BlockingQueuedConnection, Q_ARG(IPCore::Session*, s)); -} + // This needs to be a blocking connection to ensure play is as close to + // starting for real. This improves the av sync lag especially om + // Windows. + // + QMetaObject::invokeMethod(m_audioOutput, "play", + Qt::BlockingQueuedConnection, + Q_ARG(IPCore::Session*, s)); + } -void -QTAudioThread::run() -{ - QTAUDIO_DEBUG("QTAudioThread::run") - TwkUtil::setThreadName("QTAudioThread"); + void QTAudioThread::run() + { + QTAUDIO_DEBUG("QTAudioThread::run") + TwkUtil::setThreadName("QTAudioThread"); - // IMPORTANT: createAudioOutput() call - // can and must only be called within run() - // so that the QTAudioOuput and QTAudioIODevice - // is created within run()'s execution thread. - if (!createAudioOutput()) return; + // IMPORTANT: createAudioOutput() call + // can and must only be called within run() + // so that the QTAudioOuput and QTAudioIODevice + // is created within run()'s execution thread. + if (!createAudioOutput()) + return; - exec(); -} + exec(); + } -bool -QTAudioThread::createAudioOutput() -{ - QMutexLocker lock(&m_mutex); - if (AudioRenderer::debug) TwkUtil::Log("AUDIO") << "createAudioOutput()"; + bool QTAudioThread::createAudioOutput() + { + QMutexLocker lock(&m_mutex); + if (AudioRenderer::debug) + TwkUtil::Log("AUDIO") << "createAudioOutput()"; - // Create the QAudioOutput and QIO devices + // Create the QAudioOutput and QIO devices - m_bytesPerSample = m_audioRenderer.m_format.channelCount() * m_audioRenderer.m_format.sampleSize() / 8; + m_bytesPerSample = m_audioRenderer.m_format.channelCount() + * m_audioRenderer.m_format.sampleSize() / 8; - if (m_ioDevice = new QTAudioIODevice(*this)) - { - if (m_audioOutput = new QTAudioOutput(m_audioRenderer.m_device, - m_audioRenderer.m_format, - *m_ioDevice, - *this)) + if (m_ioDevice = new QTAudioIODevice(*this)) { - m_ioDevice->start(); - return true; + if (m_audioOutput = new QTAudioOutput(m_audioRenderer.m_device, + m_audioRenderer.m_format, + *m_ioDevice, *this)) + { + m_ioDevice->start(); + return true; + } + else + { + m_audioRenderer.setErrorCondition( + "Unable to create QIODevice for QAudioOutput."); + return false; + } } else { - m_audioRenderer.setErrorCondition("Unable to create QIODevice for QAudioOutput."); + m_audioRenderer.setErrorCondition("Unable to create QAudioOutput."); return false; } - } - else - { - m_audioRenderer.setErrorCondition("Unable to create QAudioOutput."); - return false; - } - - return true; -} - -void -QTAudioThread::detachAudioOutputDevice() -{ - if (AudioRenderer::debug) TwkUtil::Log("AUDIO") << "detachAudioOutputDevice"; - if (m_ioDevice) - { - emitStopDevice(); + return true; } - if (m_audioOutput) + void QTAudioThread::detachAudioOutputDevice() { - emitStopAudio(); - } + if (AudioRenderer::debug) + TwkUtil::Log("AUDIO") << "detachAudioOutputDevice"; - quit(); - wait(); + if (m_ioDevice) + { + emitStopDevice(); + } - if (m_audioOutput) - { - delete m_audioOutput; - m_audioOutput = 0; - } + if (m_audioOutput) + { + emitStopAudio(); + } - if (m_ioDevice) - { - delete m_ioDevice; - m_ioDevice = 0; - } + quit(); + wait(); -} + if (m_audioOutput) + { + delete m_audioOutput; + m_audioOutput = 0; + } -// -// This is the callback called by QTAudioIODevice::readData() for -// pushing audio data to the audio device. -// -qint64 -QTAudioThread::qIODeviceCallback(char* data, qint64 maxLenInBytes) -{ - if (m_patch9355Enabled && isInInitialization()) - { - TwkUtil::SystemClock::Time dura = endOfInitialization(); - setDeviceLatency(dura); - m_lastDeviceLatency = dura; - if (AudioRenderer::debug) TwkUtil::Log("AUDIO") << "Initialization duration:" << dura << "s"; + if (m_ioDevice) + { + delete m_ioDevice; + m_ioDevice = 0; + } } - if (AudioRenderer::debugVerbose) + // + // This is the callback called by QTAudioIODevice::readData() for + // pushing audio data to the audio device. + // + qint64 QTAudioThread::qIODeviceCallback(char* data, qint64 maxLenInBytes) { - TwkUtil::Log("AUDIO") - << "qIODeviceCallback: asking maxLenInBytes=" << (int) maxLenInBytes - << " isPlayingAudio=" << (int) m_audioRenderer.isPlaying() - << " audiooutput state=" << (int) m_audioOutput->state(); - } + if (m_patch9355Enabled && isInInitialization()) + { + TwkUtil::SystemClock::Time dura = endOfInitialization(); + setDeviceLatency(dura); + m_lastDeviceLatency = dura; + if (AudioRenderer::debug) + TwkUtil::Log("AUDIO") + << "Initialization duration:" << dura << "s"; + } - const AudioRenderer::DeviceState &state = deviceState(); + if (AudioRenderer::debugVerbose) + { + TwkUtil::Log("AUDIO") + << "qIODeviceCallback: asking maxLenInBytes=" + << (int)maxLenInBytes + << " isPlayingAudio=" << (int)m_audioRenderer.isPlaying() + << " audiooutput state=" << (int)m_audioOutput->state(); + } - if (data && - (m_audioRenderer.isPlaying()) && - (maxLenInBytes >= m_bytesPerSample) && - ((m_audioOutput->state() == QAudio::ActiveState) || - (m_audioOutput->state() == QAudio::IdleState))) - { - const int bufferSize = m_audioOutput->bufferSize(); - const int periodSize = m_audioOutput->periodSize(); + const AudioRenderer::DeviceState& state = deviceState(); + + if (data && (m_audioRenderer.isPlaying()) + && (maxLenInBytes >= m_bytesPerSample) + && ((m_audioOutput->state() == QAudio::ActiveState) + || (m_audioOutput->state() == QAudio::IdleState))) + { + const int bufferSize = m_audioOutput->bufferSize(); + const int periodSize = m_audioOutput->periodSize(); #ifdef PLATFORM_DARWIN - const bool doPreRoll = false; + const bool doPreRoll = false; #else - const bool doPreRoll = ((m_preRollMode && !m_preRollDisable && maxLenInBytes >= bufferSize - periodSize)?true:false); + const bool doPreRoll = + ((m_preRollMode && !m_preRollDisable + && maxLenInBytes >= bufferSize - periodSize) + ? true + : false); #endif #ifdef PLATFORM_DARWIN - // - // Figure out the latency. - // Only valid for OSX as processedUSecs() doesnt return - // anything useful on Linux/Windows. - qint64 processedUSecs = m_audioOutput->processedUSecs(); - TwkAudio::Time actualPlayedTime = TwkAudio::Time(processedUSecs / 1000000.0); - TwkAudio::Time targetPlayedTime = TwkAudio::samplesToTime(m_processedSamples, state.rate); - setDeviceLatency(targetPlayedTime - actualPlayedTime); + // + // Figure out the latency. + // Only valid for OSX as processedUSecs() doesnt return + // anything useful on Linux/Windows. + qint64 processedUSecs = m_audioOutput->processedUSecs(); + TwkAudio::Time actualPlayedTime = + TwkAudio::Time(processedUSecs / 1000000.0); + TwkAudio::Time targetPlayedTime = + TwkAudio::samplesToTime(m_processedSamples, state.rate); + setDeviceLatency(targetPlayedTime - actualPlayedTime); #endif - // - // I am qualifying this on a per platform basis. - // - // On OSX, I found that QAudioOutput requires that you write - // periodSize() bytes at a time. Otherwise I found subtle crackles - // in the playback. Try a sine 48kHz test. - // - // On Linux, we want to write no more than bufferSize. - // Writing anything smaller can potential cause a corrupt audio - // buffer when running multiple RV through mixer like pulse. - // + // + // I am qualifying this on a per platform basis. + // + // On OSX, I found that QAudioOutput requires that you write + // periodSize() bytes at a time. Otherwise I found subtle crackles + // in the playback. Try a sine 48kHz test. + // + // On Linux, we want to write no more than bufferSize. + // Writing anything smaller can potential cause a corrupt audio + // buffer when running multiple RV through mixer like pulse. + // #ifdef PLATFORM_DARWIN - if (periodSize && maxLenInBytes > periodSize) - { - maxLenInBytes = periodSize; - } + if (periodSize && maxLenInBytes > periodSize) + { + maxLenInBytes = periodSize; + } #else - if (bufferSize && maxLenInBytes > bufferSize) - { - maxLenInBytes = bufferSize; - } + if (bufferSize && maxLenInBytes > bufferSize) + { + maxLenInBytes = bufferSize; + } #endif - // - // If the request bytes i.e. maxLenInBytes is within - // a periodSize worths of the bufferSize we do a silent preroll - // fill of the audio device. - // This prevents almost any lag time on start of play for an - // oversized audiobufferfill request. - // NB: This does not apply to DARWIN where writes happen - // at max periodSize amounts. - if (doPreRoll && m_preRollSamples == 0) - { - memset(data, 0, maxLenInBytes); + // + // If the request bytes i.e. maxLenInBytes is within + // a periodSize worths of the bufferSize we do a silent preroll + // fill of the audio device. + // This prevents almost any lag time on start of play for an + // oversized audiobufferfill request. + // NB: This does not apply to DARWIN where writes happen + // at max periodSize amounts. + if (doPreRoll && m_preRollSamples == 0) + { + memset(data, 0, maxLenInBytes); - const size_t preRollSamplesWritten = (size_t) (maxLenInBytes / m_bytesPerSample); - m_preRollSamples += preRollSamplesWritten; - m_processedSamples += preRollSamplesWritten; + const size_t preRollSamplesWritten = + (size_t)(maxLenInBytes / m_bytesPerSample); + m_preRollSamples += preRollSamplesWritten; + m_processedSamples += preRollSamplesWritten; - if (AudioRenderer::debug) - { - TwkUtil::Log("AUDIO") - << "qIODeviceCallback: PreRollWrite: " - << " bufferSize=" << bufferSize - << " periodSize=" << periodSize - << " maxLenInBytes=" << maxLenInBytes - << " PreRollDelay=" << TwkAudio::samplesToTime(preRollSamplesWritten, state.rate); - } + if (AudioRenderer::debug) + { + TwkUtil::Log("AUDIO") + << "qIODeviceCallback: PreRollWrite: " + << " bufferSize=" << bufferSize + << " periodSize=" << periodSize + << " maxLenInBytes=" << maxLenInBytes + << " PreRollDelay=" + << TwkAudio::samplesToTime(preRollSamplesWritten, + state.rate); + } - return maxLenInBytes; - } + return maxLenInBytes; + } - if (m_preRollMode && !m_preRollDisable && m_preRollSamples > 0) - { - // - // After much fiddling I found this to be the best rule. - // I noticed that there seems to be a residual buffer of one - // period size (noticed from the difference in the first two the buffer - // request when play first starts). - // NB: the preRoll delay is divided by the number of channels since - // this is actual delay in time during playback. - // + if (m_preRollMode && !m_preRollDisable && m_preRollSamples > 0) + { + // + // After much fiddling I found this to be the best rule. + // I noticed that there seems to be a residual buffer of one + // period size (noticed from the difference in the first two the + // buffer request when play first starts). NB: the preRoll delay + // is divided by the number of channels since this is actual + // delay in time during playback. + // #ifdef PLATFORM_LINUX - TwkAudio::Time writtenPreRollTime = - TwkAudio::samplesToTime(m_preRollSamples-(periodSize /m_bytesPerSample), state.rate) / TwkAudio::channelsCount(state.layout); + TwkAudio::Time writtenPreRollTime = + TwkAudio::samplesToTime( + m_preRollSamples - (periodSize / m_bytesPerSample), + state.rate) + / TwkAudio::channelsCount(state.layout); #else - TwkAudio::Time writtenPreRollTime = - TwkAudio::samplesToTime(m_preRollSamples, state.rate) / TwkAudio::channelsCount(state.layout); + TwkAudio::Time writtenPreRollTime = + TwkAudio::samplesToTime(m_preRollSamples, state.rate) + / TwkAudio::channelsCount(state.layout); #endif - m_audioRenderer.setPreRollDelay(writtenPreRollTime); + m_audioRenderer.setPreRollDelay(writtenPreRollTime); - if (AudioRenderer::debug) + if (AudioRenderer::debug) + { + TwkUtil::Log("AUDIO") << "qIODeviceCallback: PreRollWrite: " + << " Total PreRoll Delay=" + << m_audioRenderer.preRollDelay(); + } + } + + m_preRollDisable = true; + + if (AudioRenderer::debugVerbose) { TwkUtil::Log("AUDIO") - << "qIODeviceCallback: PreRollWrite: " - << " Total PreRoll Delay=" << m_audioRenderer.preRollDelay(); + << "qIODeviceCallback: NormalWrite: " + << " m_startSample=" << m_startSample << " startSampleTime=" + << TwkAudio::samplesToTime(m_startSample, state.rate) + << " m_deviceState.latency: " + << m_audioRenderer.m_deviceState.latency + << " maxLenInBytes=" << maxLenInBytes; } - } - m_preRollDisable = true; - - if (AudioRenderer::debugVerbose) - { - TwkUtil::Log("AUDIO") - << "qIODeviceCallback: NormalWrite: " - << " m_startSample=" << m_startSample - << " startSampleTime=" << TwkAudio::samplesToTime(m_startSample, state.rate) - << " m_deviceState.latency: " << m_audioRenderer.m_deviceState.latency - << " maxLenInBytes=" << maxLenInBytes; - } - - size_t numSamplesToWrite = (size_t) (maxLenInBytes / m_bytesPerSample); - size_t numSamplesForAbuffer = numSamplesToWrite; - size_t bytesWrittenToDevice = 0; + size_t numSamplesToWrite = + (size_t)(maxLenInBytes / m_bytesPerSample); + size_t numSamplesForAbuffer = numSamplesToWrite; + size_t bytesWrittenToDevice = 0; - if (numSamplesForAbuffer) - { - QMutexLocker lock(&m_mutex); + if (numSamplesForAbuffer) + { + QMutexLocker lock(&m_mutex); - // Fetch the samples - // - m_abuffer.reconfigure(numSamplesForAbuffer, - state.layout, - TwkAudio::Time(state.rate), - TwkAudio::samplesToTime(m_startSample, state.rate)); + // Fetch the samples + // + m_abuffer.reconfigure( + numSamplesForAbuffer, state.layout, + TwkAudio::Time(state.rate), + TwkAudio::samplesToTime(m_startSample, state.rate)); - m_abuffer.zero(); + m_abuffer.zero(); - try - { - m_audioRenderer.audioFillBuffer(m_abuffer); - } - catch (std::exception &exc) - { - cout << "WARNING: QAudio fillBuffer exception: " << exc.what() << endl; - } + try + { + m_audioRenderer.audioFillBuffer(m_abuffer); + } + catch (std::exception& exc) + { + cout << "WARNING: QAudio fillBuffer exception: " + << exc.what() << endl; + } - switch (state.format) - { - case TwkAudio::Float32Format: - bytesWrittenToDevice = m_abuffer.sizeInBytes(); - m_startSample += numSamplesForAbuffer; - m_processedSamples += numSamplesForAbuffer; - memcpy(data, m_abuffer.pointer(), bytesWrittenToDevice); - break; - - case TwkAudio::Int32Format: - bytesWrittenToDevice = m_abuffer.sizeInBytes(); - m_startSample += numSamplesForAbuffer; - m_processedSamples += numSamplesForAbuffer; - transform(m_abuffer.pointer(), - m_abuffer.pointer() + m_abuffer.sizeInFloats(), - (int*) data, - AudioRenderer::toType); - break; - - case TwkAudio::Int24Format: - bytesWrittenToDevice = m_abuffer.sizeInFloats() * sizeof(char) * 3; - m_startSample += numSamplesForAbuffer; - m_processedSamples += numSamplesForAbuffer; - AudioRenderer::transformFloat32ToInt24(m_abuffer.pointer(), - data, - m_abuffer.sizeInFloats(), - (m_audioRenderer.m_format.byteOrder() == QAudioFormat::LittleEndian)); - break; - - case TwkAudio::Int16Format: - bytesWrittenToDevice = m_abuffer.sizeInFloats() * sizeof(short); - m_startSample += numSamplesForAbuffer; - m_processedSamples += numSamplesForAbuffer; - transform(m_abuffer.pointer(), - m_abuffer.pointer() + m_abuffer.sizeInFloats(), - (short*) data, - AudioRenderer::toType); - break; - - case TwkAudio::Int8Format: - bytesWrittenToDevice = m_abuffer.sizeInFloats() * sizeof(signed char); - m_startSample += numSamplesForAbuffer; - m_processedSamples += numSamplesForAbuffer; + switch (state.format) + { + case TwkAudio::Float32Format: + bytesWrittenToDevice = m_abuffer.sizeInBytes(); + m_startSample += numSamplesForAbuffer; + m_processedSamples += numSamplesForAbuffer; + memcpy(data, m_abuffer.pointer(), bytesWrittenToDevice); + break; + + case TwkAudio::Int32Format: + bytesWrittenToDevice = m_abuffer.sizeInBytes(); + m_startSample += numSamplesForAbuffer; + m_processedSamples += numSamplesForAbuffer; + transform(m_abuffer.pointer(), + m_abuffer.pointer() + m_abuffer.sizeInFloats(), + (int*)data, AudioRenderer::toType); + break; + + case TwkAudio::Int24Format: + bytesWrittenToDevice = + m_abuffer.sizeInFloats() * sizeof(char) * 3; + m_startSample += numSamplesForAbuffer; + m_processedSamples += numSamplesForAbuffer; + AudioRenderer::transformFloat32ToInt24( + m_abuffer.pointer(), data, m_abuffer.sizeInFloats(), + (m_audioRenderer.m_format.byteOrder() + == QAudioFormat::LittleEndian)); + break; + + case TwkAudio::Int16Format: + bytesWrittenToDevice = + m_abuffer.sizeInFloats() * sizeof(short); + m_startSample += numSamplesForAbuffer; + m_processedSamples += numSamplesForAbuffer; + transform(m_abuffer.pointer(), + m_abuffer.pointer() + m_abuffer.sizeInFloats(), + (short*)data, AudioRenderer::toType); + break; + + case TwkAudio::Int8Format: + bytesWrittenToDevice = + m_abuffer.sizeInFloats() * sizeof(signed char); + m_startSample += numSamplesForAbuffer; + m_processedSamples += numSamplesForAbuffer; #ifdef PLATFORM_DARWIN - transform(m_abuffer.pointer(), - m_abuffer.pointer() + m_abuffer.sizeInFloats(), - (signed char*) data, - AudioRenderer::toType); + transform(m_abuffer.pointer(), + m_abuffer.pointer() + m_abuffer.sizeInFloats(), + (signed char*)data, + AudioRenderer::toType); #else - transform(m_abuffer.pointer(), - m_abuffer.pointer() + m_abuffer.sizeInFloats(), - (unsigned char*) data, - AudioRenderer::toUnsignedType); + transform(m_abuffer.pointer(), + m_abuffer.pointer() + m_abuffer.sizeInFloats(), + (unsigned char*)data, + AudioRenderer::toUnsignedType); #endif - break; + break; - default: - cout << "WARNING: Unsupported format for QAudio: " << endl; - break; + default: + cout << "WARNING: Unsupported format for QAudio: " << endl; + break; + } } - } - if (AudioRenderer::debugVerbose) - { - TwkUtil::Log("AUDIO") - << "qIODeviceCallback: NormalWrite: " - << " numSamplesForAbuffer=" << numSamplesForAbuffer - << " bytesWrittenToDevice=" << bytesWrittenToDevice - << " m_processedSamples=" << m_processedSamples; - - if (bytesWrittenToDevice != maxLenInBytes) + if (AudioRenderer::debugVerbose) { - cout << "AUDIO: qIODeviceCallback: WARNING bytesWrittenToDevice != maxLenInBytes" << endl; + TwkUtil::Log("AUDIO") + << "qIODeviceCallback: NormalWrite: " + << " numSamplesForAbuffer=" << numSamplesForAbuffer + << " bytesWrittenToDevice=" << bytesWrittenToDevice + << " m_processedSamples=" << m_processedSamples; + + if (bytesWrittenToDevice != maxLenInBytes) + { + cout << "AUDIO: qIODeviceCallback: WARNING " + "bytesWrittenToDevice != maxLenInBytes" + << endl; + } } - } - return ((qint64) bytesWrittenToDevice); + return ((qint64)bytesWrittenToDevice); + } + else + { + return 0; + } } - else + + void QTAudioThread::startOfInitialization() { - return 0; + m_startOfInitialization = m_systemClock.now(); + m_endOfInitialization = -1; } -} -void -QTAudioThread::startOfInitialization() -{ - m_startOfInitialization = m_systemClock.now(); - m_endOfInitialization = -1; -} - -TwkUtil::SystemClock::Time -QTAudioThread::endOfInitialization() -{ - m_endOfInitialization = m_systemClock.now(); - return (m_endOfInitialization - m_startOfInitialization); -} - -bool QTAudioThread::isInInitialization() const -{ - return (m_endOfInitialization < 0); -} - -//---------------------------------------------------------------------- -// QTAudioIODevice -// -// This is the Qt audio IO device class that lives -// with the audio thread. -//---------------------------------------------------------------------- -QTAudioIODevice::QTAudioIODevice(QTAudioThread &audiothread) : - m_thread(audiothread) -{ - QTAUDIO_DEBUG("QTAudioIODevice:") -} + TwkUtil::SystemClock::Time QTAudioThread::endOfInitialization() + { + m_endOfInitialization = m_systemClock.now(); + return (m_endOfInitialization - m_startOfInitialization); + } -QTAudioIODevice::~QTAudioIODevice() -{ -} + bool QTAudioThread::isInInitialization() const + { + return (m_endOfInitialization < 0); + } -void -QTAudioIODevice::start() -{ - QTAUDIO_DEBUG("QTAudioIODevice::start") - open(QIODevice::ReadOnly | QIODevice::Unbuffered); -} + //---------------------------------------------------------------------- + // QTAudioIODevice + // + // This is the Qt audio IO device class that lives + // with the audio thread. + //---------------------------------------------------------------------- + QTAudioIODevice::QTAudioIODevice(QTAudioThread& audiothread) + : m_thread(audiothread){QTAUDIO_DEBUG("QTAudioIODevice:")} -void -QTAudioIODevice::stopDevice() -{ - QTAUDIO_DEBUG("QTAudioIODevice::stopDevice") - close(); -} + QTAudioIODevice::~QTAudioIODevice() + { + } -void -QTAudioIODevice::resetDevice() -{ - QTAUDIO_DEBUG("QTAudioIODevice::resetDevice") - reset(); -} + void QTAudioIODevice::start() + { + QTAUDIO_DEBUG("QTAudioIODevice::start") + open(QIODevice::ReadOnly | QIODevice::Unbuffered); + } -qint64 QTAudioIODevice::readData(char* data, qint64 maxLenInBytes) -{ - // QTAUDIO_DEBUG("QTAudioIODevice::readData") - int bytesWritten = m_thread.qIODeviceCallback(data, maxLenInBytes); - return bytesWritten; -} + void QTAudioIODevice::stopDevice() + { + QTAUDIO_DEBUG("QTAudioIODevice::stopDevice") + close(); + } -qint64 QTAudioIODevice::writeData(const char* data, qint64 len) -{ - Q_UNUSED(data); - Q_UNUSED(len); + void QTAudioIODevice::resetDevice() + { + QTAUDIO_DEBUG("QTAudioIODevice::resetDevice") + reset(); + } - return 0; -} + qint64 QTAudioIODevice::readData(char* data, qint64 maxLenInBytes) + { + // QTAUDIO_DEBUG("QTAudioIODevice::readData") + int bytesWritten = m_thread.qIODeviceCallback(data, maxLenInBytes); + return bytesWritten; + } -qint64 QTAudioIODevice::bytesAvailable() const -{ + qint64 QTAudioIODevice::writeData(const char* data, qint64 len) + { + Q_UNUSED(data); + Q_UNUSED(len); - return QIODevice::bytesAvailable(); -} + return 0; + } -//---------------------------------------------------------------------- -// QTAudioOutput -// -// This is the Qt audio output class that lives -// with the audio thread. -//---------------------------------------------------------------------- -QTAudioOutput::QTAudioOutput(QAudioDeviceInfo &audioDeviceInfo, - QAudioFormat &audioFormat, - QTAudioIODevice &ioDevice, - QTAudioThread &audioThread) : - QAudioOutput(audioDeviceInfo, audioFormat) - , m_device(audioDeviceInfo) - , m_format(audioFormat) - , m_ioDevice(ioDevice) - , m_thread(audioThread) -{ - QTAUDIO_DEBUG("QTAudioOutput") -} + qint64 QTAudioIODevice::bytesAvailable() const + { -QTAudioOutput::~QTAudioOutput() -{ -} + return QIODevice::bytesAvailable(); + } -std::string QTAudioOutput::toString(QAudio::State state ) -{ - switch(state) + //---------------------------------------------------------------------- + // QTAudioOutput + // + // This is the Qt audio output class that lives + // with the audio thread. + //---------------------------------------------------------------------- + QTAudioOutput::QTAudioOutput(QAudioDeviceInfo& audioDeviceInfo, + QAudioFormat& audioFormat, + QTAudioIODevice& ioDevice, + QTAudioThread& audioThread) + : QAudioOutput(audioDeviceInfo, audioFormat) + , m_device(audioDeviceInfo) + , m_format(audioFormat) + , m_ioDevice(ioDevice) + , m_thread(audioThread){QTAUDIO_DEBUG("QTAudioOutput")} + + QTAudioOutput::~QTAudioOutput() { - case QAudio::ActiveState: return "active"; - case QAudio::SuspendedState: return "suspended"; - case QAudio::StoppedState: return "stopped"; - case QAudio::IdleState: return "idle"; - default: return "???"; } -} -void -QTAudioOutput::startAudio() -{ - QTAUDIO_DEBUG("QTAudioOutput::startAudio check") + std::string QTAudioOutput::toString(QAudio::State state) + { + switch (state) + { + case QAudio::ActiveState: + return "active"; + case QAudio::SuspendedState: + return "suspended"; + case QAudio::StoppedState: + return "stopped"; + case QAudio::IdleState: + return "idle"; + default: + return "???"; + } + } - if (state() == QAudio::StoppedState) + void QTAudioOutput::startAudio() { - m_thread.startOfInitialization(); + QTAUDIO_DEBUG("QTAudioOutput::startAudio check") + + if (state() == QAudio::StoppedState) + { + m_thread.startOfInitialization(); - QTAUDIO_DEBUG("QTAudioOutput::startAudio start()") + QTAUDIO_DEBUG("QTAudioOutput::startAudio start()") #ifdef PLATFORM_WINDOWS - // This is needed for Windows because when QAudioOutput - // reset() or stop() is called (thus putting the - // device into the StoppedState), the bufferSize also gets - // reset to zero. - // So we need to recalc the buffer size we want to use - // again before calling start(). - setAudioOutputBufferSize(); + // This is needed for Windows because when QAudioOutput + // reset() or stop() is called (thus putting the + // device into the StoppedState), the bufferSize also gets + // reset to zero. + // So we need to recalc the buffer size we want to use + // again before calling start(). + setAudioOutputBufferSize(); #endif - m_thread.setStartSample(0); - m_thread.setProcessedSamples(0); - m_thread.setPreRollDelay(0); - start(&m_ioDevice); - - } - else if (state() == QAudio::SuspendedState) - { - QTAUDIO_DEBUG("QTAudioOutput::startAudio resume()") + m_thread.setStartSample(0); + m_thread.setProcessedSamples(0); + m_thread.setPreRollDelay(0); + start(&m_ioDevice); + } + else if (state() == QAudio::SuspendedState) + { + QTAUDIO_DEBUG("QTAudioOutput::startAudio resume()") #ifdef PLATFORM_LINUX - m_thread.setPreRollDelay(0); + m_thread.setPreRollDelay(0); #endif - resume(); + resume(); + } } -} -void -QTAudioOutput::resetAudio() -{ - QTAUDIO_DEBUG("QTAudioOutput::resetAudio") - reset(); -} + void QTAudioOutput::resetAudio() + { + QTAUDIO_DEBUG("QTAudioOutput::resetAudio") + reset(); + } -void -QTAudioOutput::stopAudio() -{ - if (AudioRenderer::debug) TwkUtil::Log("AUDIO") << "Stop audio output"; + void QTAudioOutput::stopAudio() + { + if (AudioRenderer::debug) + TwkUtil::Log("AUDIO") << "Stop audio output"; - QTAUDIO_DEBUG("QTAudioOutput::stopAudio") + QTAUDIO_DEBUG("QTAudioOutput::stopAudio") - if (state() != QAudio::StoppedState) - { - stop(); + if (state() != QAudio::StoppedState) + { + stop(); + } } -} - -void -QTAudioOutput::suspendAudio() -{ - QTAUDIO_DEBUG("QTAudioOutput::suspendAudio") - if (state() != QAudio::StoppedState) + void QTAudioOutput::suspendAudio() { - suspend(); - } -} + QTAUDIO_DEBUG("QTAudioOutput::suspendAudio") -void -QTAudioOutput::suspendAndResetAudio() -{ - QTAUDIO_DEBUG("QTAudioOutput::suspendAndResetAudio") + if (state() != QAudio::StoppedState) + { + suspend(); + } + } - if (state() != QAudio::StoppedState) + void QTAudioOutput::suspendAndResetAudio() { - suspend(); - QTAUDIO_DEBUG("QTAudioOutput::suspendAndResetAudio - before reset") - reset(); - QTAUDIO_DEBUG("QTAudioOutput::suspendAndResetAudio - after reset") + QTAUDIO_DEBUG("QTAudioOutput::suspendAndResetAudio") + + if (state() != QAudio::StoppedState) + { + suspend(); + QTAUDIO_DEBUG("QTAudioOutput::suspendAndResetAudio - before reset") + reset(); + QTAUDIO_DEBUG("QTAudioOutput::suspendAndResetAudio - after reset") + } } -} -int -QTAudioOutput::calcAudioBufferSize(const int channels, - const int sampleRate, - const int sampleSizeInBytes, - const int defaultBufferSize) const -{ - // For sample rates 8k,11k 8bit, make the bufferSize - // small to avoid audio cache misses. - if (m_format.sampleRate() < 22000 && - m_thread.bytesPerSample() <= 2 ) + int QTAudioOutput::calcAudioBufferSize(const int channels, + const int sampleRate, + const int sampleSizeInBytes, + const int defaultBufferSize) const { - return 1024; - } + // For sample rates 8k,11k 8bit, make the bufferSize + // small to avoid audio cache misses. + if (m_format.sampleRate() < 22000 && m_thread.bytesPerSample() <= 2) + { + return 1024; + } - // QAudioOutput's default is 8192 bytes. (OSX) - // QAudioOutput's default is 200ms for all channels. (Windows) - const float minBufferSizeInTimePerChannel = 0.1f; + // QAudioOutput's default is 8192 bytes. (OSX) + // QAudioOutput's default is 200ms for all channels. (Windows) + const float minBufferSizeInTimePerChannel = 0.1f; - // Compute buffer size so it is at least minBufferSizeInTimePerChannel. - float defaultBufferSizeInTimePerChannel = (defaultBufferSize / sampleSizeInBytes) / ((float) (sampleRate * channels)); + // Compute buffer size so it is at least minBufferSizeInTimePerChannel. + float defaultBufferSizeInTimePerChannel = + (defaultBufferSize / sampleSizeInBytes) + / ((float)(sampleRate * channels)); - if (defaultBufferSizeInTimePerChannel < minBufferSizeInTimePerChannel) - { - return ((int) ceilf(minBufferSizeInTimePerChannel * ((float) (sampleRate * channels * sampleSizeInBytes)))); - } - else - { - return defaultBufferSize; + if (defaultBufferSizeInTimePerChannel < minBufferSizeInTimePerChannel) + { + return ((int)ceilf( + minBufferSizeInTimePerChannel + * ((float)(sampleRate * channels * sampleSizeInBytes)))); + } + else + { + return defaultBufferSize; + } } -} -void -QTAudioOutput::setAudioOutputBufferSize() -{ - QTAUDIO_DEBUG("QTAudioOutput::setAudioOutputBufferSize") - - // For linux we need to start the m_audioOutput to determine the buffersize thats - // used. - // On Windows, if we dont set the bufferSize (use the default), then the size of the buffer - // is set by the audioOutput start() call. - - // The AudioRenderer::defaultParameters().framesPerBuffer is zero it means the - // audio preference "Audio Cache samples" is zero; - // in which case we calculate what the audioOutput - // bufferSize should be. - if (AudioRenderer::defaultParameters().framesPerBuffer == 0) + void QTAudioOutput::setAudioOutputBufferSize() { + QTAUDIO_DEBUG("QTAudioOutput::setAudioOutputBufferSize") + + // For linux we need to start the m_audioOutput to determine the + // buffersize thats used. On Windows, if we dont set the bufferSize (use + // the default), then the size of the buffer is set by the audioOutput + // start() call. + + // The AudioRenderer::defaultParameters().framesPerBuffer is zero it + // means the audio preference "Audio Cache samples" is zero; in which + // case we calculate what the audioOutput bufferSize should be. + if (AudioRenderer::defaultParameters().framesPerBuffer == 0) + { #ifdef PLATFORM_DARWIN - setBufferSize(calcAudioBufferSize(m_format.channelCount(), - m_format.sampleRate(), - m_format.sampleSize() / 8, - bufferSize())); + setBufferSize(calcAudioBufferSize( + m_format.channelCount(), m_format.sampleRate(), + m_format.sampleSize() / 8, bufferSize())); #endif #ifdef PLATFORM_WINDOWS - // Note On Windows we need to set the buffer size 10x smaller because it is resize to - // a 10x value when the AudioOutput is started. - // First determine if this is a WASAPI device - // Note that on windows, an audio device can come from of those two Qt - // Audio Plugins: - // WASAPI (Windows Audio Session API) or WinMM (Windows Multimedia). - // Robert's fix above needs to be applied only to WASAPI audio devices. - // In Qt 5.12.5, there is no mechanism to identify from which audio - // plugin an audio device orginated. So for the time being we will always - // assume that it is an AWASPI device unless we detect that the WASAPI Qt - // audio plugin dll was removed from the Qt/Audio plugin directory. - // This is a temporary mechanism that will unblock our clients - // without introducing an RV preference that would have polluted the RV - // preferences unnecessarily. - const bool audioDeviceIsWASAPI = m_device.realm() == "wasapi"; - if (audioDeviceIsWASAPI && evApplyWasapiFix.getValue()) - { - setBufferSize(calcAudioBufferSize(m_format.channelCount(), - m_format.sampleRate(), - m_format.sampleSize() / 8, - bufferSize()) / 10); + // Note On Windows we need to set the buffer size 10x smaller + // because it is resize to + // a 10x value when the AudioOutput is started. + // First determine if this is a WASAPI device + // Note that on windows, an audio device can come from of those two + // Qt Audio Plugins: WASAPI (Windows Audio Session API) or WinMM + // (Windows Multimedia). Robert's fix above needs to be applied only + // to WASAPI audio devices. In Qt 5.12.5, there is no mechanism to + // identify from which audio plugin an audio device orginated. So + // for the time being we will always assume that it is an AWASPI + // device unless we detect that the WASAPI Qt audio plugin dll was + // removed from the Qt/Audio plugin directory. This is a temporary + // mechanism that will unblock our clients without introducing an RV + // preference that would have polluted the RV preferences + // unnecessarily. + const bool audioDeviceIsWASAPI = m_device.realm() == "wasapi"; + if (audioDeviceIsWASAPI && evApplyWasapiFix.getValue()) + { + setBufferSize(calcAudioBufferSize(m_format.channelCount(), + m_format.sampleRate(), + m_format.sampleSize() / 8, + bufferSize()) + / 10); + } + else + { + setBufferSize(calcAudioBufferSize( + m_format.channelCount(), m_format.sampleRate(), + m_format.sampleSize() / 8, bufferSize())); + } +#endif } else { - setBufferSize(calcAudioBufferSize(m_format.channelCount(), - m_format.sampleRate(), - m_format.sampleSize() / 8, - bufferSize())); - } -#endif - } - else - { - // Note: This might not always succeed as audio device buffer cannot - // be set below a certain size. - // If you hear crackles on playback at high sample rates - // this is probably due to the buffer not being filled fast - // enough because it is too small... so a user can increase - // the size in the preference tab i.e. "Device Packet Size". + // Note: This might not always succeed as audio device buffer cannot + // be set below a certain size. + // If you hear crackles on playback at high sample rates + // this is probably due to the buffer not being filled fast + // enough because it is too small... so a user can increase + // the size in the preference tab i.e. "Device Packet Size". #ifdef PLATFORM_LINUX - // For linux it is in ms * 1000. - int targetBufferSize = (1000000 * m_thread.framesPerBuffer() / m_format.sampleRate()); + // For linux it is in ms * 1000. + int targetBufferSize = + (1000000 * m_thread.framesPerBuffer() / m_format.sampleRate()); #else - int targetBufferSize = m_thread.framesPerBuffer() * m_thread.bytesPerSample(); + int targetBufferSize = + m_thread.framesPerBuffer() * m_thread.bytesPerSample(); #endif - setBufferSize(targetBufferSize); - if (bufferSize() != targetBufferSize) - { - cout << "Warning: Audio Device Cache of size " << m_thread.framesPerBuffer() << - " samples cannot be set below the device min sample limit of " - << bufferSize() / m_thread.bytesPerSample() - << " samples. Using device min limit instead." << endl; + setBufferSize(targetBufferSize); + if (bufferSize() != targetBufferSize) + { + cout << "Warning: Audio Device Cache of size " + << m_thread.framesPerBuffer() + << " samples cannot be set below the device min sample " + "limit of " + << bufferSize() / m_thread.bytesPerSample() + << " samples. Using device min limit instead." << endl; + } } - } - AudioRenderer::DeviceState newState = m_thread.deviceState(); - newState.framesPerBuffer = bufferSize() / m_thread.bytesPerSample(); - m_thread.setDeviceState(newState); + AudioRenderer::DeviceState newState = m_thread.deviceState(); + newState.framesPerBuffer = bufferSize() / m_thread.bytesPerSample(); + m_thread.setDeviceState(newState); - if (AudioRenderer::debug) - { - TwkUtil::Log("AUDIO") << "setAudioOutputBufferSize: bufferSize= " << bufferSize(); + if (AudioRenderer::debug) + { + TwkUtil::Log("AUDIO") + << "setAudioOutputBufferSize: bufferSize= " << bufferSize(); + } } -} - -void -QTAudioOutput::play(IPCore::Session* s) -{ - if (AudioRenderer::debug) TwkUtil::Log("QTAudioOutput") << "play()"; + void QTAudioOutput::play(IPCore::Session* s) + { + if (AudioRenderer::debug) + TwkUtil::Log("QTAudioOutput") << "play()"; #ifdef DEBUG_QTAUDIO - if (AudioRenderer::debugVerbose) - TwkUtil::Log("QTAudioThread") << "setup thread:" << QThread::currentThread() - << " isRunning=" << (int) m_thread.isRunning(); + if (AudioRenderer::debugVerbose) + TwkUtil::Log("QTAudioThread") + << "setup thread:" << QThread::currentThread() + << " isRunning=" << (int)m_thread.isRunning(); #endif - m_thread.setDeviceLatency(m_thread.getLastDeviceLatency()); + m_thread.setDeviceLatency(m_thread.getLastDeviceLatency()); - AudioRenderer::DeviceState newState = m_thread.deviceState(); - newState.framesPerBuffer = bufferSize() / m_thread.bytesPerSample(); - m_thread.setDeviceState(newState); + AudioRenderer::DeviceState newState = m_thread.deviceState(); + newState.framesPerBuffer = bufferSize() / m_thread.bytesPerSample(); + m_thread.setDeviceState(newState); - s->audioConfigure(); + s->audioConfigure(); - if (AudioRenderer::debug) - { - TwkUtil::Log("QTAudioOutput") << "play session:setup: startSample =" << m_thread.startSample() - << " shift=" << s->shift() - << " isPlaying=" << (int) s->isPlaying() - << " isScrubbingAudio=" << (int) s->isScrubbingAudio() - << " audioOutput state=" << (int) state() - << " audioOutput bufferSize=" << (int) bufferSize() - << " audioOutput periodSize=" << (int) periodSize(); + if (AudioRenderer::debug) + { + TwkUtil::Log("QTAudioOutput") + << "play session:setup: startSample =" << m_thread.startSample() + << " shift=" << s->shift() + << " isPlaying=" << (int)s->isPlaying() + << " isScrubbingAudio=" << (int)s->isScrubbingAudio() + << " audioOutput state=" << (int)state() + << " audioOutput bufferSize=" << (int)bufferSize() + << " audioOutput periodSize=" << (int)periodSize(); + } } -} -//---------------------------------------------------------------------- -// QTAudioRenderer -// -// This is the audio render class that lives -// with the main/UI thread. -// -//---------------------------------------------------------------------- -QTAudioRenderer::QTAudioRenderer(const RendererParameters ¶ms, - QObject* parent) : - AudioRenderer(params) - , m_parent(parent) - , m_codec("audio/pcm") -{ - init(); - QTAUDIO_DEBUG("QTAudioRenderer") -} + //---------------------------------------------------------------------- + // QTAudioRenderer + // + // This is the audio render class that lives + // with the main/UI thread. + // + //---------------------------------------------------------------------- + QTAudioRenderer::QTAudioRenderer(const RendererParameters& params, + QObject* parent) + : AudioRenderer(params) + , m_parent(parent) + , m_codec("audio/pcm") + { + init(); + QTAUDIO_DEBUG("QTAudioRenderer") + } -QTAudioRenderer::~QTAudioRenderer() -{ - if (m_thread) + QTAudioRenderer::~QTAudioRenderer() { - delete m_thread; + if (m_thread) + { + delete m_thread; + } } -} -TwkAudio::Format -QTAudioRenderer::getTwkAudioFormat() const -{ - return convertToTwkAudioFormat(m_format.sampleSize(), - m_format.sampleType()); -} + TwkAudio::Format QTAudioRenderer::getTwkAudioFormat() const + { + return convertToTwkAudioFormat(m_format.sampleSize(), + m_format.sampleType()); + } -TwkAudio::Format -QTAudioRenderer::convertToTwkAudioFormat(int fmtSize, - QAudioFormat::SampleType fmtType) const -{ - switch (fmtSize) + TwkAudio::Format QTAudioRenderer::convertToTwkAudioFormat( + int fmtSize, QAudioFormat::SampleType fmtType) const { - case 8: - switch (fmtType) - { + switch (fmtSize) + { + case 8: + switch (fmtType) + { case QAudioFormat::SignedInt: return TwkAudio::Int8Format; break; default: break; - } + } - break; + break; - case 16: - switch (fmtType) - { + case 16: + switch (fmtType) + { case QAudioFormat::SignedInt: return TwkAudio::Int16Format; break; default: break; - } + } - break; + break; - case 24: - switch (fmtType) - { + case 24: + switch (fmtType) + { case QAudioFormat::SignedInt: return TwkAudio::Int24Format; break; default: break; - } + } - break; + break; - case 32: - switch (fmtType) - { + case 32: + switch (fmtType) + { case QAudioFormat::SignedInt: return TwkAudio::Int32Format; break; @@ -1130,575 +1121,626 @@ QTAudioRenderer::convertToTwkAudioFormat(int fmtSize, default: break; - } + } - break; + break; - case 64: - break; - } + case 64: + break; + } - return TwkAudio::UnknownFormat; -} + return TwkAudio::UnknownFormat; + } -void -QTAudioRenderer::availableLayouts(const Device &d, LayoutsVector &layouts) -{ - const QAudioDeviceInfo &info = m_deviceList[d.index]; - const QList channelCounts = info.supportedChannelCounts(); + void QTAudioRenderer::availableLayouts(const Device& d, + LayoutsVector& layouts) + { + const QAudioDeviceInfo& info = m_deviceList[d.index]; + const QList channelCounts = info.supportedChannelCounts(); - layouts.clear(); + layouts.clear(); - for (QList::const_iterator ci = channelCounts.begin(); ci != channelCounts.end(); ci++) - { - LayoutsVector l = TwkAudio::channelLayouts(*ci); - for (int i = 0; i < l.size(); i++) layouts.push_back(l[i]); + for (QList::const_iterator ci = channelCounts.begin(); + ci != channelCounts.end(); ci++) + { + LayoutsVector l = TwkAudio::channelLayouts(*ci); + for (int i = 0; i < l.size(); i++) + layouts.push_back(l[i]); + } } -} -void -QTAudioRenderer::availableFormats(const Device &d, FormatVector &formats) -{ - const QAudioDeviceInfo &info = m_deviceList[d.index]; - const QList sizes = info.supportedSampleSizes(); - const QList types = info.supportedSampleTypes(); - const QList rates = info.supportedSampleRates(); - const int channelCount = TwkAudio::channelsCount(d.layout); + void QTAudioRenderer::availableFormats(const Device& d, + FormatVector& formats) + { + const QAudioDeviceInfo& info = m_deviceList[d.index]; + const QList sizes = info.supportedSampleSizes(); + const QList types = + info.supportedSampleTypes(); + const QList rates = info.supportedSampleRates(); + const int channelCount = TwkAudio::channelsCount(d.layout); - formats.clear(); + formats.clear(); - for (QList::const_iterator ci = sizes.begin(); ci != sizes.end(); ci++) - { - for (QList::const_iterator cj = types.begin(); cj != types.end(); cj++) + for (QList::const_iterator ci = sizes.begin(); ci != sizes.end(); + ci++) { - TwkAudio::Format fmt = convertToTwkAudioFormat(*ci, *cj); - - if (fmt != TwkAudio::UnknownFormat) + for (QList::const_iterator cj = + types.begin(); + cj != types.end(); cj++) { - QAudioFormat f; - - f.setChannelCount(channelCount); - f.setCodec(QString(m_codec.c_str())); - f.setByteOrder(QAudioFormat::LittleEndian); - f.setSampleSize(*ci); - f.setSampleType(*cj); - - // Now we check that a supported format - // has a supported rate. - // Oddly on linux a supported format can - // have no rate thats supported! - for (size_t i = 0; i < rates.size(); i++) + TwkAudio::Format fmt = convertToTwkAudioFormat(*ci, *cj); + + if (fmt != TwkAudio::UnknownFormat) { - f.setSampleRate(rates[i]); - if (info.isFormatSupported(f)) + QAudioFormat f; + + f.setChannelCount(channelCount); + f.setCodec(QString(m_codec.c_str())); + f.setByteOrder(QAudioFormat::LittleEndian); + f.setSampleSize(*ci); + f.setSampleType(*cj); + + // Now we check that a supported format + // has a supported rate. + // Oddly on linux a supported format can + // have no rate thats supported! + for (size_t i = 0; i < rates.size(); i++) { - formats.push_back(fmt); - break; + f.setSampleRate(rates[i]); + if (info.isFormatSupported(f)) + { + formats.push_back(fmt); + break; + } } } } } } -} - -// -// Sets the sample size and type in qformat for a given twkFormat. -// -void -QTAudioRenderer::setSampleSizeAndType(Layout twkLayout, - Format twkFormat, - QAudioFormat &qformat) const -{ - qformat.setChannelCount(TwkAudio::channelsCount(twkLayout)); - switch (twkFormat) + // + // Sets the sample size and type in qformat for a given twkFormat. + // + void QTAudioRenderer::setSampleSizeAndType(Layout twkLayout, + Format twkFormat, + QAudioFormat& qformat) const { - case TwkAudio::Float32Format: - qformat.setSampleSize(32); - qformat.setSampleType(QAudioFormat::Float); - break; - - case TwkAudio::Int32Format: - qformat.setSampleSize(32); - qformat.setSampleType(QAudioFormat::SignedInt); - break; - - case TwkAudio::Int24Format: - qformat.setSampleSize(24); - qformat.setSampleType(QAudioFormat::SignedInt); - break; - - case TwkAudio::Int16Format: - qformat.setSampleSize(16); - qformat.setSampleType(QAudioFormat::SignedInt); - break; - - case TwkAudio::Int8Format: - qformat.setSampleSize(8); - qformat.setSampleType(QAudioFormat::SignedInt); - break; - - default: - cout << "AUDIO: format unknown" << endl; - return; + qformat.setChannelCount(TwkAudio::channelsCount(twkLayout)); + + switch (twkFormat) + { + case TwkAudio::Float32Format: + qformat.setSampleSize(32); + qformat.setSampleType(QAudioFormat::Float); + break; + + case TwkAudio::Int32Format: + qformat.setSampleSize(32); + qformat.setSampleType(QAudioFormat::SignedInt); + break; + + case TwkAudio::Int24Format: + qformat.setSampleSize(24); + qformat.setSampleType(QAudioFormat::SignedInt); + break; + + case TwkAudio::Int16Format: + qformat.setSampleSize(16); + qformat.setSampleType(QAudioFormat::SignedInt); + break; + + case TwkAudio::Int8Format: + qformat.setSampleSize(8); + qformat.setSampleType(QAudioFormat::SignedInt); + break; + + default: + cout << "AUDIO: format unknown" << endl; + return; + } } -} -void -QTAudioRenderer::availableRates(const Device &d, Format format, RateVector &audiorates) -{ - QAudioFormat f; + void QTAudioRenderer::availableRates(const Device& d, Format format, + RateVector& audiorates) + { + QAudioFormat f; - f.setChannelCount(TwkAudio::channelsCount(d.layout)); - f.setCodec(QString(m_codec.c_str())); - f.setByteOrder(QAudioFormat::LittleEndian); + f.setChannelCount(TwkAudio::channelsCount(d.layout)); + f.setCodec(QString(m_codec.c_str())); + f.setByteOrder(QAudioFormat::LittleEndian); - setSampleSizeAndType(d.layout, format, f); + setSampleSizeAndType(d.layout, format, f); - const QAudioDeviceInfo &info = m_deviceList[d.index]; - QList rates = info.supportedSampleRates(); + const QAudioDeviceInfo& info = m_deviceList[d.index]; + QList rates = info.supportedSampleRates(); - sort(rates.begin(), rates.end()); + sort(rates.begin(), rates.end()); - audiorates.clear(); + audiorates.clear(); - for (size_t i = 0; i < rates.size(); i++) - { - f.setSampleRate(rates[i]); - if (info.isFormatSupported(f)) audiorates.push_back(rates[i]); + for (size_t i = 0; i < rates.size(); i++) + { + f.setSampleRate(rates[i]); + if (info.isFormatSupported(f)) + audiorates.push_back(rates[i]); + } } -} -// -// Check that the device supports the number -// of channels as specified by m_parameters.layout. -// -bool -QTAudioRenderer::supportsRequiredChannels(const QAudioDeviceInfo &info) const -{ -#ifdef PLATFORM_LINUX - if (AudioRenderer::debug) + // + // Check that the device supports the number + // of channels as specified by m_parameters.layout. + // + bool QTAudioRenderer::supportsRequiredChannels( + const QAudioDeviceInfo& info) const { - const QList channels = info.supportedChannelCounts(); - for (QList::const_iterator ci = channels.begin(); ci != channels.end(); ci++) - TwkUtil::Log("AUDIO") << info.deviceName().toStdString() << " supports channel count = " << (*ci); - } +#ifdef PLATFORM_LINUX + if (AudioRenderer::debug) + { + const QList channels = info.supportedChannelCounts(); + for (QList::const_iterator ci = channels.begin(); + ci != channels.end(); ci++) + TwkUtil::Log("AUDIO") << info.deviceName().toStdString() + << " supports channel count = " << (*ci); + } - // Its possible e.g. Linux that some devices hv no channel count info - // so we assume its supported... hence we always return true. - return true; + // Its possible e.g. Linux that some devices hv no channel count info + // so we assume its supported... hence we always return true. + return true; #else - const QList channels = info.supportedChannelCounts(); + const QList channels = info.supportedChannelCounts(); - if (AudioRenderer::debug) - { - for (QList::const_iterator ci = channels.begin(); ci != channels.end(); ci++) - TwkUtil::Log("Audio") << info.deviceName().toStdString() << " supports channel count = " << (*ci); - } + if (AudioRenderer::debug) + { + for (QList::const_iterator ci = channels.begin(); + ci != channels.end(); ci++) + TwkUtil::Log("Audio") << info.deviceName().toStdString() + << " supports channel count = " << (*ci); + } - // - // Now we can support driving whatever channels the device advertizes - // even if we have to fake it by upscaling the limited channels available - // in the input sources - // + // + // Now we can support driving whatever channels the device advertizes + // even if we have to fake it by upscaling the limited channels + // available in the input sources + // - return (!channels.empty()); + return (!channels.empty()); #endif -} + } -void -QTAudioRenderer::initDeviceList() -{ - if (m_deviceList.empty()) + void QTAudioRenderer::initDeviceList() { - // - // This appears to be a bug with Linux (on centos6.5). - // Basically the size returned by availbleDevices() is different - // the first time you call it compared to all subsequent times. - // So this logic between keeps calling availableDevices() until - // its size doesnt change; we limit this to five attempts. - // - int noOfAttempts = 5; - int noOfDevices = 0; - int prev_noOfDevices = 0; - - do + if (m_deviceList.empty()) { - prev_noOfDevices = noOfDevices; - noOfDevices = QAudioDeviceInfo::availableDevices(QAudio::AudioOutput).size(); - --noOfAttempts; - } while (prev_noOfDevices != noOfDevices && noOfAttempts); + // + // This appears to be a bug with Linux (on centos6.5). + // Basically the size returned by availbleDevices() is different + // the first time you call it compared to all subsequent times. + // So this logic between keeps calling availableDevices() until + // its size doesnt change; we limit this to five attempts. + // + int noOfAttempts = 5; + int noOfDevices = 0; + int prev_noOfDevices = 0; - m_deviceList << QAudioDeviceInfo::availableDevices(QAudio::AudioOutput); + do + { + prev_noOfDevices = noOfDevices; + noOfDevices = + QAudioDeviceInfo::availableDevices(QAudio::AudioOutput) + .size(); + --noOfAttempts; + } while (prev_noOfDevices != noOfDevices && noOfAttempts); + + m_deviceList << QAudioDeviceInfo::availableDevices( + QAudio::AudioOutput); + } } -} - -// The purpose of init() is to -// 1. Populate the AudioRenderer m_outputDevices(); -// 2. Initialise the current Device, m_device based on current -// preference device choice while finding the closest sample rate -// allowed for that device. -// 3. Initialise the current QAudioFormat, m_format, based of current -// preference sample size and sample rate. -// 4. Create QAudioThread. -// -void -QTAudioRenderer::init() -{ - const int channelCount = TwkAudio::channelsCount(m_parameters.layout); - - if (AudioRenderer::debug) TwkUtil::Log("AUDIO") << "init()"; + // The purpose of init() is to + // 1. Populate the AudioRenderer m_outputDevices(); + // 2. Initialise the current Device, m_device based on current + // preference device choice while finding the closest sample rate + // allowed for that device. + // 3. Initialise the current QAudioFormat, m_format, based of current + // preference sample size and sample rate. + // 4. Create QAudioThread. // - // Init the device list - // - initDeviceList(); - - if (m_parameters.device == "Default" || m_parameters.device.empty()) + void QTAudioRenderer::init() { - const QAudioDeviceInfo &defaultInfo = QAudioDeviceInfo::defaultOutputDevice(); + const int channelCount = TwkAudio::channelsCount(m_parameters.layout); - bool validDevice = false; + if (AudioRenderer::debug) + TwkUtil::Log("AUDIO") << "init()"; - for (size_t i = 0; i < m_deviceList.size(); ++i) + // + // Init the device list + // + initDeviceList(); + + if (m_parameters.device == "Default" || m_parameters.device.empty()) { - if (m_deviceList[i].deviceName() == defaultInfo.deviceName()) + const QAudioDeviceInfo& defaultInfo = + QAudioDeviceInfo::defaultOutputDevice(); + + bool validDevice = false; + + for (size_t i = 0; i < m_deviceList.size(); ++i) { - validDevice = true; - break; + if (m_deviceList[i].deviceName() == defaultInfo.deviceName()) + { + validDevice = true; + break; + } } - } - // Check that the defaultOutputDevice does support the required - // number of channels. - if (validDevice && supportsRequiredChannels(defaultInfo)) - { - m_parameters.device = defaultInfo.deviceName().toStdString(); - if (AudioRenderer::debug) + // Check that the defaultOutputDevice does support the required + // number of channels. + if (validDevice && supportsRequiredChannels(defaultInfo)) { - TwkUtil::Log("AUDIO") << "Using default device=" << m_parameters.device; - } + m_parameters.device = defaultInfo.deviceName().toStdString(); + if (AudioRenderer::debug) + { + TwkUtil::Log("AUDIO") + << "Using default device=" << m_parameters.device; + } - QAudioFormat qformat; + QAudioFormat qformat; - qformat.setSampleRate((int) m_parameters.rate); - qformat.setChannelCount(channelCount); - qformat.setCodec(QString(m_codec.c_str())); - qformat.setByteOrder(QAudioFormat::LittleEndian); - //qformat.setByteOrder(QAudioFormat::BigEndian); + qformat.setSampleRate((int)m_parameters.rate); + qformat.setChannelCount(channelCount); + qformat.setCodec(QString(m_codec.c_str())); + qformat.setByteOrder(QAudioFormat::LittleEndian); + // qformat.setByteOrder(QAudioFormat::BigEndian); - setSampleSizeAndType(m_parameters.layout, m_parameters.format, qformat); + setSampleSizeAndType(m_parameters.layout, m_parameters.format, + qformat); - // - // If the default device does not support the format - // defined by m_parameters; we change to the - // preferredFormat() of the default device. - if (!defaultInfo.isFormatSupported(qformat)) - { - const QAudioFormat defaultFormat = defaultInfo.preferredFormat(); + // + // If the default device does not support the format + // defined by m_parameters; we change to the + // preferredFormat() of the default device. + if (!defaultInfo.isFormatSupported(qformat)) + { + const QAudioFormat defaultFormat = + defaultInfo.preferredFormat(); - m_parameters.format = convertToTwkAudioFormat(defaultFormat.sampleSize(), - defaultFormat.sampleType()); + m_parameters.format = convertToTwkAudioFormat( + defaultFormat.sampleSize(), defaultFormat.sampleType()); + } } } - } - m_outputDevices.clear(); - for (size_t i = 0; i < m_deviceList.size(); ++i) - { - const QAudioDeviceInfo &info = m_deviceList[i]; + m_outputDevices.clear(); + for (size_t i = 0; i < m_deviceList.size(); ++i) + { + const QAudioDeviceInfo& info = m_deviceList[i]; - if (info.isNull() || !supportsRequiredChannels(info)) continue; + if (info.isNull() || !supportsRequiredChannels(info)) + continue; - const QAudioFormat defaultFormat = info.preferredFormat(); + const QAudioFormat defaultFormat = info.preferredFormat(); - std::string deviceName = info.deviceName().toStdString(); + std::string deviceName = info.deviceName().toStdString(); - // On Windows, a QAudioDevice can be listed twice with the same name - // This is due to the fact that both Qt audio plugins, wasapi and WinMM, - // can return the exact same name for an audiio output device - // https://bugreports.qt.io/browse/QTBUG-75781 - // Both will have different capabilities and RV references the output - // audio device by name, so it is important that a unique name be used - // to reference those distinct devices of the same name. - while (findDeviceByName(deviceName)!=-1) - { - deviceName+="_"+info.realm().toStdString(); - } + // On Windows, a QAudioDevice can be listed twice with the same name + // This is due to the fact that both Qt audio plugins, wasapi and + // WinMM, can return the exact same name for an audiio output device + // https://bugreports.qt.io/browse/QTBUG-75781 + // Both will have different capabilities and RV references the + // output audio device by name, so it is important that a unique + // name be used to reference those distinct devices of the same + // name. + while (findDeviceByName(deviceName) != -1) + { + deviceName += "_" + info.realm().toStdString(); + } - Device d(deviceName); + Device d(deviceName); - d.layout = m_parameters.layout; - d.defaultRate = defaultFormat.sampleRate(); - d.latencyLow = 0; - d.latencyHigh = 0; - d.index = i; + d.layout = m_parameters.layout; + d.defaultRate = defaultFormat.sampleRate(); + d.latencyLow = 0; + d.latencyHigh = 0; + d.index = i; + if (m_parameters.device == "Default" || m_parameters.device.empty()) + { + // If we got here it implies + // QAudioDeviceInfo::defaultOutputDevice() returns a device with + // too few channels so we cannot use it as our default device. + // Instead we pick the first device that supports the channel + // count we need. + m_parameters.device = d.name; + m_parameters.format = convertToTwkAudioFormat( + defaultFormat.sampleSize(), defaultFormat.sampleType()); + } - if (m_parameters.device == "Default" || m_parameters.device.empty()) - { - // If we got here it implies QAudioDeviceInfo::defaultOutputDevice() - // returns a device with too few channels so we cannot use it - // as our default device. Instead we pick the first device that - // supports the channel count we need. - m_parameters.device = d.name; - m_parameters.format = convertToTwkAudioFormat(defaultFormat.sampleSize(), - defaultFormat.sampleType()); - } + if (m_parameters.device == d.name) + { + d.isDefaultDevice = true; + m_device = info; + } + else + { + d.isDefaultDevice = false; + } - if (m_parameters.device == d.name) - { - d.isDefaultDevice = true; - m_device = info; - } - else - { - d.isDefaultDevice = false; + if (AudioRenderer::debug) + { + cout << "AUDIO: device=" << d.name << " with channelsCount = " + << TwkAudio::channelsCount(d.layout) + << " defaultSampleSize=" << (int)defaultFormat.sampleSize() + << " defaultSampleType=" << (int)defaultFormat.sampleType() + << " defaultSampleByteOrder=" + << (int)defaultFormat.byteOrder() + << " defaultrate=" << (int)d.defaultRate + << " isDefaultDevice=" << (int)d.isDefaultDevice << endl; + } + + m_outputDevices.push_back(d); } if (AudioRenderer::debug) { - cout << "AUDIO: device=" << d.name << " with channelsCount = " << TwkAudio::channelsCount(d.layout) - << " defaultSampleSize=" << (int) defaultFormat.sampleSize() - << " defaultSampleType=" << (int) defaultFormat.sampleType() - << " defaultSampleByteOrder=" << (int) defaultFormat.byteOrder() - << " defaultrate=" << (int) d.defaultRate - << " isDefaultDevice=" << (int) d.isDefaultDevice << endl; + cout << "AUDIO: init default device=" + << m_device.deviceName().toStdString() << endl; + cout << "AUDIO: init m_parameters.device=" << m_parameters.device + << endl; + cout << "AUDIO: init m_parameters.format=" + << (int)m_parameters.format << " (" + << TwkAudio::formatString(m_parameters.format) << ")" << endl; + cout << "AUDIO: init m_parameters.rate=" << (int)m_parameters.rate + << endl; + cout << "AUDIO: init m_parameters.layout=" + << (int)m_parameters.layout << " (" + << TwkAudio::channelsCount(m_parameters.layout) << " channels)" + << endl; + cout << "AUDIO: init m_parameters.framesPerBuffer=" + << (int)m_parameters.framesPerBuffer << endl; + cout << "AUDIO: init m_parameters.latency=" << m_parameters.latency + << endl; + cout << "AUDIO: init m_parameters.preRoll=" + << (m_parameters.preRoll ? 1 : 0) << endl; + cout << "AUDIO: init m_parameters.hardwareLock=" + << (m_parameters.hardwareLock ? 1 : 0) << endl; } - m_outputDevices.push_back(d); - } + if (!m_outputDevices.empty()) + { + size_t defaultDeviceIndex = 0; - if (AudioRenderer::debug) - { - cout << "AUDIO: init default device=" << m_device.deviceName().toStdString() << endl; - cout << "AUDIO: init m_parameters.device=" << m_parameters.device << endl; - cout << "AUDIO: init m_parameters.format=" << (int) m_parameters.format - << " (" << TwkAudio::formatString(m_parameters.format) << ")" << endl; - cout << "AUDIO: init m_parameters.rate=" << (int) m_parameters.rate << endl; - cout << "AUDIO: init m_parameters.layout=" << (int) m_parameters.layout - << " (" << TwkAudio::channelsCount(m_parameters.layout) << " channels)" << endl; - cout << "AUDIO: init m_parameters.framesPerBuffer=" << (int) m_parameters.framesPerBuffer << endl; - cout << "AUDIO: init m_parameters.latency=" << m_parameters.latency << endl; - cout << "AUDIO: init m_parameters.preRoll=" << (m_parameters.preRoll ? 1 : 0) << endl; - cout << "AUDIO: init m_parameters.hardwareLock=" << (m_parameters.hardwareLock ? 1 : 0) << endl; - } + for (size_t i = 0; i < m_outputDevices.size(); ++i) + { + if (m_outputDevices[i].isDefaultDevice) + { + defaultDeviceIndex = i; + break; + } + } - if (!m_outputDevices.empty()) - { - size_t defaultDeviceIndex = 0; + const Device& defaultDevice = m_outputDevices[defaultDeviceIndex]; - for (size_t i = 0; i < m_outputDevices.size(); ++i) - { - if (m_outputDevices[i].isDefaultDevice) + if (!defaultDevice.isDefaultDevice) { - defaultDeviceIndex = i; - break; + if (m_parameters.device == "Default") + { + cout << "ERROR: audio default device is NOT available." + << endl; + } + else + { + // The device that was picked and registered in the + // preferences might no longer be available because its + // unplugged. + cout << "WARNING: audio device '" << m_parameters.device + << "' is unavailable: Using default." << endl; + m_parameters.device = "Default"; + m_parameters.layout = TwkAudio::Stereo_2; + init(); + return; + } } - } - const Device &defaultDevice = m_outputDevices[defaultDeviceIndex]; + DeviceState state; - if (!defaultDevice.isDefaultDevice) - { - if (m_parameters.device == "Default") + state.framesPerBuffer = m_parameters.framesPerBuffer; + state.format = m_parameters.format; + state.layout = defaultDevice.layout; + state.device = defaultDevice.name; + state.rate = defaultDevice.defaultRate; + state.latency = m_parameters.latency; + + // Find the best matching sample rate for the + // select device. + if (m_parameters.rate != 0.0) { - cout << "ERROR: audio default device is NOT available." << endl; + state.rate = m_parameters.rate; } else { - // The device that was picked and registered in the preferences - // might no longer be available because its unplugged. - cout << "WARNING: audio device '" << m_parameters.device << - "' is unavailable: Using default." << endl; - m_parameters.device = "Default"; - m_parameters.layout = TwkAudio::Stereo_2; - init(); - return; + m_parameters.rate = state.rate; } - } - DeviceState state; + RateVector rates; - state.framesPerBuffer = m_parameters.framesPerBuffer; - state.format = m_parameters.format; - state.layout = defaultDevice.layout; - state.device = defaultDevice.name; - state.rate = defaultDevice.defaultRate; - state.latency = m_parameters.latency; + availableRates(defaultDevice, state.format, rates); - // Find the best matching sample rate for the - // select device. - if (m_parameters.rate != 0.0) - { - state.rate = m_parameters.rate; - } - else - { - m_parameters.rate = state.rate; - } + if (!rates.empty()) + { + double nearRate = rates[0]; + + for (size_t i = 1; i < rates.size(); i++) + { + if (fabs(rates[i] - state.rate) + < fabs(nearRate - state.rate)) + { + nearRate = rates[i]; + } + } - RateVector rates; + state.rate = nearRate; + m_parameters.rate = state.rate; + } - availableRates(defaultDevice, state.format, rates); + // + // Init the QAudioFormat to use in m_format + // + m_format.setSampleRate((int)state.rate); + m_format.setChannelCount(TwkAudio::channelsCount(state.layout)); + m_format.setCodec(QString(m_codec.c_str())); + m_format.setByteOrder(QAudioFormat::LittleEndian); + // m_format.setByteOrder(QAudioFormat::BigEndian); - if (!rates.empty()) - { - double nearRate = rates[0]; + setSampleSizeAndType(state.layout, state.format, m_format); - for (size_t i = 1; i < rates.size(); i++) + if (!m_device.isFormatSupported(m_format)) { - if (fabs(rates[i] - state.rate) < fabs(nearRate - state.rate)) + m_format = m_device.nearestFormat(m_format); + if (m_format.sampleType() == QAudioFormat::Unknown) + { + cout << "AUDIO: Default format not supported - trying to " + "use nearest" + << endl; + setErrorCondition( + "Default format not supported - trying to use nearest"); + } + else { - nearRate = rates[i]; + if (AudioRenderer::debug) + { + cout << "AUDIO: nearest m_format.sampleType()=" + << (int)m_format.sampleType() << endl; + cout << "AUDIO: nearest m_format.sampleSize()=" + << (int)m_format.sampleSize() << endl; + cout << "AUDIO: nearest m_format.sampleRate()=" + << (int)m_format.sampleRate() << endl; + cout << "AUDIO: nearest m_format.channelCount()=" + << (int)m_format.channelCount() << endl; + } } + + state.rate = m_parameters.rate = m_format.sampleRate(); + state.layout = m_parameters.layout = + TwkAudio::channelLayouts(m_format.channelCount()).front(); + state.format = m_parameters.format = getTwkAudioFormat(); } - state.rate = nearRate; - m_parameters.rate = state.rate; - } +#ifdef DEBUG_QTAUDIO + if (AudioRenderer::debug) + { + cout << "AUDIO: m_format.sampleType()=" + << (int)m_format.sampleType() << endl; + cout << "AUDIO: m_format.sampleSize()=" + << (int)m_format.sampleSize() << endl; + cout << "AUDIO: m_format.sampleRate()=" + << (int)m_format.sampleRate() << endl; + cout << "AUDIO: m_format.channelCount()=" + << (int)m_format.channelCount() << endl; + } +#endif - // - // Init the QAudioFormat to use in m_format - // - m_format.setSampleRate((int) state.rate); - m_format.setChannelCount(TwkAudio::channelsCount(state.layout)); - m_format.setCodec(QString(m_codec.c_str())); - m_format.setByteOrder(QAudioFormat::LittleEndian); - //m_format.setByteOrder(QAudioFormat::BigEndian); + setDeviceState(state); - setSampleSizeAndType(state.layout, state.format, m_format); + if (AudioRenderer::debug) + { + cout << "AUDIO: init: state.format =" << (int)state.format + << " (" << TwkAudio::formatString(state.format) << ")" + << endl; + cout << "AUDIO: init: state.rate =" << state.rate << endl; + cout << "AUDIO: init: state.layout =" << (int)state.layout + << " (" << TwkAudio::channelsCount(state.layout) + << " channels)" << endl; + cout << "AUDIO: init: state.framesPerBuffer =" + << state.framesPerBuffer << endl; + } - if (!m_device.isFormatSupported(m_format)) - { - m_format = m_device.nearestFormat(m_format); - if (m_format.sampleType() == QAudioFormat::Unknown) + // Create the audio renderer thread. + // The renderer runs in this thread. + // + m_thread = new QTAudioThread(*this, m_parent); + if (!m_thread) { - cout << "AUDIO: Default format not supported - trying to use nearest" << endl; - setErrorCondition("Default format not supported - trying to use nearest"); + setErrorCondition( + "Unable to create QThread for Platform Audio."); } else { - if (AudioRenderer::debug) - { - cout << "AUDIO: nearest m_format.sampleType()=" << (int) m_format.sampleType() << endl; - cout << "AUDIO: nearest m_format.sampleSize()=" << (int) m_format.sampleSize() << endl; - cout << "AUDIO: nearest m_format.sampleRate()=" << (int) m_format.sampleRate() << endl; - cout << "AUDIO: nearest m_format.channelCount()=" << (int) m_format.channelCount() << endl; - } + m_thread->startMe(); } - - state.rate = m_parameters.rate = m_format.sampleRate(); - state.layout = m_parameters.layout = TwkAudio::channelLayouts(m_format.channelCount()).front(); - state.format = m_parameters.format = getTwkAudioFormat(); } - -#ifdef DEBUG_QTAUDIO - if (AudioRenderer::debug) + else { - cout << "AUDIO: m_format.sampleType()=" << (int) m_format.sampleType() << endl; - cout << "AUDIO: m_format.sampleSize()=" << (int) m_format.sampleSize() << endl; - cout << "AUDIO: m_format.sampleRate()=" << (int) m_format.sampleRate() << endl; - cout << "AUDIO: m_format.channelCount()=" << (int) m_format.channelCount() << endl; + setErrorCondition("No devices available for Platform Audio."); } -#endif + } - setDeviceState(state); + void QTAudioRenderer::play() + { - if (AudioRenderer::debug) + if (m_thread) { - cout << "AUDIO: init: state.format =" << (int) state.format - << " (" << TwkAudio::formatString(state.format) << ")" << endl; - cout << "AUDIO: init: state.rate =" << state.rate << endl; - cout << "AUDIO: init: state.layout =" << (int) state.layout - << " (" << TwkAudio::channelsCount(state.layout) << " channels)" << endl; - cout << "AUDIO: init: state.framesPerBuffer =" << state.framesPerBuffer << endl; + m_thread->emitStartAudio(); } - // Create the audio renderer thread. - // The renderer runs in this thread. - // - m_thread = new QTAudioThread(*this, m_parent); - if (!m_thread) - { - setErrorCondition("Unable to create QThread for Platform Audio."); - } - else - { - m_thread->startMe(); - } - } - else - { - setErrorCondition("No devices available for Platform Audio."); + if (AudioRenderer::debug) + TwkUtil::Log("AUDIO") << "play"; + AudioRenderer::play(); } -} - -void QTAudioRenderer::play() -{ - if (m_thread) + void QTAudioRenderer::play(IPCore::Session* s) { - m_thread->emitStartAudio(); - } - - if (AudioRenderer::debug) TwkUtil::Log("AUDIO") << "play"; - AudioRenderer::play(); -} - -void QTAudioRenderer::play(IPCore::Session* s) -{ - if (AudioRenderer::debug) TwkUtil::Log("AUDIO") << "play session"; - - s->audioVarLock(); - s->setAudioTimeShift(numeric_limits::max()); - s->setAudioStartSample(0); - s->setAudioFirstPass(true); - s->audioVarUnLock(); - - AudioRenderer::play(s); - - if (m_thread) m_thread->emitPlay(s); -} - + if (AudioRenderer::debug) + TwkUtil::Log("AUDIO") << "play session"; -void QTAudioRenderer::stop() -{ - if (AudioRenderer::debug) TwkUtil::Log("AUDIO") << "stop"; + s->audioVarLock(); + s->setAudioTimeShift(numeric_limits::max()); + s->setAudioStartSample(0); + s->setAudioFirstPass(true); + s->audioVarUnLock(); - if (m_thread) m_thread->emitSuspendAndResetAudio(); + AudioRenderer::play(s); - AudioRenderer::stop(); -} + if (m_thread) + m_thread->emitPlay(s); + } -void QTAudioRenderer::stop(IPCore::Session* s) -{ - if (AudioRenderer::debug) TwkUtil::Log("AUDIO") << "stop session"; + void QTAudioRenderer::stop() + { + if (AudioRenderer::debug) + TwkUtil::Log("AUDIO") << "stop"; + if (m_thread) + m_thread->emitSuspendAndResetAudio(); - AudioRenderer::stop(s); - s->audioVarLock(); - s->setAudioTimeShift(numeric_limits::max()); - s->audioVarUnLock(); -} + AudioRenderer::stop(); + } -void -QTAudioRenderer::shutdown() -{ - if (AudioRenderer::debug) TwkUtil::Log("AUDIO") << "shutdown"; + void QTAudioRenderer::stop(IPCore::Session* s) + { + if (AudioRenderer::debug) + TwkUtil::Log("AUDIO") << "stop session"; + AudioRenderer::stop(s); + s->audioVarLock(); + s->setAudioTimeShift(numeric_limits::max()); + s->audioVarUnLock(); + } - if (m_thread) + void QTAudioRenderer::shutdown() { - if (!m_parameters.holdOpen) + if (AudioRenderer::debug) + TwkUtil::Log("AUDIO") << "shutdown"; + + if (m_thread) { - // NB: You only get here if you have the "Hold - // audio device open" preference unchecked. - // - m_thread->emitStopAudio(); + if (!m_parameters.holdOpen) + { + // NB: You only get here if you have the "Hold + // audio device open" preference unchecked. + // + m_thread->emitStopAudio(); + } } } -} - -} // IPCore +} // namespace IPCore diff --git a/src/lib/audio/QTAudioRenderer/QTAudioRenderer/QTAudioRenderer.h b/src/lib/audio/QTAudioRenderer/QTAudioRenderer/QTAudioRenderer.h index 9134590b5..f17cb52c4 100644 --- a/src/lib/audio/QTAudioRenderer/QTAudioRenderer/QTAudioRenderer.h +++ b/src/lib/audio/QTAudioRenderer/QTAudioRenderer/QTAudioRenderer.h @@ -1,9 +1,9 @@ //****************************************************************************** // Copyright (c) 2013, 2014 Tweak Software. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #ifndef __audio__QTAudioRenderer__h__ #define __audio__QTAudioRenderer__h__ @@ -23,251 +23,241 @@ #include -namespace IPCore { - -class QTAudioThread; -class QTAudioRenderer; - - -class QTAudioIODevice : public QIODevice -{ - Q_OBJECT - - public: - QTAudioIODevice(QTAudioThread &audioThread); - virtual ~QTAudioIODevice(); - - virtual qint64 readData(char* data, qint64 maxlen); - virtual qint64 writeData(const char* data, qint64 len); - qint64 bytesAvailable() const; - - void start(); - - public slots: - void resetDevice(); - void stopDevice(); - - private: - QTAudioThread &m_thread; -}; - - -class QTAudioOutput : public QAudioOutput -{ - Q_OBJECT - - public: - QTAudioOutput(QAudioDeviceInfo &audioDeviceInfo, - QAudioFormat &audioFormat, - QTAudioIODevice &ioDevice, - QTAudioThread &audioThread); - ~QTAudioOutput(); - - - public slots: - void startAudio(); - void resetAudio(); - void stopAudio(); - void suspendAudio(); - void suspendAndResetAudio(); - void setAudioOutputBufferSize(); - void play(IPCore::Session *s); - - private: - int calcAudioBufferSize(const int channels, - const int sampleRate, - const int sampleSizeInBytes, - const int defaultBufferSize) const; - std::string toString(QAudio::State state); - - private: - QAudioDeviceInfo &m_device; - QAudioFormat &m_format; - QTAudioIODevice &m_ioDevice; - QTAudioThread &m_thread; -}; - - -class QTAudioThread : public QThread +namespace IPCore { - Q_OBJECT - public: - QTAudioThread(QTAudioRenderer &audioRenderer, - QObject* parent = 0); - ~QTAudioThread(); + class QTAudioThread; + class QTAudioRenderer; - void startMe(); + class QTAudioIODevice : public QIODevice + { + Q_OBJECT - size_t processedSamples() const; - void setProcessedSamples(size_t n); + public: + QTAudioIODevice(QTAudioThread& audioThread); + virtual ~QTAudioIODevice(); - size_t startSample() const; - void setStartSample(size_t value); + virtual qint64 readData(char* data, qint64 maxlen); + virtual qint64 writeData(const char* data, qint64 len); + qint64 bytesAvailable() const; - TwkAudio::Time actualPlayedTimeOffset() const; - void setActualPlayedTimeOffset(TwkAudio::Time t); + void start(); - void setDeviceLatency(double t); + public slots: + void resetDevice(); + void stopDevice(); - bool preRollDisable() const; - void setPreRollDisable(bool disable); + private: + QTAudioThread& m_thread; + }; - void setPreRollDelay(TwkAudio::Time t); + class QTAudioOutput : public QAudioOutput + { + Q_OBJECT - int bytesPerSample() const; - size_t framesPerBuffer() const; + public: + QTAudioOutput(QAudioDeviceInfo& audioDeviceInfo, + QAudioFormat& audioFormat, QTAudioIODevice& ioDevice, + QTAudioThread& audioThread); + ~QTAudioOutput(); - bool holdOpen() const; + public slots: + void startAudio(); + void resetAudio(); + void stopAudio(); + void suspendAudio(); + void suspendAndResetAudio(); + void setAudioOutputBufferSize(); + void play(IPCore::Session* s); - const AudioRenderer::DeviceState& deviceState() const; - void setDeviceState(AudioRenderer::DeviceState &state); + private: + int calcAudioBufferSize(const int channels, const int sampleRate, + const int sampleSizeInBytes, + const int defaultBufferSize) const; + std::string toString(QAudio::State state); - void emitStartAudio(); - void emitResetAudio(); - void emitStopAudio(); - void emitSuspendAudio(); - void emitSuspendAndResetAudio(); + private: + QAudioDeviceInfo& m_device; + QAudioFormat& m_format; + QTAudioIODevice& m_ioDevice; + QTAudioThread& m_thread; + }; - void emitResetDevice(); - void emitStopDevice(); + class QTAudioThread : public QThread + { + Q_OBJECT - void emitPlay(IPCore::Session* s); + public: + QTAudioThread(QTAudioRenderer& audioRenderer, QObject* parent = 0); + ~QTAudioThread(); - // - // callback for QTAudioIODevice's readData() to call - // - qint64 qIODeviceCallback(char* data, qint64 maxLenInBytes); + void startMe(); - void startOfInitialization(); - TwkUtil::SystemClock::Time endOfInitialization(); - bool isInInitialization()const; + size_t processedSamples() const; + void setProcessedSamples(size_t n); - TwkUtil::SystemClock::Time getLastDeviceLatency() const { return m_lastDeviceLatency; } + size_t startSample() const; + void setStartSample(size_t value); + TwkAudio::Time actualPlayedTimeOffset() const; + void setActualPlayedTimeOffset(TwkAudio::Time t); - protected: - virtual void run(); + void setDeviceLatency(double t); - private: + bool preRollDisable() const; + void setPreRollDisable(bool disable); - bool createAudioOutput(); + void setPreRollDelay(TwkAudio::Time t); - void detachAudioOutputDevice(); + int bytesPerSample() const; + size_t framesPerBuffer() const; - private: - QMutex m_mutex; - - QObject* m_parent; + bool holdOpen() const; - QTAudioIODevice* m_ioDevice; - QTAudioOutput* m_audioOutput; - TwkAudio::AudioBuffer m_abuffer; - QTAudioRenderer &m_audioRenderer; + const AudioRenderer::DeviceState& deviceState() const; + void setDeviceState(AudioRenderer::DeviceState& state); - int m_bytesPerSample; - size_t m_preRollSamples; - size_t m_processedSamples; - size_t m_startSample; - int m_preRollMode; - bool m_preRollDisable; + void emitStartAudio(); + void emitResetAudio(); + void emitStopAudio(); + void emitSuspendAudio(); + void emitSuspendAndResetAudio(); - bool m_patch9355Enabled; - TwkUtil::SystemClock m_systemClock; - TwkUtil::SystemClock::Time m_startOfInitialization; - TwkUtil::SystemClock::Time m_endOfInitialization; - TwkUtil::SystemClock::Time m_lastDeviceLatency; -}; + void emitResetDevice(); + void emitStopDevice(); + void emitPlay(IPCore::Session* s); -class QTAudioRenderer : public IPCore::AudioRenderer -{ - public: - typedef TwkAudio::AudioBuffer AudioBuffer; + // + // callback for QTAudioIODevice's readData() to call + // + qint64 qIODeviceCallback(char* data, qint64 maxLenInBytes); - QTAudioRenderer(const RendererParameters&, QObject* parent); - virtual ~QTAudioRenderer(); + void startOfInitialization(); + TwkUtil::SystemClock::Time endOfInitialization(); + bool isInInitialization() const; - // - // AudioRenderer API - // + TwkUtil::SystemClock::Time getLastDeviceLatency() const + { + return m_lastDeviceLatency; + } - virtual void availableLayouts(const Device&, LayoutsVector&); - virtual void availableFormats(const Device&, FormatVector&); - virtual void availableRates(const Device&, Format, RateVector&); + protected: + virtual void run(); - // - // play() will return almost immediately -- a worker thread will - // be released and start playing. - // + private: + bool createAudioOutput(); - virtual void play(); - virtual void play(IPCore::Session*); + void detachAudioOutputDevice(); - // - // stop() will cause the worker thread to wait until play. - // + private: + QMutex m_mutex; - virtual void stop(); - virtual void stop(IPCore::Session*); + QObject* m_parent; - // - // shutdown() close all hardware devices - // + QTAudioIODevice* m_ioDevice; + QTAudioOutput* m_audioOutput; + TwkAudio::AudioBuffer m_abuffer; + QTAudioRenderer& m_audioRenderer; - virtual void shutdown(); + int m_bytesPerSample; + size_t m_preRollSamples; + size_t m_processedSamples; + size_t m_startSample; + int m_preRollMode; + bool m_preRollDisable; - // - // T is the Application type that is adding this - // renderer as an audio module e.g. 'RvApplication' - // or 'NoodleApplication'. - template - static IPCore::AudioRenderer::Module addQTAudioModule(); + bool m_patch9355Enabled; + TwkUtil::SystemClock m_systemClock; + TwkUtil::SystemClock::Time m_startOfInitialization; + TwkUtil::SystemClock::Time m_endOfInitialization; + TwkUtil::SystemClock::Time m_lastDeviceLatency; + }; - TwkAudio::Format getTwkAudioFormat() const; - TwkAudio::Format convertToTwkAudioFormat(int fmtSize, - QAudioFormat::SampleType fmtType) const; + class QTAudioRenderer : public IPCore::AudioRenderer + { + public: + typedef TwkAudio::AudioBuffer AudioBuffer; - void setSampleSizeAndType(Layout twkLayout, - Format twkFormat, - QAudioFormat &qformat) const; + QTAudioRenderer(const RendererParameters&, QObject* parent); + virtual ~QTAudioRenderer(); - friend class QTAudioThread; + // + // AudioRenderer API + // - private: + virtual void availableLayouts(const Device&, LayoutsVector&); + virtual void availableFormats(const Device&, FormatVector&); + virtual void availableRates(const Device&, Format, RateVector&); - bool supportsRequiredChannels(const QAudioDeviceInfo &info) const; + // + // play() will return almost immediately -- a worker thread will + // be released and start playing. + // - void init(); + virtual void play(); + virtual void play(IPCore::Session*); - void initDeviceList(); + // + // stop() will cause the worker thread to wait until play. + // - private: - QObject* m_parent; - QTAudioThread* m_thread; - QAudioFormat m_format; - QAudioDeviceInfo m_device; - QList m_deviceList; - std::string m_codec; -}; + virtual void stop(); + virtual void stop(IPCore::Session*); + // + // shutdown() close all hardware devices + // + virtual void shutdown(); + // + // T is the Application type that is adding this + // renderer as an audio module e.g. 'RvApplication' + // or 'NoodleApplication'. + template + static IPCore::AudioRenderer::Module addQTAudioModule(); + + TwkAudio::Format getTwkAudioFormat() const; + TwkAudio::Format + convertToTwkAudioFormat(int fmtSize, + QAudioFormat::SampleType fmtType) const; -template -static IPCore::AudioRenderer* -createQTAudio(const IPCore::AudioRenderer::RendererParameters &p) -{ - return (new QTAudioRenderer(p, static_cast(IPCore::App()))); -} + void setSampleSizeAndType(Layout twkLayout, Format twkFormat, + QAudioFormat& qformat) const; -template -IPCore::AudioRenderer::Module -QTAudioRenderer::addQTAudioModule() -{ - return IPCore::AudioRenderer::Module("Platform Audio", "", createQTAudio); -} + friend class QTAudioThread; + + private: + bool supportsRequiredChannels(const QAudioDeviceInfo& info) const; + + void init(); -} // IPCore + void initDeviceList(); + + private: + QObject* m_parent; + QTAudioThread* m_thread; + QAudioFormat m_format; + QAudioDeviceInfo m_device; + QList m_deviceList; + std::string m_codec; + }; + + template + static IPCore::AudioRenderer* + createQTAudio(const IPCore::AudioRenderer::RendererParameters& p) + { + return (new QTAudioRenderer(p, static_cast(IPCore::App()))); + } + + template + IPCore::AudioRenderer::Module QTAudioRenderer::addQTAudioModule() + { + return IPCore::AudioRenderer::Module("Platform Audio", "", + createQTAudio); + } + +} // namespace IPCore #endif // __audio__QTAudioRenderer__h__ diff --git a/src/lib/audio/TwkAudio/Audio.cpp b/src/lib/audio/TwkAudio/Audio.cpp index cbf0e67c6..1922d760f 100644 --- a/src/lib/audio/TwkAudio/Audio.cpp +++ b/src/lib/audio/TwkAudio/Audio.cpp @@ -1,9 +1,9 @@ //****************************************************************************** -// Copyright (c) 2007 Tweak Inc. +// Copyright (c) 2007 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #include @@ -15,283 +15,256 @@ #include #include -namespace TwkAudio { -using namespace std; - -AudioBuffer::AudioBuffer() - : m_rate(0), - m_startTime(0), - m_numSamples(0), - m_data(0), - m_margin(0) -{ -} - -AudioBuffer::AudioBuffer(size_t numSamples, - ChannelsVector channels, - Time rate, - Time startTime, - size_t margin) - : m_rate(rate), - m_startTime(startTime), - m_numSamples(numSamples), - m_data(0), - m_margin(margin), - m_channels(channels) -{ - m_buffer.resize((m_numSamples + 2 * m_margin) * m_channels.size()); - m_data = numSamples ? (&m_buffer.front() + margin * m_channels.size()) : 0; -} - -AudioBuffer::AudioBuffer(size_t numSamples, - TwkAudio::Layout layout, - Time rate, - Time startTime, - size_t margin) - : m_rate(rate), - m_startTime(startTime), - m_numSamples(numSamples), - m_data(0), - m_margin(margin), - m_channels(TwkAudio::layoutChannels(layout)) -{ - m_buffer.resize((m_numSamples + 2 * m_margin) * m_channels.size()); - m_data = numSamples ? (&m_buffer.front() + margin * m_channels.size()) : 0; -} - -AudioBuffer::AudioBuffer(Time start, - Time duration, - Time rate, - ChannelsVector channels, - size_t margin) - : m_startTime(start), - m_rate(rate), - m_numSamples(size_t(duration * rate + 0.49)), - m_margin(margin), - m_channels(channels) -{ - m_buffer.resize((m_numSamples + 2 * m_margin) * m_channels.size()); - m_data = m_numSamples ? (&m_buffer.front() + margin * m_channels.size()) : 0; -} - -AudioBuffer::AudioBuffer(BufferPointer externalMemory, - ChannelsVector channels, - size_t numSamples, - Time start, - Time rate, - size_t margin) - : m_startTime(start), - m_rate(rate), - m_data(externalMemory + margin), - m_numSamples(numSamples), - m_margin(margin), - m_channels(channels) +namespace TwkAudio { -} + using namespace std; + + AudioBuffer::AudioBuffer() + : m_rate(0) + , m_startTime(0) + , m_numSamples(0) + , m_data(0) + , m_margin(0) + { + } -AudioBuffer::AudioBuffer(AudioBuffer& inbuffer, - size_t startOffsetSample, - size_t numSamples, - Time startTime) -{ - m_channels = inbuffer.channels(); - m_numSamples = numSamples; - m_margin = 0; - m_rate = inbuffer.rate(); - m_startTime = startTime; - m_data = inbuffer.size() - ? (inbuffer.pointer() + startOffsetSample * m_channels.size()) - : 0; -} - -void -AudioBuffer::ownData() -{ - if (!bufferOwnsData()) + AudioBuffer::AudioBuffer(size_t numSamples, ChannelsVector channels, + Time rate, Time startTime, size_t margin) + : m_rate(rate) + , m_startTime(startTime) + , m_numSamples(numSamples) + , m_data(0) + , m_margin(margin) + , m_channels(channels) { m_buffer.resize((m_numSamples + 2 * m_margin) * m_channels.size()); - - if (!m_buffer.empty()) - { - memcpy(&m_buffer.front(), - m_data - m_margin, - sizeof(float) * m_channels.size() * (m_numSamples + 2 * m_margin)); - - m_data = &m_buffer.front() + m_margin * m_channels.size(); - } - else - { - m_data = 0; - } - - m_numSamples = m_buffer.size() / m_channels.size() - 2 * m_margin; + m_data = + numSamples ? (&m_buffer.front() + margin * m_channels.size()) : 0; } -} - -void -AudioBuffer::reconfigure(size_t numSamples, - ChannelsVector channels, - Time rate, - Time startTime, - size_t margin) -{ - ownData(); - m_buffer.resize((numSamples + 2 * margin) * channels.size()); - - m_channels = channels; - m_numSamples = numSamples; - m_rate = rate; - m_startTime = startTime; - m_margin = margin; - m_data = numSamples ? (&m_buffer.front() + margin * m_channels.size()) : 0; -} - -void -AudioBuffer::reconfigure(size_t numSamples, - TwkAudio::Layout layout, - Time rate, - Time startTime, - size_t margin) -{ - return reconfigure(numSamples, - layoutChannels(layout), - rate, - startTime, - margin); -} - -void -AudioBuffer::zero() -{ - if (m_data) memset(m_data - m_margin * m_channels.size(), 0, sizeInBytesIncludingMargin()); -} -void -AudioBuffer::zeroRegion(size_t start, size_t n) -{ - if (!m_data) return; - assert(n <= (m_numSamples - start)); - - size_t a = (m_margin + start) * m_channels.size(); - memset(m_data + a, 0, n * m_channels.size() * sizeof(SampleType)); -} - -bool -AudioBuffer::bufferOwnsData() const -{ - if (m_buffer.empty()) + AudioBuffer::AudioBuffer(size_t numSamples, TwkAudio::Layout layout, + Time rate, Time startTime, size_t margin) + : m_rate(rate) + , m_startTime(startTime) + , m_numSamples(numSamples) + , m_data(0) + , m_margin(margin) + , m_channels(TwkAudio::layoutChannels(layout)) { - return m_data == 0; + m_buffer.resize((m_numSamples + 2 * m_margin) * m_channels.size()); + m_data = + numSamples ? (&m_buffer.front() + margin * m_channels.size()) : 0; } - else + + AudioBuffer::AudioBuffer(Time start, Time duration, Time rate, + ChannelsVector channels, size_t margin) + : m_startTime(start) + , m_rate(rate) + , m_numSamples(size_t(duration * rate + 0.49)) + , m_margin(margin) + , m_channels(channels) { - return m_data == (&m_buffer.front() + m_channels.size() * m_margin); + m_buffer.resize((m_numSamples + 2 * m_margin) * m_channels.size()); + m_data = + m_numSamples ? (&m_buffer.front() + margin * m_channels.size()) : 0; } -} - - -void -AudioBuffer::reverse(bool reverseChannels) -{ - float* data = m_data; - if (reverseChannels) + AudioBuffer::AudioBuffer(BufferPointer externalMemory, + ChannelsVector channels, size_t numSamples, + Time start, Time rate, size_t margin) + : m_startTime(start) + , m_rate(rate) + , m_data(externalMemory + margin) + , m_numSamples(numSamples) + , m_margin(margin) + , m_channels(channels) { - std::reverse(data, data + m_numSamples * m_channels.size()); - std::reverse(m_channels.begin(), m_channels.end()); } - else + + AudioBuffer::AudioBuffer(AudioBuffer& inbuffer, size_t startOffsetSample, + size_t numSamples, Time startTime) { - size_t halfNumSamples = m_numSamples/2; + m_channels = inbuffer.channels(); + m_numSamples = numSamples; + m_margin = 0; + m_rate = inbuffer.rate(); + m_startTime = startTime; + m_data = + inbuffer.size() + ? (inbuffer.pointer() + startOffsetSample * m_channels.size()) + : 0; + } - for (size_t i=0; i < halfNumSamples; ++i) + void AudioBuffer::ownData() + { + if (!bufferOwnsData()) { - float* out0 = data + i * m_channels.size(); - float* out1 = data + (m_numSamples - 1 - i) * m_channels.size(); + m_buffer.resize((m_numSamples + 2 * m_margin) * m_channels.size()); - for (size_t j=0; j < m_channels.size(); ++j) + if (!m_buffer.empty()) { - float tmp = out0[j]; - out0[j] = out1[j]; - out1[j] = tmp; + memcpy(&m_buffer.front(), m_data - m_margin, + sizeof(float) * m_channels.size() + * (m_numSamples + 2 * m_margin)); + + m_data = &m_buffer.front() + m_margin * m_channels.size(); } + else + { + m_data = 0; + } + + m_numSamples = m_buffer.size() / m_channels.size() - 2 * m_margin; } } -} -bool -AudioBuffer::checkBuffer(const char* label) const -{ - size_t zeroCount = 0; - size_t outOfBoundsCount = 0; - size_t maxCount = 0; - size_t gapCount = 0; - const float* data = m_data; - const size_t numOfFloats = m_numSamples * m_channels.size(); + void AudioBuffer::reconfigure(size_t numSamples, ChannelsVector channels, + Time rate, Time startTime, size_t margin) + { + ownData(); + m_buffer.resize((numSamples + 2 * margin) * channels.size()); + + m_channels = channels; + m_numSamples = numSamples; + m_rate = rate; + m_startTime = startTime; + m_margin = margin; + m_data = + numSamples ? (&m_buffer.front() + margin * m_channels.size()) : 0; + } + + void AudioBuffer::reconfigure(size_t numSamples, TwkAudio::Layout layout, + Time rate, Time startTime, size_t margin) + { + return reconfigure(numSamples, layoutChannels(layout), rate, startTime, + margin); + } + + void AudioBuffer::zero() + { + if (m_data) + memset(m_data - m_margin * m_channels.size(), 0, + sizeInBytesIncludingMargin()); + } - float maxValue = -std::numeric_limits::max(); - float minValue = std::numeric_limits::max(); + void AudioBuffer::zeroRegion(size_t start, size_t n) + { + if (!m_data) + return; + assert(n <= (m_numSamples - start)); + + size_t a = (m_margin + start) * m_channels.size(); + memset(m_data + a, 0, n * m_channels.size() * sizeof(SampleType)); + } - for (size_t i=0; i < numOfFloats; ++i) + bool AudioBuffer::bufferOwnsData() const { - if (data[i] == 0.0f) + if (m_buffer.empty()) { - if (zeroCount == 0) - { - ++gapCount; - } + return m_data == 0; + } + else + { + return m_data == (&m_buffer.front() + m_channels.size() * m_margin); + } + } - ++zeroCount; + void AudioBuffer::reverse(bool reverseChannels) + { + float* data = m_data; + + if (reverseChannels) + { + std::reverse(data, data + m_numSamples * m_channels.size()); + std::reverse(m_channels.begin(), m_channels.end()); } else { - if (zeroCount > maxCount) + size_t halfNumSamples = m_numSamples / 2; + + for (size_t i = 0; i < halfNumSamples; ++i) { - maxCount = zeroCount; + float* out0 = data + i * m_channels.size(); + float* out1 = data + (m_numSamples - 1 - i) * m_channels.size(); + + for (size_t j = 0; j < m_channels.size(); ++j) + { + float tmp = out0[j]; + out0[j] = out1[j]; + out1[j] = tmp; + } } - zeroCount = 0; } + } + + bool AudioBuffer::checkBuffer(const char* label) const + { + size_t zeroCount = 0; + size_t outOfBoundsCount = 0; + size_t maxCount = 0; + size_t gapCount = 0; + const float* data = m_data; + const size_t numOfFloats = m_numSamples * m_channels.size(); + + float maxValue = -std::numeric_limits::max(); + float minValue = std::numeric_limits::max(); - if ((data[i] > 1.0f) || (data[i] < -1.0f) ) + for (size_t i = 0; i < numOfFloats; ++i) { - if (data[i] > maxValue) + if (data[i] == 0.0f) { - maxValue = data[i]; + if (zeroCount == 0) + { + ++gapCount; + } + + ++zeroCount; } - else if (data[i] < minValue) + else { - minValue = data[i]; + if (zeroCount > maxCount) + { + maxCount = zeroCount; + } + zeroCount = 0; } - ++outOfBoundsCount; + if ((data[i] > 1.0f) || (data[i] < -1.0f)) + { + if (data[i] > maxValue) + { + maxValue = data[i]; + } + else if (data[i] < minValue) + { + minValue = data[i]; + } + + ++outOfBoundsCount; + } } + if (maxCount > 1 && m_startTime != 0.0) + { + cerr << "Time=" << m_startTime + << " : AudioBuffer::check() called from " << label << ": " + << "zeroCount=" << maxCount << " gapCount=" << gapCount + << endl; - } - - if (maxCount > 1 && m_startTime != 0.0) - { - cerr << "Time=" << m_startTime << " : AudioBuffer::check() called from " << label << ": " - << "zeroCount=" << maxCount - << " gapCount=" << gapCount - << endl; - - return false; - } + return false; + } + if (outOfBoundsCount) + { + cerr << "Time=" << m_startTime + << " : AudioBuffer::check() called from " << label << ": " + << "outOfBoundsCount=" << outOfBoundsCount + << "maxValue=" << maxValue << "minValue=" << minValue << endl; - if (outOfBoundsCount) - { - cerr << "Time=" << m_startTime << " : AudioBuffer::check() called from " << label << ": " - << "outOfBoundsCount=" << outOfBoundsCount - << "maxValue=" << maxValue - << "minValue=" << minValue - << endl; + return false; + } - return false; + return true; } - return true; -} - -} // TwkAudio +} // namespace TwkAudio diff --git a/src/lib/audio/TwkAudio/AudioCache.cpp b/src/lib/audio/TwkAudio/AudioCache.cpp index d2306e807..3b3ca80a5 100644 --- a/src/lib/audio/TwkAudio/AudioCache.cpp +++ b/src/lib/audio/TwkAudio/AudioCache.cpp @@ -1,9 +1,9 @@ //****************************************************************************** -// Copyright (c) 2008 Tweak Inc. +// Copyright (c) 2008 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #include @@ -14,371 +14,359 @@ #include #include -namespace TwkAudio { -using namespace std; - -AudioCache::AudioCache() - : m_packetSize(512), - m_packetLayout(TwkAudio::Stereo_2), - m_count(0), - m_packetRate(0), - m_totalSecondsCached(0), - m_cachedRangesStatFrameRate(0.0) -{ - pthread_mutex_init(&m_lock, 0); -} - -AudioCache::~AudioCache() +namespace TwkAudio { - clear(); - pthread_mutex_destroy(&m_lock); -} - -void -AudioCache::clear() -{ - for (PacketMap::iterator i = m_map.begin(); - i != m_map.end(); - ++i) + using namespace std; + + AudioCache::AudioCache() + : m_packetSize(512) + , m_packetLayout(TwkAudio::Stereo_2) + , m_count(0) + , m_packetRate(0) + , m_totalSecondsCached(0) + , m_cachedRangesStatFrameRate(0.0) { - //delete [] i->second; - TwkUtil::MemPool::dealloc(i->second); + pthread_mutex_init(&m_lock, 0); } - for (size_t i = 0; i < m_freePackets.size(); i++) + AudioCache::~AudioCache() { - TwkUtil::MemPool::dealloc(m_freePackets[i]); + clear(); + pthread_mutex_destroy(&m_lock); } - m_freePackets.clear(); - m_map.clear(); - m_count = 0; - m_totalSecondsCached = 0; - m_cachedRangesStat.clear(); -} - -void -AudioCache::clearBefore(Time t) -{ - size_t s = sampleAtTime(t); - - PacketMap::iterator a = m_map.end(); - PacketMap::iterator b = a; - - for (PacketMap::iterator i = m_map.begin(); - i != m_map.end(); - ++i) + void AudioCache::clear() { - if (i->first < s) + for (PacketMap::iterator i = m_map.begin(); i != m_map.end(); ++i) { - m_freePackets.push_back(i->second); - m_count--; - i->second = 0; - if (a == m_map.end()) a = i; + // delete [] i->second; + TwkUtil::MemPool::dealloc(i->second); } - else if (i->first >= s) + + for (size_t i = 0; i < m_freePackets.size(); i++) { - b = i; - break; + TwkUtil::MemPool::dealloc(m_freePackets[i]); } - } - if (a != b && a != m_map.end()) - { - m_map.erase(a, b); + m_freePackets.clear(); + m_map.clear(); + m_count = 0; + m_totalSecondsCached = 0; m_cachedRangesStat.clear(); } - m_totalSecondsCached = Time(m_count) * Time(m_packetSize) / m_packetRate; -} - -void -AudioCache::clearAfter(Time t) -{ - SampleTime s = sampleAtTime(t); + void AudioCache::clearBefore(Time t) + { + size_t s = sampleAtTime(t); - PacketMap::iterator a = m_map.end(); - PacketMap::iterator b = a; + PacketMap::iterator a = m_map.end(); + PacketMap::iterator b = a; - vector tbd; + for (PacketMap::iterator i = m_map.begin(); i != m_map.end(); ++i) + { + if (i->first < s) + { + m_freePackets.push_back(i->second); + m_count--; + i->second = 0; + if (a == m_map.end()) + a = i; + } + else if (i->first >= s) + { + b = i; + break; + } + } - for (PacketMap::iterator i = m_map.begin(); - i != m_map.end(); - ++i) - { - if (i->first > s) + if (a != b && a != m_map.end()) { - m_freePackets.push_back(i->second); - m_count--; - i->second = 0; - if (a == m_map.end()) a = i; + m_map.erase(a, b); + m_cachedRangesStat.clear(); } - } - if (a != b && a != m_map.end()) - { - m_map.erase(a, b); - m_cachedRangesStat.clear(); + m_totalSecondsCached = + Time(m_count) * Time(m_packetSize) / m_packetRate; } - m_totalSecondsCached = Time(m_count) * Time(m_packetSize) / m_packetRate; -} - -void -AudioCache::clear(Time time0, Time time1) -{ - SampleTime s0 = sampleAtTime(time0); - SampleTime s1 = sampleAtTime(time1); + void AudioCache::clearAfter(Time t) + { + SampleTime s = sampleAtTime(t); - PacketMap::iterator a = m_map.end(); - PacketMap::iterator b = a; + PacketMap::iterator a = m_map.end(); + PacketMap::iterator b = a; - vector tbd; + vector tbd; - for (PacketMap::iterator i = m_map.begin(); - i != m_map.end(); - ++i) - { - if ( i->first > s0 ) + for (PacketMap::iterator i = m_map.begin(); i != m_map.end(); ++i) { - if ( i->first < s1 ) + if (i->first > s) { - m_freePackets.push_back( i->second ); + m_freePackets.push_back(i->second); m_count--; i->second = 0; - if ( a == m_map.end() ) a = i; - } - else - { - b = i; - break; + if (a == m_map.end()) + a = i; } } - } - if (a != b && a != m_map.end()) - { - m_map.erase(a, b); - m_cachedRangesStat.clear(); - } + if (a != b && a != m_map.end()) + { + m_map.erase(a, b); + m_cachedRangesStat.clear(); + } - m_totalSecondsCached = Time(m_count) * Time(m_packetSize) / m_packetRate; -} + m_totalSecondsCached = + Time(m_count) * Time(m_packetSize) / m_packetRate; + } -void -AudioCache::configurePacket(size_t samples, - TwkAudio::Layout layout, - Time rate) -{ - if (m_packetSize != samples || - m_packetLayout != layout || - m_packetRate != rate) + void AudioCache::clear(Time time0, Time time1) { - clear(); - m_packetSize = samples; - m_packetLayout = layout; - m_packetRate = rate; - } -} + SampleTime s0 = sampleAtTime(time0); + SampleTime s1 = sampleAtTime(time1); -const AudioCache::Packet -AudioCache::find(SampleTime s) const -{ - s -= packetOffset(s); + PacketMap::iterator a = m_map.end(); + PacketMap::iterator b = a; - PacketMap::const_iterator i = m_map.find(s); - - if (i != m_map.end()) - { - return i->second; - } - else - { - return 0; - } -} + vector tbd; -void -AudioCache::add(const AudioBuffer& buffer) -{ - Time t = buffer.startTime(); - SampleTime s = sampleAtTime(t); + for (PacketMap::iterator i = m_map.begin(); i != m_map.end(); ++i) + { + if (i->first > s0) + { + if (i->first < s1) + { + m_freePackets.push_back(i->second); + m_count--; + i->second = 0; + if (a == m_map.end()) + a = i; + } + else + { + b = i; + break; + } + } + } - // - // Since all samples in the cache are stored in packet size clumps we must - // make sure that this sample set starts exactly on a packet boundary, - // is the right amount of samples and channels, and is at the correct - // sampling rate. - // + if (a != b && a != m_map.end()) + { + m_map.erase(a, b); + m_cachedRangesStat.clear(); + } + + m_totalSecondsCached = + Time(m_count) * Time(m_packetSize) / m_packetRate; + } - if (packetOffset(s) != 0 || - buffer.size() != m_packetSize || - buffer.channels() != channels() || - buffer.rate() != m_packetRate) + void AudioCache::configurePacket(size_t samples, TwkAudio::Layout layout, + Time rate) { - cout << "WARNING: s = " << s - << ", packetOffset = " << packetOffset(s) - << ", m_packetSize = " << m_packetSize - << ", size = " << buffer.size() - << ", m_packetLayout = " << TwkAudio::layoutString(m_packetLayout) - << ", channels = " << buffer.numChannels() - << ", m_packetRate = " << m_packetRate - << ", rate: " << buffer.rate() - << endl; + if (m_packetSize != samples || m_packetLayout != layout + || m_packetRate != rate) + { + clear(); + m_packetSize = samples; + m_packetLayout = layout; + m_packetRate = rate; + } } - assert(packetOffset(s) == 0); - assert(buffer.size() == m_packetSize); - assert(buffer.channels() == channels()); - assert(buffer.rate() == m_packetRate); - if (!find(s)) + const AudioCache::Packet AudioCache::find(SampleTime s) const { - unlock(); - Packet p = 0; + s -= packetOffset(s); - if (m_freePackets.empty()) + PacketMap::const_iterator i = m_map.find(s); + + if (i != m_map.end()) { - int numChannels = TwkAudio::channelsCount(m_packetLayout); - p = (float*) TwkUtil::MemPool::alloc(sizeof(float) * m_packetSize * numChannels); + return i->second; } else { - p = m_freePackets.back(); - m_freePackets.pop_back(); + return 0; } - - memcpy(p, buffer.pointer(), buffer.sizeInBytes()); - lock(); - - m_map[s] = p; - m_count++; - m_totalSecondsCached = Time(m_count) * Time(m_packetSize) / m_packetRate; - m_cachedRangesStat.clear(); } - else - { - cout << "dup @ " << s << endl; - } -} - -bool -AudioCache::fillBuffer(AudioBuffer& buffer) const -{ - const SampleTime s0 = sampleAtTime(buffer.startTime()); - const SampleTime d0 = sampleAtTime(buffer.duration()); - const SampleTime e0 = s0 + d0 - 1; - int numChannels = TwkAudio::channelsCount(m_packetLayout); - - //assert(d0 == m_packetSize); - if (d0 <= m_packetSize) + void AudioCache::add(const AudioBuffer& buffer) { - const Packet p0 = find(s0); - const Packet p1 = find(e0); - - if (p0 && p0 == p1) + Time t = buffer.startTime(); + SampleTime s = sampleAtTime(t); + + // + // Since all samples in the cache are stored in packet size clumps we + // must make sure that this sample set starts exactly on a packet + // boundary, is the right amount of samples and channels, and is at the + // correct sampling rate. + // + + if (packetOffset(s) != 0 || buffer.size() != m_packetSize + || buffer.channels() != channels() || buffer.rate() != m_packetRate) { - // - // This should be the most common case: the buffer range is - // completely contained inside one packet. - // - - memcpy(buffer.pointer(), - p0 + packetOffset(s0) * numChannels, - buffer.sizeInBytes()); - - return true; + cout << "WARNING: s = " << s + << ", packetOffset = " << packetOffset(s) + << ", m_packetSize = " << m_packetSize + << ", size = " << buffer.size() << ", m_packetLayout = " + << TwkAudio::layoutString(m_packetLayout) + << ", channels = " << buffer.numChannels() + << ", m_packetRate = " << m_packetRate + << ", rate: " << buffer.rate() << endl; } - else if (p0 && p1) + assert(packetOffset(s) == 0); + assert(buffer.size() == m_packetSize); + assert(buffer.channels() == channels()); + assert(buffer.rate() == m_packetRate); + + if (!find(s)) { - // - // Straddles two packets - // + unlock(); + Packet p = 0; - const SampleTime n0 = SampleTime(m_packetSize) - packetOffset(s0); - const SampleTime n1 = packetOffset(e0) + 1; + if (m_freePackets.empty()) + { + int numChannels = TwkAudio::channelsCount(m_packetLayout); + p = (float*)TwkUtil::MemPool::alloc(sizeof(float) * m_packetSize + * numChannels); + } + else + { + p = m_freePackets.back(); + m_freePackets.pop_back(); + } - memcpy(buffer.pointer(), - p0 + packetOffset(s0) * numChannels, - n0 * sizeof(float) * numChannels); - - memcpy(buffer.pointer() + n0 * numChannels, - p1, - n1 * sizeof(float) * numChannels); + memcpy(p, buffer.pointer(), buffer.sizeInBytes()); + lock(); - return true; + m_map[s] = p; + m_count++; + m_totalSecondsCached = + Time(m_count) * Time(m_packetSize) / m_packetRate; + m_cachedRangesStat.clear(); + } + else + { + cout << "dup @ " << s << endl; } } - else + + bool AudioCache::fillBuffer(AudioBuffer& buffer) const { - const SampleTime total = buffer.size(); - const SampleTime n = total / SampleTime(m_packetSize); - const SampleTime r = total % SampleTime(m_packetSize); + const SampleTime s0 = sampleAtTime(buffer.startTime()); + const SampleTime d0 = sampleAtTime(buffer.duration()); + const SampleTime e0 = s0 + d0 - 1; + int numChannels = TwkAudio::channelsCount(m_packetLayout); + + // assert(d0 == m_packetSize); - for (size_t i = 0; i < n; i++) + if (d0 <= m_packetSize) { - size_t offset = i * m_packetSize; + const Packet p0 = find(s0); + const Packet p1 = find(e0); - AudioBuffer newBuffer(buffer.pointer() + offset * buffer.numChannels(), - buffer.channels(), - m_packetSize, - buffer.startTime() + double(i * m_packetSize) / m_packetRate, - m_packetRate); + if (p0 && p0 == p1) + { + // + // This should be the most common case: the buffer range is + // completely contained inside one packet. + // - if (!fillBuffer(newBuffer)) return false; - } + memcpy(buffer.pointer(), p0 + packetOffset(s0) * numChannels, + buffer.sizeInBytes()); - if (r) - { - SampleTime offset = n * SampleTime(m_packetSize); + return true; + } + else if (p0 && p1) + { + // + // Straddles two packets + // + + const SampleTime n0 = + SampleTime(m_packetSize) - packetOffset(s0); + const SampleTime n1 = packetOffset(e0) + 1; + + memcpy(buffer.pointer(), p0 + packetOffset(s0) * numChannels, + n0 * sizeof(float) * numChannels); - AudioBuffer newBuffer(buffer.pointer() + offset * buffer.numChannels(), - buffer.channels(), - r, - buffer.startTime() + double(n * m_packetSize) / m_packetRate, - m_packetRate); + memcpy(buffer.pointer() + n0 * numChannels, p1, + n1 * sizeof(float) * numChannels); - if (!fillBuffer(newBuffer)) return false; + return true; + } } + else + { + const SampleTime total = buffer.size(); + const SampleTime n = total / SampleTime(m_packetSize); + const SampleTime r = total % SampleTime(m_packetSize); - return true; - } + for (size_t i = 0; i < n; i++) + { + size_t offset = i * m_packetSize; - return false; -} + AudioBuffer newBuffer( + buffer.pointer() + offset * buffer.numChannels(), + buffer.channels(), m_packetSize, + buffer.startTime() + + double(i * m_packetSize) / m_packetRate, + m_packetRate); -//------------------------------------------------------------------------------ -// -void -AudioCache::computeCachedRangesStat(double frameRate, FrameRangeVector& array) -{ - lock(); + if (!fillBuffer(newBuffer)) + return false; + } - if (frameRate != m_cachedRangesStatFrameRate) - { - m_cachedRangesStatFrameRate = frameRate; - m_cachedRangesStat.clear(); + if (r) + { + SampleTime offset = n * SampleTime(m_packetSize); + + AudioBuffer newBuffer( + buffer.pointer() + offset * buffer.numChannels(), + buffer.channels(), r, + buffer.startTime() + + double(n * m_packetSize) / m_packetRate, + m_packetRate); + + if (!fillBuffer(newBuffer)) + return false; + } + + return true; + } + + return false; } - if (m_cachedRangesStat.empty()) + //------------------------------------------------------------------------------ + // + void AudioCache::computeCachedRangesStat(double frameRate, + FrameRangeVector& array) { - for (PacketMap::iterator i = m_map.begin(); - i != m_map.end(); - ++i) + lock(); + + if (frameRate != m_cachedRangesStatFrameRate) + { + m_cachedRangesStatFrameRate = frameRate; + m_cachedRangesStat.clear(); + } + + if (m_cachedRangesStat.empty()) { - const SampleTime s = i->first; - const Time t = samplesToTime(s, m_packetRate); - const Time duration = Time(m_packetSize) / m_packetRate; - const int startFrame = ROUND(t * frameRate); - const int endFrame = ROUND((t + duration ) * frameRate); + for (PacketMap::iterator i = m_map.begin(); i != m_map.end(); ++i) + { + const SampleTime s = i->first; + const Time t = samplesToTime(s, m_packetRate); + const Time duration = Time(m_packetSize) / m_packetRate; + const int startFrame = ROUND(t * frameRate); + const int endFrame = ROUND((t + duration) * frameRate); - m_cachedRangesStat.push_back(make_pair(startFrame, endFrame)); + m_cachedRangesStat.push_back(make_pair(startFrame, endFrame)); + } } - } - array = m_cachedRangesStat; + array = m_cachedRangesStat; + + unlock(); + } - unlock(); -} - -} // TwkAudio +} // namespace TwkAudio diff --git a/src/lib/audio/TwkAudio/AudioFormats.cpp b/src/lib/audio/TwkAudio/AudioFormats.cpp index 117e4d135..d89486515 100644 --- a/src/lib/audio/TwkAudio/AudioFormats.cpp +++ b/src/lib/audio/TwkAudio/AudioFormats.cpp @@ -1,9 +1,9 @@ //****************************************************************************** -// Copyright (c) 2015 Autodesk Inc. +// Copyright (c) 2015 Autodesk Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #include @@ -11,271 +11,425 @@ #include #include -namespace TwkAudio { - - -bool -ChannelsVector::hasAllChannels(const ChannelsVector &b) const +namespace TwkAudio { - const ChannelsVector &a = *this; - const size_t asize = a.size(); - const size_t bsize = b.size(); - if (asize != bsize) return false; - else + + bool ChannelsVector::hasAllChannels(const ChannelsVector& b) const { - for (int ch = 0; ch < asize; ch++) + const ChannelsVector& a = *this; + const size_t asize = a.size(); + const size_t bsize = b.size(); + if (asize != bsize) + return false; + else { - ChannelsVector::const_iterator it; - it = find (b.begin(), b.end(), a[ch]); - if (it == b.end()) + for (int ch = 0; ch < asize; ch++) { - return false; + ChannelsVector::const_iterator it; + it = find(b.begin(), b.end(), a[ch]); + if (it == b.end()) + { + return false; + } } } + return true; } - return true; -} - -bool -ChannelsVector::identical(const ChannelsVector &a, const ChannelsVector &b) const -{ - const size_t asize = a.size(); - const size_t bsize = b.size(); - if (asize != bsize) return false; - return (memcmp(&a.front(), &b.front(), asize * sizeof(Channels))?false:true); -} + bool ChannelsVector::identical(const ChannelsVector& a, + const ChannelsVector& b) const + { + const size_t asize = a.size(); + const size_t bsize = b.size(); + if (asize != bsize) + return false; + return (memcmp(&a.front(), &b.front(), asize * sizeof(Channels)) + ? false + : true); + } -std::string -formatString(Format f) -{ - std::string fstr; - switch (f) + std::string formatString(Format f) { - case Float32Format: fstr = "32 bit float"; break; - case Int32Format: fstr = "32 bit"; break; - case Int24Format: fstr = "24 bit"; break; - default: - case Int16Format: fstr = "16 bit"; break; - case Int8Format: fstr = "8 bit"; break; - case UInt32_SMPTE272M_20Format: fstr = "20 bit (NV/SMPTE272M)"; break; - case UInt32_SMPTE299M_24Format: fstr = "24 bit (NV/SMPTE299M)"; break; + std::string fstr; + switch (f) + { + case Float32Format: + fstr = "32 bit float"; + break; + case Int32Format: + fstr = "32 bit"; + break; + case Int24Format: + fstr = "24 bit"; + break; + default: + case Int16Format: + fstr = "16 bit"; + break; + case Int8Format: + fstr = "8 bit"; + break; + case UInt32_SMPTE272M_20Format: + fstr = "20 bit (NV/SMPTE272M)"; + break; + case UInt32_SMPTE299M_24Format: + fstr = "24 bit (NV/SMPTE299M)"; + break; + } + return fstr; } - return fstr; -} -size_t -formatSizeInBytes(Format f) -{ - size_t fsize; - switch (f) + size_t formatSizeInBytes(Format f) { - case Float32Format: fsize = sizeof(float); break; - case Int32Format: fsize = sizeof(int); break; - case Int24Format: fsize = sizeof(char) * 3; break; + size_t fsize; + switch (f) + { + case Float32Format: + fsize = sizeof(float); + break; + case Int32Format: + fsize = sizeof(int); + break; + case Int24Format: + fsize = sizeof(char) * 3; + break; default: - case Int16Format: fsize = sizeof(short); break; - case Int8Format: fsize = sizeof(signed char); break; - case UInt32_SMPTE272M_20Format: fsize = sizeof(unsigned int); break; - case UInt32_SMPTE299M_24Format: fsize = sizeof(unsigned int); break; + case Int16Format: + fsize = sizeof(short); + break; + case Int8Format: + fsize = sizeof(signed char); + break; + case UInt32_SMPTE272M_20Format: + fsize = sizeof(unsigned int); + break; + case UInt32_SMPTE299M_24Format: + fsize = sizeof(unsigned int); + break; + } + return fsize; } - return fsize; -} -std::string -channelString(Channels channel) -{ - std::string chstr; - switch (channel) + std::string channelString(Channels channel) { - case FrontLeft: chstr = "FL: front left"; break; - case FrontRight: chstr = "FR: front right"; break; - case FrontCenter: chstr = "FC: front center"; break; - case LowFrequency: chstr = "LF: low frequency"; break; - case BackLeft: chstr = "BL: back left"; break; - case BackRight: chstr = "BR: back right"; break; - case FrontLeftOfCenter: chstr = "FLC: front left center"; break; - case FrontRightOfCenter: chstr = "FRC: front right center"; break; - case BackCenter: chstr = "BC: back center"; break; - case SideLeft: chstr = "SL: side left"; break; - case SideRight: chstr = "SR: side right"; break; - case LeftHeight: chstr = "LH: left height"; break; - case RightHeight: chstr = "RH: right height"; break; - case Channel14: chstr = "CH14: channel 14"; break; - case Channel15: chstr = "CH15: channel 15"; break; - case Channel16: chstr = "CH16: channel 16"; break; + std::string chstr; + switch (channel) + { + case FrontLeft: + chstr = "FL: front left"; + break; + case FrontRight: + chstr = "FR: front right"; + break; + case FrontCenter: + chstr = "FC: front center"; + break; + case LowFrequency: + chstr = "LF: low frequency"; + break; + case BackLeft: + chstr = "BL: back left"; + break; + case BackRight: + chstr = "BR: back right"; + break; + case FrontLeftOfCenter: + chstr = "FLC: front left center"; + break; + case FrontRightOfCenter: + chstr = "FRC: front right center"; + break; + case BackCenter: + chstr = "BC: back center"; + break; + case SideLeft: + chstr = "SL: side left"; + break; + case SideRight: + chstr = "SR: side right"; + break; + case LeftHeight: + chstr = "LH: left height"; + break; + case RightHeight: + chstr = "RH: right height"; + break; + case Channel14: + chstr = "CH14: channel 14"; + break; + case Channel15: + chstr = "CH15: channel 15"; + break; + case Channel16: + chstr = "CH16: channel 16"; + break; case UnknownLayout: - default: chstr = "UKN: Unknown"; break; + default: + chstr = "UKN: Unknown"; + break; + } + return chstr; } - return chstr; -} -std::string -layoutString(Layout layout) -{ - std::string chstr; - switch (layout) + std::string layoutString(Layout layout) { - case Mono_1: chstr = "Mono"; break; - case Stereo_2: chstr = "Stereo"; break; - case Stereo_2_1: chstr = "2.1"; break; - case Quad_4_0: chstr = "Quadrophonic"; break; - case Surround_4_1: chstr = "4.1"; break; - case Generic_4_1: chstr = "4.1 (Swap)"; break; - case Surround_5_1: chstr = "5.1"; break; - case Back_5_1: chstr = "5.1 (Back)"; break; - case Generic_5_1: chstr = "5.1 (Swap)"; break; - case AC3_5_1: chstr = "5.1 (AC3)"; break; - case DTS_5_1: chstr = "5.1 (DTS)"; break; - case AIFF_5_1: chstr = "5.1 (AIFF)"; break; - case Generic_6_1: chstr = "6.1"; break; - case SDDS_7_1: chstr = "7.1 (SDDS)"; break; - case Surround_7_1: chstr = "7.1"; break; - case Back_7_1: chstr = "7.1 (Back)"; break; - case Surround_9_1: chstr = "9.1"; break; - case Generic_16: chstr = "16"; break; + std::string chstr; + switch (layout) + { + case Mono_1: + chstr = "Mono"; + break; + case Stereo_2: + chstr = "Stereo"; + break; + case Stereo_2_1: + chstr = "2.1"; + break; + case Quad_4_0: + chstr = "Quadrophonic"; + break; + case Surround_4_1: + chstr = "4.1"; + break; + case Generic_4_1: + chstr = "4.1 (Swap)"; + break; + case Surround_5_1: + chstr = "5.1"; + break; + case Back_5_1: + chstr = "5.1 (Back)"; + break; + case Generic_5_1: + chstr = "5.1 (Swap)"; + break; + case AC3_5_1: + chstr = "5.1 (AC3)"; + break; + case DTS_5_1: + chstr = "5.1 (DTS)"; + break; + case AIFF_5_1: + chstr = "5.1 (AIFF)"; + break; + case Generic_6_1: + chstr = "6.1"; + break; + case SDDS_7_1: + chstr = "7.1 (SDDS)"; + break; + case Surround_7_1: + chstr = "7.1"; + break; + case Back_7_1: + chstr = "7.1 (Back)"; + break; + case Surround_9_1: + chstr = "9.1"; + break; + case Generic_16: + chstr = "16"; + break; case UnknownLayout: - default: chstr = "Unknown"; break; + default: + chstr = "Unknown"; + break; + } + return chstr; } - return chstr; -} -LayoutsVector -channelLayouts(int channelCount) -{ - LayoutsVector lv; - switch (channelCount) + LayoutsVector channelLayouts(int channelCount) { - case 1: lv.push_back(Mono_1); break; - case 2: lv.push_back(Stereo_2); break; - case 3: lv.push_back(Stereo_2_1); break; - case 4: lv.push_back(Quad_4_0); break; - case 5: lv.push_back(Surround_4_1); - lv.push_back(Generic_4_1); break; - case 6: lv.push_back(Surround_5_1); - lv.push_back(Back_5_1); - lv.push_back(Generic_5_1); - lv.push_back(AC3_5_1); - lv.push_back(DTS_5_1); - lv.push_back(AIFF_5_1); break; - case 7: lv.push_back(Generic_6_1); break; - case 8: lv.push_back(Surround_7_1); - lv.push_back(Back_7_1); break; - lv.push_back(SDDS_7_1); break; - case 10: lv.push_back(Surround_9_1); break; - case 16: lv.push_back(Generic_16); break; + LayoutsVector lv; + switch (channelCount) + { + case 1: + lv.push_back(Mono_1); + break; + case 2: + lv.push_back(Stereo_2); + break; + case 3: + lv.push_back(Stereo_2_1); + break; + case 4: + lv.push_back(Quad_4_0); + break; + case 5: + lv.push_back(Surround_4_1); + lv.push_back(Generic_4_1); + break; + case 6: + lv.push_back(Surround_5_1); + lv.push_back(Back_5_1); + lv.push_back(Generic_5_1); + lv.push_back(AC3_5_1); + lv.push_back(DTS_5_1); + lv.push_back(AIFF_5_1); + break; + case 7: + lv.push_back(Generic_6_1); + break; + case 8: + lv.push_back(Surround_7_1); + lv.push_back(Back_7_1); + break; + lv.push_back(SDDS_7_1); + break; + case 10: + lv.push_back(Surround_9_1); + break; + case 16: + lv.push_back(Generic_16); + break; case 0: - default: lv.push_back(UnknownLayout); break; + default: + lv.push_back(UnknownLayout); + break; + } + return lv; } - return lv; -} -Layout -channelLayout(const ChannelsVector &cv) -{ - if (cv == layoutChannels(Stereo_2)) + Layout channelLayout(const ChannelsVector& cv) { - return Stereo_2; - } - else if (cv == layoutChannels(Surround_5_1)) - { - return Surround_5_1; - } - else if (cv == layoutChannels(Surround_7_1)) - { - return Surround_7_1; - } - else if (cv == layoutChannels(Back_5_1)) - { - return Back_5_1; - } - else if (cv == layoutChannels(Back_7_1)) - { - return Back_7_1; - } - else if (cv == layoutChannels(Generic_5_1)) - { - return Generic_5_1; - } - else if (cv == layoutChannels(AC3_5_1)) - { - return AC3_5_1; - } - else if (cv == layoutChannels(DTS_5_1)) - { - return DTS_5_1; - } - else if (cv == layoutChannels(AIFF_5_1)) - { - return AIFF_5_1; - } - else if (cv == layoutChannels(Mono_1)) - { - return Mono_1; - } - else if (cv == layoutChannels(Quad_4_0)) - { - return Quad_4_0; - } - else if (cv == layoutChannels(Surround_4_1)) - { - return Surround_4_1; - } - else if (cv == layoutChannels(Generic_4_1)) - { - return Generic_4_1; - } - else if (cv == layoutChannels(SDDS_7_1)) - { - return SDDS_7_1; - } - else if (cv == layoutChannels(Generic_16)) - { - return Generic_16; - } - + if (cv == layoutChannels(Stereo_2)) + { + return Stereo_2; + } + else if (cv == layoutChannels(Surround_5_1)) + { + return Surround_5_1; + } + else if (cv == layoutChannels(Surround_7_1)) + { + return Surround_7_1; + } + else if (cv == layoutChannels(Back_5_1)) + { + return Back_5_1; + } + else if (cv == layoutChannels(Back_7_1)) + { + return Back_7_1; + } + else if (cv == layoutChannels(Generic_5_1)) + { + return Generic_5_1; + } + else if (cv == layoutChannels(AC3_5_1)) + { + return AC3_5_1; + } + else if (cv == layoutChannels(DTS_5_1)) + { + return DTS_5_1; + } + else if (cv == layoutChannels(AIFF_5_1)) + { + return AIFF_5_1; + } + else if (cv == layoutChannels(Mono_1)) + { + return Mono_1; + } + else if (cv == layoutChannels(Quad_4_0)) + { + return Quad_4_0; + } + else if (cv == layoutChannels(Surround_4_1)) + { + return Surround_4_1; + } + else if (cv == layoutChannels(Generic_4_1)) + { + return Generic_4_1; + } + else if (cv == layoutChannels(SDDS_7_1)) + { + return SDDS_7_1; + } + else if (cv == layoutChannels(Generic_16)) + { + return Generic_16; + } - return UnknownLayout; -} + return UnknownLayout; + } -int -channelsCount (Layout layout) -{ - int count; - switch (layout) + int channelsCount(Layout layout) { - case Mono_1: count = 1; break; - case Stereo_2: count = 2; break; - case Stereo_2_1: count = 3; break; - case Quad_4_0: count = 4; break; - case Surround_4_1: count = 5; break; - case Generic_4_1: count = 5; break; - case Surround_5_1: count = 6; break; - case Back_5_1: count = 6; break; - case Generic_5_1: count = 6; break; - case AC3_5_1: count = 6; break; - case DTS_5_1: count = 6; break; - case AIFF_5_1: count = 6; break; - case Generic_6_1: count = 7; break; - case Surround_7_1: count = 8; break; - case SDDS_7_1: count = 8; break; - case Back_7_1: count = 8; break; - case Surround_9_1: count = 10; break; - case Generic_16: count = 16; break; + int count; + switch (layout) + { + case Mono_1: + count = 1; + break; + case Stereo_2: + count = 2; + break; + case Stereo_2_1: + count = 3; + break; + case Quad_4_0: + count = 4; + break; + case Surround_4_1: + count = 5; + break; + case Generic_4_1: + count = 5; + break; + case Surround_5_1: + count = 6; + break; + case Back_5_1: + count = 6; + break; + case Generic_5_1: + count = 6; + break; + case AC3_5_1: + count = 6; + break; + case DTS_5_1: + count = 6; + break; + case AIFF_5_1: + count = 6; + break; + case Generic_6_1: + count = 7; + break; + case Surround_7_1: + count = 8; + break; + case SDDS_7_1: + count = 8; + break; + case Back_7_1: + count = 8; + break; + case Surround_9_1: + count = 10; + break; + case Generic_16: + count = 16; + break; case UnknownLayout: default: - std::cout << "AUDIO: channels format unsupported: Layout=" << (int) layout << std::endl; - count = 0; break; + std::cout << "AUDIO: channels format unsupported: Layout=" + << (int)layout << std::endl; + count = 0; + break; + } + return count; } - return count; -} -ChannelsVector -layoutChannels(Layout layout) -{ - ChannelsVector chv; - switch (layout) + ChannelsVector layoutChannels(Layout layout) { + ChannelsVector chv; + switch (layout) + { case Mono_1: chv.push_back(FrontCenter); break; @@ -407,7 +561,7 @@ layoutChannels(Layout layout) chv.push_back(LeftHeight); chv.push_back(RightHeight); break; - case Generic_16: // Not sure? + case Generic_16: // Not sure? chv.push_back(FrontLeft); chv.push_back(FrontRight); chv.push_back(FrontCenter); @@ -429,100 +583,35 @@ layoutChannels(Layout layout) case UnknownLayout: default: break; - } - return chv; -} - -void -initChannelsMap(const ChannelsVector &a, const ChannelsVector &b, ChannelsMap &chmap) -{ - chmap.clear(); - - if (a == b) - { - // Just copy the input to the output. - for (int ch = 0; ch < b.size(); ch++) - { - ChannelMixState mix; - ChannelState state; - state.index = ch; - if ((a[ch] & Center) == Center) - { - state.weight = 0.5f; - mix.lefts.push_back(state); - mix.rights.push_back(state); - } - else if (b[ch] & Left) - { - state.weight = 1.0f; - mix.lefts.push_back(state); - } - else - { - state.weight = 1.0f; - mix.rights.push_back(state); - } - chmap[b[ch]] = mix; } + return chv; } - else if (a.size() == b.size()) + + void initChannelsMap(const ChannelsVector& a, const ChannelsVector& b, + ChannelsMap& chmap) { - if (b.hasAllChannels(a)) - { - // The order of channels are mismtached - for (int bch = 0; bch < b.size(); bch++) - { - for (int ach = 0; ach < a.size(); ach++) - { - if (a[ach] == b[bch]) - { - ChannelMixState mix; - ChannelState state; - state.index = ach; - if ((a[ach] & Center) == Center) - { - state.weight = 0.5f; - mix.lefts.push_back(state); - mix.rights.push_back(state); - } - else if (a[ach] & Left) - { - state.weight = 1.0f; - mix.lefts.push_back(state); - } - else - { - state.weight = 1.0f; - mix.rights.push_back(state); - } - chmap[b[bch]] = mix; - break; - } - } - } - } - else + chmap.clear(); + + if (a == b) { - // Same number of channels but not all channels - // are the same. In this case we just copy the - // input to the output. + // Just copy the input to the output. for (int ch = 0; ch < b.size(); ch++) { ChannelMixState mix; ChannelState state; state.index = ch; - if ((a[ch] & Center) == Center) + if ((a[ch] & Center) == Center) { state.weight = 0.5f; mix.lefts.push_back(state); mix.rights.push_back(state); } - else if (a[ch] & Left) + else if (b[ch] & Left) { state.weight = 1.0f; mix.lefts.push_back(state); } - else + else { state.weight = 1.0f; mix.rights.push_back(state); @@ -530,233 +619,300 @@ initChannelsMap(const ChannelsVector &a, const ChannelsVector &b, ChannelsMap &c chmap[b[ch]] = mix; } } - } - else - { - // Mix up or down channel cases. - // - // Cases: - // 1. output=stereo input=anything; use mix down weight - // 2. output=mono input=anything; use mix down weight - // 3. output=n n > 2; matched channel assignment only - - if (b.size() == 2) // Stereo Output Case + else if (a.size() == b.size()) { - float normalizeFactor = 0.0f; - for (int ach = 0; ach < a.size(); ach++) + if (b.hasAllChannels(a)) { - normalizeFactor += LEFT_CHANNEL_WEIGHT(a[ach]); - } - - for (int bch = 0; bch < b.size(); bch++) - { - ChannelMixState mix; - if ((b[bch] & Center) == Center) + // The order of channels are mismtached + for (int bch = 0; bch < b.size(); bch++) { for (int ach = 0; ach < a.size(); ach++) { - float weight = LEFT_CHANNEL_WEIGHT(a[ach]); - if (weight > 0) + if (a[ach] == b[bch]) { + ChannelMixState mix; ChannelState state; state.index = ach; - state.weight = weight / normalizeFactor; - mix.lefts.push_back(state); - } - - weight = RIGHT_CHANNEL_WEIGHT(a[ach]); - if (weight > 0) - { - ChannelState state; - state.index = ach; - state.weight = weight / normalizeFactor; - mix.rights.push_back(state); + if ((a[ach] & Center) == Center) + { + state.weight = 0.5f; + mix.lefts.push_back(state); + mix.rights.push_back(state); + } + else if (a[ach] & Left) + { + state.weight = 1.0f; + mix.lefts.push_back(state); + } + else + { + state.weight = 1.0f; + mix.rights.push_back(state); + } + chmap[b[bch]] = mix; + break; } } } - else if (b[bch] & Left) + } + else + { + // Same number of channels but not all channels + // are the same. In this case we just copy the + // input to the output. + for (int ch = 0; ch < b.size(); ch++) { - for (int ach = 0; ach < a.size(); ach++) + ChannelMixState mix; + ChannelState state; + state.index = ch; + if ((a[ch] & Center) == Center) { - float weight = LEFT_CHANNEL_WEIGHT(a[ach]); - if (weight > 0) - { - ChannelState state; - state.index = ach; - state.weight = weight / normalizeFactor; - mix.lefts.push_back(state); - } + state.weight = 0.5f; + mix.lefts.push_back(state); + mix.rights.push_back(state); } - } - else - { - for (int ach = 0; ach < a.size(); ach++) + else if (a[ch] & Left) { - float weight = RIGHT_CHANNEL_WEIGHT(a[ach]); - if (weight > 0) - { - ChannelState state; - state.index = ach; - state.weight = weight / normalizeFactor; - mix.rights.push_back(state); - } + state.weight = 1.0f; + mix.lefts.push_back(state); + } + else + { + state.weight = 1.0f; + mix.rights.push_back(state); } + chmap[b[ch]] = mix; } - - chmap[b[bch]] = mix; } } - else if (b.size() == 1) // Mono Output Case + else { - ChannelMixState mix; - - float normalizeFactor = 0.0f; - for (int ach = 0; ach < a.size(); ach++) + // Mix up or down channel cases. + // + // Cases: + // 1. output=stereo input=anything; use mix down weight + // 2. output=mono input=anything; use mix down weight + // 3. output=n n > 2; matched channel assignment only + + if (b.size() == 2) // Stereo Output Case { - normalizeFactor += LEFT_CHANNEL_WEIGHT(a[ach]) + - RIGHT_CHANNEL_WEIGHT(a[ach]); - } - - for (int ach = 0; ach < a.size(); ach++) - { - float weight = LEFT_CHANNEL_WEIGHT(a[ach]); - if (weight > 0) + float normalizeFactor = 0.0f; + for (int ach = 0; ach < a.size(); ach++) { - ChannelState state; - state.index = ach; - state.weight = weight / normalizeFactor; - mix.lefts.push_back(state); + normalizeFactor += LEFT_CHANNEL_WEIGHT(a[ach]); } - weight = RIGHT_CHANNEL_WEIGHT(a[ach]); - if (weight > 0) + for (int bch = 0; bch < b.size(); bch++) { - ChannelState state; - state.index = ach; - state.weight = weight / normalizeFactor; - mix.rights.push_back(state); + ChannelMixState mix; + if ((b[bch] & Center) == Center) + { + for (int ach = 0; ach < a.size(); ach++) + { + float weight = LEFT_CHANNEL_WEIGHT(a[ach]); + if (weight > 0) + { + ChannelState state; + state.index = ach; + state.weight = weight / normalizeFactor; + mix.lefts.push_back(state); + } + + weight = RIGHT_CHANNEL_WEIGHT(a[ach]); + if (weight > 0) + { + ChannelState state; + state.index = ach; + state.weight = weight / normalizeFactor; + mix.rights.push_back(state); + } + } + } + else if (b[bch] & Left) + { + for (int ach = 0; ach < a.size(); ach++) + { + float weight = LEFT_CHANNEL_WEIGHT(a[ach]); + if (weight > 0) + { + ChannelState state; + state.index = ach; + state.weight = weight / normalizeFactor; + mix.lefts.push_back(state); + } + } + } + else + { + for (int ach = 0; ach < a.size(); ach++) + { + float weight = RIGHT_CHANNEL_WEIGHT(a[ach]); + if (weight > 0) + { + ChannelState state; + state.index = ach; + state.weight = weight / normalizeFactor; + mix.rights.push_back(state); + } + } + } + + chmap[b[bch]] = mix; } } - chmap[b[0]] = mix; - } - else - { - // N output channel mix down or mix up case. N > 2 - - ChannelMixState mixFrontCenter; - ChannelMixState mixFrontLeft; - ChannelMixState mixFrontRight; - - for (int bch = 0; bch < b.size(); bch++) + else if (b.size() == 1) // Mono Output Case { - bool foundMatch = false; + ChannelMixState mix; + + float normalizeFactor = 0.0f; + for (int ach = 0; ach < a.size(); ach++) + { + normalizeFactor += LEFT_CHANNEL_WEIGHT(a[ach]) + + RIGHT_CHANNEL_WEIGHT(a[ach]); + } for (int ach = 0; ach < a.size(); ach++) { - if ((a[ach] == FrontLeft) && mixFrontCenter.lefts.empty() ) + float weight = LEFT_CHANNEL_WEIGHT(a[ach]); + if (weight > 0) { ChannelState state; state.index = ach; - state.weight = 1.0f; - mixFrontCenter.lefts.push_back(state); - } - else if ((a[ach] == FrontRight) && mixFrontCenter.rights.empty() ) + state.weight = weight / normalizeFactor; + mix.lefts.push_back(state); + } + + weight = RIGHT_CHANNEL_WEIGHT(a[ach]); + if (weight > 0) { ChannelState state; state.index = ach; - state.weight = 1.0f; - mixFrontCenter.rights.push_back(state); + state.weight = weight / normalizeFactor; + mix.rights.push_back(state); } - else if (a[ach] == FrontCenter) + } + chmap[b[0]] = mix; + } + else + { + // N output channel mix down or mix up case. N > 2 + + ChannelMixState mixFrontCenter; + ChannelMixState mixFrontLeft; + ChannelMixState mixFrontRight; + + for (int bch = 0; bch < b.size(); bch++) + { + bool foundMatch = false; + + for (int ach = 0; ach < a.size(); ach++) { - if (mixFrontLeft.lefts.empty() ) + if ((a[ach] == FrontLeft) + && mixFrontCenter.lefts.empty()) { ChannelState state; state.index = ach; state.weight = 1.0f; - mixFrontLeft.lefts.push_back(state); + mixFrontCenter.lefts.push_back(state); } - if (mixFrontRight.rights.empty() ) + else if ((a[ach] == FrontRight) + && mixFrontCenter.rights.empty()) { ChannelState state; state.index = ach; state.weight = 1.0f; - mixFrontRight.rights.push_back(state); + mixFrontCenter.rights.push_back(state); + } + else if (a[ach] == FrontCenter) + { + if (mixFrontLeft.lefts.empty()) + { + ChannelState state; + state.index = ach; + state.weight = 1.0f; + mixFrontLeft.lefts.push_back(state); + } + if (mixFrontRight.rights.empty()) + { + ChannelState state; + state.index = ach; + state.weight = 1.0f; + mixFrontRight.rights.push_back(state); + } + } + + if (a[ach] == b[bch]) + { + ChannelMixState mix; + ChannelState state; + state.index = ach; + if ((a[ach] & Center) == Center) + { + state.weight = 0.5f; + mix.lefts.push_back(state); + mix.rights.push_back(state); + } + else if (a[ach] & Left) + { + state.weight = 1.0f; + mix.lefts.push_back(state); + } + else + { + state.weight = 1.0f; + mix.rights.push_back(state); + } + chmap[b[bch]] = mix; + foundMatch = true; + break; } } - if (a[ach] == b[bch]) + if (!foundMatch) { - ChannelMixState mix; - ChannelState state; - state.index = ach; - if ((a[ach] & Center) == Center) + if ((b[bch] == FrontCenter) + && (mixFrontCenter.lefts.size() == 1) + && (mixFrontCenter.rights.size() == 1)) { - state.weight = 0.5f; - mix.lefts.push_back(state); - mix.rights.push_back(state); + // + // We define an unmatched output FrontCenter channel + // as a combination of the input FrontLeft channel + // and FrontRight iff there wasnt an input + // FrontCenter channel. + // + chmap[FrontCenter] = mixFrontCenter; + continue; } - else if (a[ach] & Left) + + if (b[bch] == FrontLeft) { - state.weight = 1.0f; - mix.lefts.push_back(state); + // + // We define an unmatched output FrontLeft channel + // as the left portion of an input FrontCenter + // channel iff there wasnt an input FrontLeft + // channel. + // + chmap[FrontLeft] = mixFrontLeft; + continue; } - else + + if (b[bch] == FrontRight) { - state.weight = 1.0f; - mix.rights.push_back(state); + // + // We define an unmatched output FrontRight channel + // as the right portion of an input FrontCenter + // iff there wasnt an input FrontRight channel. + // + chmap[FrontRight] = mixFrontRight; + continue; } - chmap[b[bch]] = mix; - foundMatch = true; - break; - } - } - if (!foundMatch) - { - if ( (b[bch] == FrontCenter) && - (mixFrontCenter.lefts.size() == 1) && - (mixFrontCenter.rights.size() == 1) ) - { - // - // We define an unmatched output FrontCenter channel - // as a combination of the input FrontLeft channel - // and FrontRight iff there wasnt an input FrontCenter channel. - // - chmap[FrontCenter] = mixFrontCenter; - continue; - } - - if (b[bch] == FrontLeft) - { - // - // We define an unmatched output FrontLeft channel - // as the left portion of an input FrontCenter channel - // iff there wasnt an input FrontLeft channel. - // - chmap[FrontLeft] = mixFrontLeft; - continue; - } - - if (b[bch] == FrontRight) - { - // - // We define an unmatched output FrontRight channel - // as the right portion of an input FrontCenter - // iff there wasnt an input FrontRight channel. - // - chmap[FrontRight] = mixFrontRight; - continue; + ChannelMixState mixEmpty; + chmap[b[bch]] = mixEmpty; } - - ChannelMixState mixEmpty; - chmap[b[bch]] = mixEmpty; } } } } -} - -} // TwkAudio - +} // namespace TwkAudio diff --git a/src/lib/audio/TwkAudio/Filters.cpp b/src/lib/audio/TwkAudio/Filters.cpp index 5dfb80939..dc6e7a8e1 100644 --- a/src/lib/audio/TwkAudio/Filters.cpp +++ b/src/lib/audio/TwkAudio/Filters.cpp @@ -1,93 +1,90 @@ // -// Copyright (c) 2008 Tweak Software. +// Copyright (c) 2008 Tweak Software. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// // #include #include -namespace TwkAudio { -using namespace std; - -void -lowPassFilter(AudioBuffer& inBuffer, - AudioBuffer& prevBuffer, - AudioBuffer& outBuffer, - float freq, - bool isBackwards) +namespace TwkAudio { - // - // Simple low-pass, seeded with outPrevious's last sample - // + using namespace std; - // f = 1 / (2 * pi * R * C) --- where R = resistance, C = capacitance - // alpha = dt / (R * C + dt) - // dt = 1 / rate - // - // so: - // - // alpha = dt / ( 1 / (f * 2 * pi) + dt ) - // - - assert(inBuffer.rate() == outBuffer.rate() && - inBuffer.rate() == prevBuffer.rate()); + void lowPassFilter(AudioBuffer& inBuffer, AudioBuffer& prevBuffer, + AudioBuffer& outBuffer, float freq, bool isBackwards) + { + // + // Simple low-pass, seeded with outPrevious's last sample + // - const double dt = 1.0 / inBuffer.rate(); - const float alpha = float(dt / ( 1.0 / (double(freq) * 2 * 3.14159265359) + dt)); + // f = 1 / (2 * pi * R * C) --- where R = resistance, C = capacitance + // alpha = dt / (R * C + dt) + // dt = 1 / rate + // + // so: + // + // alpha = dt / ( 1 / (f * 2 * pi) + dt ) + // - // Reverse the buffers on backwards playback - // otherwise the buffer segments will be discontinuous - // at the boundaries. - if (isBackwards) - { - inBuffer.reverse(); - prevBuffer.reverse(); - } + assert(inBuffer.rate() == outBuffer.rate() + && inBuffer.rate() == prevBuffer.rate()); - AudioBuffer::BufferPointer out = outBuffer.pointer(); - const AudioBuffer::BufferPointer in = inBuffer.pointer(); - const AudioBuffer::BufferPointer prev = prevBuffer.pointer(); - const size_t nc = outBuffer.numChannels(); - const size_t n = outBuffer.size(); - const size_t pend = (prevBuffer.size() - 1) * nc; + const double dt = 1.0 / inBuffer.rate(); + const float alpha = + float(dt / (1.0 / (double(freq) * 2 * 3.14159265359) + dt)); - // - // Seed the first value - // + // Reverse the buffers on backwards playback + // otherwise the buffer segments will be discontinuous + // at the boundaries. + if (isBackwards) + { + inBuffer.reverse(); + prevBuffer.reverse(); + } - for (size_t c = 0; c < nc; c++) - { - const float p = prev[pend + c]; - out[c] = p + alpha * (in[c] - p); - } + AudioBuffer::BufferPointer out = outBuffer.pointer(); + const AudioBuffer::BufferPointer in = inBuffer.pointer(); + const AudioBuffer::BufferPointer prev = prevBuffer.pointer(); + const size_t nc = outBuffer.numChannels(); + const size_t n = outBuffer.size(); + const size_t pend = (prevBuffer.size() - 1) * nc; - // - // Do the rest - // + // + // Seed the first value + // - for (size_t i = 1; i < n; i++) - { for (size_t c = 0; c < nc; c++) { - const size_t q = i * nc + c; - const float p = out[q-nc]; - - out[q] = p + alpha * (in[q] - p); + const float p = prev[pend + c]; + out[c] = p + alpha * (in[c] - p); } - } - if (isBackwards) - { - inBuffer.reverse(); - prevBuffer.reverse(); - if (in != out) + // + // Do the rest + // + + for (size_t i = 1; i < n; i++) { - outBuffer.reverse(); + for (size_t c = 0; c < nc; c++) + { + const size_t q = i * nc + c; + const float p = out[q - nc]; + + out[q] = p + alpha * (in[q] - p); + } } - } -} + if (isBackwards) + { + inBuffer.reverse(); + prevBuffer.reverse(); + if (in != out) + { + outBuffer.reverse(); + } + } + } -} // TwkAudio +} // namespace TwkAudio diff --git a/src/lib/audio/TwkAudio/Interlace.cpp b/src/lib/audio/TwkAudio/Interlace.cpp index c94c807ce..c6225e596 100644 --- a/src/lib/audio/TwkAudio/Interlace.cpp +++ b/src/lib/audio/TwkAudio/Interlace.cpp @@ -1,9 +1,9 @@ //****************************************************************************** -// Copyright (c) 2007 Tweak Inc. +// Copyright (c) 2007 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #include @@ -11,157 +11,147 @@ #include #include -namespace TwkAudio { -using namespace std; - - -void -deinterlace(const float* inbuffer, - size_t inSamples, - int nchannels, - vector& outbuffers) +namespace TwkAudio { - outbuffers.resize(nchannels); + using namespace std; - for (unsigned int i=0; i < nchannels; i++) + void deinterlace(const float* inbuffer, size_t inSamples, int nchannels, + vector& outbuffers) { - outbuffers[i].resize(inSamples); - } + outbuffers.resize(nchannels); - // - // De-interlace - // + for (unsigned int i = 0; i < nchannels; i++) + { + outbuffers[i].resize(inSamples); + } - const float* inp = inbuffer; - const float* endp = inp + (inSamples * nchannels); + // + // De-interlace + // - for (unsigned int c = 0; c < nchannels; c++) - { - float* o = &(outbuffers[c].front()); + const float* inp = inbuffer; + const float* endp = inp + (inSamples * nchannels); - for (const float* p = inp + c; p < endp; p += nchannels, o++) + for (unsigned int c = 0; c < nchannels; c++) { - *o = *p; + float* o = &(outbuffers[c].front()); + + for (const float* p = inp + c; p < endp; p += nchannels, o++) + { + *o = *p; + } } } -} - -void -deinterlace(const SampleVector& inbuffer, - int nchannels, - vector& outbuffers) -{ - outbuffers.resize(nchannels); - for (unsigned int i=0; i < outbuffers.size(); i++) + void deinterlace(const SampleVector& inbuffer, int nchannels, + vector& outbuffers) { - outbuffers[i].resize(inbuffer.size() / nchannels); - } + outbuffers.resize(nchannels); - // - // De-interlace - // + for (unsigned int i = 0; i < outbuffers.size(); i++) + { + outbuffers[i].resize(inbuffer.size() / nchannels); + } - const float* inp = &(inbuffer.front()); - const float* endp = inp + inbuffer.size(); + // + // De-interlace + // - for (unsigned int c = 0; c < nchannels; c++) - { - float* o = &(outbuffers[c].front()); + const float* inp = &(inbuffer.front()); + const float* endp = inp + inbuffer.size(); - for (const float* p = inp + c; p < endp; p += nchannels, o++) + for (unsigned int c = 0; c < nchannels; c++) { - *o = *p; + float* o = &(outbuffers[c].front()); + + for (const float* p = inp + c; p < endp; p += nchannels, o++) + { + *o = *p; + } } } -} - -void -interlace(const vector& inbuffers, SampleVector& outbuffer) -{ - const unsigned int nc = inbuffers.size(); - outbuffer.resize(inbuffers.front().size() * inbuffers.size()); - // - // Have a special case for the most used forms - // - - if (inbuffers.size() == 1) + void interlace(const vector& inbuffers, + SampleVector& outbuffer) { - memcpy(&outbuffer.front(), - &inbuffers[0].front(), - inbuffers[0].size() * sizeof(float)); - } - else if (inbuffers.size() == 2) - { - const float* p0 = &inbuffers[0].front(); - const float* p1 = &inbuffers[1].front(); - float* o = &outbuffer.front(); + const unsigned int nc = inbuffers.size(); + outbuffer.resize(inbuffers.front().size() * inbuffers.size()); + + // + // Have a special case for the most used forms + // - for (const float* e = o + outbuffer.size(); o < e; o++, p0++, p1++) + if (inbuffers.size() == 1) { - *o = *p0; o++; - *o = *p1; + memcpy(&outbuffer.front(), &inbuffers[0].front(), + inbuffers[0].size() * sizeof(float)); } - } - else - { - for (unsigned int i = 0; i < outbuffer.size(); i+= nc) + else if (inbuffers.size() == 2) { - for (unsigned int q = 0; q < nc; q++) + const float* p0 = &inbuffers[0].front(); + const float* p1 = &inbuffers[1].front(); + float* o = &outbuffer.front(); + + for (const float* e = o + outbuffer.size(); o < e; o++, p0++, p1++) { - outbuffer[i + q] = inbuffers[q][i/nc]; + *o = *p0; + o++; + *o = *p1; + } + } + else + { + for (unsigned int i = 0; i < outbuffer.size(); i += nc) + { + for (unsigned int q = 0; q < nc; q++) + { + outbuffer[i + q] = inbuffers[q][i / nc]; + } } } } -} -void -interlace(const vector& inbuffers, float* outbuffer, - size_t start, size_t num) -{ - const unsigned int nc = inbuffers.size(); - const size_t n = num > 0 ? num : inbuffers.front().size(); + void interlace(const vector& inbuffers, float* outbuffer, + size_t start, size_t num) + { + const unsigned int nc = inbuffers.size(); + const size_t n = num > 0 ? num : inbuffers.front().size(); - // - // Have a special case for the most used forms - // + // + // Have a special case for the most used forms + // - if (inbuffers.size() == 1) - { - memcpy(outbuffer + start, - &inbuffers[0].front(), - n * sizeof(float)); - } - else if (inbuffers.size() == 2) - { - assert(inbuffers[0].size() == inbuffers[1].size()); - assert(inbuffers[0].size() >= n); - assert(inbuffers[0].size() > 0); - assert(inbuffers[1].size() > 0); - const float* p0 = &(inbuffers[0].front()); - const float* p1 = &(inbuffers[1].front()); - float* o = outbuffer + (start * 2); - - for (const float* e = o + (n*2); - o < e; - o++, p0++, p1++) + if (inbuffers.size() == 1) { - *o = *p0; o++; - *o = *p1; + memcpy(outbuffer + start, &inbuffers[0].front(), n * sizeof(float)); } - } - else - { - for (unsigned int i = 0; i < (n * nc); i+= nc) + else if (inbuffers.size() == 2) { - for (unsigned int q = 0; q < nc; q++) + assert(inbuffers[0].size() == inbuffers[1].size()); + assert(inbuffers[0].size() >= n); + assert(inbuffers[0].size() > 0); + assert(inbuffers[1].size() > 0); + const float* p0 = &(inbuffers[0].front()); + const float* p1 = &(inbuffers[1].front()); + float* o = outbuffer + (start * 2); + + for (const float* e = o + (n * 2); o < e; o++, p0++, p1++) { - outbuffer[i + q + start * nc] = inbuffers[q][i/nc]; + *o = *p0; + o++; + *o = *p1; + } + } + else + { + for (unsigned int i = 0; i < (n * nc); i += nc) + { + for (unsigned int q = 0; q < nc; q++) + { + outbuffer[i + q + start * nc] = inbuffers[q][i / nc]; + } } } } -} - -} // TwkAudio +} // namespace TwkAudio diff --git a/src/lib/audio/TwkAudio/Mix.cpp b/src/lib/audio/TwkAudio/Mix.cpp index 4ca1761f6..90ec25fc0 100644 --- a/src/lib/audio/TwkAudio/Mix.cpp +++ b/src/lib/audio/TwkAudio/Mix.cpp @@ -1,9 +1,9 @@ //****************************************************************************** -// Copyright (c) 2008 Tweak Inc. +// Copyright (c) 2008 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #include @@ -12,119 +12,123 @@ #include #include -namespace TwkAudio { -using namespace TwkMath; -using namespace std; - -void -mixChannels(const AudioBuffer& in, - AudioBuffer& out, - const float lVolume, - const float rVolume, - const bool compose) +namespace TwkAudio { - const size_t inSize = in.size(); - const size_t outSize = out.size(); + using namespace TwkMath; + using namespace std; - if (inSize != outSize) + void mixChannels(const AudioBuffer& in, AudioBuffer& out, + const float lVolume, const float rVolume, + const bool compose) { - cout << "WARNING: audio mix: inSize = " << inSize - << ", outSize = " << outSize << endl; - return; - } + const size_t inSize = in.size(); + const size_t outSize = out.size(); + + if (inSize != outSize) + { + cout << "WARNING: audio mix: inSize = " << inSize + << ", outSize = " << outSize << endl; + return; + } - // XXX Uncomment to skip mix - // cerr << "MIX inChans: " << in.numChannels() << " inSize: " << in.size() << endl; - // memcpy(out.pointer(), in.pointer(), in.numChannels() * in.size() * sizeof(float)); - // return; + // XXX Uncomment to skip mix + // cerr << "MIX inChans: " << in.numChannels() << " inSize: " << + // in.size() << endl; memcpy(out.pointer(), in.pointer(), + // in.numChannels() * in.size() * sizeof(float)); return; - const float* ip = in.pointer(); - float* op = out.pointer(); + const float* ip = in.pointer(); + float* op = out.pointer(); - if ((in.channels() == out.channels()) && (lVolume == rVolume)) - { - size_t sampleCount = inSize * in.numChannels(); - if (compose) + if ((in.channels() == out.channels()) && (lVolume == rVolume)) { - for (size_t s = 0; s < sampleCount; s++) + size_t sampleCount = inSize * in.numChannels(); + if (compose) { - (*op++) += (*ip++) * lVolume; + for (size_t s = 0; s < sampleCount; s++) + { + (*op++) += (*ip++) * lVolume; + } } - } - else - { - for (size_t s = 0; s < sampleCount; s++) + else { - (*op++) = (*ip++) * lVolume; + for (size_t s = 0; s < sampleCount; s++) + { + (*op++) = (*ip++) * lVolume; + } } } - } - else - { - ChannelsMap chmap; - initChannelsMap(in.channels(), out.channels(), chmap); - size_t sampleCount = inSize; - if (compose) + else { - for (size_t s = 0; s < sampleCount; s++) + ChannelsMap chmap; + initChannelsMap(in.channels(), out.channels(), chmap); + size_t sampleCount = inSize; + if (compose) { - for (int och = 0; och < out.channels().size(); och++) + for (size_t s = 0; s < sampleCount; s++) { - const ChannelMixState &cmixState = chmap[out.channels()[och]]; - - float lMix = 0.0f; - const std::vector &leftChs = cmixState.lefts; - for (int n = 0; n < leftChs.size(); ++n) + for (int och = 0; och < out.channels().size(); och++) { - const ChannelState &chState = leftChs[n]; - lMix += chState.weight * ip[chState.index]; + const ChannelMixState& cmixState = + chmap[out.channels()[och]]; + + float lMix = 0.0f; + const std::vector& leftChs = + cmixState.lefts; + for (int n = 0; n < leftChs.size(); ++n) + { + const ChannelState& chState = leftChs[n]; + lMix += chState.weight * ip[chState.index]; + } + + float rMix = 0.0f; + const std::vector& rightCh = + cmixState.rights; + for (int n = 0; n < rightCh.size(); ++n) + { + const ChannelState& chState = rightCh[n]; + rMix += chState.weight * ip[chState.index]; + } + + (*op++) += lMix * lVolume + rMix * rVolume; } - float rMix = 0.0f; - const std::vector &rightCh = cmixState.rights; - for (int n=0; n < rightCh.size(); ++n) - { - const ChannelState &chState = rightCh[n]; - rMix += chState.weight * ip[chState.index]; - } - - (*op++) += lMix * lVolume + rMix * rVolume; + ip += in.numChannels(); } - - ip += in.numChannels(); } - } - else - { - for (size_t s = 0; s < sampleCount; s++) + else { - for (int och = 0; och < out.channels().size(); och++) + for (size_t s = 0; s < sampleCount; s++) { - const ChannelMixState &cmixState = chmap[out.channels()[och]]; - - float lMix = 0.0f; - const std::vector &leftChs = cmixState.lefts; - for (int n = 0; n < leftChs.size(); ++n) + for (int och = 0; och < out.channels().size(); och++) { - const ChannelState &chState = leftChs[n]; - lMix += chState.weight * ip[chState.index]; + const ChannelMixState& cmixState = + chmap[out.channels()[och]]; + + float lMix = 0.0f; + const std::vector& leftChs = + cmixState.lefts; + for (int n = 0; n < leftChs.size(); ++n) + { + const ChannelState& chState = leftChs[n]; + lMix += chState.weight * ip[chState.index]; + } + + float rMix = 0.0f; + const std::vector& rightCh = + cmixState.rights; + for (int n = 0; n < rightCh.size(); ++n) + { + const ChannelState& chState = rightCh[n]; + rMix += chState.weight * ip[chState.index]; + } + + (*op++) = lMix * lVolume + rMix * rVolume; } - float rMix = 0.0f; - const std::vector &rightCh = cmixState.rights; - for (int n=0; n < rightCh.size(); ++n) - { - const ChannelState &chState = rightCh[n]; - rMix += chState.weight * ip[chState.index]; - } - - (*op++) = lMix * lVolume + rMix * rVolume; + ip += in.numChannels(); } - - ip += in.numChannels(); } } } -} -} // TwkAudio +} // namespace TwkAudio diff --git a/src/lib/audio/TwkAudio/Resampler.cpp b/src/lib/audio/TwkAudio/Resampler.cpp index 9c6d215c1..61e4f03ec 100644 --- a/src/lib/audio/TwkAudio/Resampler.cpp +++ b/src/lib/audio/TwkAudio/Resampler.cpp @@ -1,9 +1,9 @@ //****************************************************************************** -// Copyright (c) 2007 Tweak Inc. +// Copyright (c) 2007 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #include #include @@ -14,192 +14,167 @@ #include #include -namespace TwkAudio { -using namespace std; - -Resampler::Resampler(double factor, size_t blocksize) - : m_factor(factor), - m_handle(0), - m_filterwidth(0), - m_blocksize(blocksize) -{ - open(); -} - -Resampler::~Resampler() -{ - close(); -} - -size_t -Resampler::process(const float* in, - size_t inSize, - float* out, - size_t outSize, - bool endFlag, - bool enableClamp) +namespace TwkAudio { - int inUsed = 0; - int inUsedTotal = 0; - int outUsedTotal = 0; + using namespace std; - for (int i=0; true; i++) + Resampler::Resampler(double factor, size_t blocksize) + : m_factor(factor) + , m_handle(0) + , m_filterwidth(0) + , m_blocksize(blocksize) { - size_t left = inSize - inUsedTotal; - int bsize = std::min(left, m_blocksize); + open(); + } - size_t outUsed = resample_process(m_handle, - m_factor, - (float*)(in + inUsedTotal), - bsize, - endFlag && left < m_blocksize, - &inUsed, - out + outUsedTotal, - outSize - outUsedTotal); + Resampler::~Resampler() { close(); } - inUsedTotal += inUsed; + size_t Resampler::process(const float* in, size_t inSize, float* out, + size_t outSize, bool endFlag, bool enableClamp) + { + int inUsed = 0; + int inUsedTotal = 0; + int outUsedTotal = 0; - if (outUsed > 0) + for (int i = 0; true; i++) { - outUsedTotal += outUsed; + size_t left = inSize - inUsedTotal; + int bsize = std::min(left, m_blocksize); + + size_t outUsed = + resample_process(m_handle, m_factor, (float*)(in + inUsedTotal), + bsize, endFlag && left < m_blocksize, &inUsed, + out + outUsedTotal, outSize - outUsedTotal); + + inUsedTotal += inUsed; + + if (outUsed > 0) + { + outUsedTotal += outUsed; + } + else if (outUsed <= 0 || (outUsed == 0 && inUsedTotal >= inSize)) + { + break; + } } - else if (outUsed <= 0 || (outUsed == 0 && inUsedTotal >= inSize)) + + if (enableClamp) { - break; + float* data = out; + for (int i = 0; i < outUsedTotal; ++i, data++) + { + if ((*data) > 1.0f) + (*data) = 1.0f; + else if ((*data) < -1.0f) + (*data) = -1.0f; + } } + + return outUsedTotal; } - if (enableClamp) + void Resampler::process(const SampleVector& in, SampleVector& out, + bool endFlag, bool enableClamp) { - float* data = out; - for (int i=0; i < outUsedTotal; ++i, data++) - { - if ((*data) > 1.0f) (*data) = 1.0f; - else if ((*data) < -1.0f) (*data) = -1.0f; - } + size_t n = size_t(double(in.size()) * m_factor); + out.resize(n); + process(&in.front(), in.size(), &out.front(), out.size(), endFlag, + enableClamp); } - return outUsedTotal; -} - -void -Resampler::process(const SampleVector& in, SampleVector& out, bool endFlag, bool enableClamp) -{ - size_t n = size_t(double(in.size()) * m_factor); - out.resize(n); - process(&in.front(), in.size(), &out.front(), out.size(), endFlag, enableClamp); -} - + void Resampler::reset() { resample_reset(m_handle); } -void -Resampler::reset() -{ - resample_reset(m_handle); -} - -void -Resampler::open() -{ - m_handle = resample_open(1, m_factor, m_factor); - m_filterwidth = resample_get_filter_width(m_handle); -} - -void -Resampler::close() -{ - if (m_handle) + void Resampler::open() { - resample_close(m_handle); + m_handle = resample_open(1, m_factor, m_factor); + m_filterwidth = resample_get_filter_width(m_handle); } - m_handle = 0; - m_filterwidth = 0; -} - -//---------------------------------------------------------------------- - -MultiResampler::MultiResampler(int numChannels, - double factor, - size_t blocksize) - : m_inbuffers(numChannels), - m_outbuffers(numChannels) -{ - for (int ch = 0; ch < numChannels; ch++) + void Resampler::close() { - m_resamplers.push_back(new Resampler(factor, blocksize)); + if (m_handle) + { + resample_close(m_handle); + } + + m_handle = 0; + m_filterwidth = 0; } -} -MultiResampler::~MultiResampler() -{ - for (int ch = 0; ch < m_resamplers.size(); ch++) + //---------------------------------------------------------------------- + + MultiResampler::MultiResampler(int numChannels, double factor, + size_t blocksize) + : m_inbuffers(numChannels) + , m_outbuffers(numChannels) { - delete m_resamplers[ch]; - m_resamplers[ch] = 0; + for (int ch = 0; ch < numChannels; ch++) + { + m_resamplers.push_back(new Resampler(factor, blocksize)); + } } - m_resamplers.clear(); -} -void -MultiResampler::close() -{ - for (int ch = 0; ch < m_resamplers.size(); ch++) + MultiResampler::~MultiResampler() { - m_resamplers[ch]->close(); + for (int ch = 0; ch < m_resamplers.size(); ch++) + { + delete m_resamplers[ch]; + m_resamplers[ch] = 0; + } + m_resamplers.clear(); } -} - -size_t -MultiResampler::process(const float* in, - size_t inSize, - float* out, - size_t outSize, - bool endFlag, - bool enableClamp) -{ - deinterlace(in, inSize, m_resamplers.size(), m_inbuffers); - - size_t n = size_t(double(inSize) * factor() + 0.49); - size_t bsize = max(n, m_outbuffers.front().size()); - if (bsize != m_outbuffers.front().size()) + void MultiResampler::close() { for (int ch = 0; ch < m_resamplers.size(); ch++) { - m_outbuffers[ch].resize(bsize); + m_resamplers[ch]->close(); } } - size_t samples = 0; - for (int ch = 0; ch < m_resamplers.size(); ch++) + size_t MultiResampler::process(const float* in, size_t inSize, float* out, + size_t outSize, bool endFlag, + bool enableClamp) { - size_t nsamps = m_resamplers[ch]->process(&(m_inbuffers[ch].front()), - inSize, - &(m_outbuffers[ch].front()), - outSize, - endFlag, - enableClamp); -#ifndef NDEBUG - if (samples != 0 && samples != nsamps) + deinterlace(in, inSize, m_resamplers.size(), m_inbuffers); + + size_t n = size_t(double(inSize) * factor() + 0.49); + size_t bsize = max(n, m_outbuffers.front().size()); + + if (bsize != m_outbuffers.front().size()) { - cout << "WARNING: resampler samples missmatch" << endl; + for (int ch = 0; ch < m_resamplers.size(); ch++) + { + m_outbuffers[ch].resize(bsize); + } } + + size_t samples = 0; + for (int ch = 0; ch < m_resamplers.size(); ch++) + { + size_t nsamps = m_resamplers[ch]->process( + &(m_inbuffers[ch].front()), inSize, &(m_outbuffers[ch].front()), + outSize, endFlag, enableClamp); +#ifndef NDEBUG + if (samples != 0 && samples != nsamps) + { + cout << "WARNING: resampler samples missmatch" << endl; + } #endif - samples = nsamps; - } - - interlace(m_outbuffers, out, 0, min(n, outSize)); + samples = nsamps; + } - return samples; -} + interlace(m_outbuffers, out, 0, min(n, outSize)); -void -MultiResampler::reset() -{ - for (int ch = 0; ch < m_resamplers.size(); ch++) + return samples; + } + + void MultiResampler::reset() { - m_resamplers[ch]->reset(); + for (int ch = 0; ch < m_resamplers.size(); ch++) + { + m_resamplers[ch]->reset(); + } } -} -} // TwkAudio +} // namespace TwkAudio diff --git a/src/lib/audio/TwkAudio/ScaleTime.cpp b/src/lib/audio/TwkAudio/ScaleTime.cpp index 7f4b87885..ca5bbd4bc 100644 --- a/src/lib/audio/TwkAudio/ScaleTime.cpp +++ b/src/lib/audio/TwkAudio/ScaleTime.cpp @@ -1,63 +1,60 @@ // -// Copyright (c) 2008 Tweak Software. +// Copyright (c) 2008 Tweak Software. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// // #include #include #include -namespace TwkAudio { -using namespace std; -using namespace TwkMath; - - -void scaleTime(const AudioBuffer& inbuffer, AudioBuffer& outbuffer) +namespace TwkAudio { - const size_t insize = inbuffer.size(); - const size_t outsize = outbuffer.size(); - const size_t ch = outbuffer.numChannels(); - - if (insize == outsize) - { - memcpy(outbuffer.pointer(), - inbuffer.pointer(), - inbuffer.sizeInBytes()); - } - else if (insize > outsize) - { - if (ch == 1) - { + using namespace std; + using namespace TwkMath; - size_t index = 0; - double s = outbuffer.size(); - float* o = outbuffer.pointer(); + void scaleTime(const AudioBuffer& inbuffer, AudioBuffer& outbuffer) + { + const size_t insize = inbuffer.size(); + const size_t outsize = outbuffer.size(); + const size_t ch = outbuffer.numChannels(); - for (const float* i = inbuffer.pointer(), *e = i + outbuffer.size(); - i < e; - i++, index++) + if (insize == outsize) + { + memcpy(outbuffer.pointer(), inbuffer.pointer(), + inbuffer.sizeInBytes()); + } + else if (insize > outsize) + { + if (ch == 1) { - *o = *i * smoothstep(1.0 - double(index) / s); - } - - index = 0; - o = outbuffer.pointer(); - for (const float* i = inbuffer.pointer() + (insize - outsize), - *e = i + outbuffer.size(); - i < e; - i++, index++) + size_t index = 0; + double s = outbuffer.size(); + float* o = outbuffer.pointer(); + + for (const float *i = inbuffer.pointer(), + *e = i + outbuffer.size(); + i < e; i++, index++) + { + *o = *i * smoothstep(1.0 - double(index) / s); + } + + index = 0; + o = outbuffer.pointer(); + + for (const float *i = inbuffer.pointer() + (insize - outsize), + *e = i + outbuffer.size(); + i < e; i++, index++) + { + *o = *i * smoothstep(double(index) / s); + } + } + else if (ch == 2) { - *o = *i * smoothstep(double(index) / s); } } - else if (ch == 2) - { - } } -} - -} // TwkAudio +} // namespace TwkAudio diff --git a/src/lib/audio/TwkAudio/TwkAudio/Audio.h b/src/lib/audio/TwkAudio/TwkAudio/Audio.h index fa9d5c69a..a1e192e09 100644 --- a/src/lib/audio/TwkAudio/TwkAudio/Audio.h +++ b/src/lib/audio/TwkAudio/TwkAudio/Audio.h @@ -1,9 +1,9 @@ //****************************************************************************** -// Copyright (c) 2007 Tweak Inc. +// Copyright (c) 2007 Tweak Inc. // All rights reserved. -// +// // SPDX-License-Identifier: Apache-2.0 -// +// //****************************************************************************** #ifndef __TwkAudio__Audio__h__ #define __TwkAudio__Audio__h__ @@ -21,352 +21,365 @@ #endif #endif - #define TWEAK_AUDIO_DEFAULT_SAMPLE_RATE 48000 -//#define ENABLE_AUDIOBUFFER_CHECK +// #define ENABLE_AUDIOBUFFER_CHECK #ifdef ENABLE_AUDIOBUFFER_CHECK -#define AUDIOBUFFER_CHECK(_audioBufferInst, _label) { (_audioBufferInst).checkBuffer(_label); } +#define AUDIOBUFFER_CHECK(_audioBufferInst, _label) \ + { \ + (_audioBufferInst).checkBuffer(_label); \ + } #else #define AUDIOBUFFER_CHECK(_audioBufferInst, _label) #endif -namespace TwkAudio { +namespace TwkAudio +{ -typedef double Time; -static const Time Always = std::numeric_limits