Ejemplo n.º 1
0
// Return the value, looking up any indirect ref.
void MHGenericOctetString::GetValue(MHOctetString &str, MHEngine *engine) const
{
    if (m_fIsDirect) str.Copy(m_Direct);
    else {
        MHUnion result;
        MHRoot *pBase = engine->FindObject(m_Indirect);
        pBase->GetVariableValue(result, engine);
        // From my reading of the MHEG documents implicit conversion is only
        // performed when assigning variables.  Nevertheless the Channel 4
        // Teletext assumes that implicit conversion takes place here as well.
        if (result.m_Type == MHUnion::U_Int) {
            // Implicit conversion of int to string.
            char buff[30]; // 30 chars is more than enough.
#ifdef WIN32
            _snprintf(buff, sizeof(buff), "%0d", result.m_nIntVal);
#else
            snprintf(buff, sizeof(buff), "%0d", result.m_nIntVal);
#endif
            str.Copy(buff);
        }
        else {
            result.CheckType(MHUnion::U_String);
            str.Copy(result.m_StrVal);
        }
    }
}
Ejemplo n.º 2
0
// Construct a substring.
MHOctetString::MHOctetString(const MHOctetString &str, int nOffset, int nLen)
{
    if (nLen < 0)
    {
        nLen = str.Size() - nOffset;    // The rest of the string.
    }

    if (nLen < 0)
    {
        nLen = 0;
    }

    if (nLen > str.Size())
    {
        nLen = str.Size();
    }

    m_nLength = nLen;

    if (nLen == 0)
    {
        m_pChars = 0;
    }
    else
    {
        m_pChars = (unsigned char *)malloc(nLen + 1);

        if (! m_pChars)
        {
            throw "Out of memory";
        }

        memcpy(m_pChars, str.m_pChars + nOffset, nLen);
    }
}
Ejemplo n.º 3
0
void MHEngine::GetDefaultFontAttrs(MHOctetString &str)
{
    MHApplication *pApp = CurrentApp();

    if (pApp && pApp->m_FontAttrs.Size() > 0)
    {
        str.Copy(pApp->m_FontAttrs);
    }
    else
    {
        str.Copy("plain.24.24.0");    // TODO: Check this.
    }
}
Ejemplo n.º 4
0
// Create a canonical path name.  The rules are given in the UK MHEG document.
QString MHEngine::GetPathName(const MHOctetString &str)
{
    if (str.Size() == 0)
        return QString();

    QString csPath = QString::fromUtf8((const char *)str.Bytes(), str.Size());
    switch (PathProtocol(csPath))
    {
    default:
    case kProtoUnknown:
    case kProtoHybrid:
    case kProtoHTTP:
    case kProtoCI:
        return csPath;
    case kProtoDSM:
        break;
    }

    if (csPath.startsWith("DSM:"))
        csPath = csPath.mid(4); // Remove DSM:
    else if (csPath.startsWith("~"))
        csPath = csPath.mid(1); // Remove ~
    if (!csPath.startsWith("//"))
    {
        // Add the current application's path name
        if (CurrentApp())
        {
            csPath = CurrentApp()->m_Path + csPath;
        }
    }

    // Remove any occurrences of x/../
    int nPos;

    while ((nPos = csPath.indexOf("/../")) >= 0)
    {
        int nEnd = nPos + 4;

        while (nPos >= 1 && csPath[nPos-1] != '/')
        {
            nPos--;
        }

        csPath = csPath.left(nPos) + csPath.mid(nEnd);
    }

    return csPath;
}
Ejemplo n.º 5
0
// Extract a string value.
static void GetString(MHParameter *parm, MHOctetString &str, MHEngine *engine)
{
    MHUnion un;
    un.GetValueFrom(*parm, engine);
    un.CheckType(MHUnion::U_String);
    str.Copy(un.m_StrVal);
}
Ejemplo n.º 6
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.º 7
0
// String
void MHParseNode::GetStringValue(MHOctetString &str)
{
    if (m_nNodeType != PNString)
    {
        Failure("Expected string");
    }

    str.Copy(((MHPString *)this)->m_Value);
}
Ejemplo n.º 8
0
// Find out what we support.
bool MHEngine::GetEngineSupport(const MHOctetString &feature)
{
    QString csFeat = QString::fromUtf8((const char *)feature.Bytes(), feature.Size());
    QStringList strings = csFeat.split(QRegExp("[\\(\\,\\)]"));

    MHLOG(MHLogNotifications, "NOTE GetEngineSupport " + csFeat);

    if (strings[0] == "ApplicationStacking" || strings[0] == "ASt")
    {
        return true;
    }

    // We're required to support cloning for Text, Bitmap and Rectangle.
    if (strings[0] == "Cloning" || strings[0] == "Clo")
    {
        return true;
    }

    if (strings[0] == "SceneCoordinateSystem" || strings[0] == "SCS")
    {
        if (strings.count() >= 3 && strings[1] == "720" && strings[2] == "576")
        {
            return true;
        }
        else
        {
            return false;
        }

        // I've also seen SceneCoordinateSystem(1,1)
    }

    if (strings[0] == "MultipleAudioStreams" || strings[0] == "MAS")
    {
        if (strings.count() >= 2 && (strings[1] == "0" || strings[1] == "1"))
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    if (strings[0] == "MultipleVideoStreams" || strings[0] == "MVS")
    {
        if (strings.count() >= 2 && (strings[1] == "0" || strings[1] == "1"))
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    // We're supposed to return true for all values of N
    if (strings[0] == "OverlappingVisibles" || strings[0] == "OvV")
    {
        return true;
    }

    if (strings[0] == "SceneAspectRatio" || strings[0] == "SAR")
    {
        if (strings.count() < 3)
        {
            return false;
        }
        else if ((strings[1] == "4" && strings[2] == "3") || (strings[1] == "16" && strings[2] == "9"))
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    // We're supposed to support these at least.  May also support(10,1440,1152)
    if (strings[0] == "VideoScaling" || strings[0] == "VSc")
    {
        if (strings.count() < 4 || strings[1] != "10")
        {
            return false;
        }
        else if ((strings[2] == "720" && strings[3] == "576") || (strings[2] == "360" && strings[3] == "288"))
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    if (strings[0] == "BitmapScaling" || strings[0] == "BSc")
    {
        if (strings.count() < 4 || strings[1] != "2")
        {
            return false;
        }
        else if ((strings[2] == "720" && strings[3] == "576") || (strings[2] == "360" && strings[3] == "288"))
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    // I think we only support the video fully on screen
    if (strings[0] == "VideoDecodeOffset" || strings[0] == "VDO")
    {
        if (strings.count() >= 3 && strings[1] == "10" && strings[1] == "0")
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    // We support bitmaps that are partially off screen (don't we?)
    if (strings[0] == "BitmapDecodeOffset" || strings[0] == "BDO")
    {
        if (strings.count() >= 3 && strings[1] == "2" && (strings[2] == "0" || strings[2] == "1"))
        {
            return true;
        }
        else if (strings.count() >= 2 && (strings[1] == "4" || strings[1] == "6"))
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    if (strings[0] == "UKEngineProfile" || strings[0] == "UniversalEngineProfile" || strings[0] == "UEP")
    {
        if (strings.count() < 2)
        {
            return false;
        }

        if (strings[1] == MHEGEngineProviderIdString)
        {
            return true;
        }

        if (strings[1] == m_Context->GetReceiverId())
        {
            return true;
        }

        if (strings[1] == m_Context->GetDSMCCId())
        {
            return true;
        }

        // The UK profile 1.06 seems a bit confused on this point.  It is not clear whether
        // we are supposed to return true for UKEngineProfile(2) or not.
        if (strings[1] == "2")
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    // InteractionChannelExtension.
    if (strings[0] == "ICProfile" || strings[0] == "ICP") {
        if (strings.count() != 2) return false;
        if (strings[1] == "0")
            return true; // // InteractionChannelExtension.
        if (strings[1] == "1")
            return false; // ICStreamingExtension.
        return false;
    }

    // Otherwise return false.
    return false;
}
Ejemplo n.º 9
0
// UK MHEG. Interpret the font attributes.
static void InterpretAttributes(const MHOctetString &attrs, int &style, int &size, int &lineSpace, int &letterSpace)
{
    // Set the defaults.
    style = 0;
    size = 0x18;
    lineSpace = 0x18;
    letterSpace = 0;

    if (attrs.Size() == 5)   // Short form.
    {
        style = attrs.GetAt(0); // Only the bottom nibble is significant.
        size = attrs.GetAt(1);
        lineSpace = attrs.GetAt(2);
        // Is this big-endian or little-endian?  Assume big.
        letterSpace = attrs.GetAt(3) * 256 + attrs.GetAt(4);

        if (letterSpace > 32767)
        {
            letterSpace -= 65536;    // Signed.
        }
    }
    else   // Textual form.
    {
        const unsigned char *str = attrs.Bytes();
        char *p = (char *)str;
        char *q = strchr(p, '.'); // Find the terminating dot

        if (q != NULL)   // plain, italic etc.
        {
            if (q - p == 6 && strncmp(p, "italic", 6) == 0)
            {
                style = 1;
            }
            else if (q - p == 4 && strncmp(p, "bold", 4) == 0)
            {
                style = 2;
            }
            else if (q - p == 11 && strncmp(p, "bold-italic", 11) == 0)
            {
                style = 3;
            }

            // else it's plain.
            p = q + 1;
            q = strchr(p, '.'); // Find the next dot.
        }

        if (q != NULL)   // Size
        {
            size = atoi(p);

            if (size == 0)
            {
                size = 0x18;
            }

            p = q + 1;
            q = strchr(p, '.'); // Find the next dot.
        }

        if (q != NULL)   // lineSpacing
        {
            lineSpace = atoi(p);

            if (lineSpace == 0)
            {
                lineSpace = 0x18;
            }

            p = q + 1;
            q = strchr(p, '.'); // Find the next dot.
        }

        if (q != NULL)   // letter spacing.  May be zero or negative
        {
            letterSpace = atoi(p);
        }
    }
}
Ejemplo n.º 10
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.º 11
0
MHParseNode *MHParseText::DoParse()
{
    MHParseNode *pRes = NULL;
    try {
        switch (m_nType) {
        case PTStartSection: // Open curly bracket
            {
                NextSym();
                // Should be followed by a tag.
                if (m_nType != PTTag) Error("Expected ':' after '{'");
                MHPTagged *pTag = new MHPTagged(m_nTag);
                pRes = pTag;
                NextSym();
                while (m_nType != PTEndSection) {
                    pTag->AddArg(DoParse());
                }
                NextSym(); // Remove the close curly bracket.
                break;
            }

        case PTTag: // Tag on its own.
            {
                int nTag = m_nTag;
                MHPTagged *pTag = new MHPTagged(nTag);
                pRes = pTag;
                NextSym();
                switch (nTag) {
                case C_ITEMS:
                case C_LINK_EFFECT:
                case C_ACTIVATE:
                case C_ADD:
                case C_ADD_ITEM:
                case C_APPEND:
                case C_BRING_TO_FRONT:
                case C_CALL:
                case C_CALL_ACTION_SLOT:
                case C_CLEAR:
                case C_CLONE:
                case C_CLOSE_CONNECTION:
                case C_DEACTIVATE:
                case C_DEL_ITEM:
                case C_DESELECT:
                case C_DESELECT_ITEM:
                case C_DIVIDE:
                case C_DRAW_ARC:
                case C_DRAW_LINE:
                case C_DRAW_OVAL:
                case C_DRAW_POLYGON:
                case C_DRAW_POLYLINE:
                case C_DRAW_RECTANGLE:
                case C_DRAW_SECTOR:
                case C_FORK:
                case C_GET_AVAILABILITY_STATUS:
                case C_GET_BOX_SIZE:
                case C_GET_CELL_ITEM:
                case C_GET_CURSOR_POSITION:
                case C_GET_ENGINE_SUPPORT:
                case C_GET_ENTRY_POINT:
                case C_GET_FILL_COLOUR:
                case C_GET_FIRST_ITEM:
                case C_GET_HIGHLIGHT_STATUS:
                case C_GET_INTERACTION_STATUS:
                case C_GET_ITEM_STATUS:
                case C_GET_LABEL:
                case C_GET_LAST_ANCHOR_FIRED:
                case C_GET_LINE_COLOUR:
                case C_GET_LINE_STYLE:
                case C_GET_LINE_WIDTH:
                case C_GET_LIST_ITEM:
                case C_GET_LIST_SIZE:
                case C_GET_OVERWRITE_MODE:
                case C_GET_PORTION:
                case C_GET_POSITION:
                case C_GET_RUNNING_STATUS:
                case C_GET_SELECTION_STATUS:
                case C_GET_SLIDER_VALUE:
                case C_GET_TEXT_CONTENT:
                case C_GET_TEXT_DATA:
                case C_GET_TOKEN_POSITION:
                case C_GET_VOLUME:
                case C_LAUNCH:
                case C_LOCK_SCREEN:
                case C_MODULO:
                case C_MOVE:
                case C_MOVE_TO:
                case C_MULTIPLY:
                case C_OPEN_CONNECTION:
                case C_PRELOAD:
                case C_PUT_BEFORE:
                case C_PUT_BEHIND:
                case C_QUIT:
                case C_READ_PERSISTENT:
                case C_RUN:
                case C_SCALE_BITMAP:
                case C_SCALE_VIDEO:
                case C_SCROLL_ITEMS:
                case C_SELECT:
                case C_SELECT_ITEM:
                case C_SEND_EVENT:
                case C_SEND_TO_BACK:
                case C_SET_BOX_SIZE:
                case C_SET_CACHE_PRIORITY:
                case C_SET_COUNTER_END_POSITION:
                case C_SET_COUNTER_POSITION:
                case C_SET_COUNTER_TRIGGER:
                case C_SET_CURSOR_POSITION:
                case C_SET_CURSOR_SHAPE:
                case C_SET_DATA:
                case C_SET_ENTRY_POINT:
                case C_SET_FILL_COLOUR:
                case C_SET_FIRST_ITEM:
                case C_SET_FONT_REF:
                case C_SET_HIGHLIGHT_STATUS:
                case C_SET_INTERACTION_STATUS:
                case C_SET_LABEL:
                case C_SET_LINE_COLOUR:
                case C_SET_LINE_STYLE:
                case C_SET_LINE_WIDTH:
                case C_SET_OVERWRITE_MODE:
                case C_SET_PALETTE_REF:
                case C_SET_PORTION:
                case C_SET_POSITION:
                case C_SET_SLIDER_VALUE:
                case C_SET_SPEED:
                case C_SET_TIMER:
                case C_SET_TRANSPARENCY:
                case C_SET_VARIABLE:
                case C_SET_VOLUME:
                case C_SPAWN:
                case C_STEP:
                case C_STOP:
                case C_STORE_PERSISTENT:
                case C_SUBTRACT:
                case C_TEST_VARIABLE:
                case C_TOGGLE:
                case C_TOGGLE_ITEM:
                case C_TRANSITION_TO:
                case C_UNLOAD:
                case C_UNLOCK_SCREEN:
                case C_CONTENT_REFERENCE:
                case C_TOKEN_GROUP_ITEMS:
                case C_POSITIONS:
                case C_MULTIPLEX:
                    {   // These are parenthesised in the text form.  We have to remove the
                        // parentheses otherwise we will return a sequence which will not be
                        // be compatible with the binary form.
                        if (m_nType != PTStartSeq) Error("Expected '('");
                        NextSym();
                        while (m_nType != PTEndSeq) pTag->AddArg(DoParse());
                        NextSym(); // Remove the close parenthesis.
                        break;
                    }
                case C_ORIGINAL_CONTENT:
                case C_NEW_GENERIC_BOOLEAN:
                case C_NEW_GENERIC_INTEGER:
                case C_NEW_GENERIC_OCTETSTRING:
                case C_NEW_GENERIC_OBJECT_REF:
                case C_NEW_GENERIC_CONTENT_REF:
                case C_ORIGINAL_VALUE:
                    // These always have an argument which may be a tagged item.
                    {
                        // Is it always the case that there is at least one argument so if we haven't
                        // had any arguments yet we should always process a tag as an argument?
                        pTag->AddArg(DoParse());
                        break;
                    }
                default:
                    // This can be followed by an int, etc but a new tag is dealt with by the caller.
                    while (m_nType == PTBool ||m_nType == PTInt || m_nType == PTString || m_nType == PTEnum || m_nType == PTStartSeq) {
                        pTag->AddArg(DoParse());
                    }

                }
                break;
            }

        case PTInt:
            {
                pRes = new MHPInt(m_nInt);
                NextSym();
                break;
            }

        case PTBool:
            {
                pRes = new MHPBool(m_fBool);
                NextSym();
                break;
            }

        case PTString:
            {
                MHOctetString str;
                str.Copy(MHOctetString((const char *)m_String, m_nStringLength));
                pRes = new MHPString(str);
                NextSym();
                break;
            }

        case PTEnum:
            {
                pRes = new MHPEnum(m_nInt);
                NextSym();
                break;
            }

        case PTNull:
            {
                pRes = new MHPNull;
                NextSym();
                break;
            }

        case PTStartSeq: // Open parenthesis.
            {
                MHParseSequence *pSeq = new MHParseSequence;
                pRes = pSeq;
                NextSym();
                while (m_nType != PTEndSeq) pSeq->Append(DoParse());
                NextSym(); // Remove the close parenthesis.
                break;
            }

        default:
            Error("Unexpected symbol");
        }
        return pRes;
    }
    catch (...) {
        delete(pRes);
        throw;
    }
}