chxavplayerui.cpp
上传用户:dangjiwu
上传日期:2013-07-19
资源大小:42019k
文件大小:41k
源码类别:

Symbian

开发平台:

Visual C++

  1. /****************************************************************************
  2.  * chxavplayerui.cpp
  3.  * -----------------
  4.  *
  5.  * Synopsis:
  6.  *
  7.  * CHXAvPlayerUI derives from CAknViewAppUI. It manages the views (main view, 
  8.  * file list view, etc.).It contains UI helpers (info messes, notes) shared by
  9.  * views and contains the implementation of UI commands that might be shared 
  10.  * among all views.
  11.  *
  12.  * Views themselves are persistent and wrap view windows. The view windows are
  13.  * normally created/destroyed upon activation/deactivation of a view to save
  14.  * resources.
  15.  *
  16.  *
  17.  * Target:
  18.  * Symbian OS
  19.  *
  20.  *
  21.  * (c) 1995-2003 RealNetworks, Inc. Patents pending. All rights reserved.
  22.  *
  23.  *****************************************************************************/
  24. #include <aknpopup.h>
  25. #include <akntitle.h>
  26. #include <stringloader.h>
  27. #include <eikenv.h>
  28. #include <bautils.h>
  29. #include <coemain.h>
  30. #include <bacntf.h> //CEnvironmentChangeNotifier
  31. //#include <hlplch.h>
  32. #include "chxavplayerdoc.h"
  33. #include "chxavvector.h"
  34. #include "player_uids.h"
  35. #include "chxavviewbase.h"
  36. #include "chxavplayer.h"
  37. #include "chxavfileview.h"
  38. #include "chxavplayview.h"
  39. #include "realplayer.rsg"
  40. #include "realplayer.hrh"
  41. #include "chxavutil.h"
  42. #include "chxavmisc.h"
  43. #include "chxavurllist.h"
  44. #include "chxavurlrep.h"
  45. #include "chxavurlinfo.h"
  46. #include "chxaveditplaylistdialog.h"
  47. #include "chxavstringutils.h"
  48. #include "chxavcleanstring.h"
  49. #include "chxavmessagedialog.h"
  50. #include "chxavrecentclipspopuplist.h"
  51. #include "chxavcleanupstack.h"
  52. #include "chxavplayerui.h"
  53. #include "chxavconfignames.h"
  54. #include "chxavmediafolderinfo.h"
  55. #include "chxavclipinfolist.h"
  56. #include "chxavsettingsview.h"
  57. #include "chxavselectsettingsview.h"
  58. #include "comptr_traits.h"
  59. #include "hxsym_debug.h"
  60. #include "hxsym_leaveutil.h"
  61. #include "hxsym_mmc_utils.h"
  62. #include "....symbianplayer.ver"
  63. #include "chxavaccesspointdb.h"
  64. #include <hal.h>
  65. #define NOKIA_7650 270487491
  66. namespace
  67. {
  68. //
  69. // enums for various shared data keys (see shareddatakeys.h):
  70. //
  71. //KSysApLightsControl
  72. enum BacklightState
  73. {
  74. BacklightNormal     = 0,
  75. BacklightDisplayOn  = 1,    // keypad only on if needeed (depends on grip's state and light sensor)
  76. BacklightAlwaysOn   = 2     // keypad forced on all the time
  77. };
  78. //KSysApMessageToneQuit
  79. enum MessageToneState
  80. {
  81.     
  82. MessageTonesOff = 0,
  83. MessageTonesOn = 1
  84. };
  85. //KSysAudioStatus
  86. enum AudioStatus
  87. {
  88. AudioStatusNull = 0,
  89. AudioStatusPlaying = 1,
  90. AudioStatusRecording = 2
  91. };
  92. //KSysApAlarmLightActive
  93. enum AlarmLightState
  94. {
  95. AlarmNotFlashing = 0,
  96. AlarmFlashing = 1
  97. };
  98. /*
  99.  * AllocAboutTextL
  100.  * ---------------
  101.  *
  102.  */
  103. HBufC* AllocAboutTextL()
  104. {
  105.     // load descriptors from char*
  106.     CHXAvCleanString buildDate(__DATE__);
  107.     CHXAvCleanString buildTime(__TIME__);
  108.     CHXAvCleanString version(TARVER_STRING_VERSION);
  109.     CHXAvCleanString buildName(TARVER_STR_BUILD_NAME);
  110.     CHXAvCleanString profile(makestr(SYMBIANPLAYER_INSTALL_NAME));
  111.  
  112.     // load about resources
  113.     CHXAvCleanString copyText(R_ABOUT_COPYRIGHT_TEXT);
  114.     CHXAvCleanString voiceAgeText(R_ABOUT_VOICE_AGE_TEXT);
  115.     CHXAvCleanString versionText(R_ABOUT_VERSION, version());
  116.     CHXAvCleanString dateText(R_ABOUT_BUILD_DATE, buildDate());
  117.     CHXAvCleanString timeText(R_ABOUT_BUILD_TIME, buildTime());
  118.     
  119.     
  120.     // calculate buffer needed for full about text
  121.     TUint32 cchTotal = copyText().Length() 
  122.                     + voiceAgeText().Length() 
  123.                     + versionText().Length() 
  124.                     + buildName().Length()
  125.                     + profile().Length()
  126.                     + dateText().Length()
  127.                     + timeText().Length() 
  128.                     ; 
  129.     // add for formatting spaces (newlines)
  130.     cchTotal += 20;
  131.     HBufC* pbuff = HBufC::NewL(cchTotal);
  132.     AUTO_PUSH_POP(pbuff);
  133.     TPtr ptr = pbuff->Des();
  134.    
  135.     // build text
  136.     _LIT(KParagraphBreak, "nn");
  137.     // version: xxx
  138.     ptr.Copy(versionText());
  139.     // date: xxx
  140.     ptr.Append(KNewLine());
  141.     ptr.Append(dateText());
  142.     // time: xxx
  143.     ptr.Append(KNewLine());
  144.     ptr.Append(timeText());
  145.     
  146.     // build name
  147.     if( buildName().Length() > 0)
  148.     {
  149.         ptr.Append(KNewLine());
  150.         ptr.Append(buildName());
  151.     }
  152.     // profile
  153.     ptr.Append(KNewLine);
  154.     ptr.Append(profile());
  155.     // copyright
  156.     ptr.Append(KParagraphBreak());
  157.     ptr.Append(copyText());
  158.     
  159.     // voice age
  160.     ptr.Append(KParagraphBreak());
  161.     ptr.Append(voiceAgeText());
  162.   
  163.     return pbuff;
  164. }
  165. /////////////////////////////////////////////////
  166. // helper
  167. CHXString GetRecentClipsFileName()
  168. {
  169.     TFileName* pFullPathRecentClips = CHXAvFile::AllocAppFolderPathL(CHXAvUtil::KPlayerDataFolder);
  170.     AUTO_PUSH_POP_DEL(pFullPathRecentClips);
  171.     CHXAvFile::AppendPath(*pFullPathRecentClips, KRecentClipsName, CHXAvFile::ntFile);
  172.     CHXString str = CHXAvStringUtils::DescToString(*pFullPathRecentClips);
  173.     return str;
  174. }
  175. } // ns anon
  176.     
  177. ////////////////////////////////////////////////
  178. // CEnvironmentChangeNotifier callback
  179. TInt HandleEnvChange_(TAny* p)
  180. {
  181.     // forward this to the ui
  182.     CHXAvPlayerUI* pUI = reinterpret_cast<CHXAvPlayerUI*>(p);
  183.     pUI->HandleEnvChange();
  184.     return EFalse; // don't call again
  185. }
  186. ////////////////////////////////////////////////
  187. //
  188. void CHXAvPlayerUI::HandleEnvChange()
  189. {
  190.     HX_ASSERT(m_pEnvChange);
  191.     TInt change = m_pEnvChange->Change();
  192.     if( m_bIgnoreFirstEnvChange )
  193.     {
  194.         // ignore:
  195.         // 
  196.         // this is an immediate notification sent after we initially request environment
  197.         // change events; in this case 'change' has bits set for all event notifications
  198.         // that we can receive
  199.         //
  200.         m_bIgnoreFirstEnvChange = false;
  201.     }
  202.     else if( EChangesOutOfMemory & change )
  203.     {
  204.         //
  205.         // OOM:
  206.         //
  207.         // Helix core typically ends up in a weird state after allocation failure
  208.         // because it does not expect/handle leave, so we just display error dialog
  209.         // (if possible) and close app.
  210.         //
  211.         // free some reserve memory we allocated up front
  212.         m_spMemoryReserve = 0;
  213.         TRAPD(err, CHXAvMessageDialog::DoSystemErrorNoteL(KErrNoMemory));
  214.         CloseApp();
  215. #if(0)
  216.         // if play view is active
  217.         CHXAvViewBase *pView = static_cast<CHXAvViewBase *>(iView);
  218.         CHXAvPlayView* pPlayView = GetPlayView();
  219.         if(pPlayView->Id() == pView->Id())
  220.         {
  221.             //pPlayView->FreeMemoryReserve();
  222.             User::CompressAllHeaps();
  223.             TRAP(err, DoBackFromCurrentViewL());
  224.             if(KErrNone != err)
  225.             {
  226.                 CloseApp();
  227.             }
  228.         }
  229. #endif
  230.     }
  231. }
  232. /*
  233.  * CHXAvPlayerUI
  234.  * -------------
  235.  * Player ui constructor.
  236.  *
  237.  */
  238. CHXAvPlayerUI::CHXAvPlayerUI()
  239. : m_recentClips(0)
  240. , m_pPrefChangeObserver(0)
  241. , m_bIsRunningEmbedded(false)
  242. , m_bLaunchAppWithClipPending(false)
  243. , m_pEnvChange(0)
  244. , m_bIgnoreFirstEnvChange(true)
  245. //, m_bIsActivePlaybackState(false)
  246. //, m_bDidScreenSaverSignal(false)
  247. //, m_pPinbModel(0) 
  248. //, m_sysSdClient(this)
  249. //, m_sysApSdClient(this)
  250. {
  251. }
  252. /* 
  253.  * ~CHXAvPlayerUI
  254.  * --------------
  255.  * Player ui destructor.
  256.  *
  257.  */
  258. CHXAvPlayerUI::~CHXAvPlayerUI()
  259. {    
  260.     DPRINTF(SYMP_INFO, ("CHXAvPlayerUI::Dtor()n"));
  261.     //m_sysSdClient.Close();
  262.     //m_sysApSdClient.Close();
  263.     HX_DELETE(m_pEnvChange);
  264. }
  265. /*
  266.  * ConstructL
  267.  * ----------
  268.  * Perform all view object construction and anything else 
  269.  * needed for this class.
  270.  *
  271.  */
  272. void 
  273. CHXAvPlayerUI::ConstructL()
  274.     DPRINTF(SYMP_INFO, ("CHXAvPlayerUI::ConstructL()n"));
  275.     BaseConstructL();
  276.     // only allow one ui instance
  277.     EnsureUniqueInstanceL();
  278.     // load client engine and services
  279.     m_spEngineMgr = new (ELeave) CHXClientEngineManager();
  280.     m_spEngineMgr->ConstructL();
  281.     CHXAvPlayerDoc* pDoc = static_cast<CHXAvPlayerDoc*>(Document());
  282.     pDoc->SetEngineManager(m_spEngineMgr);
  283.     // reserve some memory to help with OOM handling
  284.     const TUint K_MEMORY_RESERVE_BYTES = 0x0400 * 4; // 4K
  285.     m_spMemoryReserve = HBufC::NewL(K_MEMORY_RESERVE_BYTES);
  286.     // enable focus events so we can watch when focus window group changes
  287.     RWindowGroup& rootWin = iCoeEnv->RootWin();
  288.     rootWin.EnableFocusChangeEvents();
  289.     //
  290.     // two shared data client connections are needed because signals are auto-
  291.     // canceled when you switch among shared data files
  292.     //
  293. #if(0)
  294.     // for enabling/disabling screen saver
  295.     HXSYM_LEAVE_IF_ERR(m_sysSdClient.Connect());
  296.     HXSYM_LEAVE_IF_ERR(m_sysSdClient.AssignToTemporaryFile(KSDUidSystem));
  297.     // for enabling/disabling backlight
  298.     HXSYM_LEAVE_IF_ERR(m_sysApSdClient.Connect());
  299.     HXSYM_LEAVE_IF_ERR(m_sysApSdClient.AssignToTemporaryFile(KSDUidSysAp));
  300.     m_sysSdClient.NotifyChange(KSDUidSystem);
  301.     m_sysApSdClient.NotifyChange(KSDUidSysAp);
  302.     // for "add to pinboard"
  303.     m_pPinbModel =  CPinbModel::NewL();
  304. #endif
  305.     // locate full path to app image file
  306.     m_spImageFilePath = CHXAvFile::AllocAppFolderPathL(CHXAvUtil::KImagesMBMName);
  307.     // recent clips
  308.     UINT32 maxRecentClipCount = prefs::GetUINT32(m_spEngineMgr->GetPrefs(), CHXAV_MaxRecentClipCount, 6);
  309.     m_recentClips = new (ELeave) CHXAvURLList(maxRecentClipCount);
  310.     m_recentClips->InitializeL();
  311.     m_recentClips->ReadFile(GetRecentClipsFileName());
  312.     // media store
  313.     UpdateMediaStoreInfoL();
  314.     
  315.     // views
  316.     CHXAvPlayView* pPlayerView = new (ELeave) CHXAvPlayView(VID_PlayerView, this);
  317.     AUTO_PUSH_POP(pPlayerView);
  318.     pPlayerView->ConstructL();
  319.   
  320.     CHXAvFileView* pFileView = new (ELeave) CHXAvFileView(VID_FileView, this);
  321.     AUTO_PUSH_POP(pFileView);
  322.     pFileView->ConstructL();
  323.     
  324.     CHXAvSettingsView *pSettingsView = new (ELeave) CHXAvSettingsView(VID_SettingsView, this);
  325.     AUTO_PUSH_POP(pSettingsView);
  326.     pSettingsView->ConstructL();
  327.     CHXAvSelectSettingsView *pSelectSettingsView = new (ELeave) CHXAvSelectSettingsView(VID_SelectSettingsView, this);
  328.     AUTO_PUSH_POP(pSelectSettingsView);
  329.     pSelectSettingsView->ConstructL();
  330.     // determine default view; add default view first
  331.     m_bIsRunningEmbedded = ContainerAppUi() || iDoorObserver;
  332.     DPRINTF(SYMP_INFO, ("CHXAvPlayerUI::ConstructL(): embedded = '%s'n", dbg::Bool(m_bIsRunningEmbedded)));
  333.     if(m_bIsRunningEmbedded)
  334.     {
  335.         // embedded; start with player view
  336.         m_idxDefaultView = VID_PlayerView;
  337.         AddViewL(pPlayerView);
  338.         AddViewL(pFileView);
  339.         AddViewL(pSettingsView);
  340.         AddViewL(pSelectSettingsView);
  341.         SetDefaultViewL(*pPlayerView);
  342.     }
  343.     else
  344.     {
  345.         // not embedded; start with file view
  346.         m_idxDefaultView = VID_FileView;
  347.         AddViewL(pFileView);
  348.         AddViewL(pPlayerView);
  349.         AddViewL(pSettingsView);
  350.         AddViewL(pSelectSettingsView);
  351.         SetDefaultViewL(*pFileView);
  352.     }
  353.     // register to receive environment change notifications (for OOM)
  354.     m_bIgnoreFirstEnvChange = true;
  355.     HX_ASSERT(!m_pEnvChange);
  356.     TCallBack cb(HandleEnvChange_, this);
  357.     m_pEnvChange = CEnvironmentChangeNotifier::NewL(CActive::EPriorityHigh, cb);
  358.     m_pEnvChange->Start();
  359.     
  360. }
  361. bool CHXAvPlayerUI::EnsureUniqueInstanceHelperL()
  362. {
  363.     DPRINTF(SYMP_INFO, ("CHXAvPlayerUI::EnsureUniqueInstanceHelperL(): acquiring instance token..."));
  364.     bool bGotIt = m_instanceToken.TryAcquire();
  365.     if( !bGotIt )
  366.     {
  367.         DPRINTF(SYMP_INFO, ("CHXAvPlayerUI::EnsureUniqueInstanceHelperL(): failed to acquire token (another app is running); broadcasting close..."));
  368.         // another instance has the instance token
  369.         //
  370.         // send message to other instances to request that it stop and exit
  371.         //
  372.     
  373.         //
  374.         // broadcast 'close' message for other instance to see; other instances
  375.         // receive this message via HandleApplicationSpecificEventL()
  376.         //
  377.         // we broadcast a close message to all apps because it is hard
  378.         // to find embedded instances
  379.         //
  380.         HBufC8* pMsg = CHXAvMisc::MakeHXPlayerPrivateMessageL(KMessage_CloseApp);
  381.         AUTO_PUSH_POP_DEL(pMsg);
  382.         CHXAvMisc::BroadcastWsEventL(KHXPlayerWsEvent, pMsg);
  383.         
  384.         //
  385.         // wait ~5 seconds for other instance
  386.         // to close down before we give up
  387.         //
  388.         const TUint k_maxTryCount = 10;
  389.         const TUint k_msBetweenAttempts = 500;
  390.         const TUint k_showMessageTryIndex = 3; // show mesage after 3 tries (1.5 secs)
  391.         for( TInt tryCount = 0; tryCount < k_maxTryCount && !bGotIt; ++tryCount)
  392.         {
  393.             // wait a bit before next attempt to try to acquire the token; use custom wait so dialogs have chance to draw
  394.             CHXAvUtil::ActiveWait(k_msBetweenAttempts);
  395.             //User::After(k_msBetweenAttempts * k_usecPerMs); 
  396.             bGotIt = m_instanceToken.TryAcquire();
  397.             if( !bGotIt && (k_showMessageTryIndex == tryCount) )   
  398.             {
  399.                 // show note to user that we are shutting down other instance
  400.                 HX_ASSERT(m_spCloseAppWaitNote);
  401.                 m_spCloseAppWaitNote->StartAndKickL();
  402.             }
  403.         }
  404.         m_spCloseAppWaitNote->EndL();
  405.         if( !bGotIt )
  406.         {
  407.             CHXAvMessageDialog::DoAlertErrorL(CHXAvCleanString(R_AVP_N_FAILED_TO_CLOSE_OTHER_INSTANCE)());
  408.         }
  409.             
  410.     }
  411.     return bGotIt;
  412. }
  413. /*
  414.  * EnsureUniqueInstanceL
  415.  * ------------
  416.  * ensure that we close any other app instances
  417.  * that might be running
  418.  *
  419.  */
  420. void CHXAvPlayerUI::EnsureUniqueInstanceL()
  421. {
  422.     m_spCloseAppWaitNote = new (ELeave) CHXAvWaitNote();
  423.     m_spCloseAppWaitNote->SetTextL(CHXAvCleanString(R_AVP_N_CLOSING_OTHER_INSTANCE)());
  424.     // token name for controlling single instance
  425.     _LIT(KUniqueInstanceSemName, "HelixPlayer10009D06");
  426.     m_instanceToken.ConstructL(KUniqueInstanceSemName);
  427.     if(!EnsureUniqueInstanceHelperL())
  428.     {
  429.         DPRINTF(SYMP_INFO, ("CHXAvPlayerUI::EnsureUniqueInstanceL(): other instance failed to close"));
  430.         HXSYM_LEAVE(KLeaveWithoutAlert);
  431.     }
  432. }
  433. ////////////////////////////////////////////
  434. // 
  435. TBool CHXAvPlayerUI::ProcessCommandParametersL(TApaCommand idCmd,
  436.                                             TFileName& aDocumentName,
  437.                                             const TDesC8& /*aTail*/)
  438. {
  439.     DPRINTF(SYMP_INFO, ("CHXAvPlayerUI::ProcessCommandParametersL(%d))n", idCmd));
  440.     DPRINTF(SYMP_INFO, ("doc = '%s'n", dbg::CharPtr(aDocumentName)()));
  441.     // this (call to 2-arg override) causes doc name to be given a new name
  442.     // return CAknViewAppUi::ProcessCommandParametersL(idCmd, aDocumentName);
  443.     
  444.     // this (default) results in CEikDocument::OpenFileL not being called
  445.     // return CAknViewAppUi::ProcessCommandParametersL(idCmd, aDocumentName, aTail);
  446.     // ensures that CEikDocument::OpenFileL is called if a command line arg was provided
  447.     return EFalse;
  448.    
  449. }
  450. ////////////////////////////////////////////
  451. // get here if:
  452. //
  453. // o click on file in file browser (while our app is running)
  454. // o click on app in file browser (while our app is running)
  455. // o someone calls TApaTask::SwitchOpenFile()
  456. // o our document calls us because it gets the openfile request
  457. // 
  458. // all external ways of getting an argument, file, etc. end up
  459. // here
  460. //
  461. // fileArg can be in local path form ('c:myfolderfile.rm') or 
  462. // url form ('rtsp://dfsd/sdf/foo.rm')
  463. //
  464. void CHXAvPlayerUI::OpenFileL(const TDesC& fileArg)
  465. {
  466.     DPRINTF(SYMP_INFO,("avPlayerUI::OpenFileL(): '%s'n", dbg::CharPtr(fileArg)()));
  467.     
  468.     bool bIsUrl = CHXAvUtil::IsValidUrl(fileArg);
  469.     if( bIsUrl )
  470.     {
  471.         // an URL was passed as the argument
  472.         ActivatePlayViewL(fileArg);
  473.     }
  474.     else
  475.     {
  476.         // local file (most likely case)
  477.         HBufC* pFile = CHXAvFile::AllocFileUrlL(fileArg);
  478.         AUTO_PUSH_POP_DEL(pFile);
  479.         ActivatePlayViewL(*pFile);
  480.     }
  481. }
  482. #if(0)
  483. /*
  484.  * CAknViewAppUi::HandleForegroundEventL
  485.  * ----------------------
  486.  * 
  487.  * Called when app gains/looses foreground (not when app views are switching)
  488.  *
  489.  */
  490. void CHXAvPlayerUI::HandleForegroundEventL(TBool bEnterForeground)
  491. {
  492.     DPRINTF(SYMP_INFO, ("CHXAvPlayerUI::HandleForegroundEventL(): enter = '%s'n", dbg::Bool(bEnterForeground)));
  493.     CAknViewAppUi::HandleForegroundEventL(bEnterForeground);
  494. }
  495. #endif
  496. /*
  497.  * CAknViewAppUi::HandleViewDeactivation
  498.  * ----------------------
  499.  * Switch views.  Set the correct back view index for future switches.
  500.  * This is called, then DoActivate for new view, then DoDeactivate for old view.
  501.  */
  502. void
  503. CHXAvPlayerUI::HandleViewDeactivation(const TVwsViewId& idOldView, const TVwsViewId& idNewView)
  504. {
  505.     DPRINTF(SYMP_INFO, ("CHXAvPlayerUI::HandleViewDeactivation()n"));
  506.     bool bIsInterAppViewSwitch = (idOldView.iAppUid != idNewView.iAppUid);
  507.     if(!bIsInterAppViewSwitch)
  508.     {
  509. // Activating another view in our own app...
  510.         HX_ASSERT(idOldView.iAppUid == CHXAvMisc::KAppUID);
  511.         TUid idNew = idNewView.iViewUid;
  512.         TUid idOld = idOldView.iViewUid;
  513.         // special case: if settings view is activating, tell player view not
  514.         // to shut down the player so return gets user back to previous player state
  515.         if(idOld == TUid::Uid(VID_PlayerView) && idNew == TUid::Uid(VID_SelectSettingsView))
  516.         {
  517.             CHXAvPlayView* pPlayView = GetPlayView();
  518.             pPlayView->SetShutdownOnViewDeactivation(false);
  519.         }
  520.         CHXAvViewBase * pNewView = static_cast<CHXAvViewBase *>(View(idNew));
  521.         CHXAvViewBase * pOldView = static_cast<CHXAvViewBase *>(View(idOld));
  522.         HX_ASSERT(pNewView);
  523.         HX_ASSERT(pOldView);
  524.         DPRINTF(SYMP_INFO, ("CHXAvPlayerUI::HandleViewDeactivation(): old = %d; new = %dn", idOld.iUid, idNew.iUid));
  525.         
  526.         if( idNew == TUid::Uid(m_idxDefaultView) )
  527.         {
  528.             // Default view is activating; there is no "last view" to go back to...
  529.             pNewView->SetBackView(-1);
  530.         }
  531.         else
  532.         {
  533.             // Do nothing if returning back to old view that 'launched' the new (now becoming old) view...
  534.             bool bReturning = (pOldView->GetBackView() == pNewView->Id().iUid);
  535.             // Don't set back view to self...
  536.             bool bSame = (pNewView->Id() == pOldView->Id());
  537.             if(!bReturning && !bSame)
  538.             {
  539.                 pNewView->SetBackView(pOldView->Id().iUid);
  540.             }
  541.         }
  542.     }
  543.     CAknViewAppUi::HandleViewDeactivation(idOldView, idNewView);
  544. }
  545. /* 
  546.  * DoBackFromCurrentViewL
  547.  * ----------------------
  548.  * Go back to the previous view from here.
  549.  *
  550.  */
  551. void 
  552. CHXAvPlayerUI::DoBackFromCurrentViewL()
  553. {
  554.     HX_ASSERT(iView);
  555.     CHXAvViewBase *pView = static_cast<CHXAvViewBase *>(iView);
  556.     TInt idxBackView = pView->GetBackView();
  557.     DPRINTF(SYMP_INFO, ("CHXAvPlayerUI::DoBackFromCurrentViewL(): back view = %dn", idxBackView));
  558.     if (idxBackView == -1)
  559.     {
  560.         // If there's no view to go back to, exit...
  561.         HX_ASSERT( TUid::Uid(m_idxDefaultView) == iView->Id());
  562.         HandleCommandL(EEikCmdExit);
  563.     }
  564.     else
  565.     {
  566.         // note: call to base class is intentional
  567.         HX_ASSERT( TUid::Uid(m_idxDefaultView) != iView->Id());
  568.         ActivateLocalViewL(TUid::Uid(idxBackView));
  569.     }
  570. }
  571. ////////////////////////////////////////
  572. // TWsEvent beyond EEventUser received...
  573. void CHXAvPlayerUI::HandleApplicationSpecificEventL(TInt aType,const TWsEvent& aEvent)
  574. {
  575.     DPRINTF(SYMP_INFO, ("CHXAvPlayerUI::HandleApplicationSpecificEventL(): type = %dn", aType));
  576.     // handle possible shutdown command coming from TWsEvent that we send
  577.     if(aType == KHXPlayerWsEvent)
  578.     {
  579.         TUint8* pData = aEvent.EventData();
  580.         if( pData )
  581.         {
  582.             TPtr8 msg(pData, TWsEvent::EWsEventDataSize);
  583.             DPRINTF(SYMP_INFO, ("HandleApplicationSpecificEventL(): message is '%.*s'n", msg.Length(), msg.Ptr()));
  584.         
  585.             // make sure it is not from this thread
  586.             HBufC8* pMsg = MakeHXPlayerPrivateMessageL(KMessage_CloseApp);
  587.             AUTO_PUSH_POP_DEL(pMsg);
  588.             // message will compare equal if it is a close app message from another instance
  589.             if( 0 != pMsg->Compare(msg) )
  590.             {
  591.                 DPRINTF(SYMP_INFO, ("HandlePossibleShutdownCommandL(): closing instancen"));
  592.                 CloseApp();
  593.             }
  594.         }
  595.     }
  596. }
  597. /* 
  598.  * HandleCommandL
  599.  * --------------
  600.  * These are commands that are shared (or conceivably can be shared) among
  601.  * several of the views
  602.  *
  603.  */
  604. void 
  605. CHXAvPlayerUI::HandleCommandL(TInt aCommand)
  606. {
  607.     switch (aCommand)
  608.     {
  609.     case EAknCmdExit:
  610.     case EEikCmdExit:
  611.     case EAknSoftkeyExit:
  612.         CloseApp();
  613. break;
  614.     case EAknSoftkeyBack:
  615. DoBackFromCurrentViewL();
  616. break;
  617.     case EOpenGuide:
  618.         DoOpenGuideL();
  619.         break;
  620.     case EViewSettings:
  621.         DoSelectSettingsL();
  622. break;
  623.     case EAboutDialog:
  624. DoAboutL();
  625. break;
  626.     case EOpenRecentDialog:
  627. DoOpenRecentL();
  628. break;
  629.     case EOpenURLDialog:
  630. DoOpenURLL();
  631. break;
  632.     
  633.     case ERestoreDefaultSettings:
  634.         DoRestoreDefaultSettingsL();
  635.         break;
  636.     case EAknCmdHelp:
  637.         //HlpLauncher::LaunchHelpApplicationL( iCoeEnv->WsSession(), AppHelpContextL() );
  638.         break;
  639.     default:
  640.         // we don't expect any other commands (except possibly a click on an empty softkey)
  641.         HX_ASSERT(EAknSoftkeyEmpty == aCommand);
  642. break;
  643.     }
  644. }
  645. ////////////////////////////////////////////////////////////////
  646. // restore config to installation default
  647. void CHXAvPlayerUI::DoRestoreDefaultSettingsL()
  648. {
  649.     if(CHXAvMessageDialog::DoQueryL(R_CONF_RESTORE_SETTINGS))
  650.     {
  651.         // user confirmed...
  652.         comptr<CHXLitePrefs> spPrefs = m_spEngineMgr->GetPrefs();
  653.         spPrefs->ResetPrefs(); //XXXLCM can fail
  654.         if( m_pPrefChangeObserver )
  655.         {
  656.             m_pPrefChangeObserver->OnPrefsChanged();
  657.         }
  658.         CHXAvMessageDialog::DoAlertConfirmL(CHXAvCleanString(R_SETTINGS_RESTORED)());
  659.     }
  660. }
  661. /* 
  662.  * DoSelectSettingsL
  663.  * -----------------
  664.  * Show the select settings view.
  665.  *
  666.  */
  667. void CHXAvPlayerUI::DoSelectSettingsL()
  668. {
  669.     // prepare select settings view to launch with first item hilighted
  670.     CAknView* pView = View(TUid::Uid(CHXAvPlayerUI::VID_SelectSettingsView));
  671.     HX_ASSERT(pView);
  672.     CHXAvSelectSettingsView* pSelectView = static_cast<CHXAvSelectSettingsView*>(pView);
  673.     pSelectView->ResetCurrentIndex();
  674.     ActivateLocalViewL(TUid::Uid(VID_SelectSettingsView));
  675. }
  676. ////////////////////////////////////////
  677. // 
  678. void
  679. CHXAvPlayerUI::DoEditPlaylistL(const TDesC& playlistPath)
  680. {
  681.     DPRINTF(SYMP_INFO, ("CHXAvPlayerUI::DoEditPlaylistL()n"));
  682.     CHXAvEditPlaylistDialog* pDlg = new (ELeave) CHXAvEditPlaylistDialog();
  683.     TInt err = KErrNone;
  684.     // save cleanupstack init until LD
  685.     {
  686.         AUTO_PUSH_POP(pDlg);
  687.         pDlg->ConstructL();
  688.         // make sure read-only is clear so we can edit (we don't honor this attribute)
  689.         CHXAvFile::EnsureClearReadOnlyAttributeL(playlistPath);
  690.         err = pDlg->SetPlaylistL(playlistPath);
  691.     }
  692.     if(KErrNone == err)
  693.     {
  694.         pDlg->ExecuteLD(R_AVP_EDIT_PLAYLIST_DLG);
  695.     }
  696.     else
  697.     {
  698.         HX_DELETE(pDlg); // <-- since dialog will not delete itself
  699.         CHXAvMessageDialog::DoAlertErrorL(CHXAvCleanString(R_ERR_UNABLE_TO_EDIT_PLAYLIST)());
  700.     }
  701. }
  702. /*
  703.  * DoOpenGuideL
  704.  * ------------
  705.  * Open the guide.
  706.  *
  707.  */
  708. void
  709. CHXAvPlayerUI::DoOpenGuideL()
  710. {
  711.     const TDesC& guideUrl = GetGuideUrlL(false);
  712.     TInt err = KErrGeneral;
  713.     if( guideUrl.Length() > 0 )
  714.     {
  715.         const TInt KWmlBrowserUid = 0x10008D39;
  716.         
  717.         // format web browser message
  718.         _LIT(KOpenUrlMessagePrefix, "4 ");
  719.         TInt cchTotal = guideUrl.Length() + CHXAvUtil::litSize(KOpenUrlMessagePrefix);
  720.         
  721.         HBufC* pBuf = HBufC::NewL(cchTotal);
  722.         AUTO_PUSH_POP_DEL(pBuf);
  723.         TPtr ptr = pBuf->Des();
  724.         ptr.Copy(KOpenUrlMessagePrefix);
  725.         ptr.Append(guideUrl);
  726.         // launch app with message argument
  727.         TRAP(err, CHXAvMisc::LaunchAppL(KWmlBrowserUid, *pBuf));
  728.     }
  729.     if(KErrNone != err)
  730.     {
  731.         //XXXLCM
  732.         CHXAvMessageDialog::DoAlertInfoL(_L("unable to launch guide"));
  733.     }
  734. }
  735. /*
  736.  * CloseApp
  737.  * --------
  738.  * Called when we receive exit command (from user or via system message)
  739.  *
  740.  */
  741. void
  742. CHXAvPlayerUI::CloseApp()
  743. {
  744.     // Write out the recent clips and release...
  745.     HX_ASSERT(m_recentClips);
  746.     if (m_recentClips)
  747.     {
  748. m_recentClips->WriteFile(GetRecentClipsFileName());
  749.     }
  750.     // this prevents mms app from hanging when we exit
  751.     if(iDoorObserver)
  752.     {
  753.         iDoorObserver->NotifyExit(MApaEmbeddedDocObserver::EEmpty);
  754.     }
  755.     // Now we can exit...
  756.     Exit();
  757. }
  758. ////////////////////////////
  759. //HandleWsEventL
  760. void CHXAvPlayerUI::HandleWsEventL(const TWsEvent& event, CCoeControl* pDest)
  761. {
  762.     DPRINTF(SYMP_WSEVENTS, ("CHXAvPlayerUI::HandleWsEventL():  type = %ld; dest = 0x%08xn", event.Type(), pDest));
  763.     switch(event.Type())
  764.     {
  765.         case EEventKeyUp:
  766.         {
  767.             DPRINTF(SYMP_WSEVENTS, ("CHXAvPlayerUI::HandleWsEventL():  key up eventn"));
  768.             TKeyEvent* pKey = event.Key();
  769.             if(pKey)
  770.             {
  771.                 CHXAvViewBase *pActiveView = static_cast<CHXAvViewBase *>(iView);
  772.                 if(pActiveView)
  773.                 {
  774.                     //
  775.                     // special case: for some reason the left-shift up is not received by the CCoeControl
  776.                     // if you click on a softkey while the shift key is held down before releasing the shift key
  777.                     //
  778.                 
  779.                     // XXXLCM we should probably do more to avoid double-event notification
  780.                     if( pKey->iScanCode == EStdKeyLeftShift)
  781.                     {
  782.                         DPRINTF(SYMP_INFO, ("CHXAvPlayerUI::HandleWsEventL():  got shift key up eventn"));
  783.                         pActiveView->GetWindow()->OfferKeyEventL(*pKey, EEventKeyUp);
  784.                     }
  785.                 }
  786.             }
  787.         }
  788.         break;
  789.         case EEventFocusGroupChanged:
  790.         {
  791.             DPRINTF(SYMP_WSEVENTS, ("CHXAvPlayerUI::HandleWsEvent(): focus group changen"));
  792.             TInt wgidFocus = iEikonEnv->WsSession().GetFocusWindowGroup();
  793.             TUid uidFocus = CHXAvMisc::GetAppUidFromWgId(wgidFocus);
  794.             bool bNeedToStopPlayback = !(uidFocus == CHXAvMisc::KScreenSaverUID || 
  795.                                     uidFocus == CHXAvMisc::KAppUID );
  796.             if( bNeedToStopPlayback )
  797.             {
  798.                 DPRINTF(SYMP_WSEVENTS, ("CHXAvPlayerUI::HandleWsEvent(): new app focus is not screen saver or playern"));
  799.                 CHXAvViewBase* pActiveView = static_cast<CHXAvViewBase *>(iView);
  800.                 if( pActiveView )
  801.                 {
  802.                     pActiveView->HandleLosePlayFocus();
  803.                 }
  804.             }
  805.         }
  806.         break;
  807.         default:
  808.             break;
  809.     }
  810.     CAknViewAppUi::HandleWsEventL(event, pDest);
  811. }
  812. ////////////////////////////////////
  813. // ensure play view is activated and attempt to play clip
  814. //
  815. void CHXAvPlayerUI::ActivatePlayViewL(const TDesC& url)
  816. {
  817.     DPRINTF(SYMP_INFO, ("CHXAvPlayerUI::ActivatePlayViewL():  current view exists = '%s' n", dbg::Bool(iView)));
  818.     if( iView && (TUid::Uid(VID_PlayerView) == iView->Id()) )
  819.     {
  820.         // play view is active view
  821.         CHXAvPlayer* pPlayer = GetPlayer();
  822.         HX_ASSERT(pPlayer);
  823.         pPlayer->Play(url);
  824.     }
  825.     else
  826.     {
  827.         // we need to activate play view
  828.         CHXAvPlayView* pPlayView = GetPlayView();
  829.         // set clip to launch on view activation (view activates asynchronously)
  830.         pPlayView->SetViewActivateClipL(url);
  831.         //
  832.         // Activate player view if not in process of app
  833.         // startup (see OnViewForegroundActivateL()).
  834.         // Otherwise wait for default view (file view) to launch.
  835.         //
  836.         // iView becomes non-0 sometime after first foreground event
  837.         // for first activating view
  838.         //
  839.         m_bLaunchAppWithClipPending = (0 == iView);
  840.         if( !m_bLaunchAppWithClipPending )
  841.         {
  842.             ActivateLocalViewL(TUid::Uid(VID_PlayerView));
  843.         }
  844.     }
  845. }
  846. //
  847. // Called when view receives first foreground event after activation
  848. //
  849. void CHXAvPlayerUI::OnViewForegroundActivateL(TInt idxView)
  850. {
  851.     DPRINTF(SYMP_INFO, ("CHXAvPlayerUI::OnViewForegroundActivateL():  current view id  = %dn", idxView));
  852.     //
  853.     // If this app instance was launched with a clip we get a call
  854.     // to OpenFileL() before the default view (i.e., file view in
  855.     // stand-alone launch case) is  activated. If we activate the
  856.     // player view at that time, the default view  will immediately
  857.     // activate after that (and yours truly has not found a good way
  858.     // to prevent this). So to work around this, we wait for the default
  859.     // view to activate before activating the play view.
  860.     //
  861.     if ( (VID_PlayerView != idxView) && m_bLaunchAppWithClipPending) 
  862.     {
  863.         ActivateLocalViewL(TUid::Uid(VID_PlayerView));
  864.     }
  865.     m_bLaunchAppWithClipPending = false;
  866. }
  867. CHXAvPlayView* CHXAvPlayerUI::GetPlayView()
  868. {
  869.     CHXAvPlayView* pPlayView = (CHXAvPlayView *)(View(TUid::Uid(VID_PlayerView)));
  870.     HX_ASSERT(pPlayView);
  871.     return pPlayView;
  872. }
  873. // player will be NULL if play view not activated
  874. comptr<CHXAvPlayer> CHXAvPlayerUI::GetPlayer()
  875. {
  876.     CHXAvPlayView* pPlayView = GetPlayView();
  877.     CHXAvPlayer* pPlayer = pPlayView->GetPlayer();
  878.     HX_ASSERT(pPlayer);
  879.     return pPlayer;
  880. }
  881. /*
  882.  * DoAboutL
  883.  * --------
  884.  * Do about screen.
  885.  *
  886.  */
  887. void 
  888. CHXAvPlayerUI::DoAboutL()
  889. {
  890.     HBufC* pText = AllocAboutTextL();
  891.     AUTO_PUSH_POP_DEL(pText);
  892.     CHXAvMessageDialog::DoLongTextInfoPromptL(CHXAvCleanString(R_ABOUT_CAPTION)(), *pText, CHXAvMessageDialog::PromptBack);
  893. }
  894. /*
  895.  * DoOpenURLL
  896.  * ----------
  897.  * Show the open url dialog.
  898.  *
  899.  */
  900. void 
  901. CHXAvPlayerUI::DoOpenURLL()
  902. {
  903.     CHXAvCleanString promptText(R_PROMPT_ENTER_URL);
  904.    
  905.     //
  906.     // keep prompting until user: a) cancels; or b) enters a valid URL
  907.     //
  908.     
  909.     for(;;)
  910.     {
  911.         HBufC* pDefaultText = 0;
  912.         if(m_lastClipEntered.IsEmpty())
  913.         {
  914.     // fill with default protocol prefix
  915.     pDefaultText = CHXAvUtil::KRTSPProtocolPrefix().AllocL();
  916.         }
  917.         else
  918.         {
  919.             // fill with last text entered by the user
  920.             pDefaultText = CHXAvStringUtils::AllocTextL(m_lastClipEntered);
  921.         }
  922.         AUTO_PUSH_POP_DEL(pDefaultText);
  923. // Query the user for the url...
  924.         HBufC* pUrl = CHXAvMessageDialog::DoQueryTextL(promptText(), *pDefaultText, KMaxFileName);
  925. if (pUrl != NULL)
  926. {
  927.             AUTO_PUSH_POP_DEL(pUrl);
  928.                     
  929.             // remember what user entered (even if it turns out to be bad)
  930.     CHXAvStringUtils::DesToString(*pUrl, m_lastClipEntered);
  931.             ValidateUrlResult res = ValidateUrl(*pUrl);
  932.             if (CHXAvUtil::vuGood == res)
  933.             {
  934.                 ActivatePlayViewL(*pUrl);
  935.                 break;
  936.             }
  937.             else if(CHXAvUtil::vuMissingScheme == res)
  938.             {
  939.                 //
  940.                 // no scheme
  941.                 //
  942.                 // try with 'rtsp' or 'file' appended, depending on whether url looks
  943.                 // like a local or remote url
  944.                 //
  945.                 HBufC* pAlt = 0;
  946.                 TInt idxDrive = CHXAvFile::GetDriveIndex(*pUrl);
  947.                 if(-1 != idxDrive)
  948.                 {
  949.                     // begins with a drive letter, looks like a file path...
  950.                     pAlt = CHXAvFile::AllocFileUrlL(*pUrl);
  951.                 }
  952.                 else
  953.                 {
  954.                     // guess that this is a remote rtsp URL...
  955.                     pAlt = CHXAvStringUtils::AllocTextL(KRTSPProtocolPrefix, *pUrl);
  956.                 }
  957.                 AUTO_PUSH_POP_DEL(pAlt);
  958.                 if(CHXAvUtil::IsValidUrl(*pAlt))
  959.                 {
  960.                     ActivatePlayViewL(*pAlt);
  961.                     break;
  962.                 }
  963.             }
  964.  
  965.             // assume typo; let user edit and try again...
  966.             CHXAvMessageDialog::DoAlertInfoL(CHXAvCleanString(R_ERR_INVALID_URL)()); 
  967. }
  968.         else
  969.         {
  970.             // user cancelled
  971.             break;
  972.         }
  973.     }
  974. }
  975. /*
  976.  * DoOpenRecentL
  977.  * -------------
  978.  * Show the open recent url dialog.  Launch the item that the user selected.
  979.  *
  980.  */
  981. void
  982. CHXAvPlayerUI::DoOpenRecentL()
  983. {
  984.     if (m_recentClips->NumURLs() > 0)
  985.     {
  986. TInt idxSelectedItem = 0;
  987. CHXAvRecentClipsPopupList* pPopup = new (ELeave) CHXAvRecentClipsPopupList(idxSelectedItem);
  988.         
  989.         // save cleanupstack init until LD
  990.         {
  991.     AUTO_PUSH_POP(pPopup);
  992.     pPopup->ConstructL(m_recentClips.raw_ptr());
  993.         }
  994. if (pPopup->ExecuteLD())
  995. {
  996.     // Launch the item that the user selected
  997.     if ((idxSelectedItem >= 0) && (idxSelectedItem < m_recentClips->NumURLs()))
  998.     {
  999.                 ActivatePlayViewL((m_recentClips->GetURL(idxSelectedItem))->URL());
  1000.     }
  1001. }
  1002.     }
  1003.     else
  1004.     {
  1005.         CHXAvMessageDialog::DoAlertInfoL(CHXAvCleanString(R_RECENT_CLIPS_EMPTY)());
  1006.     }
  1007. }
  1008. /*
  1009.  * GetMediaStoreInfoL
  1010.  * ------------------
  1011.  * Return the list of media information..
  1012.  *
  1013.  */
  1014. const CHXAvVector<CHXAvMediaFolderInfoPtr>& 
  1015. CHXAvPlayerUI::GetMediaStoreInfoL(bool bForceUpdate)
  1016. {
  1017.     if( 0 == m_mediaStoreInfo.Nelements() || bForceUpdate )
  1018.     {
  1019.         UpdateMediaStoreInfoL();
  1020.     }
  1021.     return m_mediaStoreInfo;
  1022. }
  1023. /* 
  1024.  * UpdateMediaStoreInfoL
  1025.  * ---------------------
  1026.  * Rebuild media store list
  1027.  *
  1028.  */
  1029. void CHXAvPlayerUI::UpdateMediaStoreInfoL()
  1030. {
  1031.     m_mediaStoreInfo.Resize(0);
  1032.     CHXString strLocalMediaFolder = prefs::GetString(m_spEngineMgr->GetPrefs(),
  1033.                                                      CHXAV_LocalMediaFolder);
  1034.     HXSYM_LEAVE_IF_TRUE(strLocalMediaFolder.IsEmpty());
  1035.     AppendMediaStoreInfoL(strLocalMediaFolder, CHXAvMediaFolderInfo::PATH_ENSURE);
  1036.     CHXString strMmcMediaFolder = prefs::GetString(m_spEngineMgr->GetPrefs(), 
  1037.                                                    CHXAV_MmcMediaFolder);
  1038.     if(!strMmcMediaFolder.IsEmpty())
  1039.     {
  1040.         //Do not try this on a 7650, It will crash the phone.
  1041.         TInt nModelNumber = 0;
  1042.         TInt nManufacture = 0;
  1043.         HAL::Get(HAL::EModel, nModelNumber);
  1044.         HAL::Get(HAL::EManufacturer, nManufacture);
  1045.         if( nManufacture != HAL::EManufacturer_Nokia || nModelNumber != NOKIA_7650 )
  1046.         {
  1047.             AppendMediaStoreInfoL(strMmcMediaFolder, CHXAvMediaFolderInfo::PATH_OPTIONAL);
  1048.         }
  1049.     }   
  1050. }
  1051. /*
  1052.  * AppendMediaStoreInfoL
  1053.  * ---------------------
  1054.  * Here we create each media store, and call routines to find out what's in those locations.
  1055.  *
  1056.  */
  1057. void 
  1058. CHXAvPlayerUI::AppendMediaStoreInfoL(const CHXString& strRootPath, CHXAvMediaFolderInfo::PathCreateType pathType)
  1059. {
  1060.     TFileName* pPath = CHXAvFile::AllocFileNameL(CHXAvCleanString(strRootPath)(), CHXAvFile::ntFolder);
  1061.     AUTO_PUSH_POP_DEL(pPath);
  1062.     CHXAvMediaFolderInfoPtr spInfo = new (ELeave) CHXAvMediaFolderInfo();
  1063.     CHXAvUtil::Append(m_mediaStoreInfo, spInfo);
  1064.     spInfo->InitL(*pPath, pathType);
  1065. }
  1066. ////////////////////////////////////////
  1067. //
  1068. // Guide can be specified in config/preferences as:
  1069. //
  1070. // 1) local file name relative to local guide folder path 
  1071. //        e.g., 'index.html', 'germanindex.wmlc'
  1072. //
  1073. // 3) http url 
  1074. //        e.g., 'http://www.real.com/mobile/home.html'
  1075. //
  1076. // In either case this returns a properly formed 'file' 
  1077. // or 'http' url.
  1078. //
  1079. TPtrC CHXAvPlayerUI::GetGuideUrlL(bool bForceUpdate)
  1080. {
  1081.     TPtrC out(KNullDesC);
  1082.     if( bForceUpdate )
  1083.     {
  1084.         // ensure url is reset
  1085.         m_spGuideUrl = 0;
  1086.     }
  1087.     if( !m_spGuideUrl )
  1088.     {
  1089.         DPRINTF(SYMP_INFO, ("GetGuideUrlL(): current locale is %dn", User::Language()));
  1090.         // look at 'guide'
  1091.         CHXString strGuide = prefs::GetString(m_spEngineMgr->GetPrefs(), CHXAV_Guide);
  1092.         if( !strGuide.IsEmpty() )
  1093.         {
  1094.             bool bLocalize = prefs::GetBool(m_spEngineMgr->GetPrefs(), CHXAV_GuideLocalize);
  1095.         
  1096.             // see if guide is specified as an 'http' url
  1097.             if(CHXAvUtil::IsHttpUrl(strGuide))
  1098.             {
  1099.                 // assume config entry is valid http url...
  1100.                 if( bLocalize )
  1101.                 {
  1102.                      // append '?locale=NN' to url to tell server to retrieve localized guide page
  1103.                     _LIT(KQuestionMark, "?");
  1104.                     _LIT(KGuideLocaleQuery,   "locale=%d");
  1105.                     const TLanguage locale = User::Language();
  1106.                     CHXAvCleanString urlText(strGuide);
  1107.                     CHXAvCleanString urlQuery(KGuideLocaleQuery, locale);
  1108.                     m_spGuideUrl = CHXAvStringUtils::AllocTextL(urlText(), KQuestionMark, urlQuery());
  1109.                 }
  1110.                 else
  1111.                 {
  1112.                     m_spGuideUrl = CHXAvStringUtils::AllocTextL(strGuide);
  1113.                 }
  1114.             }
  1115.             else
  1116.             {
  1117.                 // looks like we are dealing with a local guide
  1118.             
  1119.                 TFileName* pFullPathGuide = CHXAvFile::AllocFullPrefPathL(m_spEngineMgr->GetPrefs(), CHXAV_Guide);
  1120.                 HXSYM_LEAVE_IF_FALSE(pFullPathGuide != 0);
  1121.                 AUTO_PUSH_POP_DEL(pFullPathGuide);
  1122.                 if(bLocalize)
  1123.                 {
  1124.                    
  1125.                     // find localized version, based on TLanguage enum in extension (e.g., for '*.rsc',  '*.r01' == English, '*.r10' == American, etc.)
  1126.                     DPRINTF(SYMP_INFO, ("GetGuideUrlL(): default guide is '%s'n", dbg::CharPtr(*pFullPathGuide)()));
  1127.                 
  1128.                     // appears to require drive in path (despite docs); path is not modified if path is invalid
  1129.                     BaflUtils::NearestLanguageFile(iCoeEnv->FsSession(), *pFullPathGuide); 
  1130.                     DPRINTF(SYMP_INFO, ("GetGuideUrlL(): localized guide is '%s'n", dbg::CharPtr(*pFullPathGuide)()));
  1131.                 }
  1132.                 // ensure path exists
  1133.                 bool bExists = CHXAvFile::PathExists(*pFullPathGuide);
  1134.                 HX_ASSERT(bExists);
  1135.                 if(bExists)
  1136.                 {
  1137.                     // save path fixed up so it is a 'file:///' url
  1138.                     m_spGuideUrl = CHXAvFile::AllocFileUrlL(*pFullPathGuide);
  1139.                 }
  1140.             }
  1141.         }
  1142.     }
  1143.     if( m_spGuideUrl )
  1144.     {
  1145.         out.Set(*m_spGuideUrl);
  1146.     }
  1147.     
  1148.     DPRINTF(SYMP_INFO, ("GetGuideUrlL(): url is '%s'n", dbg::CharPtr(out)()));
  1149.     return out; 
  1150. }
  1151. #if(0)
  1152. ////////////////////////////////////////////////         
  1153. // shared data client notifier
  1154. void CHXAvPlayerUI::HandleNotifyL(const TUid uid, const TDesC& key, const TDesC& val)
  1155. {
  1156.     DPRINTF(SYMP_INFO, ("avPlayerUI::HandleNotifyL(): uid = 0x%08x, key = '%s', val = '%s'n", uid.iUid, dbg::CharPtr(key)(), dbg::CharPtr(val)()));
  1157.     // note: we should not get notifications in cases where we are the source of the change
  1158.     if(KSDUidSysAp == uid)
  1159.     {
  1160.         if (0 == key.CompareF(KSysApLightsControl))
  1161.         {
  1162.             if( !IsEqual(val, BacklightAlwaysOn) )
  1163.             {
  1164.                 DPRINTF(SYMP_INFO, ("CHXAvPlayerUI::HandleNotifyL(): backlight resetn"));
  1165.                 // some events (e.g., incoming sms) reset backlight behavior; ensure this is set correctly
  1166.                 SetActivePlaybackState(m_bIsActivePlaybackState);
  1167.             }
  1168.         }
  1169.         else if(0 == key.CompareF(KSysApAlarmLightActive))
  1170.         {
  1171.             // also see RAlarmServer
  1172.             if( IsEqual(val, AlarmFlashing) )
  1173.             {
  1174.                 DPRINTF(SYMP_INFO, ("CHXAvPlayerUI::HandleNotifyL(): alarm firingn"));
  1175.                 // handle this same way as if we loose app focus
  1176.                 CHXAvViewBase *pActiveView = static_cast<CHXAvViewBase *>(iView);
  1177.                 pActiveView->HandleLosePlayFocus();
  1178.             }
  1179.         }
  1180.         else if(0 == key.CompareF(KSysApMessageToneQuit))
  1181.         {
  1182.             if( IsEqual(val, MessageTonesOff) )
  1183.             {
  1184.                 // we get this when a message comes in in silent mode
  1185.                 DPRINTF(SYMP_INFO, ("CHXAvPlayerUI::HandleNotifyL(): msg tone offn"));
  1186.                 
  1187.                 // in silent mode this resets volume; now we (possibly) reset volume back
  1188.                 m_player->SetVolume(m_player->GetVolume());
  1189.             }
  1190.         }
  1191.     }
  1192. }
  1193. #endif
  1194. /*
  1195.  * GetRecentClipCount
  1196.  * ------------------
  1197.  * Returns the count of urls.
  1198.  *
  1199.  */
  1200. TInt
  1201. CHXAvPlayerUI::GetRecentClipCount() const
  1202. {
  1203.     TInt count = 0;
  1204.     if (m_recentClips)
  1205.     {
  1206. count = m_recentClips->NumURLs();
  1207.     }
  1208.     return count;
  1209. }