radioapp/radiouiengine/src/radiouiengine.cpp
branchGCC_SURGE
changeset 37 451b2e1545b2
parent 19 afea38384506
parent 33 11b6825f0862
equal deleted inserted replaced
26:6bcf277166c1 37:451b2e1545b2
    17 
    17 
    18 // System includes
    18 // System includes
    19 #include <QScopedPointer>
    19 #include <QScopedPointer>
    20 #include <QProcess>
    20 #include <QProcess>
    21 #include <QFile>
    21 #include <QFile>
       
    22 #include <QTimer>
       
    23 #include <QDesktopServices>
       
    24 #include <QUrl>
    22 
    25 
    23 #ifdef BUILD_WIN32
    26 #ifdef BUILD_WIN32
    24 #   include <QSettings>
    27 #   include <QSettings>
    25 #else
    28 #else
    26 #   include <qsysteminfo.h>
       
    27 #   include <XQSettingsManager>
    29 #   include <XQSettingsManager>
    28 using namespace QtMobility;
       
    29 #endif // WIN32_BUILD
    30 #endif // WIN32_BUILD
    30 
    31 
    31 // User includes
    32 // User includes
    32 #include "radiouiengine.h"
    33 #include "radiouiengine.h"
    33 #include "radiouiengine_p.h"
    34 #include "radiouiengine_p.h"
    34 #include "radiologger.h"
       
    35 #include "radioenginewrapper.h"
    35 #include "radioenginewrapper.h"
    36 #include "radiostationmodel.h"
    36 #include "radiostationmodel.h"
    37 #include "radiohistorymodel.h"
    37 #include "radiohistorymodel.h"
    38 #include "radiocarouselmodel.h"
       
    39 #include "radiohistoryitem.h"
    38 #include "radiohistoryitem.h"
    40 #include "radiosettings.h"
    39 #include "radiosettings.h"
    41 #include "radiostationfiltermodel.h"
       
    42 #include "radioscannerengine.h"
    40 #include "radioscannerengine.h"
       
    41 #include "radiogenrelocalizer.h"
       
    42 #include "radiologger.h"
    43 
    43 
    44 // Constants
    44 // Constants
    45 const QString KPathFormatter = "%1:%2%3";
    45 const uint RADIO_CENREP_UID = 0x2002FF52;
    46 const QString KApplicationDir = "\\sys\\bin\\";
    46 const uint RADIO_CENREP_FREQUENCY_KEY = 0x207;
    47 const QString KSongRecognitionApp = "Shazam_0x200265B3.exe";
    47 const uint RADIO_CENREP_HEADSET_VOLUME = 0x200;
    48 const QString KSongRecognitionAppParams = "-listen";
    48 
    49 
    49 const QLatin1String OVI_STORE_URL( "http://www.music.nokia.co.uk/Touch/Search.aspx?artistsearch=#artist#&titlesearch=#title#" );
    50 const uint DEFAULT_MIN_FREQUENCY = 87500000;
    50 const QLatin1String OTHER_STORE_URL( "http://www.amazon.com/gp/search/ref=sr_adv_m_digital/?search-alias=digital-music&field-author=#artist#&field-title=#title#" );
    51 const uint RADIO_CENREP_UID = 0x101FF976;
    51 const QLatin1String OTHER_STORE_ARTIST_TAG( "#artist#" );
    52 const uint RADIO_CENREP_FREQUENCY_KEY = 0x00000107;
    52 const QLatin1String OTHER_STORE_TITLE_TAG( "#title#" );
    53 
    53 const char WHITESPACE = ' ';
    54 struct GenreStruct
    54 const char WHITESPACE_REPLACEMENT = '+';
    55 {
    55 
    56     int mGenreCode;
    56 // Constants used when launching radio server
    57     const char* mInCarousel;
    57 const QLatin1String RADIO_SERVER_NAME( "radioserver.exe" );
    58     const char* mInStationsList;
    58 const QLatin1String RADIO_RANGE_USEURO( "useuro" );
    59     const char* mInHomeScreen;
    59 const QLatin1String RADIO_RANGE_JAPAN( "japan" );
    60 };
    60 
    61 
    61 // ====== STATIC FUNCTIONS ========
    62 const GenreStruct EuropeanGenres[] =
    62 
    63 {
    63 /*!
    64      { GenreEurope::RdsNone, "", "", "" }
    64  * Gets the last tuned frequency from central repository
    65     ,{ GenreEurope::RdsNews, "txt_rad_info_news", "txt_rad_dblist_l1_mhz_val_news", "txt_rad_info_news_hs" }
    65  */
    66     ,{ GenreEurope::RdsCurrentAffairs, "txt_rad_info_current_affairs", "txt_rad_dblist_l1_mhz_val_current_affairs", "txt_rad_info_current_affairs_hs" }
    66 uint RadioUiEngine::lastTunedFrequency( uint defaultFrequency )
    67     ,{ GenreEurope::RdsInformation, "txt_rad_info_information", "txt_rad_dblist_l1_mhz_val_information", "txt_rad_info_information_hs" }
    67 {
    68     ,{ GenreEurope::RdsSport, "txt_rad_info_sport", "txt_rad_dblist_l1_mhz_val_sport", "txt_rad_info_sport_hs" }
    68     uint frequency = defaultFrequency;
    69     ,{ GenreEurope::RdsEducation, "txt_rad_info_education", "txt_rad_dblist_l1_mhz_val_education", "txt_rad_info_education_hs" }
       
    70     ,{ GenreEurope::RdsDrama, "txt_rad_info_drama", "txt_rad_dblist_l1_mhz_val_drama", "txt_rad_info_drama_hs" }
       
    71     ,{ GenreEurope::RdsCulture, "txt_rad_info_culture", "txt_rad_dblist_l1_mhz_val_culture", "txt_rad_info_culture_hs" }
       
    72     ,{ GenreEurope::RdsScience, "txt_rad_info_science", "txt_rad_dblist_l1_mhz_val_science", "txt_rad_info_science_hs" }
       
    73     ,{ GenreEurope::RdsVariedSpeech, "txt_rad_info_varied", "txt_rad_dblist_l1_mhz_val_varied", "txt_rad_info_varied_hs" }
       
    74     ,{ GenreEurope::RdsPopMusic, "txt_rad_info_pop_music", "txt_rad_dblist_l1_mhz_val_pop_music", "txt_rad_info_pop_music_hs" }
       
    75     ,{ GenreEurope::RdsRockMusic, "txt_rad_info_rock_music", "txt_rad_dblist_l1_mhz_val_rock_music", "txt_rad_info_rock_music_hs" }
       
    76     ,{ GenreEurope::RdsEasyListening, "txt_rad_info_easy_listening", "txt_rad_dblist_l1_mhz_val_easy_listening", "txt_rad_info_easy_listening_hs" }
       
    77     ,{ GenreEurope::RdsLightClassical, "txt_rad_info_light_classical", "txt_rad_dblist_l1_mhz_val_light_classical", "txt_rad_info_light_classical_hs" }
       
    78     ,{ GenreEurope::RdsSeriousClassical, "txt_rad_info_serious_classical", "txt_rad_dblist_l1_mhz_val_serious_classical", "txt_rad_info_serious_classical_hs" }
       
    79     ,{ GenreEurope::RdsOtherMusic, "txt_rad_info_other_music", "txt_rad_dblist_l1_mhz_val_other_music", "txt_rad_info_other_music_hs" }
       
    80     ,{ GenreEurope::RdsWeather, "txt_rad_info_weather", "txt_rad_dblist_l1_mhz_val_weather", "txt_rad_info_weather_hs" }
       
    81     ,{ GenreEurope::RdsFinance, "txt_rad_info_finance", "txt_rad_dblist_l1_mhz_val_finance", "txt_rad_info_finance_hs" }
       
    82     ,{ GenreEurope::RdsChildrensProgrammes, "txt_rad_info_childrens_programmes", "txt_rad_dblist_l1_mhz_val_childrens_programmes", "txt_rad_info_childrens_programmes_hs" }
       
    83     ,{ GenreEurope::RdsSocialAffairs, "txt_rad_info_social_affairs", "txt_rad_dblist_l1_mhz_val_social_affairs", "txt_rad_info_social_affairs_hs" }
       
    84     ,{ GenreEurope::RdsReligion, "txt_rad_info_religion", "txt_rad_dblist_l1_mhz_val_religion", "txt_rad_info_religion_hs" }
       
    85     ,{ GenreEurope::RdsPhoneIn, "txt_rad_info_phone_in", "txt_rad_dblist_l1_mhz_val_phone_in", "txt_rad_info_phone_in_hs" }
       
    86     ,{ GenreEurope::RdsTravel, "txt_rad_info_travel", "txt_rad_dblist_l1_mhz_val_travel", "txt_rad_info_travel_hs" }
       
    87     ,{ GenreEurope::RdsLeisure, "txt_rad_info_leisure", "txt_rad_dblist_l1_mhz_val_leisure", "txt_rad_info_leisure_hs" }
       
    88     ,{ GenreEurope::RdsJazzMusic, "txt_rad_info_jazz_music", "txt_rad_dblist_l1_mhz_val_jazz_music", "txt_rad_info_jazz_music_hs" }
       
    89     ,{ GenreEurope::RdsCountryMusic, "txt_rad_info_country_music", "txt_rad_dblist_l1_mhz_val_country_music", "txt_rad_info_country_music_hs" }
       
    90     ,{ GenreEurope::RdsNationalMusic, "txt_rad_info_national_music", "txt_rad_dblist_l1_mhz_val_national_music", "txt_rad_info_national_music_hs" }
       
    91     ,{ GenreEurope::RdsOldiesMusic, "txt_rad_info_oldies_music", "txt_rad_dblist_l1_mhz_val_oldies_music", "txt_rad_info_oldies_music_hs" }
       
    92     ,{ GenreEurope::RdsFolkMusic, "txt_rad_info_folk_music", "txt_rad_dblist_l1_mhz_val_folk_music", "txt_rad_info_folk_music_hs" }
       
    93     ,{ GenreEurope::RdsDocumentary, "txt_rad_info_documentary", "txt_rad_dblist_l1_mhz_val_documentary", "txt_rad_info_documentary_hs" }
       
    94     ,{ GenreEurope::RdsAlarmTest, "txt_rad_info_alarm_test", "txt_rad_dblist_l1_mhz_val_alarm_test", "txt_rad_info_alarm_test_hs" }
       
    95     ,{ GenreEurope::RdsAlarm, "txt_rad_info_alarm", "txt_rad_dblist_l1_mhz_val_alarm", "txt_rad_info_alarm_hs" }
       
    96 };
       
    97 const int EuropeanGenresCount = sizeof( EuropeanGenres ) / sizeof ( EuropeanGenres[0] );
       
    98 
       
    99 const GenreStruct AmericanGenres[] =
       
   100 {
       
   101      { GenreAmerica::RbdsNone, "", "", "" }
       
   102     ,{ GenreAmerica::RbdsNews, "txt_rad_info_news", "txt_rad_dblist_l1_mhz_val_news", "txt_rad_info_news_hs" }
       
   103     ,{ GenreAmerica::RbdsInformation, "txt_rad_info_information", "txt_rad_dblist_l1_mhz_val_information", "txt_rad_info_information_hs" }
       
   104     ,{ GenreAmerica::RbdsSports, "txt_rad_info_sport", "txt_rad_dblist_l1_mhz_val_sport", "txt_rad_info_sport_hs" }
       
   105     ,{ GenreAmerica::RbdsTalk, "txt_rad_info_talk", "txt_rad_dblist_l1_mhz_val_talk", "txt_rad_info_talk_hs" }
       
   106     ,{ GenreAmerica::RbdsRock, "txt_rad_info_rock_music", "txt_rad_dblist_l1_mhz_val_rock_music", "txt_rad_info_rock_music_hs" } //TODO: Check
       
   107     ,{ GenreAmerica::RbdsClassicRock, "txt_rad_info_classic_rock", "txt_rad_dblist_l1_mhz_val_classic_rock", "txt_rad_info_classic_rock_hs" }
       
   108     ,{ GenreAmerica::RbdsAdultHits, "txt_rad_info_adult_hits", "txt_rad_dblist_l1_mhz_val_adult_hits", "txt_rad_info_adult_hits_hs" }
       
   109     ,{ GenreAmerica::RbdsSoftRock, "txt_rad_info_soft_rock", "txt_rad_dblist_l1_mhz_val_soft_rock", "txt_rad_info_soft_rock_hs" }
       
   110     ,{ GenreAmerica::RbdsTop40, "txt_rad_info_top_40", "txt_rad_dblist_l1_mhz_val_top_40", "txt_rad_info_top_40_hs" }
       
   111     ,{ GenreAmerica::RbdsCountry, "txt_rad_info_country_music", "txt_rad_dblist_l1_mhz_val_country_music", "txt_rad_info_country_music_hs" }  //TODO: Check
       
   112     ,{ GenreAmerica::RbdsOldies, "txt_rad_info_oldies_music", "txt_rad_dblist_l1_mhz_val_oldies_music", "txt_rad_info_oldies_music_hs" }  //TODO: Check
       
   113     ,{ GenreAmerica::RbdsSoft, "txt_rad_info_soft", "txt_rad_dblist_l1_mhz_val_soft", "txt_rad_info_soft_hs" }
       
   114     ,{ GenreAmerica::RbdsNostalgia, "txt_rad_info_nostalgia", "txt_rad_dblist_l1_mhz_val_nostalgia", "txt_rad_info_nostalgia_hs" }
       
   115     ,{ GenreAmerica::RbdsJazz, "txt_rad_info_jazz_music", "txt_rad_dblist_l1_mhz_val_jazz_music", "txt_rad_info_jazz_music_hs" } //TODO: Check
       
   116     ,{ GenreAmerica::RbdsClassical, "txt_rad_info_classical", "txt_rad_dblist_l1_mhz_val_classical", "txt_rad_info_classical_hs" }
       
   117     ,{ GenreAmerica::RbdsRhythmAndBlues, "txt_rad_info_rhythm_and_blues", "txt_rad_dblist_l1_mhz_val_rhythm_and_blues", "txt_rad_info_rhythm_and_blues_hs" }
       
   118     ,{ GenreAmerica::RbdsSoftRhythmAndBlues, "txt_rad_info_soft_rhythm_and_blues", "txt_rad_dblist_l1_mhz_val_soft_rhythm_and_blues", "txt_rad_info_soft_rhythm_and_blues_hs" }
       
   119     ,{ GenreAmerica::RbdsLanguage, "txt_rad_info_language", "txt_rad_dblist_l1_mhz_val_language", "txt_rad_info_language_hs" }
       
   120     ,{ GenreAmerica::RbdsReligiousMusic, "txt_rad_info_religious_music", "txt_rad_dblist_l1_mhz_val_religious_music", "txt_rad_info_religious_music_hs" }
       
   121     ,{ GenreAmerica::RbdsReligiousTalk, "txt_rad_info_religious_talk", "txt_rad_dblist_l1_mhz_val_religious_talk", "txt_rad_info_religious_talk_hs" }
       
   122     ,{ GenreAmerica::RbdsPersonality, "txt_rad_info_personality", "txt_rad_dblist_l1_mhz_val_personality", "txt_rad_info_personality_hs" }
       
   123     ,{ GenreAmerica::RbdsPublic, "txt_rad_info_public", "txt_rad_dblist_l1_mhz_val_public", "txt_rad_info_public_hs" }
       
   124     ,{ GenreAmerica::RbdsCollege, "txt_rad_info_college", "txt_rad_dblist_l1_mhz_val_college", "txt_rad_info_college_hs" }
       
   125     ,{ GenreAmerica::RbdsUnassigned1, "", "", "" }
       
   126     ,{ GenreAmerica::RbdsUnassigned2, "", "", "" }
       
   127     ,{ GenreAmerica::RbdsUnassigned3, "", "", "" }
       
   128     ,{ GenreAmerica::RbdsUnassigned4, "", "", "" }
       
   129     ,{ GenreAmerica::RbdsUnassigned5, "", "", "" }
       
   130     ,{ GenreAmerica::RbdsWeather, "txt_rad_info_weather", "txt_rad_dblist_l1_mhz_val_weather", "txt_rad_info_weather_hs" }//TODO: Check
       
   131     ,{ GenreAmerica::RbdsEmergencyTest, "txt_rad_info_alarm_test", "txt_rad_dblist_l1_mhz_val_alarm_test", "txt_rad_info_alarm_test_hs" }//TODO: Check
       
   132     ,{ GenreAmerica::RbdsEmergency, "txt_rad_info_alarm", "txt_rad_dblist_l1_mhz_val_alarm", "txt_rad_info_alarm_hs" }//TODO: Check
       
   133 };
       
   134 const int AmericanGenresCount = sizeof( AmericanGenres ) / sizeof ( AmericanGenres[0] );
       
   135 
       
   136 /*!
       
   137  *
       
   138  */
       
   139 bool RadioUiEngine::isOfflineProfile()
       
   140 {
       
   141     bool offline = false;
       
   142 
       
   143 #ifdef BUILD_WIN32
       
   144     QScopedPointer<QSettings> settings( new QSettings( "Nokia", "QtFmRadio" ) );
       
   145     offline = settings->value( "Offline", false ).toBool();
       
   146 #else
       
   147     QSystemDeviceInfo deviceInfo;
       
   148     if ( deviceInfo.currentProfile() == QSystemDeviceInfo::OfflineProfile ) {
       
   149         offline = true;
       
   150     }
       
   151 #endif
       
   152 
       
   153     return offline;
       
   154 }
       
   155 
       
   156 /*!
       
   157  *
       
   158  */
       
   159 uint RadioUiEngine::lastTunedFrequency()
       
   160 {
       
   161     uint frequency = DEFAULT_MIN_FREQUENCY;
       
   162 
    69 
   163 #ifdef BUILD_WIN32
    70 #ifdef BUILD_WIN32
   164     QScopedPointer<QSettings> settings( new QSettings( "Nokia", "QtFmRadio" ) );
    71     QScopedPointer<QSettings> settings( new QSettings( "Nokia", "QtFmRadio" ) );
   165     frequency = settings->value( "CurrentFreq", DEFAULT_MIN_FREQUENCY ).toUInt();
    72     frequency = settings->value( "CurrentFreq", DEFAULT_MIN_FREQUENCY ).toUInt();
   166     if ( frequency == 0 ) {
    73     if ( frequency == 0 ) {
   167         frequency = DEFAULT_MIN_FREQUENCY;
    74         frequency = defaultFrequency;
   168     }
    75     }
   169 #else
    76 #else
   170     QScopedPointer<XQSettingsManager> settings( new XQSettingsManager() );
    77     QScopedPointer<XQSettingsManager> settings( new XQSettingsManager() );
   171     XQSettingsKey key( XQSettingsKey::TargetCentralRepository, RADIO_CENREP_UID, RADIO_CENREP_FREQUENCY_KEY );
    78     XQSettingsKey key( XQSettingsKey::TargetCentralRepository, RADIO_CENREP_UID, RADIO_CENREP_FREQUENCY_KEY );
   172     frequency = settings->readItemValue( key, XQSettingsManager::TypeInt ).toUInt();
    79     frequency = settings->readItemValue( key, XQSettingsManager::TypeInt ).toUInt();
       
    80     if ( frequency == 0 ) {
       
    81         frequency = defaultFrequency;
       
    82     }
   173 #endif
    83 #endif
   174 
    84 
   175     return frequency;
    85     return frequency;
   176 }
    86 }
       
    87 
       
    88 /*!
       
    89  * Gets the last used volume level
       
    90  */
       
    91 int RadioUiEngine::lastVolume()
       
    92 {
       
    93     int volume = DEFAULT_VOLUME_LEVEL;
       
    94 
       
    95 #ifndef BUILD_WIN32
       
    96     QScopedPointer<XQSettingsManager> settings( new XQSettingsManager() );
       
    97     XQSettingsKey key( XQSettingsKey::TargetCentralRepository, RADIO_CENREP_UID, RADIO_CENREP_HEADSET_VOLUME );
       
    98     volume = settings->readItemValue( key, XQSettingsManager::TypeInt ).toInt();
       
    99     if ( volume == 0 ) {
       
   100         volume = DEFAULT_VOLUME_LEVEL;
       
   101     }
       
   102 #endif
       
   103 
       
   104     return volume;
       
   105 }
       
   106 
       
   107 /*!
       
   108  * Launches the radio server process
       
   109  */
       
   110 void RadioUiEngine::launchRadioServer()
       
   111 {
       
   112     QStringList args;
       
   113     args << RADIO_RANGE_USEURO; //TODO: Determine current region
       
   114     args << QString::number( lastTunedFrequency( 0 ) );
       
   115     args << QString::number( lastVolume() );
       
   116 
       
   117     QProcess serverProcess;
       
   118     bool success = serverProcess.startDetached( RADIO_SERVER_NAME, args );
       
   119     LOG_ASSERT( success, LOG( "Failed to start radio server!" ) );
       
   120 }
       
   121 
       
   122 // ====== MEMBER FUNCTIONS ========
   177 
   123 
   178 /*!
   124 /*!
   179  *
   125  *
   180  */
   126  */
   181 RadioUiEngine::RadioUiEngine( QObject* parent ) :
   127 RadioUiEngine::RadioUiEngine( QObject* parent ) :
   187 /*!
   133 /*!
   188  *
   134  *
   189  */
   135  */
   190 RadioUiEngine::~RadioUiEngine()
   136 RadioUiEngine::~RadioUiEngine()
   191 {
   137 {
   192     delete d_ptr;
       
   193 }
   138 }
   194 
   139 
   195 /*!
   140 /*!
   196  *
   141  *
   197  */
   142  */
   218     Q_D( RadioUiEngine );
   163     Q_D( RadioUiEngine );
   219     return d->mEngineWrapper->settings().isFirstTimeStart();
   164     return d->mEngineWrapper->settings().isFirstTimeStart();
   220 }
   165 }
   221 
   166 
   222 /*!
   167 /*!
       
   168  *
       
   169  */
       
   170 void RadioUiEngine::setFirstTimeStartPerformed( bool firstTimeStartPerformed )
       
   171 {
       
   172     Q_D( RadioUiEngine );
       
   173     d->mEngineWrapper->settings().setFirstTimeStartPerformed( firstTimeStartPerformed );
       
   174 }
       
   175 
       
   176 /*!
       
   177  *
       
   178  */
       
   179 void RadioUiEngine::setPowerOn()
       
   180 {
       
   181     setMute( false );
       
   182 
       
   183     Q_D( RadioUiEngine );
       
   184     if ( d->mPowerOffTimer ) {
       
   185         d->mPowerOffTimer->stop();
       
   186         d->mPowerOffTimer->deleteLater();
       
   187         d->mPowerOffTimer = NULL;
       
   188     }
       
   189 }
       
   190 
       
   191 /*!
       
   192  *
       
   193  */
       
   194 void RadioUiEngine::setPowerOff( int delay )
       
   195 {
       
   196     Q_D( RadioUiEngine );
       
   197     d->mEngineWrapper->setMute( true, false );
       
   198 
       
   199     if ( delay > 0 ) {
       
   200         if ( !d->mPowerOffTimer ) {
       
   201             d->mPowerOffTimer = new QTimer( this );
       
   202             Radio::connect( d->mPowerOffTimer,  SIGNAL(timeout()),
       
   203                             this,               SIGNAL(powerOffRequested()) );
       
   204         }
       
   205 
       
   206         d->mPowerOffTimer->start( delay );
       
   207     } else {
       
   208         emit powerOffRequested();
       
   209     }
       
   210 }
       
   211 
       
   212 /*!
       
   213  *
       
   214  */
       
   215 bool RadioUiEngine::isPoweringOff() const
       
   216 {
       
   217     Q_D( const RadioUiEngine );
       
   218     return d->mPowerOffTimer && d->mPowerOffTimer->isActive();
       
   219 }
       
   220 
       
   221 /*!
   223  * Returns the settings handler owned by the engine
   222  * Returns the settings handler owned by the engine
   224  */
   223  */
   225 RadioSettingsIf& RadioUiEngine::settings()
   224 RadioSettingsIf& RadioUiEngine::settings()
   226 {
   225 {
   227     Q_D( RadioUiEngine );
   226     Q_D( RadioUiEngine );
   245     Q_D( RadioUiEngine );
   244     Q_D( RadioUiEngine );
   246     return *d->mHistoryModel;
   245     return *d->mHistoryModel;
   247 }
   246 }
   248 
   247 
   249 /*!
   248 /*!
   250  * Creates a new filter model
   249  * Creates a scanner engine and returns a pointer to it
   251  */
   250  * The returned pointer is wrapped inside a QScopedPointer to ensure this won't
   252 RadioStationFilterModel* RadioUiEngine::createNewFilterModel( QObject* parent )
   251  * leak memory. The returned engine will be deleted even if the caller ignored
   253 {
   252  * the return value.
   254     return new RadioStationFilterModel( *this, parent );
   253  */
   255 }
   254 RadioScannerEnginePtr RadioUiEngine::createScannerEngine()
   256 
   255 {
   257 /*!
   256     Q_D( RadioUiEngine );
   258  * Creates a new carousel model
   257 #if defined BUILD_WIN32 || defined __WINS__
   259  */
   258     Q_ASSERT_X( !d->mScannerEngine, "RadioUiEngine::createScannerEngine", "Previous scanner instance not freed" );
   260 RadioCarouselModel* RadioUiEngine::carouselModel()
   259 #endif
   261 {
   260 
   262     Q_D( RadioUiEngine );
   261     RadioScannerEnginePtr enginePtr( new RadioScannerEngine( *d ) );
   263     if ( !d->mCarouselModel ) {
   262     d->mScannerEngine = enginePtr;
   264         d->mCarouselModel.reset( new RadioCarouselModel( *this, *d->mStationModel ) );
   263 
   265     }
   264     return enginePtr;
   266 
       
   267     return d->mCarouselModel.data();
       
   268 }
   265 }
   269 
   266 
   270 /*!
   267 /*!
   271  *
   268  *
   272  */
   269  */
   273 RadioScannerEngine* RadioUiEngine::scannerEngine()
   270 RadioScannerEngine* RadioUiEngine::scannerEngine()
   274 {
   271 {
   275     Q_D( RadioUiEngine );
   272     Q_D( RadioUiEngine );
   276     if ( !d->mScannerEngine ) {
   273     return d->mScannerEngine.data();
   277         d->mScannerEngine = new RadioScannerEngine( *d );
       
   278     }
       
   279     return d->mScannerEngine;
       
   280 }
   274 }
   281 
   275 
   282 /*!
   276 /*!
   283  *
   277  *
   284  */
   278  */
   293  */
   287  */
   294 bool RadioUiEngine::isScanning() const
   288 bool RadioUiEngine::isScanning() const
   295 {
   289 {
   296     Q_D( const RadioUiEngine );
   290     Q_D( const RadioUiEngine );
   297     if ( d->mScannerEngine ) {
   291     if ( d->mScannerEngine ) {
   298         return d->mScannerEngine->isScanning();
   292         return d->mScannerEngine.data()->isScanning();
   299     }
   293     }
   300     return false;
   294     return false;
   301 }
   295 }
   302 
   296 
   303 /*!
   297 /*!
   393 /*!
   387 /*!
   394  *
   388  *
   395  */
   389  */
   396 QString RadioUiEngine::genreToString( int genre, GenreTarget::Target target )
   390 QString RadioUiEngine::genreToString( int genre, GenreTarget::Target target )
   397 {
   391 {
   398     RadioRegion::Region currentRegion = region();
   392     return RadioGenreLocalizer::genreToString( region(), genre, target );
   399 
       
   400     const GenreStruct* genreArray = currentRegion == RadioRegion::America ? AmericanGenres : EuropeanGenres;
       
   401     const int genreCount = currentRegion == RadioRegion::America ? AmericanGenresCount : EuropeanGenresCount;
       
   402 
       
   403     for( int i = 0; i < genreCount; ++i ) {
       
   404         if ( genreArray[i].mGenreCode == genre ) {
       
   405             if ( target == GenreTarget::Carousel ) {
       
   406                 return qtTrId( genreArray[i].mInCarousel );
       
   407             } else if ( target == GenreTarget::StationsList ) {
       
   408                 return qtTrId( genreArray[i].mInStationsList );
       
   409             } else if ( target == GenreTarget::HomeScreen ) {
       
   410                 return qtTrId( genreArray[i].mInHomeScreen );
       
   411             }
       
   412         }
       
   413     }
       
   414 
       
   415     return "";
       
   416 }
   393 }
   417 
   394 
   418 /*!
   395 /*!
   419  *
   396  *
   420  */
   397  */
   421 bool RadioUiEngine::isSongRecognitionAppAvailable()
   398 bool RadioUiEngine::isSongRecognitionAppAvailable()
   422 {
   399 {
   423     //TODO: Check if there is a better way to check if an application is available
   400     //TODO: Implement Shazam support
   424     bool available = false;
   401     return false;
   425 
       
   426     // Check the Z: drive
       
   427     QString fullPath = QString( KPathFormatter ).arg( "Z" ).arg( KApplicationDir ).arg( KSongRecognitionApp );
       
   428     available = QFile::exists( fullPath );
       
   429 
       
   430     LOG_FORMAT( "Checking file: %s. found %d", GETSTRING( fullPath ), available );
       
   431 
       
   432     if ( !available ) {
       
   433         // Check the C: drive
       
   434         fullPath = QString( KPathFormatter ).arg( "C" ).arg( KApplicationDir ).arg( KSongRecognitionApp );
       
   435         available = QFile::exists( fullPath );
       
   436         LOG_FORMAT( "Checking file: %s. found %d", GETSTRING( fullPath ), available );
       
   437         if ( !available ) {
       
   438             // Check the E: drive
       
   439             fullPath = QString( KPathFormatter ).arg( "E" ).arg( KApplicationDir ).arg( KSongRecognitionApp );
       
   440             available = QFile::exists( fullPath );
       
   441             LOG_FORMAT( "Checking file: %s. found %d", GETSTRING( fullPath ), available );
       
   442         }
       
   443     }
       
   444     return available;
       
   445 }
   402 }
   446 
   403 
   447 /*!
   404 /*!
   448  *
   405  *
   449  */
   406  */
   465 /*!
   422 /*!
   466  *
   423  *
   467  */
   424  */
   468 void RadioUiEngine::openMusicStore( const RadioHistoryItem& item, MusicStore store )
   425 void RadioUiEngine::openMusicStore( const RadioHistoryItem& item, MusicStore store )
   469 {
   426 {
   470     Q_UNUSED( item );
   427     QString artist = item.artist();
   471     Q_UNUSED( store );
   428     artist.replace( WHITESPACE, WHITESPACE_REPLACEMENT );
   472     //TODO: Integrate to music store
   429     QString title = item.title();
   473 }
   430     title.replace( WHITESPACE, WHITESPACE_REPLACEMENT );
   474 
   431 
   475 /*!
   432     QString url = store == OviStore ? OVI_STORE_URL : OTHER_STORE_URL;
   476  * Public slot
   433     url.replace( OTHER_STORE_ARTIST_TAG, artist );
   477  * Tunes to the given frequency
   434     url.replace( OTHER_STORE_TITLE_TAG, title );
   478  */
   435 
   479 void RadioUiEngine::tuneFrequency( uint frequency, const int reason )
   436     launchBrowser( url );
       
   437 }
       
   438 
       
   439 /*!
       
   440  *
       
   441  */
       
   442 void RadioUiEngine::launchBrowser( const QString& url )
       
   443 {
       
   444     QDesktopServices::openUrl( QUrl( url ) );
       
   445 }
       
   446 
       
   447 /*!
       
   448  * Sets or unsets the engine to manual seek mode
       
   449  */
       
   450 void RadioUiEngine::setManualSeekMode( bool manualSeek )
       
   451 {
       
   452     Q_D( RadioUiEngine );
       
   453     d->mEngineWrapper->setManualSeekMode( manualSeek );
       
   454 }
       
   455 
       
   456 /*!
       
   457  * Checks if the engine is in manual seek mode
       
   458  */
       
   459 bool RadioUiEngine::isInManualSeekMode() const
       
   460 {
       
   461     Q_D( const RadioUiEngine );
       
   462     return d->mEngineWrapper->isInManualSeekMode();
       
   463 }
       
   464 
       
   465 /*!
       
   466  * Tunes the radio engine to given frequency
       
   467  */
       
   468 void RadioUiEngine::setFrequency( uint frequency, const int reason )
   480 {
   469 {
   481     Q_D( RadioUiEngine );
   470     Q_D( RadioUiEngine );
   482     if ( frequency != d->mStationModel->currentStation().frequency() && d->mEngineWrapper->isFrequencyValid( frequency ) ) {
   471     if ( frequency != d->mStationModel->currentStation().frequency() && d->mEngineWrapper->isFrequencyValid( frequency ) ) {
   483         LOG_FORMAT( "RadioUiEngine::tuneFrequency, frequency: %d", frequency );
   472         LOG_FORMAT( "RadioUiEngine::tuneFrequency, frequency: %d", frequency );
   484         d->cancelSeeking();
   473         d->cancelSeeking();
   485         d->mEngineWrapper->tuneFrequency( frequency, reason );
   474         d->mEngineWrapper->setFrequency( frequency, reason );
   486     }
       
   487 }
       
   488 
       
   489 /*!
       
   490  * Public slot
       
   491  * Tunes to the given frequency after a delay
       
   492  */
       
   493 void RadioUiEngine::tuneWithDelay( uint frequency, const int reason )
       
   494 {
       
   495     Q_D( RadioUiEngine );
       
   496     if ( frequency != d->mStationModel->currentStation().frequency() &&  d->mEngineWrapper->isFrequencyValid( frequency ) ) {
       
   497         LOG_FORMAT( "RadioEngineWrapperPrivate::tuneWithDelay, frequency: %d", frequency );
       
   498         d->cancelSeeking();
       
   499         d->mEngineWrapper->tuneWithDelay( frequency, reason );
       
   500     }
       
   501 }
       
   502 
       
   503 /*!
       
   504  * Public slot
       
   505  * Tunes to the given preset
       
   506  */
       
   507 void RadioUiEngine::tunePreset( int presetIndex )
       
   508 {
       
   509     Q_D( RadioUiEngine );
       
   510     if ( presetIndex != d->mStationModel->currentStation().presetIndex() ) {
       
   511         RadioStation station;
       
   512         if ( d->mStationModel->findPresetIndex( presetIndex, station ) != RadioStation::NotFound &&
       
   513                 d->mEngineWrapper->isFrequencyValid( station.frequency() ) ) {
       
   514             LOG_FORMAT( "RadioEngineWrapperPrivate::tunePreset, presetIndexPosition: %d", presetIndex );
       
   515 
       
   516             d->mEngineWrapper->tuneFrequency( station.frequency(), TuneReason::Unspecified );
       
   517         }
       
   518     }
   475     }
   519 }
   476 }
   520 
   477 
   521 /*!
   478 /*!
   522  * Public slot
   479  * Public slot
   556  */
   513  */
   557 void RadioUiEngine::seekStation( int seekDirection )
   514 void RadioUiEngine::seekStation( int seekDirection )
   558 {
   515 {
   559     if ( isAntennaAttached() ) {
   516     if ( isAntennaAttached() ) {
   560         Q_D( RadioUiEngine );
   517         Q_D( RadioUiEngine );
   561         Seeking::Direction direction = static_cast<Seeking::Direction>( seekDirection );
   518         Seek::Direction direction = static_cast<Seek::Direction>( seekDirection );
   562         emitSeekingStarted( direction );
   519         emitSeekingStarted( direction );
   563         d->mEngineWrapper->startSeeking( direction, TuneReason::Seek );
   520         d->mEngineWrapper->startSeeking( direction, TuneReason::Seek );
   564     }
   521     }
   565 }
   522 }
   566 
   523 
   568  * Public slot
   525  * Public slot
   569  *
   526  *
   570  */
   527  */
   571 void RadioUiEngine::launchSongRecognition()
   528 void RadioUiEngine::launchSongRecognition()
   572 {
   529 {
   573     LOG_FORMAT("RadioUiEngine::launchSongRecognition() starting:  %s", GETSTRING( KSongRecognitionApp ) );
   530     //TODO: Implement Shazam support
   574 
       
   575     QStringList arguments;
       
   576     arguments << KSongRecognitionAppParams;
       
   577 
       
   578     bool started = QProcess::startDetached( KSongRecognitionApp, arguments );
       
   579     Q_UNUSED( started );
       
   580     LOG_ASSERT( started, LOG_FORMAT("RadioUiEngine::launchSongRecognition() failed to start %s", GETSTRING( KSongRecognitionApp ) ) );
       
   581 }
   531 }
   582 
   532 
   583 /*!
   533 /*!
   584  * Function used by the private implementation to emit a tunedToFrequency signal
   534  * Function used by the private implementation to emit a tunedToFrequency signal
   585  */
   535  */
   589 }
   539 }
   590 
   540 
   591 /*!
   541 /*!
   592  * Function used by the private implementation to emit a seekingStarted signal
   542  * Function used by the private implementation to emit a seekingStarted signal
   593  */
   543  */
   594 void RadioUiEngine::emitSeekingStarted( Seeking::Direction direction )
   544 void RadioUiEngine::emitSeekingStarted( Seek::Direction direction )
   595 {
   545 {
   596     emit seekingStarted( direction );
   546     emit seekingStarted( direction );
   597 }
   547 }
   598 
   548 
   599 /*!
   549 /*!