radioapp/radiouiengine/src/radiostation.cpp
changeset 28 075425b8d9a4
parent 24 6df133bd92e1
child 32 189d20c34778
child 34 bc10a61bd7d3
equal deleted inserted replaced
24:6df133bd92e1 28:075425b8d9a4
    23 #include "radiostation_p.h"
    23 #include "radiostation_p.h"
    24 #include "radiologger.h"
    24 #include "radiologger.h"
    25 #include "radio_global.h"
    25 #include "radio_global.h"
    26 
    26 
    27 // Constants
    27 // Constants
    28 const QString KTagArtist = "artist";
    28 const QString TAG_ARTIST = "artist";
    29 const QString KTagTitle = "title";
    29 const QString TAG_TITLE = "title";
    30 const QString KLinkArtist = "<a href=\"" + KTagArtist + "\">";
    30 const QString HTML_ARTIST = "<a href=\"" + TAG_ARTIST + "\">";
    31 const QString KLinkTitle = "<a href=\"" + KTagTitle + "\">";
    31 const QString HTML_TITLE = "<a href=\"" + TAG_TITLE + "\">";
    32 const QString KLinkClose = "</a>";
    32 const QString HTML_CLOSE = "</a>";
    33 
    33 
    34 const char* callSign[KThreeLetterCallSignCount] =
    34 const uint LAST_CALLSIGN_CHAR_CODE = 25;
       
    35 const uint THREE_LETTER_CALLSIGN_COUNT = 72;
       
    36 const uint KXXX_CALLSIGN_PI_FIRST = 0x1000;
       
    37 const uint WXXX_CALLSIGN_PI_FIRST = 0x54A8;
       
    38 const uint WXXX_CALLSIGN_PI_LAST = 0x994F;
       
    39 const uint XXX_CALLSIGN_PI_FIRST = 0x9950;
       
    40 const uint XXX_CALLSIGN_PI_LAST = 0x99B9;
       
    41 
       
    42 const char* CALLSIGN_TABLE[THREE_LETTER_CALLSIGN_COUNT] =
    35    {"KBW", "KCY", "KDB", "KDF", "KEX", "KFH","KFI","KGA","KGB",
    43    {"KBW", "KCY", "KDB", "KDF", "KEX", "KFH","KFI","KGA","KGB",
    36     "KGO", "KGU", "KGW", "KGY", "KHQ", "KID", "KIT", "KJR", "KLO",
    44     "KGO", "KGU", "KGW", "KGY", "KHQ", "KID", "KIT", "KJR", "KLO",
    37     "KLZ", "KMA", "KMJ", "KNX", "KOA", "KOB", "KOY", "KPQ", "KQV",
    45     "KLZ", "KMA", "KMJ", "KNX", "KOA", "KOB", "KOY", "KPQ", "KQV",
    38     "KSD", "KSL", "KUJ", "KUT", "KVI", "KWG", "KXL", "KXO", "KYW",
    46     "KSD", "KSL", "KUJ", "KUT", "KVI", "KWG", "KXL", "KXO", "KYW",
    39     "WBT", "WBZ", "WDZ", "WEW", "WGH", "WGL", "WGN", "WGR", "WGY",
    47     "WBT", "WBZ", "WDZ", "WEW", "WGH", "WGL", "WGN", "WGR", "WGY",
    40     "WHA", "WHB", "WHK", "WHO", "WHP", "WIL", "WIP", "WIS", "WJR",
    48     "WHA", "WHB", "WHK", "WHO", "WHP", "WIL", "WIP", "WIS", "WJR",
    41     "WJW", "WJZ", "WKY", "WLS", "WLW", "WMC", "WMT", "WOC", "WOI",
    49     "WJW", "WJZ", "WKY", "WLS", "WLW", "WMC", "WMT", "WOC", "WOI",
    42     "WOL", "WOR", "WOW", "WRC", "WRR", "WSB", "WSM", "WWJ", "WWL"};
    50     "WOL", "WOR", "WOW", "WRC", "WRR", "WSB", "WSM", "WWJ", "WWL"};
    43 
    51 
    44 const uint piCode[KThreeLetterCallSignCount] =
    52 const uint PI_CODE_TABLE[THREE_LETTER_CALLSIGN_COUNT] =
    45    {0x99A5, 0x99A6, 0x9990, 0x99A7, 0x9950, 0x9951, 0x9952, 0x9953,
    53    {0x99A5, 0x99A6, 0x9990, 0x99A7, 0x9950, 0x9951, 0x9952, 0x9953,
    46     0x9991, 0x9954, 0x9955, 0x9956, 0x9957, 0x99AA, 0x9958, 0x9959,
    54     0x9991, 0x9954, 0x9955, 0x9956, 0x9957, 0x99AA, 0x9958, 0x9959,
    47     0x995A, 0x995B, 0x995C, 0x995D, 0x995E, 0x995F, 0x9960, 0x99AB,
    55     0x995A, 0x995B, 0x995C, 0x995D, 0x995E, 0x995F, 0x9960, 0x99AB,
    48     0x9992, 0x9993, 0x9964, 0x9994, 0x9965, 0x9966, 0x9995, 0x9967,
    56     0x9992, 0x9993, 0x9964, 0x9994, 0x9965, 0x9966, 0x9995, 0x9967,
    49     0x9968, 0x9996, 0x9997, 0x996B, 0x9999, 0x996D, 0x996E, 0x996F,
    57     0x9968, 0x9996, 0x9997, 0x996B, 0x9999, 0x996D, 0x996E, 0x996F,
    50     0x999A, 0x9971, 0x9972, 0x9973, 0x999B, 0x9975, 0x9976, 0x9977,
    58     0x999A, 0x9971, 0x9972, 0x9973, 0x999B, 0x9975, 0x9976, 0x9977,
    51     0x9978, 0x999C, 0x999D, 0x997A, 0x99B3, 0x997B, 0x99B4, 0x99B5,
    59     0x9978, 0x999C, 0x999D, 0x997A, 0x99B3, 0x997B, 0x99B4, 0x99B5,
    52     0x997C, 0x997D, 0x997E, 0x999E, 0x999F, 0x9981, 0x99A0, 0x9983,
    60     0x997C, 0x997D, 0x997E, 0x999E, 0x999F, 0x9981, 0x99A0, 0x9983,
    53     0x9984, 0x99A1, 0x99B9, 0x99A2, 0x99A3, 0x99A4, 0x9988, 0x9989};
    61     0x9984, 0x99A1, 0x99B9, 0x99A2, 0x99A3, 0x99A4, 0x9988, 0x9989};
    54 
    62 
    55 const uint KDisableLocalAreaCoverageMask = 0x0800;
    63 const uint DISABLE_LOCAL_AREA_COVERAGE_MASK = 0x0800;
    56 
    64 
    57 const int KPsNameChangeThresholdSeconds = 10;
    65 const int PS_NAME_CHANGE_THRESHOLD_SECONDS = 10;
    58 
    66 
    59 /**
    67 /**
    60  * Static shared data instance that is used by all default-constructed RadioStation instances
    68  * Static shared data instance that is used by all default-constructed RadioStation instances
    61  */
    69  */
    62 Q_GLOBAL_STATIC_WITH_ARGS( RadioStationPrivate, shared_null, ( RadioStation::SharedNull ) )
    70 Q_GLOBAL_STATIC_WITH_ARGS( RadioStationPrivate, shared_null, ( RadioStation::SharedNull ) )
    65  *
    73  *
    66  */
    74  */
    67 QString RadioStation::parseFrequency( uint frequency )
    75 QString RadioStation::parseFrequency( uint frequency )
    68 {
    76 {
    69     QString freqString;
    77     QString freqString;
    70     freqString.sprintf( "%.1f", qreal( frequency ) / KFrequencyMultiplier );
    78     freqString.sprintf( "%.1f", qreal( frequency ) / FREQUENCY_MULTIPLIER );
    71     return freqString;
    79     return freqString;
    72 }
    80 }
    73 
    81 
    74 /*!
    82 /*!
    75  *
    83  *
   177         // Save the time when PS name changed and if the last change was too close to the current time
   185         // Save the time when PS name changed and if the last change was too close to the current time
   178         // change the PS type to dynamic if it has already been incorrectly determined to be static.
   186         // change the PS type to dynamic if it has already been incorrectly determined to be static.
   179         QTime previousChange = mData->mLastPsNameChangeTime;
   187         QTime previousChange = mData->mLastPsNameChangeTime;
   180         mData->mLastPsNameChangeTime = QTime::currentTime();
   188         mData->mLastPsNameChangeTime = QTime::currentTime();
   181         if ( previousChange.isValid() && mData->mPsType == RadioStation::Static &&
   189         if ( previousChange.isValid() && mData->mPsType == RadioStation::Static &&
   182              previousChange.secsTo( mData->mLastPsNameChangeTime ) < KPsNameChangeThresholdSeconds ) {
   190              previousChange.secsTo( mData->mLastPsNameChangeTime ) < PS_NAME_CHANGE_THRESHOLD_SECONDS ) {
   183             LOG( "Station changed PS name too often. PS type changed to Dynamic" );
   191             LOG( "Station changed PS name too often. PS type changed to Dynamic" );
   184             mData->mPsType = RadioStation::Dynamic;
   192             mData->mPsType = RadioStation::Dynamic;
   185             mData->mDynamicPsText = mData->mName;
   193             mData->mDynamicPsText = mData->mName;
   186             mData->mName = "";
   194             mData->mName = "";
   187             mData->mChangeFlags |= RadioStation::PsTypeChanged | RadioStation::DynamicPsChanged;
   195             mData->mChangeFlags |= RadioStation::PsTypeChanged | RadioStation::DynamicPsChanged;
   230 {
   238 {
   231     LOG_FORMAT( "RadioStation::setPiCode new PI: %d", piCode );
   239     LOG_FORMAT( "RadioStation::setPiCode new PI: %d", piCode );
   232     // toggling local area coverage bit code must not be interpreted as new PI code
   240     // toggling local area coverage bit code must not be interpreted as new PI code
   233     if( region != RadioRegion::America )
   241     if( region != RadioRegion::America )
   234     {
   242     {
   235         piCode &= ~KDisableLocalAreaCoverageMask;
   243         piCode &= ~DISABLE_LOCAL_AREA_COVERAGE_MASK;
   236     }
   244     }
   237 
   245 
   238     LOG_FORMAT( "stored PI: %d", mData->mPiCode );
   246     LOG_FORMAT( "stored PI: %d", mData->mPiCode );
   239     LOG_FORMAT( "call sign check done: %d", mData->mCallSignCheckDone );
   247     LOG_FORMAT( "call sign check done: %d", mData->mCallSignCheckDone );
   240     //prevent executing the below code when unnessesary
   248     //prevent executing the below code when unnessesary
   309         }
   317         }
   310 
   318 
   311         detach();
   319         detach();
   312         QString replacement = "";
   320         QString replacement = "";
   313         if ( rtPlusClass == RtPlus::Artist ) {
   321         if ( rtPlusClass == RtPlus::Artist ) {
   314             replacement = KLinkArtist;
   322             replacement = HTML_ARTIST;
   315         } else if ( rtPlusClass == RtPlus::Title ) {
   323         } else if ( rtPlusClass == RtPlus::Title ) {
   316             replacement = KLinkTitle;
   324             replacement = HTML_TITLE;
   317         }
   325         }
   318         replacement += rtPlusItem + KLinkClose;
   326         replacement += rtPlusItem + HTML_CLOSE;
   319 
   327 
   320         mData->mRadioText.replace( rtPlusItem, replacement );
   328         mData->mRadioText.replace( rtPlusItem, replacement );
   321         mData->mChangeFlags |= RadioStation::RadioTextChanged;
   329         mData->mChangeFlags |= RadioStation::RadioTextChanged;
   322     }
   330     }
   323 }
   331 }
   384 /*!
   392 /*!
   385  *
   393  *
   386  */
   394  */
   387 QString RadioStation::frequencyMhz() const
   395 QString RadioStation::frequencyMhz() const
   388 {
   396 {
   389     return parseFrequency( mData->mFrequency );
   397     return qtTrId( "txt_rad_list_l1_mhz_big" ).arg( parseFrequency( mData->mFrequency ) );
       
   398 }
       
   399 
       
   400 /*!
       
   401  *
       
   402  */
       
   403 QString RadioStation::nameOrFrequencyMhz() const
       
   404 {
       
   405     if ( !mData->mName.isEmpty() ) {
       
   406         return mData->mName;
       
   407     }
       
   408     return frequencyMhz();
   390 }
   409 }
   391 
   410 
   392 /*!
   411 /*!
   393  *
   412  *
   394  */
   413  */
   574  {
   593  {
   575     QString callSign;
   594     QString callSign;
   576 
   595 
   577     LOG_FORMAT( "RadioStation::piCodeToCallSign PI: %d", programmeIdentification );
   596     LOG_FORMAT( "RadioStation::piCodeToCallSign PI: %d", programmeIdentification );
   578     // call signs beginning with 'K'
   597     // call signs beginning with 'K'
   579     if( ( programmeIdentification>=KKxxxCallSignPiFirst ) && ( programmeIdentification < KWxxxCallSignPiFirst ) ) {
   598     if( ( programmeIdentification>=KXXX_CALLSIGN_PI_FIRST ) && ( programmeIdentification < WXXX_CALLSIGN_PI_FIRST ) ) {
   580         callSign += "K";
   599         callSign += "K";
   581         callSign += iterateCallSign( KKxxxCallSignPiFirst, programmeIdentification );
   600         callSign += iterateCallSign( KXXX_CALLSIGN_PI_FIRST, programmeIdentification );
   582     }
   601     }
   583     // call signs beginning with 'W'
   602     // call signs beginning with 'W'
   584     else if (( programmeIdentification >= KWxxxCallSignPiFirst ) && ( programmeIdentification <= KWxxxCallSignPiLast )) {
   603     else if (( programmeIdentification >= WXXX_CALLSIGN_PI_FIRST ) && ( programmeIdentification <= WXXX_CALLSIGN_PI_LAST )) {
   585         callSign += "W";
   604         callSign += "W";
   586         callSign += iterateCallSign( KWxxxCallSignPiFirst, programmeIdentification );
   605         callSign += iterateCallSign( WXXX_CALLSIGN_PI_FIRST, programmeIdentification );
   587     }
   606     }
   588     // 3 letter only call signs
   607     // 3 letter only call signs
   589     else if(( programmeIdentification >= KxxxCallSignPiFirst ) && ( programmeIdentification <= KxxxCallSignPiLast)) {
   608     else if(( programmeIdentification >= XXX_CALLSIGN_PI_FIRST ) && ( programmeIdentification <= XXX_CALLSIGN_PI_LAST)) {
   590         callSign += callSignString( programmeIdentification );
   609         callSign += callSignString( programmeIdentification );
   591     }
   610     }
   592     else
   611     else
   593     {
   612     {
   594         LOG( "RadioStation::piCodeToCallSign - Unhandled else" );
   613         LOG( "RadioStation::piCodeToCallSign - Unhandled else" );
   639 /*!
   658 /*!
   640  *
   659  *
   641  */
   660  */
   642 QString RadioStation::callSignString( uint programmeIdentification )
   661 QString RadioStation::callSignString( uint programmeIdentification )
   643 {
   662 {
   644     for ( uint i = 0; i < KThreeLetterCallSignCount; ++i ) {
   663     for ( uint i = 0; i < THREE_LETTER_CALLSIGN_COUNT; ++i ) {
   645         if( piCode[i] == programmeIdentification ) {
   664         if( PI_CODE_TABLE[i] == programmeIdentification ) {
   646             return callSign[i];
   665             return CALLSIGN_TABLE[i];
   647         }
   666         }
   648     }
   667     }
   649 
   668 
   650     LOG_FORMAT( "RadioStation::callSignString, Not found PI: %d", programmeIdentification );
   669     LOG_FORMAT( "RadioStation::callSignString, Not found PI: %d", programmeIdentification );
   651 
   670 
   656  *
   675  *
   657  */
   676  */
   658 char RadioStation::callSignChar( uint decimalValue )
   677 char RadioStation::callSignChar( uint decimalValue )
   659 {
   678 {
   660     LOG_FORMAT( "RadioStation::callSignChar A+: %d", decimalValue );
   679     LOG_FORMAT( "RadioStation::callSignChar A+: %d", decimalValue );
   661     if ( decimalValue <= KLastCallSignCharCode ) {
   680     if ( decimalValue <= LAST_CALLSIGN_CHAR_CODE ) {
   662         return static_cast<char>( 'A' + decimalValue );
   681         return static_cast<char>( 'A' + decimalValue );
   663     }
   682     }
   664     return '?';
   683     return '?';
   665 }
   684 }
   666 
   685