QList<InputPin> BackendNode::pins(const Filter &filter, PIN_DIRECTION wantedDirection) { QList<InputPin> ret; if (filter) { ComPointer<IEnumPins> enumPin; HRESULT hr = filter->EnumPins(enumPin.pparam()); Q_UNUSED(hr); Q_ASSERT( SUCCEEDED(hr)); InputPin pin; while (enumPin->Next(1, pin.pparam(), 0) == S_OK) { PIN_DIRECTION dir; hr = pin->QueryDirection(&dir); Q_ASSERT( SUCCEEDED(hr)); if (dir == wantedDirection) { ret.append(pin); } } } return ret; }
void WorkerThread::handleTask() { const Work w = dequeueWork(); if (m_finished) { return; } HRESULT hr = S_OK; m_currentRender = w.graph; m_currentRenderId = w.id; if (w.task == ReplaceGraph) { QMutexLocker locker(&m_mutex); HANDLE h; int index = -1; for(int i = 0; i < FILTER_COUNT; ++i) { if (m_graphHandle[i].graph == w.oldGraph) { m_graphHandle[i].graph = Graph(); index = i; break; } else if (index == -1 && m_graphHandle[i].graph == 0) { //this is the first available slot index = i; } } Q_ASSERT(index != -1); //add the new graph if (SUCCEEDED(ComPointer<IMediaEvent>(w.graph, IID_IMediaEvent) ->GetEventHandle(reinterpret_cast<OAEVENT*>(&h)))) { m_graphHandle[index].graph = w.graph; m_graphHandle[index].handle = h; } } else if (w.task == Render) { if (w.filter) { //let's render pins w.graph->AddFilter(w.filter, 0); const QList<OutputPin> outputs = BackendNode::pins(w.filter, PINDIR_OUTPUT); for (int i = 0; i < outputs.count(); ++i) { //blocking call hr = w.graph->Render(outputs.at(i)); if (FAILED(hr)) { break; } } } else if (!w.url.isEmpty()) { //let's render a url (blocking call) hr = w.graph->RenderFile(reinterpret_cast<const wchar_t *>(w.url.utf16()), 0); } if (hr != E_ABORT) { emit asyncRenderFinished(w.id, hr, w.graph); } } else if (w.task == Seek) { //that's a seekrequest ComPointer<IMediaSeeking> mediaSeeking(w.graph, IID_IMediaSeeking); qint64 newtime = w.time * 10000; hr = mediaSeeking->SetPositions(&newtime, AM_SEEKING_AbsolutePositioning, 0, AM_SEEKING_NoPositioning); qint64 currentTime = -1; if (SUCCEEDED(hr)) { hr = mediaSeeking->GetCurrentPosition(¤tTime); if (SUCCEEDED(hr)) { currentTime /= 10000; //convert to ms } } emit asyncSeekingFinished(w.id, currentTime); hr = E_ABORT; //to avoid emitting asyncRenderFinished } else if (w.task == ChangeState) { //remove useless decoders QList<Filter> unused; for (int i = 0; i < w.decoders.count(); ++i) { const Filter &filter = w.decoders.at(i); bool used = false; const QList<OutputPin> pins = BackendNode::pins(filter, PINDIR_OUTPUT); for( int i = 0; i < pins.count(); ++i) { InputPin input; if (pins.at(i)->ConnectedTo(input.pparam()) == S_OK) { used = true; } } if (!used) { unused += filter; } } //we can get the state for (int i = 0; i < unused.count(); ++i) { //we should remove this filter from the graph w.graph->RemoveFilter(unused.at(i)); } //we can get the state ComPointer<IMediaControl> mc(w.graph, IID_IMediaControl); //we change the state here switch(w.state) { case State_Stopped: mc->Stop(); break; case State_Paused: mc->Pause(); break; case State_Running: mc->Run(); break; } OAFilterState s; //blocking call HRESULT hr = mc->GetState(INFINITE, &s); if (SUCCEEDED(hr)) { if (s == State_Stopped) { emit stateReady(w.graph, Phonon::StoppedState); } else if (s == State_Paused) { emit stateReady(w.graph, Phonon::PausedState); } else { /*if (s == State_Running)*/ emit stateReady(w.graph, Phonon::PlayingState); } } } m_currentRender = Graph(); m_currentRenderId = 0; }