Пример #1
0
StString StProcess::getStCoreFolder() {
    StString aCoreEnvValue = getEnv(ST_ENV_NAME_STCORE_PATH);
#ifdef _WIN32
    if(aCoreEnvValue.isEmpty()) {
        // read env. value directly from registry (before first log off / log in)
        const StString aRegisterPath = "Environment";
        loadStringFromRegister(aRegisterPath, ST_ENV_NAME_STCORE_PATH, aCoreEnvValue);
    }
#endif

    // repair filesystem splitter
    if(!aCoreEnvValue.isEmpty() && !aCoreEnvValue.isEndsWith(SYS_FS_SPLITTER)) {
        aCoreEnvValue += StString(SYS_FS_SPLITTER);
    }

    if(isValidStCorePath(aCoreEnvValue)) {
        // environment variable is correctly set
        return aCoreEnvValue;
    }

    const StString aProcessPath = getProcessFolder();
    if(isValidStCorePath(aProcessPath)) {
        return aProcessPath;
    }
    return StString();
}
Пример #2
0
int StActiveXCtrl::OnCreate(LPCREATESTRUCT theCreateStruct) {
    myBackBrush.CreateSolidBrush(RGB(0, 0, 0));
    if(COleControl::OnCreate(theCreateStruct) == -1) {
        return -1;
    }

    const StString ST_ASTERIX = '*';
    StMIME aMime(StString(myMimeType), ST_ASTERIX, ST_ASTERIX);
    myOpenInfo.setMIME(aMime);

    StArgumentsMap aDrawerArgs;
    const StString ST_SETTING_SRCFORMAT    = stCString("srcFormat");
    const StString ST_SETTING_COMPRESS     = stCString("toCompress");
    const StString ST_SETTING_ESCAPENOQUIT = stCString("escNoQuit");
    const StMIME ST_MIME_X_JPS("image/x-jps", ST_ASTERIX, ST_ASTERIX);
    const StMIME ST_MIME_JPS  ("image/jps",   ST_ASTERIX, ST_ASTERIX);
    const StMIME ST_MIME_X_PNS("image/x-pns", ST_ASTERIX, ST_ASTERIX);
    const StMIME ST_MIME_PNS  ("image/pns",   ST_ASTERIX, ST_ASTERIX);
    StArgument anArgSrcFormat = aDrawerArgs[ST_SETTING_SRCFORMAT];
    if(!anArgSrcFormat.isValid()) {
        anArgSrcFormat.setKey(ST_SETTING_SRCFORMAT);
        if(aMime == ST_MIME_X_JPS
        || aMime == ST_MIME_JPS
        || aMime == ST_MIME_X_PNS
        || aMime == ST_MIME_PNS) {
            anArgSrcFormat.setValue(st::formatToString(StFormat_SideBySide_RL));
            aDrawerArgs.add(anArgSrcFormat);
        }
    }
    aDrawerArgs.add(StArgument(ST_SETTING_COMPRESS,     "true")); // optimize memory usage
    aDrawerArgs.add(StArgument(ST_SETTING_ESCAPENOQUIT, "true")); // do not close plugin instance by Escape key
    myOpenInfo.setArgumentsMap(aDrawerArgs);

    // set window
    myParentWin = m_hWnd;

    // starts out plugin main loop in another thread
    myThread = new StThread(stThreadFunction, (void* )this, "StActiveXCtrl");

    // load URL
    StString aFilePath = loadURL(myHasPreview ? myUrlPreview : myUrlFull);
    if(aFilePath.isEmpty()) {
        if(!myHasPreview) {
            return 0;
        }
        if(myHasPreview) {
            // if we have 2 URLs - try to load another one
            aFilePath = loadURL(myUrlFull);
            if(aFilePath.isEmpty()) {
                return 0;
            }
            myHasPreview = false;
        }
    }

    myOpenInfo.setPath(aFilePath);
    myOpenEvent.set();
    return 0;
}
Пример #3
0
unsigned int decodeHotKey(const StString& theString) {
    unsigned int aKey = 0;
    if(theString.isEmpty()) {
        return aKey;
    }

    // decode flags (split by + separator)
    StUtf8Iter aFrom  = theString.iterator();
    StUtf8Iter anIter = theString.iterator();
    for(; *anIter != 0; ++anIter) {
        if(*anIter == stUtf32_t('+')) {
            if(anIter.getIndex() == 0) {
                return ST_VK_OEM_PLUS; // single '+'
            }

            const StCStringUtf8 aSubStr = {
                aFrom.getBufferHere(),
                size_t(anIter.getBufferHere() - aFrom.getBufferHere()),
                       anIter.getIndex()      - aFrom.getIndex()
            };

            if(aSubStr.isEquals(THE_VKEYS_NAMES[ST_VK_SHIFT])) {
                aKey |= ST_VF_SHIFT;
            } else if(aSubStr.isEquals(THE_VKEYS_NAMES[ST_VK_CONTROL])) {
                aKey |= ST_VF_CONTROL;
            }

            aFrom = anIter;
            ++aFrom;
        }
    }

    // decode VKey itself
    const StCStringUtf8 aSubStr = {
        aFrom.getBufferHere(),
        size_t(anIter.getBufferHere() - aFrom.getBufferHere()),
               anIter.getIndex()      - aFrom.getIndex()
    };

    if(aSubStr.Size == 1) {
        // optimized code for letters
        if(*aSubStr.String >= 'A'
        && *aSubStr.String <= 'Z') {
            aKey |= (unsigned int )*aSubStr.String;
            return aKey;
        } else if(*aSubStr.String >= '0'
               && *aSubStr.String <= '9') {
            aKey |= (unsigned int )*aSubStr.String;
            return aKey;
        }
    }
    for(unsigned int aKeyIter = 0; aKeyIter <= 223; ++aKeyIter) {
        if(aSubStr.isEquals(THE_VKEYS_NAMES[aKeyIter])) {
            aKey |= aKeyIter;
            break;
        }
    }

    return aKey;
}
Пример #4
0
int main(int , char** ) { // force console output
#else
int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) { // prevent console output
#endif
    setlocale(LC_ALL, ".OCP"); // we set default locale for console output (useful only for debug)
#else
int main(int , char** ) {
#endif
    StOutPageFlip::initGlobalsAsync();
    if(!StVersionInfo::checkTimeBomb("sView")) {
        return 1;
    }

    // setup environment variables
    const StString ST_ENV_NAME_STCORE_PATH =
    #if defined(_WIN64) || defined(_LP64) || defined(__LP64__)
        "StCore64";
    #else
        "StCore32";
    #endif
    const StString aProcessPath = StProcess::getProcessFolder();
    StString aProcessUpPath = StFileNode::getFolderUp(aProcessPath);
    if(!aProcessUpPath.isEmpty()) {
        aProcessUpPath += SYS_FS_SPLITTER;
    }
    StProcess::setEnv(ST_ENV_NAME_STCORE_PATH, aProcessPath);
    if(StFolder::isFolder(aProcessPath + "textures")) {
        StProcess::setEnv("StShare", aProcessPath);
    } else if(StFolder::isFolder(aProcessUpPath + "textures")) {
        StProcess::setEnv("StShare", aProcessUpPath);
    }

    StString aResDir = StProcess::getStShareFolder();
    StProcess::setEnv("CSF_UnitsLexicon",          aResDir + "UnitsAPI" ST_FILE_SPLITTER "Lexi_Expr.dat");
    StProcess::setEnv("CSF_UnitsDefinition",       aResDir + "UnitsAPI" ST_FILE_SPLITTER "Units.dat");
    StProcess::setEnv("CSF_ShadersDirectory",      aResDir + "shaders" ST_FILE_SPLITTER "StCADViewer");
    StProcess::setEnv("CSF_SHMessage",             aResDir + "lang");
    StProcess::setEnv("CSF_MDTVTexturesDirectory", aResDir + "textures");

    StHandle<StOpenInfo> anInfo;
    if(anInfo.isNull()
    || (!anInfo->hasPath() && !anInfo->hasArgs())) {
        anInfo = StApplication::parseProcessArguments();
    }
    if(anInfo.isNull()) {
        // show help
        StString aShowHelpString = getAbout();
        st::cout << aShowHelpString;
        stInfo(aShowHelpString);
        return 0;
    }

    StHandle<StResourceManager> aResMgr = new StResourceManager();
    StHandle<StCADViewer> anApp  = new StCADViewer(aResMgr, NULL, anInfo);
    if(!anApp->open()) {
        return 1;
    }
    return anApp->exec();
}
Пример #5
0
LRESULT StActiveXCtrl::WindowProc(UINT theMsg, WPARAM theParamW, LPARAM theParamL) {
    // Special case for WM_INITMENUPOPUP event.
    // Standard implementation of COleControl::WindowProc does not find handlers for popup menu items created
    // by plugin and disables them
    if(theMsg == WM_INITMENUPOPUP) {
        return 0;
    } else if(theMsg == WM_ERASEBKGND) {
        return 1;
    } else if(theMsg == WM_PAINT) {
        if(!myIsActive) {
            PAINTSTRUCT aPaintStruct;
            CDC* aDevCtx = BeginPaint(&aPaintStruct);
            FillRect(aDevCtx->GetSafeHdc(), &aPaintStruct.rcPaint, myBackBrush);
            EndPaint(&aPaintStruct);
        }
        return 0;
    }

    // use fake WM_TIMER event to switch between fullscreen / windowed image in correct thread
    if(theMsg == WM_TIMER && myHasPreview) {
        if(theParamW == 1) {
            const StString aFilePath = loadURL(myUrlFull);
            if(!aFilePath.isEmpty()) {
                myOpenInfo.setPath(aFilePath);
                myOpenEvent.set();
            } else {
                // don't try to load broken URL anymore
                myHasPreview = false;
            }
        } else if(theParamW == 0) {
            const StString aFilePath = loadURL(myUrlPreview);
            if(!aFilePath.isEmpty()) {
                myOpenInfo.setPath(aFilePath);
                myOpenEvent.set();
            } else {
                // don't try to load broken URL anymore
                myHasPreview = false;
            }
        }
    }

    return COleControl::WindowProc(theMsg, theParamW, theParamL);
}
Пример #6
0
size_t StPlayList::findRecent(const StString thePathL,
                              const StString thePathR) const {
    StFileNode aNode;
    if(thePathR.isEmpty()) {
        aNode.setSubPath(thePathL);
    } else {
        aNode.add(new StFileNode(thePathL, &aNode));
        aNode.add(new StFileNode(thePathR, &aNode));
    }

    StMutexAuto anAutoLock(myMutex);
    for(size_t anIter = 0; anIter < myRecent.size(); ++anIter) {
        const StHandle<StRecentItem>& aRecent = myRecent[anIter];
        if(stAreSameRecent(aNode, *aRecent->File)) {
            return anIter;
        }
    }
    return size_t(-1);
}
Пример #7
0
bool StGLProgram::link(StGLContext& theCtx) {
    if(!isValid()) {
        return false;
    }
    theCtx.core20fwd->glLinkProgram(myProgramId);

    // if linkage failed - automatically remove the program!
    if(!isLinked(theCtx)) {
        theCtx.pushError(StString("Linking of the program '") + myTitle + "' failed!\n" + getLinkageInfo(theCtx));
        release(theCtx);
        return false;
    }
#ifdef __ST_DEBUG_SHADERS__
    const StString anInfo = getLinkageInfo(theCtx);
    ST_DEBUG_LOG("Program '" + myTitle + "' has been linked"
              + (!anInfo.isEmpty() ? (StString(". Log:\n") + anInfo) : (StString())));
#endif
    return true;
}
Пример #8
0
void StPlayList::open(const StCString& thePath,
                      const StCString& theItem) {
    StMutexAuto anAutoLock(myMutex);

    // check if it is recently played playlist
    bool hasTarget = !theItem.isEmpty();
    StString aTarget = hasTarget ? theItem : thePath;
    if(!hasTarget) {
        for(size_t anIter = 0; anIter < myRecent.size(); ++anIter) {
            const StHandle<StRecentItem>& aRecent = myRecent[anIter];
            const StHandle<StFileNode>&   aFile   = aRecent->File;
            if(aFile->size() != 1) {
                continue;
            }

            if(thePath.isEquals(aFile->getPath())) {
                hasTarget = true;
                aTarget = aFile->getValue(0)->getSubPath();
                break;
            }
        }
    }

    clear();
    int aSearchDeep = myRecursionDeep;
    StString aFolderPath;
    StString aFileName;
    if(StFolder::isFolder(thePath)) {
        // add all files from the folder and subfolders
        aFolderPath = thePath;
        aSearchDeep = myRecursionDeep;
        myPlsFile   = addRecentFile(StFileNode(thePath)); // append to recent files list
    } else if(StFileNode::isFileExists(thePath)) {
        // search only current folder
        StFileNode::getFolderAndFile(thePath, aFolderPath, aFileName);
        aSearchDeep = 1;
        bool hasSupportedExt = false;
        StString anExt = StFileNode::getExtension(aFileName);
        for(size_t anExtId = 0; anExtId < myExtensions.size() && !hasSupportedExt; ++anExtId) {
            hasSupportedExt = anExt.isEqualsIgnoreCase(myExtensions[anExtId]);
        }

        // parse m3u playlist
        if(anExt.isEqualsIgnoreCase(stCString("m3u"))) {
            StRawFile aRawFile(thePath);
            if(aRawFile.readFile()) {
                StString aTitle;
                char* anIter = (char* )aRawFile.getBuffer();
                if(anIter[0] == '\xEF' && anIter[1] == '\xBB' && anIter[2] == '\xBF') {
                    // skip BOM for UTF8 written by some stupid programs
                    anIter += 3;
                }
                while(anIter != NULL) {
                    anIter = parseM3UIter(anIter, aTitle);
                }

                myPlsFile = addRecentFile(StFileNode(thePath)); // append to recent files list
                if(hasTarget) {
                    // set current item
                    for(StPlayItem* anItem = myFirst; anItem != NULL; anItem = anItem->getNext()) {
                        if(anItem->getPath() == aTarget) {
                            myCurrent = anItem;
                            break;
                        }
                    }
                }

                anAutoLock.unlock();
                signals.onPlaylistChange();
                return;
            }
        }

        if(!hasSupportedExt) {
            // file with unsupported extension?
            StFileNode* aFileNode = new StFileNode(thePath, &myFoldersRoot);
            myFoldersRoot.add(aFileNode);
            addPlayItem(new StPlayItem(aFileNode, myDefStParams));
        }
    } else {
        // not a filesystem element - probably url or invalid path
        StFileNode* aFileNode = new StFileNode(thePath, &myFoldersRoot);
        myFoldersRoot.add(aFileNode);
        addRecentFile(*aFileNode); // append to recent files list
        addPlayItem(new StPlayItem(aFileNode, myDefStParams));

        anAutoLock.unlock();
        signals.onPlaylistChange();
        return;
    }
    StFolder* aSubFolder = new StFolder(aFolderPath, &myFoldersRoot);
    aSubFolder->init(myExtensions, aSearchDeep);
    myFoldersRoot.add(aSubFolder);

    addToPlayList(aSubFolder);

    myCurrent = myFirst;
    if(hasTarget || !aFileName.isEmpty()) {
        // set current item
        for(StPlayItem* anItem = myFirst; anItem != NULL; anItem = anItem->getNext()) {
            if(anItem->getPath() == aTarget) {
                myCurrent = anItem;
                if(myPlsFile.isNull()) {
                    addRecentFile(*anItem->getFileNode()); // append to recent files list
                }
                break;
            }
        }
    }

    anAutoLock.unlock();
    signals.onPlaylistChange();
}
Пример #9
0
void StWindowImpl::processEvents() {
    if(myParentWin == NULL
    || myToResetDevice) {
        // window is closed!
        return;
    }

    // check if we are exiting
    if(myParentWin->ToDestroy()) {
        myStEvent.Type       = stEvent_Close;
        myStEvent.Close.Time = getEventTime();
        signals.onClose->emit(myStEvent.Close);
        return;
    }

    // check onNewIntent event
    StString aDndFile;
    myParentWin->setHardwareStereoOn(myToEnableStereoHW);
    myParentWin->setTrackOrientation(myToTrackOrient);
    myParentWin->setHideSystemBars(myToHideStatusBar, myToHideNavBar);
    myParentWin->fetchState(aDndFile, myQuaternion, myToSwapEyesHW, myKeysState);
    if(!aDndFile.isEmpty()) {
        std::vector<const char*> aDndList;
        aDndList.push_back(aDndFile.toCString());
        myStEvent.Type = stEvent_FileDrop;
        myStEvent.DNDrop.Time = getEventTime();
        myStEvent.DNDrop.NbFiles = aDndList.size();
        myStEvent.DNDrop.Files   = &aDndList[0];
        myEventsBuffer.append(myStEvent);
    }

    updateActiveState();

    StPointD_t anOldMousePt = myMousePt;
    int aPollRes  = 0;
    int aNbEvents = 0;
    StAndroidPollSource* aSource = NULL;
    bool toWaitEvents = false;
    while((aPollRes = ALooper_pollAll(toWaitEvents ? -1 : 0, NULL, &aNbEvents, (void** )&aSource)) >= 0) {
        if(aSource != NULL) {
            aSource->process(myParentWin, aSource);
        }
        if(myToResetDevice) {
            break;
        }

        // check if we are exiting
        if(myParentWin->ToDestroy()) {
            break;
        }
    }

    // check if we are exiting
    if(myParentWin->ToDestroy()) {
        myStEvent.Type       = stEvent_Close;
        myStEvent.Close.Time = getEventTime();
        signals.onClose->emit(myStEvent.Close);
        return;
    }

    myIsMouseMoved = false;
    if(myMousePt.x() >= 0.0 && myMousePt.x() <= 1.0 && myMousePt.y() >= 0.0 && myMousePt.y() <= 1.0) {
        StPointD_t aDspl = myMousePt - anOldMousePt;
        if(std::abs(aDspl.x()) >= 0.0008 || std::abs(aDspl.y()) >= 0.0008) {
            myIsMouseMoved = true;
        }
    }

    // update position only when all messages are parsed
    updateWindowPos();
    myIsUpdated = false;

    // StWindow XLib implementation process events in the same thread
    // thus this double buffer is not in use
    // however user events may be posted to it
    swapEventsBuffers();
}
Пример #10
0
void StLogger::write(const StString&       theMessage,
                     const StLogger::Level theLevel,
                     const StLogContext*   ) {
    if(theLevel > myFilter || theMessage.isEmpty()) {
        // just ignore
        return;
    }

    // lock for safety
    if(!myMutex.isNull()) {
        myMutex->lock();
    }

    // log to the file
    if(!myFilePath.isEmpty()) {
    #ifdef _WIN32
        myFileHandle = _wfopen(myFilePath.toCString(), L"ab");
    #elif defined(__linux__)
        myFileHandle =   fopen(myFilePath.toCString(),  "ab");
    #endif
        if(myFileHandle != NULL) {
            switch(theLevel) {
                case ST_PANIC:
                    fwrite("PANIC !! ", 1, 9, myFileHandle);
                    fwrite(theMessage.toCString(), 1, theMessage.getSize(), myFileHandle);
                    break;
                case ST_FATAL:
                    fwrite("FATAL !! ", 1, 9, myFileHandle);
                    fwrite(theMessage.toCString(), 1, theMessage.getSize(), myFileHandle);
                    break;
                case ST_ERROR:
                    fwrite("ERROR !! ", 1, 9, myFileHandle);
                    fwrite(theMessage.toCString(), 1, theMessage.getSize(), myFileHandle);
                    break;
                case ST_WARNING:
                    fwrite("WARN  -- ", 1, 9, myFileHandle);
                    fwrite(theMessage.toCString(), 1, theMessage.getSize(), myFileHandle);
                    break;
                case ST_INFO:
                case ST_VERBOSE:
                    fwrite("INFO  -- ", 1, 9, myFileHandle);
                    fwrite(theMessage.toCString(), 1, theMessage.getSize(), myFileHandle);
                    break;
                case ST_DEBUG:
                    fwrite("DEBUG -- ", 1, 9, myFileHandle);
                    fwrite(theMessage.toCString(), 1, theMessage.getSize(), myFileHandle);
                    break;
                default:
                    fwrite(theMessage.toCString(), 1, theMessage.getSize(), myFileHandle);
                    break;
            }
            fwrite("\n", 1, 1, myFileHandle);
            fclose(myFileHandle);
            myFileHandle = NULL;
        }
    }

    // log to standard output (with colored prefix)
    if(myToLogCout) {
        switch(theLevel) {
            case ST_PANIC:
                ST_LOG_CERR << st::COLOR_FOR_RED      << stostream_text("PANIC !! ") << st::COLOR_FOR_WHITE << theMessage << stostream_text('\n');
                break;
            case ST_FATAL:
                ST_LOG_CERR << st::COLOR_FOR_RED      << stostream_text("FATAL !! ") << st::COLOR_FOR_WHITE << theMessage << stostream_text('\n');
                break;
            case ST_ERROR:
                ST_LOG_CERR << st::COLOR_FOR_RED      << stostream_text("ERROR !! ") << st::COLOR_FOR_WHITE << theMessage << stostream_text('\n');
                break;
            case ST_WARNING:
                ST_LOG_CERR << st::COLOR_FOR_YELLOW_L << stostream_text("WARN  -- ") << st::COLOR_FOR_WHITE << theMessage << stostream_text('\n');
                break;
            case ST_INFO:
            case ST_VERBOSE:
                ST_LOG_CERR << st::COLOR_FOR_YELLOW_L << stostream_text("INFO  -- ") << st::COLOR_FOR_WHITE << theMessage << stostream_text('\n');
                break;
            case ST_DEBUG:
                ST_LOG_CERR << st::COLOR_FOR_YELLOW_L << stostream_text("DEBUG -- ") << st::COLOR_FOR_WHITE << theMessage << stostream_text('\n');
                break;
            default:
                ST_LOG_CERR << theMessage << stostream_text('\n');
                break;
        }
    }

    // log to the system journal(s)
/*#ifdef _WIN32
    // get a handle to the event log
    HANDLE anEventLog = RegisterEventSource(NULL,      // local computer
                                            L"sView"); // event source name
    if(anEventLog != NULL) {
        WORD aLogType = 0;
        switch(theLevel) {
            case ST_PANIC:
            case ST_FATAL:
            case ST_ERROR:
                aLogType = EVENTLOG_ERROR_TYPE;
                break;
            case ST_WARNING:
                aLogType = EVENTLOG_WARNING_TYPE;
                break;
            case ST_INFO:
            case ST_VERBOSE:
            case ST_DEBUG:
            default:
                aLogType = EVENTLOG_INFORMATION_TYPE;
                break;
        }
        ReportEvent(anEventLog, aLogType,
                    0,               // event category
                    0,               // event identifier
                    NULL,            // no user security identifier
                    1,               // number of substitution strings
                    0,               // no data
                    (LPCWSTR* )&theMessage.utfText(), // pointer to strings
                    NULL))           // no binary data
        DeregisterEventSource(anEventLog);
    }
#endif*/

    // unlock mutex
    if(!myMutex.isNull()) {
        myMutex->unlock();
    }
}
Пример #11
0
bool StAVVideoMuxer::save(const StString& theFile) {
    if(myCtxListSrc.isEmpty()
    || theFile.isEmpty()) {
        return false;
    }

    StString aFormatName = myCtxListSrc[0]->iformat->name;
    const char* aFormatStr = formatToMetadata(myStereoFormat);

    std::vector<StRemuxContext> aSrcCtxList;
    //StArrayList<StRemuxContext> aSrcCtxList;
    unsigned int aStreamCount = 0;

    StAVOutContext aCtxOut;
    if(!aCtxOut.findFormat(NULL, theFile.toCString())) {
        signals.onError(StString("Unable to find a suitable output format for '") + theFile + "'.");
        return false;
    } else if(!aCtxOut.create(theFile)) {
        signals.onError(StString("Could not create output context."));
        return false;
    }

    for(size_t aCtxId = 0; aCtxId < myCtxListSrc.size(); ++aCtxId) {
        StRemuxContext aCtxSrc;
        aCtxSrc.Context = myCtxListSrc[aCtxId];
        if(aCtxId == 0) {
            av_dict_copy(&aCtxOut.Context->metadata, aCtxSrc.Context->metadata, AV_DICT_DONT_OVERWRITE);
            av_dict_set(&aCtxOut.Context->metadata, "STEREO_MODE", aFormatStr, 0);
        }
        for(unsigned int aStreamId = 0; aStreamId < aCtxSrc.Context->nb_streams; ++aStreamId) {
            aCtxSrc.Streams.add((unsigned int )-1);
            AVStream* aStreamSrc = aCtxSrc.Context->streams[aStreamId];
            if(aStreamSrc->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
                if(addStream(aCtxOut.Context, aStreamSrc)) {
                    aCtxSrc.Streams[aStreamId] = aStreamCount++;
                }
            }
        }
        aSrcCtxList.push_back(aCtxSrc);
    }

    // add audio streams after video
    for(size_t aCtxId = 0; aCtxId < myCtxListSrc.size(); ++aCtxId) {
        StRemuxContext& aCtxSrc = aSrcCtxList[aCtxId];
        for(unsigned int aStreamId = 0; aStreamId < aCtxSrc.Context->nb_streams; ++aStreamId) {
            AVStream* aStreamSrc = aCtxSrc.Context->streams[aStreamId];
            if(aStreamSrc->codec->codec_type == AVMEDIA_TYPE_AUDIO
            && addStream(aCtxOut.Context, aStreamSrc)) {
                aCtxSrc.Streams[aStreamId] = aStreamCount++;
            }
        }
    }

    // add other streams (subtitles) at the end
    for(size_t aCtxId = 0; aCtxId < myCtxListSrc.size(); ++aCtxId) {
        StRemuxContext& aCtxSrc = aSrcCtxList[aCtxId];
        for(unsigned int aStreamId = 0; aStreamId < aCtxSrc.Context->nb_streams; ++aStreamId) {
            AVStream* aStreamSrc = aCtxSrc.Context->streams[aStreamId];
            if(aStreamSrc->codec->codec_type != AVMEDIA_TYPE_VIDEO
            && aStreamSrc->codec->codec_type != AVMEDIA_TYPE_AUDIO
            && addStream(aCtxOut.Context, aStreamSrc)) {
                aCtxSrc.Streams[aStreamId] = aStreamCount++;
            }
        }
    }

    av_dump_format(aCtxOut.Context, 0, theFile.toCString(), 1);
    if(!(aCtxOut.Context->oformat->flags & AVFMT_NOFILE)) {
        const int aState = avio_open2(&aCtxOut.Context->pb, theFile.toCString(), AVIO_FLAG_WRITE, NULL, NULL);
        if(aState < 0) {
            signals.onError(StString("Could not open output file '") + theFile + "' (" + stAV::getAVErrorDescription(aState) + ")");
            return false;
        }
    }

    int aState = avformat_write_header(aCtxOut.Context, NULL);
    if(aState < 0) {
        signals.onError(StString("Error occurred when opening output file (") + stAV::getAVErrorDescription(aState) + ").");
        return false;
    }

    AVPacket aPacket;
    for(;;) {
        size_t aNbEmpty = 0;
        for(size_t aCtxId = 0; aCtxId < aSrcCtxList.size(); ++aCtxId) {
            StRemuxContext& aCtxSrc = aSrcCtxList[aCtxId];
            if(!aCtxSrc.State) {
                ++aNbEmpty;
                continue;
            }

            if(av_read_frame(aCtxSrc.Context, &aPacket) < 0) {
                aCtxSrc.State = false;
                ++aNbEmpty;
                continue;
            }

            unsigned int aStreamOutIndex = aCtxSrc.Streams[aPacket.stream_index];
            if(aStreamOutIndex == (unsigned int )-1) {
                continue;
            }

            AVStream* aStreamIn  = aCtxSrc.Context->streams[aPacket.stream_index];
            AVStream* aStreamOut = aCtxOut.Context->streams[aStreamOutIndex];

        #ifdef ST_LIBAV_FORK
            const AVRounding aRoundParams = AV_ROUND_NEAR_INF;
        #else
            const AVRounding aRoundParams = AVRounding(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX);
        #endif
            aPacket.pts      = av_rescale_q_rnd(aPacket.pts, aStreamIn->time_base, aStreamOut->time_base, aRoundParams);
            aPacket.dts      = av_rescale_q_rnd(aPacket.dts, aStreamIn->time_base, aStreamOut->time_base, aRoundParams);
            aPacket.duration = static_cast<int >(av_rescale_q(aPacket.duration, aStreamIn->time_base, aStreamOut->time_base));
            aPacket.pos      = -1;

            aState = av_interleaved_write_frame(aCtxOut.Context, &aPacket);
            if(aState < 0) {
                signals.onError(StString("Error muxing packet (") + stAV::getAVErrorDescription(aState) + ").");
                return false;
            }
            av_free_packet(&aPacket);
        }
        if(aNbEmpty == aSrcCtxList.size()) {
            break;
        }
    }
    av_write_trailer(aCtxOut.Context);
    return true;
}
Пример #12
0
void StTranslations::reload() {
    params.language->changeValues().clear();

    // detect available translations
    StArrayList<StString> aFolders;
    myResMgr->listSubFolders("lang", aFolders);
    for(size_t aNodeId = 0; aNodeId < aFolders.size(); ++aNodeId) {
        myLangFolderList.add(aFolders[aNodeId]);

        const StString aNameFile = StString("lang" ST_FILE_SPLITTER) + aFolders[aNodeId] + ST_FILE_SPLITTER "language.lng";
        StHandle<StResource> aRes = myResMgr->getResource(aNameFile);
        StString aName;
        if(!aRes.isNull()
        &&  aRes->read()) {
            const char*  aSrc = (const char* )aRes->getData();
            const size_t aLen = (size_t      )aRes->getSize();
            aName = StString(aSrc, aLen);
        }
        params.language->changeValues().add(aName.isEmpty() ? aFolders[aNodeId] : aName);
    }
#if defined(__ANDROID__)
    if(params.language->getValues().isEmpty()) {
        // no way to list sub-folder on Android - check known translations
        if(myResMgr->isResourceExist(StString("lang" ST_FILE_SPLITTER "English" ST_FILE_SPLITTER) + myModuleName + StTranslations::DEFAULT_SUFFIX)) {
            params.language->changeValues().add("English");
            myLangFolderList.add("English");
        }
        if(myResMgr->isResourceExist(StString("lang" ST_FILE_SPLITTER "Russian" ST_FILE_SPLITTER) + myModuleName + StTranslations::DEFAULT_SUFFIX)) {
            params.language->changeValues().add("русский");
            myLangFolderList.add("Russian");
        }
        if(myResMgr->isResourceExist(StString("lang" ST_FILE_SPLITTER "French" ST_FILE_SPLITTER) + myModuleName + StTranslations::DEFAULT_SUFFIX)) {
            params.language->changeValues().add("français");
            myLangFolderList.add("French");
        }
        if(myResMgr->isResourceExist(StString("lang" ST_FILE_SPLITTER "German" ST_FILE_SPLITTER) + myModuleName + StTranslations::DEFAULT_SUFFIX)) {
            params.language->changeValues().add("Deutsch");
            myLangFolderList.add("German");
        }
        if(myResMgr->isResourceExist(StString("lang" ST_FILE_SPLITTER "Korean" ST_FILE_SPLITTER) + myModuleName + StTranslations::DEFAULT_SUFFIX)) {
            params.language->changeValues().add("한국어");
            myLangFolderList.add("Korean");
        }
        if(myResMgr->isResourceExist(StString("lang" ST_FILE_SPLITTER "ChineseS" ST_FILE_SPLITTER) + myModuleName + StTranslations::DEFAULT_SUFFIX)) {
            params.language->changeValues().add("简体中文");
            myLangFolderList.add("ChineseS");
        }
        if(myResMgr->isResourceExist(StString("lang" ST_FILE_SPLITTER "Czech"  ST_FILE_SPLITTER) + myModuleName + StTranslations::DEFAULT_SUFFIX)) {
            params.language->changeValues().add("Čeština");
            myLangFolderList.add("Czech");
        }
    }
#endif

    if(params.language->getValues().isEmpty()) {
        // add built-in language
        params.language->changeValues().add("English");
        myLangFolderList.add("English");
    }

    size_t     anIdInList = 0;
    StString   aLangParam("English");
    StSettings aGlobalSettings(myResMgr, ST_GLOBAL_SETTINGS_GROUP);
    bool isLangSet = false;
    if(!aGlobalSettings.loadString(ST_SETTING_LANGUAGE, aLangParam)) {
        // try to use system-wide language settings
        const StString& aLang = myResMgr->getSystemLanguage();
        if(aLang.isEqualsIgnoreCase(stCString("ru"))) {
            if(myLangFolderList.contains(stCString("Russian"),  anIdInList)
            || myLangFolderList.contains(stCString("русский"),  anIdInList)) {
                params.language->setValue(int32_t(anIdInList));
                isLangSet = true;
            }
        } else if(aLang.isEqualsIgnoreCase(stCString("de"))) {
            if(myLangFolderList.contains(stCString("German"),   anIdInList)
            || myLangFolderList.contains(stCString("Deutsch"),  anIdInList)) {
                params.language->setValue(int32_t(anIdInList));
                isLangSet = true;
            }
        } else if(aLang.isEqualsIgnoreCase(stCString("fr"))) {
            if(myLangFolderList.contains(stCString("French"),   anIdInList)
            || myLangFolderList.contains(stCString("français"), anIdInList)) {
                params.language->setValue(int32_t(anIdInList));
                isLangSet = true;
            }
        } else if(aLang.isEqualsIgnoreCase(stCString("ko"))) {
            if(myLangFolderList.contains(stCString("Korean"),   anIdInList)) {
                params.language->setValue(int32_t(anIdInList));
                isLangSet = true;
            }
        } else if(aLang.isEqualsIgnoreCase(stCString("zh"))) {
            if(myLangFolderList.contains(stCString("ChineseS"), anIdInList)) {
                params.language->setValue(int32_t(anIdInList));
                isLangSet = true;
            }
        } else if(aLang.isEqualsIgnoreCase(stCString("cs"))) {
            if(myLangFolderList.contains(stCString("Čeština"), anIdInList)) {
                params.language->setValue(int32_t(anIdInList));
                isLangSet = true;
            }
        }
    }
    if(!isLangSet) {
        if(myLangFolderList.contains(aLangParam,           anIdInList)
        || myLangFolderList.contains(stCString("English"), anIdInList)) {
            params.language->setValue(int32_t(anIdInList));
        }
    }
    updateLangCode(int32_t(anIdInList));

    const StString& aFolderName = myLangFolderList[anIdInList];
    const StString  aResName    = StString()
                                + "lang"       + SYS_FS_SPLITTER
                                + aFolderName  + SYS_FS_SPLITTER
                                + myModuleName + StTranslations::DEFAULT_SUFFIX;
    StHandle<StResource> aRes = myResMgr->getResource(aResName);
    if(!aRes.isNull()
    &&  aRes->read()) {
        const char* aSrc = (const char* )aRes->getData();
        const int   aLen = aRes->getSize();
        read(aSrc, aLen);
    }

    // connect signal
    params.language->signals.onChanged.connect(this, &StTranslations::setLanguage);
}