Ejemplo n.º 1
0
// Parse a string argument.  ASN1 strings can include nulls as valid characters.
void MHParseBinary::ParseString(int endStr, MHOctetString &str)
{
    // TODO: Don't deal with indefinite length at the moment.
    if (endStr == INDEFINITE_LENGTH)
    {
        MHERROR("Indefinite length strings are not implemented");
    }

    int nLength = endStr - m_p;
    unsigned char *stringValue = (unsigned char *)malloc(nLength + 1);
    if (stringValue == NULL)
    {
        MHERROR("Out of memory");
    }

    unsigned char *p = stringValue;

    while (m_p < endStr)
    {
        *p++ = GetNextChar();
    }

    str.Copy(MHOctetString((const char *)stringValue, nLength));
    free(stringValue);
}
Ejemplo n.º 2
0
void MHBitmap::ContentPreparation(MHEngine *engine)
{
    MHVisible::ContentPreparation(engine);
    if (m_ContentType == IN_NoContent)
        MHERROR("Bitmap must contain a content");
    if (m_ContentType == IN_IncludedContent) // We can't handle included content at the moment.
        MHERROR("Included content in bitmap is not implemented");
}
Ejemplo n.º 3
0
// Implement the TestVariable action.  Triggers a TestEvent event on the result.
void MHIntegerVar::TestVariable(int nOp, const MHUnion &parm, MHEngine *engine)
{
    parm.CheckType(MHUnion::U_Int);
    bool fRes = false;

    switch (nOp)
    {
        case TC_Equal:
            fRes = m_nValue == parm.m_nIntVal;
            break;
        case TC_NotEqual:
            fRes = m_nValue != parm.m_nIntVal;
            break;
        case TC_Less:
            fRes = m_nValue < parm.m_nIntVal;
            break;
        case TC_LessOrEqual:
            fRes = m_nValue <= parm.m_nIntVal;
            break;
        case TC_Greater:
            fRes = m_nValue > parm.m_nIntVal;
            break;
        case TC_GreaterOrEqual:
            fRes = m_nValue >= parm.m_nIntVal;
            break;
        default:
            MHERROR("Invalid comparison for int"); // Shouldn't ever happen
    }

    MHLOG(MHLogDetail, QString("Comparison %1 between %2 and %3 => %4").arg(TestToText(nOp))
          .arg(m_nValue).arg(parm.m_nIntVal).arg(fRes ? "true" : "false"));
    engine->EventTriggered(this, EventTestEvent, fRes);
}
Ejemplo n.º 4
0
// Implement the TestVariable action.  Triggers a TestEvent event on the result.
void MHOctetStrVar::TestVariable(int nOp, const MHUnion &parm, MHEngine *engine)
{
    parm.CheckType(MHUnion::U_String);
    int nRes = m_Value.Compare(parm.m_StrVal);
    bool fRes = false;

    switch (nOp)
    {
        case TC_Equal:
            fRes = nRes == 0;
            break;
        case TC_NotEqual:
            fRes = nRes != 0;
            break;
            /*  case TC_Less: fRes = nRes < 0; break;
                case TC_LessOrEqual: fRes = nRes <= 0; break;
                case TC_Greater: fRes = nRes > 0; break;
                case TC_GreaterOrEqual: fRes = nRes >= 0; break;*/
        default:
            MHERROR("Invalid comparison for string"); // Shouldn't ever happen
    }

    MHOctetString sample1(m_Value, 0, 10);
    MHOctetString sample2(parm.m_StrVal, 0, 10);
    MHLOG(MHLogDetail, QString("Comparison %1 %2 and %3 => %4").arg(TestToText(nOp))
          .arg(sample1.Printable()).arg(sample2.Printable()).arg(fRes ? "true" : "false"));
    engine->EventTriggered(this, EventTestEvent, fRes);
}
Ejemplo n.º 5
0
// Decode the content.
void MHBitmap::ContentArrived(const unsigned char *data, int length, MHEngine *engine)
{
    QRegion updateArea = GetVisibleArea(); // If there's any content already we have to redraw it.
    if (! m_pContent) return; // Shouldn't happen.

    int nCHook = m_nContentHook;
    if (nCHook == 0) nCHook = engine->GetDefaultBitmapCHook();

    // TODO: What if we can't convert it?
    if (nCHook == 4) { // PNG.
        m_pContent->CreateFromPNG(data, length);
    }
    // CHook 5 seems to be used by the BBC on Freesat for an MPEG I-frame for the
    // background but enabling it here results in it overlaying the video.
    // Presumably it is not simply the same as CHook 2.
    else if (nCHook == 2 /* ||nCHook == 5 */) { // MPEG I-frame.
        m_pContent->CreateFromMPEG(data, length);
    }

    else MHERROR(QString("Unknown bitmap content hook %1").arg(nCHook));

    updateArea += GetVisibleArea(); // Redraw this bitmap.
    engine->Redraw(updateArea); // Mark for redrawing

    // Now signal that the content is available.
    engine->EventTriggered(this, EventContentAvailable);
}
Ejemplo n.º 6
0
void MHUnion::CheckType(enum UnionTypes t) const
{
    if (m_Type != t)
    {
        MHERROR(QString("Type mismatch - expected %1 found %2").arg(GetAsString(m_Type)).arg(GetAsString(t)));
    }
}
Ejemplo n.º 7
0
// Parse an integer argument.  Also used for bool and enum.
int MHParseBinary::ParseInt(int endInt)
{
    int intVal = 0;
    bool firstByte = true;

    if (endInt == INDEFINITE_LENGTH)
    {
        MHERROR("Indefinite length integers are not implemented");
    }

    while (m_p < endInt)
    {
        unsigned char ch = GetNextChar();

        // Integer values are signed so if the top bit is set in the first byte
        // we need to set the sign bit.
        if (firstByte && ch >= 128)
        {
            intVal = -1;
        }

        firstByte = false;
        intVal = (intVal << 8) | ch;
    }

    return intVal;
}
Ejemplo n.º 8
0
// Return the indirect reference or fail if it's direct
MHObjectRef *MHGenericBase::GetReference()
{
    if (m_fIsDirect)
    {
        MHERROR("Expected indirect reference");
    }

    return &m_Indirect;
}
Ejemplo n.º 9
0
// Get the next byte.  In most all cases it's an error if we reach end-of-file
// and we throw an exception.
unsigned char MHParseBinary::GetNextChar()
{
    if (m_p >= (int)m_data.size())
    {
        MHERROR("Unexpected end of file");
    }

    return m_data[m_p++];
}
Ejemplo n.º 10
0
// Implement the TestVariable action.  Triggers a TestEvent event on the result.
void MHContentRefVar::TestVariable(int nOp, const MHUnion &parm, MHEngine *engine)
{
    parm.CheckType(MHUnion::U_ContentRef);
    bool fRes = false;
    switch (nOp) {
    case TC_Equal: fRes = m_Value.Equal(parm.m_ContentRefVal, engine); break;
    case TC_NotEqual: fRes = !m_Value.Equal(parm.m_ContentRefVal, engine); break;
    default: MHERROR("Invalid comparison for content ref");
    }
    engine->EventTriggered(this, EventTestEvent, fRes);
}
Ejemplo n.º 11
0
void MHGenericContentRef::Initialise(MHParseNode *pArg, MHEngine *engine)
{
    if (pArg->GetTagNo() == C_INDIRECTREFERENCE) {
        // Indirect reference.
        m_fIsDirect = false;
        m_Indirect.Initialise(pArg->GetArgN(0), engine);
    }
    else if (pArg->GetTagNo() == C_CONTENT_REFERENCE){ // Direct reference.
        m_fIsDirect = true;
        m_Direct.Initialise(pArg->GetArgN(0), engine);
    }
    else MHERROR("Expected direct or indirect content reference");
}
Ejemplo n.º 12
0
// Implement the TestVariable action.  Triggers a TestEvent event on the result.
void MHBooleanVar::TestVariable(int nOp, const MHUnion &parm, MHEngine *engine)
{
    parm.CheckType(MHUnion::U_Bool);
    bool fRes = false;
    switch (nOp) {
    case TC_Equal: fRes = m_fValue == parm.m_fBoolVal; break;
    case TC_NotEqual: fRes = m_fValue != parm.m_fBoolVal; break;
    default: MHERROR("Invalid comparison for bool");
    }
    MHLOG(MHLogDetail, QString("Comparison %1 between %2 and %3 => %4").arg(TestToText(nOp))
        .arg(m_fValue ? "true" : "false").arg(parm.m_fBoolVal ? "true" : "false").arg(fRes ? "true" : "false"));
    engine->EventTriggered(this, EventTestEvent, fRes);
}
Ejemplo n.º 13
0
// Content preparation.  If it's included we can set up the content.
void MHText::ContentPreparation(MHEngine *engine)
{
    MHVisible::ContentPreparation(engine);

    if (m_ContentType == IN_NoContent)
    {
        MHERROR("Text object must have content");
    }

    if (m_ContentType == IN_IncludedContent)
    {
        CreateContent(m_IncludedContent.Bytes(), m_IncludedContent.Size(), engine);
    }
}
Ejemplo n.º 14
0
void MHIngredient::SetData(const MHContentRef &referenced, bool /*fSizeGiven*/, int size, bool fCCGiven, int /*cc*/, MHEngine *engine)
{
    if (m_ContentType != IN_ReferencedContent)
    {
        MHERROR("SetData with referenced content applied to an ingredient without referenced content");
    }

    m_ContentRef.Copy(referenced);
    m_nContentSize = size;

    if (fCCGiven)
    {
        m_nCCPrio = m_nOrigCCPrio;
    }

    ContentPreparation(engine);
}
Ejemplo n.º 15
0
void MHEngine::TransitionToScene(const MHObjectRef &target)
{
    int i;

    if (m_fInTransition)
    {
        // TransitionTo is not allowed in OnStartUp or OnCloseDown actions.
        MHLOG(MHLogWarning, "WARN TransitionTo during transition - ignoring");
        return;
    }

    if (target.m_GroupId.Size() == 0)
    {
        return;    // No file name.
    }

    QString csPath = GetPathName(target.m_GroupId);

    // Check that the file exists before we commit to the transition.
    // This may block if we cannot be sure whether the object is present.
    QByteArray text;
    if (! m_Context->GetCarouselData(csPath, text)) {
        EngineEvent(2); // GroupIDRefError
        return;
    }

    // Parse and run the file.
    MHGroup *pProgram = ParseProgram(text);

    if (!pProgram )
        MHERROR("Empty scene");

    if (pProgram->m_fIsApp)
    {
        delete pProgram;
        MHERROR("Expected a scene");
    }

    // Clear the action queue of anything pending.
    m_ActionStack.clear();

    // At this point we have managed to load the scene.
    // Deactivate any non-shared ingredients in the application.
    MHApplication *pApp = CurrentApp();

    for (i = pApp->m_Items.Size(); i > 0; i--)
    {
        MHIngredient *pItem = pApp->m_Items.GetAt(i - 1);

        if (! pItem->IsShared())
        {
            pItem->Deactivation(this);    // This does not remove them from the display stack.
        }
    }

    m_fInTransition = true; // TransitionTo etc are not allowed.

    if (pApp->m_pCurrentScene)
    {
        pApp->m_pCurrentScene->Deactivation(this); // This may involve a call to RunActions
        pApp->m_pCurrentScene->Destruction(this);
    }

    // Everything that belongs to the previous scene should have been removed from the display stack.

    // At this point we may have added actions to the queue as a result of synchronous
    // events during the deactivation.

    // Remove any events from the asynch event queue unless they derive from
    // the application itself or a shared ingredient.
    MHAsynchEvent *pEvent;
    QQueue<MHAsynchEvent *>::iterator it = m_EventQueue.begin();

    while (it != m_EventQueue.end())
    {
        pEvent = *it;

        if (!pEvent->pEventSource->IsShared())
        {
            delete pEvent;
            it = m_EventQueue.erase(it);
        }
        else
        {
            ++it;
        }
    }

    // Can now actually delete the old scene.
    if (pApp->m_pCurrentScene)
    {
        delete(pApp->m_pCurrentScene);
        pApp->m_pCurrentScene = NULL;
    }

    m_Interacting = 0;

    // Switch to the new scene.
    CurrentApp()->m_pCurrentScene = static_cast< MHScene* >(pProgram);
    SetInputRegister(CurrentScene()->m_nEventReg);
    m_redrawRegion = QRegion(0, 0, CurrentScene()->m_nSceneCoordX, CurrentScene()->m_nSceneCoordY); // Redraw the whole screen

    if ((__mhlogoptions & MHLogScenes) && __mhlogStream != 0)   // Print it so we know what's going on.
    {
        pProgram->PrintMe(__mhlogStream, 0);
    }

    pProgram->Preparation(this);
    pProgram->Activation(this);
    m_fInTransition = false; // The transition is complete
}
Ejemplo n.º 16
0
// Lexical analysis.  Get the next symbol.
void MHParseText::NextSym()
{
    while (1) {

        switch (m_ch) {
        case '\n': m_lineCount++; // And drop to next
        case ' ': case '\r': case '\t': case '\f':
            // Skip white space.
            GetNextChar();
            continue;

        case '/':
            { // Comment.
                GetNextChar();
                if (m_ch != '/') Error("Malformed comment");
                do { GetNextChar(); } while (m_ch != '\n' && m_ch != '\f' && m_ch != '\r');
                continue; // Next symbol
            }

        case ':': // Start of a tag
            {
                m_nType = PTTag;
                char buff[MAX_TAG_LENGTH+1];
                char *p = buff;
                do {
                    *p++ = m_ch;
                    GetNextChar();
                    if (p == buff + MAX_TAG_LENGTH) break;
                } while ((m_ch >= 'a' && m_ch <= 'z') || (m_ch >= 'A' && m_ch <= 'Z'));
                *p = 0;

                // Look it up and return it if it's found.
                m_nTag = FindTag(buff);
                if (m_nTag >= 0) return;
                // Unrecognised tag.
                Error("Unrecognised tag");
            }

        case '"': // Start of a string
            {
                m_nType = PTString;
                // MHEG strings can include NULLs.  For the moment we pass back the length and also
                // null-terminate the strings.
                m_nStringLength = 0;
                while (1) {
                    GetNextChar();
                    if (m_ch == '"') break; // Finished the string.
                    if (m_ch == '\\') GetNextChar(); // Escape character. Include the next char in the string.
                    if (m_ch == '\n' || m_ch == '\r') Error("Unterminated string");
                    // We grow the buffer to the largest string in the input.
                    unsigned char *str = (unsigned char*)realloc(m_String, m_nStringLength+2);
                    if (str == NULL) Error("Insufficient memory");
                    m_String = str;
                    m_String[m_nStringLength++] = m_ch;
                }
                GetNextChar(); // Skip the closing quote
                m_String[m_nStringLength] = 0;
                return;
            }

        case '\'': // Start of a string using quoted printable
            {
                m_nType = PTString;
                m_nStringLength = 0;
                // Quotable printable strings contain escape sequences beginning with the
                // escape character '='.  The strings can span lines but each line must
                // end with an equal sign.
                while (1) {
                    GetNextChar();
                    if (m_ch == '\'') break;
                    if (m_ch == '\n') Error("Unterminated string");
                    if (m_ch == '=') { // Special code in quoted-printable.
                        // Should be followed by two hex digits or by white space and a newline.
                        GetNextChar();
                        if (m_ch == ' ' || m_ch == '\t' || m_ch == '\r' || m_ch == '\n') {
                            // White space.  Remove everything up to the newline.
                            while (m_ch != '\n') {
                                if (! (m_ch == ' ' || m_ch == '\t' || m_ch == '\r')) {
                                    Error("Malformed quoted printable string");
                                }
                                GetNextChar();
                            }
                            continue; // continue with the first character on the next line
                        }
                        else {
                            int byte = 0;
                            if (m_ch >= '0' && m_ch <= '9') byte = m_ch - '0';
                            else if (m_ch >= 'A' && m_ch <= 'F') byte = m_ch - 'A' + 10;
                            else if (m_ch >= 'a' && m_ch <= 'f') byte = m_ch - 'a' + 10;
                            else Error("Malformed quoted printable string");
                            byte *= 16;
                            GetNextChar();
                            if (m_ch >= '0' && m_ch <= '9') byte += m_ch - '0';
                            else if (m_ch >= 'A' && m_ch <= 'F') byte += m_ch - 'A' + 10;
                            else if (m_ch >= 'a' && m_ch <= 'f') byte += m_ch - 'a' + 10;
                            else Error("Malformed quoted printable string");
                            m_ch = byte; // Put this into the string.
                        }
                    }
                    // We grow the buffer to the largest string in the input.
                    unsigned char *str = (unsigned char*)realloc(m_String, m_nStringLength+2);
                    if (str == NULL) Error("Insufficient memory");
                    m_String = str;
                    m_String[m_nStringLength++] = m_ch;
                }
                GetNextChar(); // Skip the closing quote
                m_String[m_nStringLength] = 0;
                return;
            }

        case '`': // Start of a string using base 64
            // These can, presumably span lines.
            MHERROR("Base 64 string is not implemented");
            break;

        case '#': // Start of 3-byte hex constant.
            MHERROR("3-byte hex constant is not implemented");
            break;

        case '-': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
            {
                m_nType = PTInt;
                bool negative = m_ch == '-';
                if (negative) {
                    GetNextChar();
                    if (m_ch < '0' || m_ch > '9') Error("Expected digit after '-'");
                }
                // Start of a number.  Hex can be represented as 0xn.
                // Strictly speaking hex values cannot be preceded by a minus sign.
                m_nInt = m_ch - '0';
                GetNextChar();
                if (m_nInt == 0 && (m_ch == 'x' || m_ch == 'X')) {
                    MHERROR("Hex constant is not implemented");
                }
                while (m_ch >= '0' && m_ch <= '9') {
                    m_nInt = m_nInt * 10 + m_ch - '0';
                    // TODO: What about overflow?
                    GetNextChar();
                }
                if (negative) m_nInt = -m_nInt;
                return;
            }

        case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': case 'j':
        case 'k': case 'l': case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': case 's': case 't':
        case 'u': case 'v': case 'w': case 'x': case 'y': case 'z': 
        case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': case 'J':
        case 'K': case 'L': case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T':
        case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z':
            { // Start of an enumerated type.
                m_nType = PTEnum;
                char buff[MAX_ENUM+1];
                char *p = buff;
                do {
                    *p++ = m_ch;
                    GetNextChar();
                    if (p == buff+MAX_ENUM) break;
                }
                while ((m_ch >= 'a' && m_ch <= 'z') || (m_ch >= 'A' && m_ch <= 'Z') || m_ch == '-');
                *p = '\0';
                if (stricmp(buff, "NULL") == 0) { m_nType = PTNull; return; }
                if (stricmp(buff, "true") == 0) { m_nType = PTBool; m_fBool = true; return; }
                if (stricmp(buff, "false") == 0) { m_nType = PTBool; m_fBool = false; return; }
                // Look up the tag in all the tables.  Fortunately all the enumerations
                // are distinct so we don't need to know the context.
                m_nInt = MHLink::GetEventType(buff);
                if (m_nInt > 0) return;
                m_nInt = MHText::GetJustification(buff);
                if (m_nInt > 0) return;
                m_nInt = MHText::GetLineOrientation(buff);
                if (m_nInt > 0) return;
                m_nInt = MHText::GetStartCorner(buff);
                if (m_nInt > 0) return;
                m_nInt = MHSlider::GetOrientation(buff);
                if (m_nInt > 0) return;
                m_nInt = MHSlider::GetStyle(buff);
                if (m_nInt > 0) return;

                // Check the colour table.  If it's there generate a string containing the colour info.
                for (int i = 0; i < (int)(sizeof(colourTable)/sizeof(colourTable[0])); i++) {
                    if (stricmp(buff, colourTable[i].name) == 0) {
                        m_nType = PTString;
                        unsigned char *str = (unsigned char*)realloc(m_String, 4+1);
                        if (str == NULL) Error("Insufficient memory");
                        m_String[0] = colourTable[i].r;
                        m_String[1] = colourTable[i].g;
                        m_String[2] = colourTable[i].b;
                        m_String[3] = colourTable[i].t;
                        m_String = str;
                        m_nStringLength = 4;
                        return;
                    }
                }

                Error("Unrecognised enumeration");
                break;
            }

        case '{': // Start of a "section".
            // The standard indicates that open brace followed by a tag should be written
            // as a single word.  We'll be more lenient and allow spaces or comments between them.
            m_nType = PTStartSection;
            GetNextChar();
            return;

        case '}': // End of a "section".
            m_nType = PTEndSection;
            GetNextChar();
            return;

        case '(': // Start of a sequence.
            m_nType = PTStartSeq;
            GetNextChar();
            return;

        case ')': // End of a sequence.
            m_nType = PTEndSeq;
            GetNextChar();
            return;

        case EOF:
            m_nType = PTEOF;
            return;

        default:
            Error("Unknown character");
            GetNextChar();
        }
    }
}
Ejemplo n.º 17
0
void MHParseText::Error(const char *str)
{
    MHERROR(QString("%1- at line %2\n").arg(str).arg(m_lineCount));
}
Ejemplo n.º 18
0
void MHGroup::Initialise(MHParseNode *p, MHEngine *engine)
{
    engine->GetGroupId().Copy(""); // Set to empty before we start (just in case).
    MHRoot::Initialise(p, engine);

    // Must be an external reference with an object number of zero.
    if (m_ObjectReference.m_nObjectNo != 0 || m_ObjectReference.m_GroupId.Size() == 0)
    {
        MHERROR("Object reference for a group object must be zero and external");
    }

    // Set the group id for the rest of the group to this.
    engine->GetGroupId().Copy(m_ObjectReference.m_GroupId);
    // Some of the information is irrelevant.
    //  MHParseNode *pStdId = p->GetNamedArg(C_STANDARD_IDENTIFIER);
    //  MHParseNode *pStdVersion = p->GetNamedArg(C_STANDARD_VERSION);
    //  MHParseNode *pObjectInfo = p->GetNamedArg(C_OBJECT_INFORMATION);

    MHParseNode *pOnStartUp = p->GetNamedArg(C_ON_START_UP);

    if (pOnStartUp)
    {
        m_StartUp.Initialise(pOnStartUp, engine);
    }

    MHParseNode *pOnCloseDown = p->GetNamedArg(C_ON_CLOSE_DOWN);

    if (pOnCloseDown)
    {
        m_CloseDown.Initialise(pOnCloseDown, engine);
    }

    MHParseNode *pOriginalGCPrio = p->GetNamedArg(C_ORIGINAL_GC_PRIORITY);

    if (pOriginalGCPrio)
    {
        m_nOrigGCPriority = pOriginalGCPrio->GetArgN(0)->GetIntValue();
    }

    // Ignore the other stuff at the moment.
    MHParseNode *pItems = p->GetNamedArg(C_ITEMS);

    if (pItems == NULL)
    {
        p->Failure("Missing :Items block");
        return;
    }

    for (int i = 0; i < pItems->GetArgCount(); i++)
    {
        MHParseNode *pItem = pItems->GetArgN(i);
        MHIngredient *pIngredient = NULL;

        try
        {
            // Generate the particular kind of ingredient.
            switch (pItem->GetTagNo())
            {
                case C_RESIDENT_PROGRAM:
                    pIngredient = new MHResidentProgram;
                    break;
                case C_REMOTE_PROGRAM:
                    pIngredient = new MHRemoteProgram;
                    break;
                case C_INTERCHANGED_PROGRAM:
                    pIngredient = new MHInterChgProgram;
                    break;
                case C_PALETTE:
                    pIngredient = new MHPalette;
                    break;
                case C_FONT:
                    pIngredient = new MHFont;
                    break;
                case C_CURSOR_SHAPE:
                    pIngredient = new MHCursorShape;
                    break;
                case C_BOOLEAN_VARIABLE:
                    pIngredient = new MHBooleanVar;
                    break;
                case C_INTEGER_VARIABLE:
                    pIngredient = new MHIntegerVar;
                    break;
                case C_OCTET_STRING_VARIABLE:
                    pIngredient = new MHOctetStrVar;
                    break;
                case C_OBJECT_REF_VARIABLE:
                    pIngredient = new MHObjectRefVar;
                    break;
                case C_CONTENT_REF_VARIABLE:
                    pIngredient = new MHContentRefVar;
                    break;
                case C_LINK:
                    pIngredient = new MHLink;
                    break;
                case C_STREAM:
                    pIngredient = new MHStream;
                    break;
                case C_BITMAP:
                    pIngredient = new MHBitmap;
                    break;
                case C_LINE_ART:
                    pIngredient = new MHLineArt;
                    break;
                case C_DYNAMIC_LINE_ART:
                    pIngredient = new MHDynamicLineArt;
                    break;
                case C_RECTANGLE:
                    pIngredient = new MHRectangle;
                    break;
                case C_HOTSPOT:
                    pIngredient = new MHHotSpot;
                    break;
                case C_SWITCH_BUTTON:
                    pIngredient = new MHSwitchButton;
                    break;
                case C_PUSH_BUTTON:
                    pIngredient = new MHPushButton;
                    break;
                case C_TEXT:
                    pIngredient = new MHText;
                    break;
                case C_ENTRY_FIELD:
                    pIngredient = new MHEntryField;
                    break;
                case C_HYPER_TEXT:
                    pIngredient = new MHHyperText;
                    break;
                case C_SLIDER:
                    pIngredient = new MHSlider;
                    break;
                case C_TOKEN_GROUP:
                    pIngredient = new MHTokenGroup;
                    break;
                case C_LIST_GROUP:
                    pIngredient = new MHListGroup;
                    break;
                default:
                    MHLOG(MHLogWarning, QString("Unknown ingredient %1").arg(pItem->GetTagNo()));
                    // Future proofing: ignore any ingredients that we don't know about.
                    // Obviously these can only arise in the binary coding.
            }

            if (pIngredient)
            {
                // Initialise it from its argments.
                pIngredient->Initialise(pItem, engine);

                // Remember the highest numbered ingredient
                if (pIngredient->m_ObjectReference.m_nObjectNo > m_nLastId)
                {
                    m_nLastId = pIngredient->m_ObjectReference.m_nObjectNo;
                }

                // Add it to the ingedients of this group.
                m_Items.Append(pIngredient);
            }
        }
        catch (...)
        {
            delete(pIngredient);
            throw;
        }
    }
}
Ejemplo n.º 19
0
 virtual void Perform(MHEngine *)
 {
     MHERROR(QString("Unimplemented action %1").arg(m_nTag));
 }
Ejemplo n.º 20
0
//  Simple recursive parser for ASN1 BER.
MHParseNode *MHParseBinary::DoParse()
{
    unsigned char ch;
    // Tag class
    enum { Universal, Context/*, Pseudo*/ } tagClass = Universal;
    // Byte count of end of this item.  Set to INDEFINITE_LENGTH if the length is Indefinite.
    int endOfItem;
    unsigned int tagNumber = 0;

    // Read the first character.
    ch = GetNextChar();

    // ASN1 Coding rules: Top two bits (0 and 1) indicate the tag class.
    // 0x00 - Universal,  0x40 - Application, 0x80 - Context-specific, 0xC0 - Private
    // We only use Universal and Context.
    switch (ch & 0xC0)
    {
        case 0x00: // Universal
            tagClass = Universal;
            break;
        case 0x80:
            tagClass = Context;
            break;
        default:
            MHERROR(QString("Invalid tag class = %1").arg(ch, 0, 16));
    }

    // Bit 2 indicates whether it is a simple or compound type.  Not used.
    // Lower bits are the tag number.
    tagNumber = ch & 0x1f;

    if (tagNumber == 0x1f)   // Except that if it is 0x1F then the tag is encoded in the following bytes.
    {
        tagNumber = 0;

        do
        {
            ch = GetNextChar();
            tagNumber = (tagNumber << 7) | (ch & 0x7f);
        }
        while (ch & 0x80);   // Top bit set means there's more to come.
    }

    // Next byte is the length.  If it is less than 128 it is the actual length, otherwise it
    // gives the number of bytes containing the length, except that if this is zero the item
    // has an "indefinite" length and is terminated by two zero bytes.
    ch = GetNextChar();

    if (ch & 0x80)
    {
        int lengthOfLength = ch & 0x7f;

        if (lengthOfLength == 0)
        {
            endOfItem = INDEFINITE_LENGTH;
        }
        else
        {
            endOfItem = 0;

            while (lengthOfLength--)
            {
                ch = GetNextChar();
                endOfItem = (endOfItem << 8) | ch;
            }

            endOfItem += m_p;
        }
    }
    else
    {
        endOfItem = ch + m_p;
    }

    if (tagClass == Context)
    {
        MHPTagged *pNode = new MHPTagged(tagNumber);

        try
        {
            // The argument here depends on the particular tag we're processing.
            switch (tagNumber)
            {
                case C_MULTIPLE_SELECTION:
                case C_OBSCURED_INPUT:
                case C_INITIALLY_AVAILABLE:
                case C_WRAP_AROUND:
                case C_TEXT_WRAPPING:
                case C_INITIALLY_ACTIVE:
                case C_MOVING_CURSOR:
                case C_SHARED:
                case C_ENGINE_RESP:
                case C_TILING:
                case C_BORDERED_BOUNDING_BOX:
                {
                    // BOOL
                    // If there is no argument we need to indicate that so that it gets
                    // the correct default value.
                    if (m_p != endOfItem)
                    {
                        int intVal = ParseInt(endOfItem); // May raise an exception
                        pNode->AddArg(new MHPBool(intVal != 0));
                    }

                    break;
                }

                case C_INPUT_TYPE:
                case C_SLIDER_STYLE:
                case C_TERMINATION:
                case C_ORIENTATION:
                case C_HORIZONTAL_JUSTIFICATION:
                case C_BUTTON_STYLE:
                case C_START_CORNER:
                case C_LINE_ORIENTATION:
                case C_VERTICAL_JUSTIFICATION:
                case C_STORAGE:
                {
                    // ENUM
                    if (m_p != endOfItem)
                    {
                        int intVal = ParseInt(endOfItem); // May raise an exception
                        pNode->AddArg(new MHPEnum(intVal));
                    }

                    break;
                }

                case C_INITIAL_PORTION:
                case C_STEP_SIZE:
                case C_INPUT_EVENT_REGISTER:
                case C_INITIAL_VALUE:
                case C_IP_CONTENT_HOOK:
                case C_MAX_VALUE:
                case C_MIN_VALUE:
                case C_LINE_ART_CONTENT_HOOK:
                case C_BITMAP_CONTENT_HOOK:
                case C_TEXT_CONTENT_HOOK:
                case C_STREAM_CONTENT_HOOK:
                case C_MAX_LENGTH:
                case C_CHARACTER_SET:
                case C_ORIGINAL_TRANSPARENCY:
                case C_ORIGINAL_GC_PRIORITY:
                case C_LOOPING:
                case C_ORIGINAL_LINE_STYLE:
                case C_STANDARD_VERSION:
                case C_ORIGINAL_LINE_WIDTH:
                case C_CONTENT_HOOK:
                case C_CONTENT_CACHE_PRIORITY:
                case C_COMPONENT_TAG:
                case C_ORIGINAL_VOLUME:
                case C_PROGRAM_CONNECTION_TAG:
                case C_CONTENT_SIZE:
                {
                    // INT
                    if (m_p != endOfItem)
                    {
                        int intVal = ParseInt(endOfItem); // May raise an exception
                        pNode->AddArg(new MHPInt(intVal));
                    }

                    break;
                }

                case C_OBJECT_INFORMATION:
                case C_CONTENT_REFERENCE:
                case C_FONT_ATTRIBUTES:
                case C_CHAR_LIST:
                case C_NAME:
                case C_ORIGINAL_LABEL:
                {
                    // STRING
                    // Unlike INT, BOOL and ENUM we can't distinguish an empty string
                    // from a missing string.
                    MHOctetString str;
                    ParseString(endOfItem, str);
                    pNode->AddArg(new MHPString(str));
                    break;
                }

                default:
                {
                    // Everything else has either no argument or is self-describing
                    // TODO: Handle indefinite length.
                    if (endOfItem == INDEFINITE_LENGTH)
                    {
                        MHERROR("Indefinite length arguments are not implemented");
                    }

                    while (m_p < endOfItem)
                    {
                        pNode->AddArg(DoParse());
                    }
                }
            }
        }
        catch (...)
        {
            // Memory clean-up
            delete pNode;
            throw;
        }

        return pNode;
    }
    else   // Universal - i.e. a primitive type.
    {
        // Tag values

        switch (tagNumber)
        {
            case U_BOOL: // Boolean
            {
                int intVal = ParseInt(endOfItem);
                return new MHPBool(intVal != 0);
            }
            case U_INT: // Integer
            {
                int intVal = ParseInt(endOfItem);
                return new MHPInt(intVal);
            }
            case U_ENUM: // ENUM
            {
                int intVal = ParseInt(endOfItem);
                return new MHPEnum(intVal);
            }
            case U_STRING: // String
            {
                MHOctetString str;
                ParseString(endOfItem, str);
                return new MHPString(str);
            }
            case U_NULL: // ASN1 NULL
            {
                return new MHPNull;
            }
            case U_SEQUENCE: // Sequence
            {
                MHParseSequence *pNode = new MHParseSequence();

                if (endOfItem == INDEFINITE_LENGTH)
                {
                    MHERROR("Indefinite length sequences are not implemented");
                }

                try
                {
                    while (m_p < endOfItem)
                    {
                        pNode->Append(DoParse());
                    }
                }
                catch (...)
                {
                    // Memory clean-up if error.
                    delete pNode;
                    throw;
                }

                return pNode;
            }
            default:
                MHERROR(QString("Unknown universal %1").arg(tagNumber));
        }
    }
}
Ejemplo n.º 21
0
void MHResidentProgram::CallProgram(bool fIsFork, const MHObjectRef &success, const MHSequence<MHParameter *> &args, MHEngine *engine)
{
    if (! m_fAvailable)
    {
        Preparation(engine);
    }

    //  if (m_fRunning) return; // Strictly speaking there should be only one instance of a program running at a time.
    Activation(engine);
    MHLOG(MHLogDetail, QString("Calling program %1").arg(m_Name.Printable()));

    try
    {
        // Run the code.
        if (m_Name.Equal("GCD"))   // GetCurrentDate - returns local time.
        {
            if (args.Size() == 2)
            {
                time_t epochSeconds = 0;
                short int timeZone = 0;
#if HAVE_GETTIMEOFDAY
                struct timeval   time;
                struct timezone  zone;

                if (gettimeofday(&time, &zone) == -1)
                {
                    MHLOG(MHLogDetail, QString("gettimeofday() failed"));
                }

                epochSeconds     = time.tv_sec;
                timeZone = zone.tz_minuteswest;
#elif HAVE_FTIME
                struct timeb timebuffer;
                if (ftime(&timebuffer) == -1)
                {
                    MHLOG(MHLogDetail, QString("ftime() failed"));
                }
                epochSeconds = timebuffer.time;
                timeZone = timebuffer.timezone;
#else
#error Configuration error? No ftime() or gettimeofday()?
#endif
                // Adjust the time to local.  TODO: Check this.
                epochSeconds -= timeZone * 60;
                // Time as seconds since midnight.
                int nTimeAsSecs = epochSeconds % (24 * 60 * 60);
                // Modified Julian date as number of days since 17th November 1858.
                // 1st Jan 1970 was date 40587.
                int nModJulianDate = 40587 + epochSeconds / (24 * 60 * 60);

                engine->FindObject(*(args.GetAt(0)->GetReference()))->SetVariableValue(nModJulianDate);
                engine->FindObject(*(args.GetAt(1)->GetReference()))->SetVariableValue(nTimeAsSecs);
                SetSuccessFlag(success, true, engine);
            }
            else
            {
                SetSuccessFlag(success, false, engine);
            }
        }

        else if (m_Name.Equal("FDa"))   // FormatDate
        {
            if (args.Size() == 4)
            {
                // This is a bit like strftime but not quite.
                MHOctetString format;
                GetString(args.GetAt(0), format, engine);
                int date = GetInt(args.GetAt(1), engine); // As produced in GCD
                int time = GetInt(args.GetAt(2), engine);
                // Convert to a Unix date (secs since 1st Jan 1970) but adjusted for time zone.
                time_t timet = (date - 40587) * (24 * 60 * 60) + time;
                struct tm *timeStr = gmtime(&timet);
                MHOctetString result;

                for (int i = 0; i < format.Size(); i++)
                {
                    unsigned char ch = format.GetAt(i);
                    char buffer[5]; // Largest text is 4 chars for a year + null terminator

                    if (ch == '%')
                    {
                        i++;

                        if (i == format.Size())
                        {
                            break;
                        }

                        ch = format.GetAt(i);
                        buffer[0] = 0;

                        switch (ch)
                        {
                            case 'Y':
                                sprintf(buffer, "%04d", timeStr->tm_year + 1900);
                                break;
                            case 'y':
                                sprintf(buffer, "%02d", timeStr->tm_year % 100);
                                break;
                            case 'X':
                                sprintf(buffer, "%02d", timeStr->tm_mon + 1);
                                break;
                            case 'x':
                                sprintf(buffer, "%1d", timeStr->tm_mon + 1);
                                break;
                            case 'D':
                                sprintf(buffer, "%02d", timeStr->tm_mday);
                                break;
                            case 'd':
                                sprintf(buffer, "%1d", timeStr->tm_mday);
                                break;
                            case 'H':
                                sprintf(buffer, "%02d", timeStr->tm_hour);
                                break;
                            case 'h':
                                sprintf(buffer, "%1d", timeStr->tm_hour);
                                break;
                            case 'I':

                                if (timeStr->tm_hour == 12 || timeStr->tm_hour == 0)
                                {
                                    strcpy(buffer, "12");
                                }
                                else
                                {
                                    sprintf(buffer, "%02d", timeStr->tm_hour % 12);
                                }

                                break;
                            case 'i':

                                if (timeStr->tm_hour == 12 || timeStr->tm_hour == 0)
                                {
                                    strcpy(buffer, "12");
                                }
                                else
                                {
                                    sprintf(buffer, "%1d", timeStr->tm_hour % 12);
                                }

                                break;
                            case 'M':
                                sprintf(buffer, "%02d", timeStr->tm_min);
                                break;
                            case 'm':
                                sprintf(buffer, "%1d", timeStr->tm_min);
                                break;
                            case 'S':
                                sprintf(buffer, "%02d", timeStr->tm_sec);
                                break;
                            case 's':
                                sprintf(buffer, "%1d", timeStr->tm_sec);
                                break;
                                // TODO: These really should be localised.
                            case 'A':

                                if (timeStr->tm_hour < 12)
                                {
                                    strcpy(buffer, "AM");
                                }
                                else
                                {
                                    strcpy(buffer, "PM");
                                }

                                break;
                            case 'a':

                                if (timeStr->tm_hour < 12)
                                {
                                    strcpy(buffer, "am");
                                }
                                else
                                {
                                    strcpy(buffer, "pm");
                                }

                                break;
                            default:
                                buffer[0] = ch;
                                buffer[1] = 0;
                        }

                        result.Append(buffer);
                    }
                    else
                    {
                        result.Append(MHOctetString(&ch, 1));
                    }
                }

                MHParameter *pResString = args.GetAt(3);
                engine->FindObject(*(pResString->GetReference()))->SetVariableValue(result);
                SetSuccessFlag(success, true, engine);
            }
            else
            {
                SetSuccessFlag(success, false, engine);
            }
        }

        else if (m_Name.Equal("GDW"))   // GetDayOfWeek - returns the day of week that the date occurred on.
        {
            if (args.Size() == 2)
            {
                int date = GetInt(args.GetAt(0), engine); // Date as produced in GCD
                // Convert to a Unix date (secs since 1st Jan 1970) but adjusted for time zone.
                time_t timet = (date - 40587) * (24 * 60 * 60);
                struct tm *timeStr = gmtime(&timet);
                // 0 => Sunday, 1 => Monday etc.
                engine->FindObject(*(args.GetAt(1)->GetReference()))->SetVariableValue(timeStr->tm_wday);
                SetSuccessFlag(success, true, engine);
            }
            else
            {
                SetSuccessFlag(success, false, engine);
            }
        }

        else if (m_Name.Equal("Rnd"))   // Random
        {
            if (args.Size() == 2)
            {
                int nLimit = GetInt(args.GetAt(0), engine);
                MHParameter *pResInt = args.GetAt(1);
                int r = random() % (nLimit + 1);
                engine->FindObject(
                    *(pResInt->GetReference()))->SetVariableValue(r);
                SetSuccessFlag(success, true, engine);
            }
            else
            {
                SetSuccessFlag(success, false, engine);
            }
        }

        else if (m_Name.Equal("CTC"))   // CastToContentRef
        {
            // Converts a string to a ContentRef.
            if (args.Size() == 2)
            {
                MHOctetString string;
                GetString(args.GetAt(0), string, engine);
                MHContentRef result;
                result.m_ContentRef.Copy(string);
                engine->FindObject(*(args.GetAt(1)->GetReference()))->SetVariableValue(result);
                SetSuccessFlag(success, true, engine);
            }
            else
            {
                SetSuccessFlag(success, false, engine);
            }
        }

        else if (m_Name.Equal("CTO"))   // CastToObjectRef
        {
            // Converts a string and an integer to an ObjectRef.
            if (args.Size() == 3)
            {
                MHObjectRef result;
                GetString(args.GetAt(0), result.m_GroupId, engine);
                result.m_nObjectNo = GetInt(args.GetAt(1), engine);
                engine->FindObject(*(args.GetAt(2)->GetReference()))->SetVariableValue(result);
                SetSuccessFlag(success, true, engine);
            }
            else
            {
                SetSuccessFlag(success, false, engine);
            }
        }

        else if (m_Name.Equal("GSL"))   // GetStringLength
        {
            if (args.Size() == 2)
            {
                // Find a substring within a string and return an index to the position.
                MHOctetString string;
                GetString(args.GetAt(0), string, engine);
                MHParameter *pResInt = args.GetAt(1);
                SetSuccessFlag(success, true, engine);
                engine->FindObject(*(pResInt->GetReference()))->SetVariableValue(string.Size());
            }
            else
            {
                SetSuccessFlag(success, false, engine);
            }
        }

        else if (m_Name.Equal("GSS"))   // GetSubString
        {
            if (args.Size() == 4)   // Extract a sub-string from a string.
            {
                MHOctetString string;
                GetString(args.GetAt(0), string, engine);
                int nBeginExtract = GetInt(args.GetAt(1), engine);
                int nEndExtract = GetInt(args.GetAt(2), engine);

                if (nBeginExtract < 1)
                {
                    nBeginExtract = 1;
                }

                if (nBeginExtract > string.Size())
                {
                    nBeginExtract = string.Size();
                }

                if (nEndExtract < 1)
                {
                    nEndExtract = 1;
                }

                if (nEndExtract > string.Size())
                {
                    nEndExtract = string.Size();
                }

                MHParameter *pResString = args.GetAt(3);
                // Returns beginExtract to endExtract inclusive.
                engine->FindObject(*(pResString->GetReference()))->SetVariableValue(
                    MHOctetString(string, nBeginExtract - 1, nEndExtract - nBeginExtract + 1));
                SetSuccessFlag(success, true, engine);
            }
            else
            {
                SetSuccessFlag(success, false, engine);
            }
        }

        else if (m_Name.Equal("SSS"))   // SearchSubString
        {
            if (args.Size() == 4)
            {
                // Find a substring within a string and return an index to the position.
                MHOctetString string, searchString;
                GetString(args.GetAt(0), string, engine);
                int nStart = GetInt(args.GetAt(1), engine);

                if (nStart < 1)
                {
                    nStart = 1;
                }

                GetString(args.GetAt(2), searchString, engine);
                // Strings are indexed from one.
                int nPos;

                for (nPos = nStart - 1; nPos <= string.Size() - searchString.Size(); nPos++)
                {
                    int i;

                    for (i = 0; i < searchString.Size(); i++)
                    {
                        if (searchString.GetAt(i) != string.GetAt(i + nPos))
                        {
                            break;
                        }
                    }

                    if (i == searchString.Size())
                    {
                        break;    // Found a match.
                    }
                }

                // Set the result.
                MHParameter *pResInt = args.GetAt(3);
                SetSuccessFlag(success, true, engine); // Set this first.

                if (nPos <= string.Size() - searchString.Size())   // Found
                {
                    // Set the index to the position of the string, counting from 1.
                    engine->FindObject(*(pResInt->GetReference()))->SetVariableValue(nPos + 1);
                }
                else   // Not found.  Set the result index to -1
                {
                    engine->FindObject(*(pResInt->GetReference()))->SetVariableValue(-1);
                }
            }
            else
            {
                SetSuccessFlag(success, false, engine);
            }
        }

        else if (m_Name.Equal("SES"))   // SearchAndExtractSubString
        {
            if (args.Size() == 5)
            {
                // Find a substring within a string and return an index to the position
                // and the prefix to the substring.
                MHOctetString string, searchString;
                GetString(args.GetAt(0), string, engine);
                int nStart = GetInt(args.GetAt(1), engine);

                if (nStart < 1)
                {
                    nStart = 1;
                }

                GetString(args.GetAt(2), searchString, engine);
                // Strings are indexed from one.
                int nPos;

                for (nPos = nStart - 1; nPos <= string.Size() - searchString.Size(); nPos++)
                {
                    int i;

                    for (i = 0; i < searchString.Size(); i++)
                    {
                        if (searchString.GetAt(i) != string.GetAt(i + nPos))
                        {
                            break;    // Doesn't match
                        }
                    }

                    if (i == searchString.Size())
                    {
                        break;    // Found a match.
                    }
                }

                // Set the results.
                MHParameter *pResString = args.GetAt(3);
                MHParameter *pResInt = args.GetAt(4);
                SetSuccessFlag(success, true, engine); // Set this first.

                if (nPos <= string.Size() - searchString.Size())   // Found
                {
                    // Set the index to the position AFTER the string, counting from 1.
                    engine->FindObject(*(pResInt->GetReference()))->SetVariableValue(nPos + 1 + searchString.Size());
                    // Return the sequence from nStart-1 of length nPos-nStart+1
                    MHOctetString resultString(string, nStart - 1, nPos - nStart + 1);
                    engine->FindObject(*(pResString->GetReference()))->SetVariableValue(resultString);
                }
                else   // Not found.  Set the result string to empty and the result index to -1
                {
                    engine->FindObject(*(pResInt->GetReference()))->SetVariableValue(-1);
                    engine->FindObject(*(pResString->GetReference()))->SetVariableValue(MHOctetString(""));
                }
            }
            else
            {
                SetSuccessFlag(success, false, engine);
            }
        }

        else if (m_Name.Equal("GSI"))   // SI_GetServiceIndex
        {
            // Returns an index indicating the service
            if (args.Size() == 2)
            {
                MHOctetString string;
                GetString(args.GetAt(0), string, engine);
                MHParameter *pResInt = args.GetAt(1);
                // The format of the service is dvb://netID.[transPortID].serviceID
                // where the IDs are in hex.
                // or rec://svc/lcn/N where N is the "logical channel number" i.e. the Freeview channel.
                QString str = QString::fromUtf8((const char *)string.Bytes(), string.Size());
                int nResult = engine->GetContext()->GetChannelIndex(str);
                engine->FindObject(*(pResInt->GetReference()))->SetVariableValue(nResult);
                SetSuccessFlag(success, nResult >= 0, engine);
            }
            else
            {
                SetSuccessFlag(success, false, engine);
            }
        }

        else if (m_Name.Equal("TIn"))   // SI_TuneIndex - Fork not allowed
        {
            // Tunes to an index returned by GSI
            if (args.Size() == 1)
            {
                int nChannel = GetInt(args.GetAt(0), engine);
                bool res = nChannel >= 0 ? engine->GetContext()->TuneTo(
                               nChannel, engine->GetTuneInfo()) : false;
                SetSuccessFlag(success, res, engine);
            }
            else
            {
                SetSuccessFlag(success, false, engine);
            }
        }
        else if (m_Name.Equal("TII"))   // SI_TuneIndexInfo
        {
            // Indicates whether to perform a subsequent TIn quietly or normally.
            if (args.Size() == 1)
            {
                int tuneinfo = GetInt(args.GetAt(0), engine);
                engine->SetTuneInfo(tuneinfo);
                SetSuccessFlag(success, true, engine);
            }
            else
            {
                SetSuccessFlag(success, false, engine);
            }
        }
        else if (m_Name.Equal("BSI"))   // SI_GetBasicSI
        {
            // Returns basic SI information about the service indicated by an index
            // returned by GSI.
            // Returns networkID, origNetworkID, transportStreamID, serviceID
            if (args.Size() == 5)
            {
                int channelId = GetInt(args.GetAt(0), engine);
                int netId, origNetId, transportId, serviceId;
                // Look the information up in the database.
                bool res = engine->GetContext()->GetServiceInfo(channelId, netId, origNetId,
                                                                transportId, serviceId);

                if (res)
                {
                    engine->FindObject(*(args.GetAt(1)->GetReference()))->SetVariableValue(netId);
                    engine->FindObject(*(args.GetAt(2)->GetReference()))->SetVariableValue(origNetId);
                    engine->FindObject(*(args.GetAt(3)->GetReference()))->SetVariableValue(transportId);
                    engine->FindObject(*(args.GetAt(4)->GetReference()))->SetVariableValue(serviceId);
                }

                SetSuccessFlag(success, res, engine);
            }
            else
            {
                SetSuccessFlag(success, false, engine);
            }
        }
        else if (m_Name.Equal("GBI"))   // GetBootInfo
        {
            // Gets the NB_info field.
            MHERROR("GetBootInfo ResidentProgram is not implemented");
        }
        else if (m_Name.Equal("CCR"))   // CheckContentRef
        {
            // Sees if an item with a particular content reference is available
            // in the carousel.  This looks like it should block until the file
            // is available.  The profile recommends that this should be forked
            // rather than called.
            if (args.Size() == 3)
            {
                MHUnion un;
                un.GetValueFrom(*(args.GetAt(0)), engine);
                un.CheckType(MHUnion::U_ContentRef);
                MHContentRef fileName;
                fileName.Copy(un.m_ContentRefVal);
                QString csPath = engine->GetPathName(fileName.m_ContentRef);
                bool result = false;
                QByteArray text;

                // Try to load the object.
                if (! csPath.isEmpty())
                {
                    result = engine->GetContext()->GetCarouselData(csPath, text);
                }

                // Set the result variable.
                MHParameter *pResFlag = args.GetAt(1);
                engine->FindObject(*(pResFlag->GetReference()))->SetVariableValue(result);
                MHParameter *pResCR = args.GetAt(2);
                // Copy the file name to the resulting content ref.
                engine->FindObject(*(pResCR->GetReference()))->SetVariableValue(fileName);
                SetSuccessFlag(success, true, engine);
            }
            else
            {
                SetSuccessFlag(success, false, engine);
            }
        }
        else if (m_Name.Equal("CGR"))   // CheckGroupIDRef
        {
            // Sees if an application or scene with a particular group id
            // is available in the carousel.
            MHERROR("CheckGroupIDRef ResidentProgram is not implemented");
        }
        else if (m_Name.Equal("VTG"))   // VideoToGraphics
        {
            // Video to graphics transformation.
            MHERROR("VideoToGraphics ResidentProgram is not implemented");
        }
        else if (m_Name.Equal("SWA"))   // SetWidescreenAlignment
        {
            // Sets either LetterBox or Centre-cut-out mode.
            // Seems to be concerned with aligning a 4:3 scene with an underlying 16:9 video
            MHERROR("SetWidescreenAlignment ResidentProgram is not implemented");
        }
        else if (m_Name.Equal("GDA"))   // GetDisplayAspectRatio
        {
            // Returns the aspcet ratio.  4:3 => 1, 16:9 => 2
            MHERROR("GetDisplayAspectRatio ResidentProgram is not implemented");
        }
        else if (m_Name.Equal("CIS"))   // CI_SendMessage
        {
            // Sends a message to a DVB CI application
            MHERROR("CI_SendMessage ResidentProgram is not implemented");
        }
        else if (m_Name.Equal("SSM"))   // SetSubtitleMode
        {
            // Enable or disable subtitles in addition to MHEG.
            if (args.Size() == 1) {
                bool status = GetBool(args.GetAt(0), engine);
                MHLOG(MHLogNotifications, QString("NOTE SetSubtitleMode %1")
                    .arg(status ? "enabled" : "disabled"));
                // TODO Notify player
                SetSuccessFlag(success, true, engine);
            }
            else SetSuccessFlag(success, false, engine);
        }

        else if (m_Name.Equal("WAI"))   // WhoAmI
        {
            // Return a concatenation of the strings we respond to in
            // GetEngineSupport(UKEngineProfile(X))
            if (args.Size() == 1)
            {
                MHOctetString result;
                result.Copy(engine->MHEGEngineProviderIdString);
                result.Append(" ");
                result.Append(engine->GetContext()->GetReceiverId());
                result.Append(" ");
                result.Append(engine->GetContext()->GetDSMCCId());
                engine->FindObject(*(args.GetAt(0)->GetReference()))->SetVariableValue(result);
                SetSuccessFlag(success, true, engine);
            }
            else
            {
                SetSuccessFlag(success, false, engine);
            }
        }

        else if (m_Name.Equal("DBG"))   // Debug - optional
        {
            QString message = "DEBUG: ";

            for (int i = 0; i < args.Size(); i++)
            {
                MHUnion un;
                un.GetValueFrom(*(args.GetAt(i)), engine);

                switch (un.m_Type)
                {
                    case MHUnion::U_Int:
                        message.append(QString("%1").arg(un.m_nIntVal));
                        break;
                    case MHParameter::P_Bool:
                        message.append(un.m_fBoolVal ? "True" : "False");
                        break;
                    case MHParameter::P_String:
                        message.append(QString::fromUtf8((const char *)un.m_StrVal.Bytes(), un.m_StrVal.Size()));
                        break;
                    case MHParameter::P_ObjRef:
                        message.append(un.m_ObjRefVal.Printable());
                        break;
                    case MHParameter::P_ContentRef:
                        message.append(un.m_ContentRefVal.Printable());
                        break;
                    case MHParameter::P_Null:
                        break;
                }
            }

            MHLOG(MHLogNotifications, message);
        }

        else if (m_Name.Equal("SBI"))   // SetBroadcastInterrupt
        {
            // Required for NativeApplicationExtension
            // En/dis/able program interruptions e.g. green button
            if (args.Size() == 1) {
                bool status = GetBool(args.GetAt(0), engine);
                MHLOG(MHLogNotifications, QString("NOTE SetBroadcastInterrupt %1")
                    .arg(status ? "enabled" : "disabled"));
                // Nothing todo at present
                SetSuccessFlag(success, true, engine);
            }
            else SetSuccessFlag(success, false, engine);
        }

        // InteractionChannelExtension
        else if (m_Name.Equal("GIS")) { // GetICStatus
            if (args.Size() == 1)
            {
                int ICstatus = engine->GetContext()->GetICStatus();
                MHLOG(MHLogNotifications, "NOTE InteractionChannel " + QString(
                    ICstatus == 0 ? "active" : ICstatus == 1 ? "inactive" :
                    ICstatus == 2 ? "disabled" : "undefined"));
                engine->FindObject(*(args.GetAt(0)->GetReference()))->SetVariableValue(ICstatus);
                SetSuccessFlag(success, true, engine);
            }
            else SetSuccessFlag(success, false, engine);
        }
        else if (m_Name.Equal("RDa")) { // ReturnData
            if (args.Size() >= 3)
            {
                MHOctetString string;
                GetString(args.GetAt(0), string, engine);
                QString url = QString::fromUtf8((const char *)string.Bytes(), string.Size());

                // Variable name/value pairs
                QStringList params;
                int i = 1;
                for (; i + 2 < args.Size(); i += 2)
                {
                    GetString(args.GetAt(i), string, engine);
                    QString name = QString::fromUtf8((const char *)string.Bytes(), string.Size());
                    QString val;
                    MHUnion un;
                    un.GetValueFrom(*(args.GetAt(i+1)), engine);
                    switch (un.m_Type) {
                    case MHUnion::U_Int:
                        val = QString::number(un.m_nIntVal);
                        break;
                    case MHParameter::P_Bool:
                        val = un.m_fBoolVal ? "true" : "false";
                        break;
                    case MHParameter::P_String:
                        val = QString::fromUtf8((const char*)un.m_StrVal.Bytes(), un.m_StrVal.Size());
                        break;
                    case MHParameter::P_ObjRef:
                        val = un.m_ObjRefVal.Printable();
                        break;
                    case MHParameter::P_ContentRef:
                        val = un.m_ContentRefVal.Printable();
                        break;
                    case MHParameter::P_Null:
                        val = "<NULL>";
                        break;
                    default:
                        val = QString("<type %1>").arg(un.m_Type);
                        break;
                    }
                    params += name + "=" + val;
                }
                // TODO
                MHLOG(MHLogNotifications, "NOTE ReturnData '" + url + "' { " + params.join(" ") + " }");
                // HTTP response code, 0= none
                engine->FindObject(*(args.GetAt(i)->GetReference()))->SetVariableValue(0);
                // HTTP response data
                string = "";
                engine->FindObject(*(args.GetAt(i+1)->GetReference()))->SetVariableValue(string);
                SetSuccessFlag(success, false, engine);
            }
            else SetSuccessFlag(success, false, engine);
        }
        else if (m_Name.Equal("SHF")) { // SetHybridFileSystem
            if (args.Size() == 2)
            {
                MHOctetString string;
                GetString(args.GetAt(0), string, engine);
                QString str = QString::fromUtf8((const char *)string.Bytes(), string.Size());
                GetString(args.GetAt(1), string, engine);
                QString str2 = QString::fromUtf8((const char *)string.Bytes(), string.Size());
                // TODO
                MHLOG(MHLogNotifications, QString("NOTE SetHybridFileSystem %1=%2")
                    .arg(str).arg(str2));
                SetSuccessFlag(success, false, engine);
            }
            else SetSuccessFlag(success, false, engine);
        }

        else
        {
            MHERROR(QString("Unknown ResidentProgram %1").arg(m_Name.Printable()));
        }
    }
    catch (char const *)
    {
        // If something went wrong set the succeeded flag to false
        SetSuccessFlag(success, false, engine);
        // And continue on.  In particular we need to deactivate.
    }

    Deactivation(engine);

    // At the moment we always treat Fork as Call.  If we do get a Fork we should signal that we're done.
    if (fIsFork)
    {
        engine->EventTriggered(this, EventAsyncStopped);
    }
}
Ejemplo n.º 22
0
// Report a failure.  This can be called when we use the parse tree to set up object tree.
void MHParseNode::Failure(const char *p)
{
    MHERROR(p);
}