Beispiel #1
0
void StPlayList::clear() {
    StMutexAuto anAutoLock(myMutex);
    if(myFirst != NULL) {
        myWasCleared = true;
        mySerial.increment();
    }

    if(!myPlsFile.isNull()
    && myCurrent != NULL) {
        if(myPlsFile->File->isEmpty()) {
            myPlsFile->File->add(new StFileNode(myCurrent->getPath(), myPlsFile->File.access()));
        } else {
            myPlsFile->File->changeValue(0)->setSubPath(myCurrent->getPath());
        }
    }
    myPlsFile.nullify();

    // destroy double-linked list content
    for(StPlayItem *anItem(myFirst), *anItemToDel(NULL); anItem != NULL;) {
        anItemToDel = anItem;
        anItem = anItem->getNext();
        delete anItemToDel;
    }
    myStackPrev.clear();
    myStackNext.clear();
    myFirst = myLast = myCurrent = NULL;
    myItemsCount = myPlayedCount = 0;

    anAutoLock.unlock();
    signals.onPlaylistChange();
}
Beispiel #2
0
bool StPlayList::walkToPosition(const size_t theId) {
    StMutexAuto anAutoLock(myMutex);

    size_t anIter = 0;
    for(StPlayItem* anItem = myFirst; anItem != NULL; anItem = anItem->getNext(), ++anIter) {
        if(anIter == theId) {
            if(myCurrent == anItem) {
                return false;
            }

            StPlayItem* aPrev = myCurrent;
            if(aPrev != NULL) {
                myStackPrev.push_back(aPrev);
                if(myStackPrev.size() > THE_UNDO_LIMIT) {
                    myStackPrev.pop_front();
                }
            }

            myCurrent = anItem;
            anAutoLock.unlock();
            signals.onPositionChange(theId);
            return true;
        }
    }

    return false;
}
Beispiel #3
0
bool StPlayList::saveM3U(const StCString& thePath) {
    StRawFile aFile;
    if(thePath.isEmpty()
    || !aFile.openFile(StRawFile::WRITE, thePath)) {
        return false;
    }

    StMutexAuto anAutoLock(myMutex);
    aFile.write(stCString("#EXTM3U"));

    for(StPlayItem* anItem = myFirst; anItem != NULL; anItem = anItem->getNext()) {
        const StFileNode* aNode = anItem->getFileNode();
        if(aNode == NULL) {
            continue;
        } else if(aNode->size() < 2) {
            aFile.write(stCString("\n#EXTINF:0,"));
            if(anItem->hasCustomTitle()) {
                aFile.write(anItem->getTitle());
            }
            aFile.write(stCString("\n"));
            aFile.write(aNode->getPath());
        }
    }
    aFile.write(stCString("\n"));
    return true;
}
Beispiel #4
0
void StPlayList::getSubList(StArrayList<StString>& theList,
                            const size_t           theStart,
                            const size_t           theEnd) const {
    theList.clear();
    StMutexAuto anAutoLock(myMutex);

    size_t anIter = 0;
    StPlayItem* anItem = myFirst;
    for(; anItem != NULL; anItem = anItem->getNext(), ++anIter) {
        if(anIter == theStart) {
            break;
        }
    }

    if(anIter != theStart) {
        return;
    }

    for(; anItem != NULL; anItem = anItem->getNext(), ++anIter) {
        if(anIter == theEnd) {
            break;
        }

        theList.add(anItem->getTitle());
    }
}
Beispiel #5
0
int32_t StPlayList::getSerial() {
    StMutexAuto anAutoLock(myMutex);
    if(myWasCleared
    && myFirst != NULL) {
        myWasCleared = false;
        mySerial.increment();
    }
    return mySerial.getValue();
}
Beispiel #6
0
void StPlayList::currentToRecent() {
    StMutexAuto anAutoLock(myMutex);
    if( myCurrent == NULL
    || !myPlsFile.isNull()) {
        return;
    }

    StHandle<StPlayList::StRecentItem> aRecent = addRecentFile(*myCurrent->getFileNode());
    aRecent->Params = myCurrent->getParams();
}
Beispiel #7
0
bool StPlayList::walkToFirst() {
    StMutexAuto anAutoLock(myMutex);
    bool wasntFirst = (myCurrent != myFirst);
    myCurrent = myFirst;
    if(wasntFirst) {
        myStackPrev.clear();
        myStackNext.clear();
        anAutoLock.unlock();
        signals.onPositionChange(0);
    }
    return wasntFirst;
}
Beispiel #8
0
bool StPlayList::remove(const StString& thePath,
                        const bool      theToRemovePhysically) {
    StString    aPath    = thePath;
    StPlayItem* aRemItem = NULL;
    StMutexAuto anAutoLock(myMutex);
    if(myCurrent == NULL) {
        // empty playlist
        return false;
    } else if(aPath != myCurrent->getPath()) {
        // search play item
        for(StPlayItem* anItem = myFirst; anItem != NULL; anItem = anItem->getNext()) {
            if(aPath == anItem->getPath()) {
                aRemItem = anItem;
                break;
            }
        }
    } else {
        // walk to another playlist position
        aRemItem = myCurrent;
        const bool aPlayedFlag = aRemItem->getPlayedFlag();
        if(myCurrent->hasNext()) {
            myCurrent = myCurrent->getNext();
        } else if(myCurrent->hasPrev()) {
            myCurrent = myCurrent->getPrev();
        } else {
            myCurrent     = NULL;
            myPlayedCount = 0;
        }

        if(myCurrent != NULL) {
            if(aRemItem->getPlayedFlag() != aPlayedFlag) {
                // the item has not been played yet - mark it as such
                aRemItem->setPlayedFlag(aPlayedFlag);
            } else {
                // one played item has been removed
                --myPlayedCount;
            }
        }
    }

    // remove item itself
    const bool isDeleted = aRemItem != NULL
                        && (!theToRemovePhysically || StFileNode::removeFile(aPath));
    if(isDeleted) {
        delPlayItem(aRemItem);
        delete aRemItem;
    }

    anAutoLock.unlock();
    signals.onPlaylistChange();
    return isDeleted;
}
Beispiel #9
0
bool StPlayList::walkToLast() {
    StMutexAuto anAutoLock(myMutex);
    bool wasntLast = (myCurrent != myLast);
    myCurrent = myLast;
    if(wasntLast) {
        myStackPrev.clear();
        myStackNext.clear();
        const size_t anItemId = myCurrent != NULL ? myCurrent->getPosition() : 0;
        anAutoLock.unlock();
        signals.onPositionChange(anItemId);
    }
    return wasntLast;
}
Beispiel #10
0
void StPlayList::addOneFile(const StString& theFilePath,
                            const StMIME&   theFileMIME) {
    StMutexAuto anAutoLock(myMutex);
    StFileNode* aFileNode = new StFileNode(theFilePath, &myFoldersRoot);
    aFileNode->setMIME(theFileMIME);
    myFoldersRoot.add(aFileNode);

    addRecentFile(*aFileNode); // append to recent files list
    addPlayItem(new StPlayItem(aFileNode, myDefStParams));

    anAutoLock.unlock();
    signals.onPlaylistChange();
}
Beispiel #11
0
StHandle<StFileNode> StPlayList::getCurrentFile() {
    StMutexAuto anAutoLock(myMutex);
    if(myCurrent == NULL) {
        // empty list
        return StHandle<StFileNode>();
    }
    StFileNode* aFileNode = myCurrent->getFileNode();
    if(aFileNode == NULL) {
        // invalid item
        return StHandle<StFileNode>();
    }
    return new StFileNode(aFileNode->getPath());
}
Beispiel #12
0
StPlayList::CurrentPosition StPlayList::getCurrentPosition() const {
    StMutexAuto anAutoLock(myMutex);
    if(myCurrent == NULL) {
        return CurrentPosition_NONE;
    } else if(myCurrent == myFirst) {
        if(myCurrent == myLast) {
            return CurrentPosition_Single;
        }
        return CurrentPosition_First;
    } else if(myCurrent == myLast) {
        return CurrentPosition_Last;
    }
    return CurrentPosition_Middle;
}
Beispiel #13
0
void StPlayList::getRecentList(StArrayList<StString>& theList) const {
    theList.clear();
    StMutexAuto anAutoLock(myMutex);
    for(size_t anIter = 0; anIter < myRecent.size(); ++anIter) {
        const StHandle<StRecentItem>& aRecent = myRecent[anIter];
        const StHandle<StFileNode>&   aFile   = aRecent->File;

        const StString aPath = aFile->size() == 2 ? aFile->getValue(0)->getPath() : aFile->getPath();
        StString aTitleString;
        StString aFolder;
        StFileNode::getFolderAndFile(aPath, aFolder, aTitleString);
        theList.add(aTitleString);
    }
}
Beispiel #14
0
void StPlayList::setTitle(const StHandle<StStereoParams>& theKey,
                          const StString&                 theTitle) {
    StMutexAuto anAutoLock(myMutex);
    if(myCurrent == NULL) {
        return;
    }

    if(theKey != myCurrent->getParams()) {
        return;
    }

    const size_t anItemId = myCurrent->getPosition();
    myCurrent->setTitle(theTitle);
    anAutoLock.unlock();
    signals.onTitleChange(anItemId);
}
Beispiel #15
0
void StPlayList::updateRecent(const StHandle<StFileNode>&     theFile,
                              const StHandle<StStereoParams>& theParams) {
    StMutexAuto anAutoLock(myMutex);
    if(!myPlsFile.isNull()
     && myPlsFile->File == theFile) {
        // remember properties of last played file
        myPlsFile->Params = theParams;
        return;
    }

    for(size_t anIter = 0; anIter < myRecent.size(); ++anIter) {
        StHandle<StRecentItem>& aRecent = myRecent[anIter];
        if(stAreSameRecent(*theFile, *aRecent->File)) {
            aRecent->Params = theParams;
            return;
        }
    }
}
Beispiel #16
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);
}
Beispiel #17
0
StString StPlayList::dumpRecentList() const {
    StMutexAuto anAutoLock(myMutex);
    StArgumentsMap aMap;
    for(size_t anIter = 0; anIter < myRecent.size(); ++anIter) {
        const StHandle<StRecentItem>&   aRecent = myRecent[anIter];
        const StHandle<StFileNode>&     aFile   = aRecent->File;
        const StHandle<StStereoParams>& aParams = aRecent->Params;
        if(!myPlsFile.isNull()
         && aFile == myPlsFile->File
         && myCurrent != NULL) {
            StArgument anArgFile(StString("file")  + anIter, aFile->getPath());
            StArgument anArgPos (StString("pos")   + anIter, myCurrent->getPath());
            aMap.add(anArgFile);
            aMap.add(anArgPos);
        } else if(aFile->isEmpty()) {
            StArgument anArgFile(StString("file")  + anIter, aFile->getPath());
            aMap.add(anArgFile);
        } else if(aFile->size() == 1) {
            StArgument anArgFile(StString("file")  + anIter, aFile->getPath());
            StArgument anArgPos (StString("pos")   + anIter, aFile->getValue(0)->getSubPath());
            aMap.add(anArgFile);
            aMap.add(anArgPos);
        } else if(aFile->size() == 2) {
            StArgument anArgLeft (StString("left")  + anIter, aFile->getValue(0)->getPath());
            StArgument anArgRight(StString("right") + anIter, aFile->getValue(1)->getPath());
            aMap.add(anArgLeft);
            aMap.add(anArgRight);
        }
        if(!aParams.isNull()) {
            if(aParams->Timestamp > 360.0) {
                std::stringstream aStream;
                aStream.imbue(std::locale("C"));
                aStream << aParams->Timestamp;
                const StString aStrValue = aStream.str().c_str();
                StArgument anArgTime(StString("time")  + anIter, aStrValue);
                aMap.add(anArgTime);
            }
        }
    }
    return aMap.toString();
}
Beispiel #18
0
void StPlayList::loadRecentList(const StString theString) {
    StMutexAuto anAutoLock(myMutex);
    StArgumentsMap aMap;
    aMap.parseString(theString);
    myRecent.clear();

    for(size_t anIter = 0; anIter < myRecentLimit; ++anIter) {
        const StArgument anArgFile  = aMap[StString("file")  + anIter];
        const StArgument anArgLeft  = aMap[StString("left")  + anIter];
        const StArgument anArgRight = aMap[StString("right") + anIter];
        const StArgument anArgTime  = aMap[StString("time")  + anIter];
        StHandle<StRecentItem> aRecent;
        if(anArgLeft.isValid() && anArgRight.isValid()) {
            StHandle<StFileNode> aFileNode = new StFileNode(StString());
            aFileNode->add(new StFileNode(anArgLeft.getValue(),  aFileNode.access()));
            aFileNode->add(new StFileNode(anArgRight.getValue(), aFileNode.access()));
            aRecent = addRecentFile(*aFileNode, false);
        } else if(anArgFile.isValid()) {
            StHandle<StFileNode> aFileNode = new StFileNode(anArgFile.getValue());
            const StArgument anArgPos = aMap[StString("pos") + anIter];
            if(anArgPos.isValid()) {
                aFileNode->add(new StFileNode(anArgPos.getValue(), aFileNode.access()));
            }
            aRecent = addRecentFile(*aFileNode, false);
        }
        if(aRecent.isNull()) {
            continue;
        }

        if(anArgTime.isValid()) {
            if(aRecent->Params.isNull()) {
                aRecent->Params = new StStereoParams();
            }
            std::stringstream aStream;
            aStream.imbue(std::locale("C"));
            aStream << anArgTime.getValue().toCString();
            aStream >> aRecent->Params->Timestamp;
        }
    }
}
Beispiel #19
0
StHandle<StStereoParams> StPlayList::openRecent(const size_t theItemId) {
    StMutexAuto anAutoLock(myMutex);
    if(theItemId >= myRecent.size()) {
        return StHandle<StStereoParams>();
    }

    const StHandle<StRecentItem> aRecent = myRecent[theItemId];
    const StHandle<StFileNode>   aFile   = aRecent->File;
    if(aFile->size() == 2) {
        // stereo pair from two files
        clear();
        addOneFile(aFile->getValue(0)->getPath(),
                   aFile->getValue(1)->getPath());
    } else if(aFile->size() == 1) {
        // playlist
        open(aFile->getPath(), aFile->getValue(0)->getSubPath());
    } else {
        // single file
        open(aFile->getPath());
    }
    return aRecent->Params;
}
Beispiel #20
0
bool StPlayList::walkToPrev() {
    StMutexAuto anAutoLock(myMutex);
    if(myCurrent == NULL) {
        return false;
    } else if(myIsShuffle && myItemsCount >= 3) {
        StPlayItem* aNext = myCurrent;
        if(!myStackPrev.empty()) {
            myCurrent = myStackPrev.back();
            myStackPrev.pop_back();
        } else if(myCurrent != myFirst) {
            myCurrent = myCurrent->getPrev();
        } else {
            aNext = NULL;
        }

        if(aNext != myCurrent
        && aNext != NULL) {
            myStackNext.push_front(aNext);
            if(myStackNext.size() > THE_UNDO_LIMIT) {
                myStackNext.pop_back();
            }
            const size_t anItemId = myCurrent->getPosition();
            anAutoLock.unlock();
            signals.onPositionChange(anItemId);
            return true;
        }
        return false;
    } else if(myCurrent != myFirst) {
        myCurrent = myCurrent->getPrev();
        const size_t anItemId = myCurrent->getPosition();
        anAutoLock.unlock();
        signals.onPositionChange(anItemId);
        return true;
    } else if(myIsLoopFlag) {
        return walkToLast();
    }
    return false;
}
Beispiel #21
0
void StPlayList::addToNode(const StHandle<StFileNode>& theFileNode,
                           const StString&             thePathToAdd) {
    StString aPath = theFileNode->getPath();
    StMutexAuto anAutoLock(myMutex);
    if(myCurrent == NULL) {
        return;
    } else if(aPath != myCurrent->getPath()) {
        for(StPlayItem* anItem = myFirst; anItem != NULL; anItem = anItem->getNext()) {
            if(aPath == anItem->getPath()) {
                myCurrent = anItem;
                break;
            }
        }
    }

    StFileNode* aFileNode = myCurrent->getFileNode();
    if(aFileNode->getParent() != &myFoldersRoot) {
        // convert filenode to metafile with empty root
        aFileNode->reParent(&myFoldersRoot);
        aFileNode->setSubPath(StString());
        aFileNode->add(new StFileNode(aPath, aFileNode));
    }
    aFileNode->add(new StFileNode(thePathToAdd, aFileNode));
}
Beispiel #22
0
bool StPlayList::getCurrentFile(StHandle<StFileNode>&     theFileNode,
                                StHandle<StStereoParams>& theParams,
                                StHandle<StFileNode>&     thePlsFile) {
    theFileNode.nullify();
    theParams.nullify();
    thePlsFile.nullify();
    StMutexAuto anAutoLock(myMutex);
    if(myCurrent == NULL) {
        // empty list
        return false;
    }
    StFileNode* aFileNode = myCurrent->getFileNode();
    if(aFileNode == NULL) {
        // invalid item
        return false;
    }

    theFileNode = aFileNode->detach();
    theParams   = myCurrent->getParams();
    if(!myPlsFile.isNull()) {
        thePlsFile = myPlsFile->File;
    }
    return true;
}
Beispiel #23
0
void StPlayList::clearRecent() {
    StMutexAuto anAutoLock(myMutex);
    myRecent.clear();
    myIsNewRecent = true;
}
Beispiel #24
0
bool StPlayList::isShuffle() const {
    StMutexAuto anAutoLock(myMutex);
    return myIsShuffle;
}
Beispiel #25
0
void StPlayList::setShuffle(bool theShuffle) {
    StMutexAuto anAutoLock(myMutex);
    myIsShuffle = theShuffle;
}
Beispiel #26
0
size_t StPlayList::getCurrentId() const {
    StMutexAuto anAutoLock(myMutex);
    return (myCurrent != NULL) ? myCurrent->getPosition() : 0;
}
Beispiel #27
0
bool StPlayList::walkToNext(const bool theToForce) {
    StMutexAuto anAutoLock(myMutex);
    if(myCurrent == NULL
    || (myToLoopSingle && !theToForce)) {
        return false;
    } else if(myIsShuffle && myItemsCount >= 3) {
        StPlayItem* aPrev = myCurrent;
        if(!myStackNext.empty()) {
            myCurrent = myStackNext.front();
            myStackNext.pop_front();
        } else {
            if((myPlayedCount >= (myItemsCount - 1)) || (myPlayedCount == 0)) {
                // reset the playback counter
            #ifdef _WIN32
                FILETIME aTime;
                GetSystemTimeAsFileTime(&aTime);
                myRandGen.setSeed(aTime.dwLowDateTime);
            #else
                timeval aTime;
                gettimeofday(&aTime, NULL);
                myRandGen.setSeed(aTime.tv_usec);
            #endif
                myPlayedCount = 0;
                myCurrent->setPlayedFlag(!myCurrent->getPlayedFlag());
                ST_DEBUG_LOG("Restart the shuffle");
            }

            // determine next random position
            const size_t aCurrPos  = myCurrent->getPosition();
            bool         aCurrFlag = myCurrent->getPlayedFlag();
            StPlayItem*  aNextItem = myCurrent;
            const size_t aNextPos  = stMin(size_t(myRandGen.next() * myItemsCount), myItemsCount - 1);
            if(aNextPos > aCurrPos) {
                // forward direction
                for(size_t aNextDiff = aNextPos - aCurrPos; aNextItem != NULL && aNextDiff != 0; --aNextDiff) {
                    aNextItem = aNextItem->getNext();
                }
            } else {
                // backward direction
                for(size_t aNextDiff = aCurrPos - aNextPos; aNextItem != NULL && aNextDiff != 0; --aNextDiff) {
                    aNextItem = aNextItem->getPrev();
                }
            }
            if(aCurrFlag == aNextItem->getPlayedFlag()) {
                // find nearest position not yet played - prefer item farther from current one
                StPlayItem* aNextItem1 = aNextPos > aCurrPos ? aNextItem->getNext() : aNextItem->getPrev();
                StPlayItem* aNextItem2 = aNextPos > aCurrPos ? aNextItem->getPrev() : aNextItem->getNext();
                for(; aNextItem1 != NULL || aNextItem2 != NULL;) {
                    if(aNextItem1 != NULL) {
                        if(aCurrFlag != aNextItem1->getPlayedFlag()) {
                            aNextItem = aNextItem1;
                            break;
                        }
                        aNextItem1 = aNextPos > aCurrPos ? aNextItem1->getNext() : aNextItem1->getPrev();
                    }
                    if(aNextItem2 != NULL) {
                        if(aCurrFlag != aNextItem2->getPlayedFlag()) {
                            aNextItem = aNextItem2;
                            break;
                        }
                        aNextItem2 = aNextPos > aCurrPos ? aNextItem2->getPrev() : aNextItem2->getNext();
                    }
                }
                if(aCurrFlag == aNextItem->getPlayedFlag()) {
                    // something wrong!
                    ST_DEBUG_LOG("Disaster - next shuffle position not found!");
                    aCurrFlag     = !aCurrFlag;
                    myPlayedCount = 0;
                }
            }

            ST_DEBUG_LOG(aCurrPos + " -> " + aNextItem->getPosition());
            ++myPlayedCount;

            aNextItem->setPlayedFlag(aCurrFlag);
            myCurrent = aNextItem;
        }

        if(aPrev != myCurrent
        && aPrev != NULL) {
            myStackPrev.push_back(aPrev);
            if(myStackPrev.size() > THE_UNDO_LIMIT) {
                myStackPrev.pop_front();
            }
        }

        const size_t anItemId = myCurrent->getPosition();
        anAutoLock.unlock();
        signals.onPositionChange(anItemId);
        return true;
    } else if(myCurrent != myLast) {
        myCurrent = myCurrent->getNext();
        const size_t anItemId = myCurrent->getPosition();
        anAutoLock.unlock();
        signals.onPositionChange(anItemId);
        return true;
    } else if(myIsLoopFlag) {
        return walkToFirst();
    }
    return false;
}
Beispiel #28
0
void StPlayList::setLoopSingle(const bool theValue) {
    StMutexAuto anAutoLock(myMutex);
    myToLoopSingle = theValue;
}
Beispiel #29
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();
}
Beispiel #30
0
StString StPlayList::getCurrentTitle() const {
    StMutexAuto anAutoLock(myMutex);
    return (myCurrent != NULL) ? myCurrent->getTitle() : StString();
}