Beispiel #1
0
// Called when an event is triggered.  Either queues the event or finds a link that matches.
void MHEngine::EventTriggered(MHRoot *pSource, enum EventType ev, const MHUnion &evData)
{
    MHLOG(MHLogLinks, QString("Event - %1 from %2")
          .arg(MHLink::EventTypeToString(ev)).arg(pSource->m_ObjectReference.Printable()));

    switch (ev)
    {
        case EventFirstItemPresented:
        case EventHeadItems:
        case EventHighlightOff:
        case EventHighlightOn:
        case EventIsAvailable:
        case EventIsDeleted:
        case EventIsDeselected:
        case EventIsRunning:
        case EventIsSelected:
        case EventIsStopped:
        case EventItemDeselected:
        case EventItemSelected:
        case EventLastItemPresented:
        case EventTailItems:
        case EventTestEvent:
        case EventTokenMovedFrom:
        case EventTokenMovedTo:
            // Synchronous events.  Fire any links that are waiting.
            // The UK MHEG describes this as the preferred interpretation.  We are checking the link
            // at the time we generate the event rather than queuing the synchronous events until
            // this elementary action is complete.  That matters if we are processing an elementary action
            // which will activate or deactivate links.
            CheckLinks(pSource->m_ObjectReference, ev, evData);
            break;
        case EventAnchorFired:
        case EventAsyncStopped:
        case EventContentAvailable:
        case EventCounterTrigger:
        case EventCursorEnter:
        case EventCursorLeave:
        case EventEngineEvent:
        case EventEntryFieldFull:
        case EventInteractionCompleted:
        case EventStreamEvent:
        case EventStreamPlaying:
        case EventStreamStopped:
        case EventTimerFired:
        case EventUserInput:
        case EventFocusMoved: // UK MHEG.  Generated by HyperText class
        case EventSliderValueChanged: // UK MHEG.  Generated by Slider class
        default:
        {
            // Asynchronous events.  Add to the event queue.
            MHAsynchEvent *pEvent = new MHAsynchEvent;
            pEvent->pEventSource = pSource;
            pEvent->eventType = ev;
            pEvent->eventData = evData;
            m_EventQueue.enqueue(pEvent);
        }
        break;
    }
}
Beispiel #2
0
// This is the main loop of the engine.
int MHEngine::RunAll()
{
    // Request to boot or reboot
    if (m_fBooting)
    {
        // Reset everything
        while (!m_ApplicationStack.isEmpty())
        {
            delete m_ApplicationStack.pop();
        }

        while (!m_EventQueue.isEmpty())
        {
            delete m_EventQueue.dequeue();
        }

        while (!m_ExternContentTable.isEmpty())
        {
            delete m_ExternContentTable.takeFirst();
        }

        m_LinkTable.clear();

        // UK MHEG applications boot from ~//a or ~//startup.  Actually the initial
        // object can also be explicitly given in the
        MHObjectRef startObj;
        startObj.m_nObjectNo = 0;
        startObj.m_GroupId.Copy(MHOctetString("~//a"));

        // Launch will block until either it finds the appropriate object and
        // begins the application or discovers that the file definitely isn't
        // present in the carousel.  It is possible that the object might appear
        // if one of the containing directories is updated.
        if (! Launch(startObj))
        {
            startObj.m_GroupId.Copy(MHOctetString("~//startup"));

            if (! Launch(startObj))
            {
                MHLOG(MHLogNotifications, "NOTE Engine auto-boot failed");
                return -1;
            }
        }

        m_fBooting = false;
    }

    int nNextTime = 0;

    do
    {
        // Check to see if we need to close.
        if (m_Context->CheckStop())
        {
            return 0;
        }

        // Run queued actions.
        RunActions();
        // Now the action stack is empty process the next asynchronous event.
        // Processing one event may affect how subsequent events are handled.

        // Check to see if some files we're waiting for have arrived.
        // This could result in ContentAvailable events.
        CheckContentRequests();

        // Check the timers.  This may result in timer events being raised.
        nNextTime = CurrentScene() ? CurrentScene()->CheckTimers(this) : 0;

        if (CurrentApp())
        {
            // The UK MHEG profile allows applications to have timers.
            int nAppTime = CurrentApp()->CheckTimers(this);

            if (nAppTime != 0 && (nNextTime == 0 || nAppTime < nNextTime))
            {
                nNextTime = nAppTime;
            }
        }

        if (! m_ExternContentTable.isEmpty())
        {
            // If we have an outstanding request for external content we need to set a timer.
            if (nNextTime == 0 || nNextTime > CONTENT_CHECK_TIME)
            {
                nNextTime = CONTENT_CHECK_TIME;
            }
        }

        if (! m_EventQueue.isEmpty())
        {
            MHAsynchEvent *pEvent = m_EventQueue.dequeue();
            MHLOG(MHLogLinks, QString("Asynchronous event dequeued - %1 from %2")
                  .arg(MHLink::EventTypeToString(pEvent->eventType))
                  .arg(pEvent->pEventSource->m_ObjectReference.Printable()));
            CheckLinks(pEvent->pEventSource->m_ObjectReference, pEvent->eventType, pEvent->eventData);
            delete pEvent;
        }
    }
    while (! m_EventQueue.isEmpty() || ! m_ActionStack.isEmpty());

    // Redraw the display if necessary.
    if (! m_redrawRegion.isEmpty())
    {
        m_Context->RequireRedraw(m_redrawRegion);
        m_redrawRegion = QRegion();
    }

    return nNextTime;
}
Beispiel #3
0
GDALProxyPoolCacheEntry* GDALDatasetPool::_RefDataset(const char* pszFileName, GDALAccess eAccess)
{
    GDALProxyPoolCacheEntry* cur = firstEntry;
    GIntBig responsiblePID = GDALGetResponsiblePIDForCurrentThread();
    GDALProxyPoolCacheEntry* lastEntryWithZeroRefCount = NULL;

    while(cur)
    {
        GDALProxyPoolCacheEntry* next = cur->next;

        if (strcmp(cur->pszFileName, pszFileName) == 0 &&
            cur->responsiblePID == responsiblePID)
        {
            if (cur != firstEntry)
            {
                /* Move to begin */
                if (cur->next)
                    cur->next->prev = cur->prev;
                else
                    lastEntry = cur->prev;
                cur->prev->next = cur->next;
                cur->prev = NULL;
                firstEntry->prev = cur;
                cur->next = firstEntry;
                firstEntry = cur;

#ifdef DEBUG_PROXY_POOL
                CheckLinks();
#endif
            }

            cur->refCount ++;
            return cur;
        }

        if (cur->refCount == 0)
            lastEntryWithZeroRefCount = cur;

        cur = next;
    }

    if (currentSize == maxSize)
    {
        if (lastEntryWithZeroRefCount == NULL)
        {
            CPLError(CE_Failure, CPLE_AppDefined,
                     "Too many threads are running for the current value of the dataset pool size (%d).\n"
                     "or too many proxy datasets are opened in a cascaded way.\n"
                     "Try increasing GDAL_MAX_DATASET_POOL_SIZE.", maxSize);
            return NULL;
        }

        CPLFree(lastEntryWithZeroRefCount->pszFileName);
        lastEntryWithZeroRefCount->pszFileName = NULL;
        if (lastEntryWithZeroRefCount->poDS)
        {
            /* Close by pretending we are the thread that GDALOpen'ed this */
            /* dataset */
            GDALSetResponsiblePIDForCurrentThread(lastEntryWithZeroRefCount->responsiblePID);

            refCountOfDisableRefCount ++;
            GDALClose(lastEntryWithZeroRefCount->poDS);
            refCountOfDisableRefCount --;

            lastEntryWithZeroRefCount->poDS = NULL;
            GDALSetResponsiblePIDForCurrentThread(responsiblePID);
        }

        /* Recycle this entry for the to-be-openeded dataset and */
        /* moves it to the top of the list */
        if (lastEntryWithZeroRefCount->prev)
            lastEntryWithZeroRefCount->prev->next = lastEntryWithZeroRefCount->next;
        else {
            CPLAssert(0);
        }
        if (lastEntryWithZeroRefCount->next)
            lastEntryWithZeroRefCount->next->prev = lastEntryWithZeroRefCount->prev;
        else
        {
            CPLAssert(lastEntryWithZeroRefCount == lastEntry);
            lastEntry->prev->next = NULL;
            lastEntry = lastEntry->prev;
        }
        lastEntryWithZeroRefCount->prev = NULL;
        lastEntryWithZeroRefCount->next = firstEntry;
        firstEntry->prev = lastEntryWithZeroRefCount;
        cur = firstEntry = lastEntryWithZeroRefCount;
#ifdef DEBUG_PROXY_POOL
        CheckLinks();
#endif
    }
    else
    {
        /* Prepend */
        cur = (GDALProxyPoolCacheEntry*) CPLMalloc(sizeof(GDALProxyPoolCacheEntry));
        if (lastEntry == NULL)
            lastEntry = cur;
        cur->prev = NULL;
        cur->next = firstEntry;
        if (firstEntry)
            firstEntry->prev = cur;
        firstEntry = cur;
        currentSize ++;
#ifdef DEBUG_PROXY_POOL
        CheckLinks();
#endif
    }

    cur->pszFileName = CPLStrdup(pszFileName);
    cur->responsiblePID = responsiblePID;
    cur->refCount = 1;

    refCountOfDisableRefCount ++;
    cur->poDS = (GDALDataset*) GDALOpen(pszFileName, eAccess);
    refCountOfDisableRefCount --;

    return cur;
}