Nav_CDDA.c
上传用户:super_houu
上传日期:2008-09-21
资源大小:4099k
文件大小:127k
源码类别:

DVD

开发平台:

Others

  1. /****************************************************************************************
  2.  *  Copyright (c) 2002 ZORAN Corporation, All Rights Reserved
  3.  *  THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ZORAN CORPORATION
  4.  *
  5.  *  File: $Workfile: Nav_CDDA.c $             
  6.  *
  7.  * Description: 
  8.  * ============
  9.  * 
  10.  * 
  11.  * Log:
  12.  * ====
  13.  * $Revision: 134 $
  14.  * Last Modified by $Author: Chaol $ at $Modtime: 04-04-02 15:40 $ 
  15.  ****************************************************************************************
  16.  * Updates:
  17.  ****************************************************************************************
  18.  * $Log: /I76/I76_Common/I76_Reference/Playcore/Nav_CDDA/Nav_CDDA.c $
  19.  * 
  20.  * 134   04-04-02 15:40 Chaol
  21.  * fix type
  22.  * 
  23.  * 133   04-04-02 15:14 Chaol
  24.  * increase CDDST detect time
  25.  * 
  26.  * 132   04-04-02 10:37 Williaml
  27.  * It may be down playing HDCD disc when check if it's a CD-DTS disc
  28.  * 
  29.  * 131   04-04-01 23:38 Leslie
  30.  * Change type definition
  31.  * 
  32.  * 130   4/01/04 10:49p Johnk
  33.  * support HW POWER_ON_RESUME for S1 spec
  34.  * 
  35.  * 129   04-03-30 16:10 Williaml
  36.  * set the play mode to normal from program, intro or shuffle after full
  37.  * stop
  38.  * 
  39.  * 128   04-03-27 15:32 Hansenw
  40.  * 
  41.  * 127   3/26/04 5:02p Aidenl
  42.  * TF changes 2
  43.  * 
  44.  * 126   04-03-24 15:11 Angieh
  45.  * For Alco,support previous func when play the first track.
  46.  * 
  47.  * 125   04-03-22 16:41 Chaol
  48.  * fix micro define
  49.  * 
  50.  * 124   04-03-22 11:37 Chaol
  51.  * enable CDTS detect code, it begin to work in version 00.2b
  52.  * 
  53.  * 123   04-03-19 12:03 Chaol
  54.  * fix _isValidCDDTS
  55.  * 
  56.  * 122   04-03-17 17:46 Chaol
  57.  * remove this code temp because ADP can't support CDDTS detect now
  58.  * 
  59.  * 121   04-03-17 11:39 Chaol
  60.  * add CDDTS support
  61.  * 
  62.  * 120   3/16/04 7:15p Rinata
  63.  * 
  64.  * 118   04-03-09 23:40 Wesleyj
  65.  * 
  66.  * 117   04-02-25 20:21 Chaol
  67.  * fix CDDA VFD bug
  68.  * 
  69.  * 116   2/20/04 6:11p Glenl
  70.  * Merged S1 code
  71.  * 
  72.  * 115   04-02-13 17:20 Chaol
  73.  * increase the CDDTS detect time
  74.  * 
  75.  * 114   1/25/04 8:20 Nmaurer
  76.  * Add drv_ prefix to Drive routines
  77.  * 
  78.  * 113   12/30/03 10:13a Chaol
  79.  * change function _isValidCDDTS
  80.  * 
  81.  * 112   12/23/03 2:49p Chaol
  82.  * change function _isValidCDDTS
  83.  * 
  84.  * 111   12/22/03 4:25p Chaol
  85.  * change function _isValidCDDTS to support CDDTS
  86.  * 
  87.  * 110   9/29/03 11:54a Chaol
  88.  * 
  89.  * 106   03-08-22 15:24 Chaol
  90.  * to support DTS output analog and SPDIF at the same time, check
  91.  * SUPPORT_DTS_ANALOG_AND_SPDIF for detail
  92.  * 
  93.  * 105   8/18/03 1:46p Mikex
  94.  * roll back to reopen the introduction function
  95.  * 
  96.  * 104   8/12/03 9:38a Mikex
  97.  * close the introductive function for CDDA
  98.  * 
  99.  * 103   8/12/03 9:24a Francisw
  100.  * Do not display "Rep Off" OSD message when the "SkipF" or "SkipB" button
  101.  * is pressed following the "Rep A-B" button.
  102.  * 
  103.  * 102   03-07-28 17:03 Leslie
  104.  * Check in changes for Task Force
  105.  * 
  106.  * 101   03-07-22 17:07 Mikelv
  107.  * support cdda de_emphasis
  108.  * 
  109.  * 100   03-07-16 17:44 Mikelv
  110.  * If current played item is the first one in the program list,then
  111.  * prohibit skipb.(as required by customer)
  112.  * 
  113.  * 99    03-07-14 20:38 Mikelv
  114.  * support scan in intro mode
  115.  * 
  116.  * 98    03-07-11 17:29 Mikelv
  117.  * For repeat single mode,we give drive 2*200ms to detect track
  118.  * transition,and 6*200ms for other conditions,
  119.  * 
  120.  * 97    03-07-10 22:52 Leslie
  121.  * Roll back Jane's change about disable Scan in Intro mode
  122.  * 
  123.  * 95    7/10/03 5:19p Clifflv
  124.  * Enlarge m_bLocationChanging margin for scan backward
  125.  * 
  126.  * 94    03-07-07 22:28 Mikelv
  127.  * when destruct cd nav,set volume to be maximum.(for vestel)
  128.  * 
  129.  * 93    03-07-07 15:42 Tonnyg
  130.  * when mode changed, clear all bookmarks
  131.  * 
  132.  * 92    03-07-06 1:39 Leslie
  133.  * Change CDDA_TRACK_CHANGE_DETECTION_COUNTER from 6 to 2
  134.  * 
  135.  * 91    7/04/03 5:00a Stephaneh
  136.  * Removed fixed from Frank regarding CDDTS. There is no need to add such
  137.  * a variable. There is already a function called CDDA_IsCDDTS() that
  138.  * return the right information.
  139.  * 
  140.  * 90    03-07-03 14:43 Mikelv
  141.  * For cdda's program play being set in pst_stop state,one condition
  142.  * should be removed from OnModeChange().(bug193)
  143.  * 
  144.  * 89    03-07-03 14:12 Mikelv
  145.  * OnIntro() should call OnModeChang() function since the pst mode
  146.  * changed(bug218)
  147.  * 
  148.  * 88    03-07-03 12:03 Frankm
  149.  * Leslie suggest to add one member to gns.cdda.
  150.  * 
  151.  * 87    03-06-30 18:21 Janeg
  152.  * Move bIsCDDAIntroMode to SHARED_INFO.
  153.  * Clear resume address when restart.
  154.  * 
  155.  * 86    03-06-30 16:46 Leslie
  156.  * 
  157.  * 85    03-06-27 21:09 Leslie
  158.  * Not use software CD_TRACK_CHECK_BY_DECODER compile switch
  159.  * 
  160.  * 84    03-06-26 19:09 Wesleyj
  161.  * fixed  can not continue FB when playing CD
  162.  * 
  163.  * 83    03-06-26 16:58 Wesleyj
  164.  * Update track number in onplaybackfinished()
  165.  * 
  166.  * 82    03-06-25 11:40 Hannahh
  167.  * 
  168.  * 81    03-06-19 17:39 Hannahh
  169.  * 
  170.  * 80    03-06-19 11:06 Mikelv
  171.  * add condition to avoid system sending "Playback finishied" event, when
  172.  * drive is just starting to play new track.
  173.  * 
  174.  * 79    03-06-17 15:00 Fwang
  175.  * Optimize NVM_BMK parameter.
  176.  * 
  177.  * 78    03-06-09 18:28 Tonnyg
  178.  * correct shuffle switch in resumable stop state
  179.  * 
  180.  * 77    03-06-02 18:23 Fwang
  181.  * Set NVM bookmark by parameter
  182.  * 
  183.  * 76    03-05-28 11:19 Fwang
  184.  * Specified auto postion in NVM_BMK_SET()
  185.  * 
  186.  * 75    03-05-28 9:40 Fwang
  187.  * Set bookmark type in NVM_BMK_SET()
  188.  * 
  189.  * 74    03-05-27 22:42 Fwang
  190.  * Add NVM bookmark
  191.  * 
  192.  * 73    03-05-21 21:41 Leslie
  193.  * Notify UI operation error for time search if time is invalid
  194.  * 
  195.  * 72    03-05-21 15:12 Billt
  196.  * Added normal finish condition to avoid press STOP twice and PLAY
  197.  * quickly and it starts playbacking 2nd track
  198.  * 
  199.  * 71    03-05-16 22:21 Leslie
  200.  * New error recovery implementation
  201.  * 
  202.  * 70    03-05-10 13:47 Mikelv
  203.  * For cddts,get time from driver
  204.  * 
  205.  * 69    03-05-07 17:37 Mikelv
  206.  * fix the bug that when jump to previous chapter,the osd and vfd's time
  207.  * are wrong.
  208.  * 
  209.  * 68    03-05-06 15:45 Dingming
  210.  * add margin for cancel mark A detection
  211.  * 
  212.  * 67    03-05-04 16:53 Dingming
  213.  * for some case, the ucode is not loaded correctly
  214.  * 
  215.  * 66    03-04-28 15:18 Leslie
  216.  * Clear Resume Bookmark before start CDDA intro playback
  217.  * 
  218.  * 65    03-04-23 20:46 Mikelv
  219.  * For everytime call onscan() function,reset the current positon,no
  220.  * matter whether it is already pst_scan or not.
  221.  * 
  222.  * 64    03-04-17 17:52 Tonnyg
  223.  * fix the bug that can't set A-B after set A/A-B then repeat single 
  224.  * 
  225.  * 63    03-04-17 14:51 Tonnyg
  226.  * Prohibit pre/next when repeat single, just jump to the beginning, same
  227.  * as DVD.
  228.  * 
  229.  * 62    4/14/03 3:30p Lyncolnc
  230.  * Modify the previous change. 
  231.  * 
  232.  * 61    4/14/03 2:03p Lyncolnc
  233.  * Immediately after subcode buffer is cleared when going to a new track,
  234.  * the current location read may be an invalid negative number. Do not use
  235.  * it in the error recovery value. 
  236.  * 
  237.  * 60    4/10/03 4:41p Lyncolnc
  238.  * In CDDA FF, sometimes track number info cannot be updated on OSD/FP.
  239.  * This can be solved by refreshing the count-down in scantrack().
  240.  * 
  241.  * 59    03-04-07 14:47 Billt
  242.  * don't cancel repeat when play from stopresume
  243.  * 
  244.  * 58    4/03/03 4:39p Lyncolnc
  245.  * Problem: When playing track 10, press Prev to play track 9. If drive
  246.  * takes time to seek/read, error may happen when Core thinks it is
  247.  * playing track 9 but OnTick() thinks it is playing track 10 because it
  248.  * reads the subcode buffer which is not updated. Rendezvous will happen
  249.  * and causes UI/Core to jump to track 10, but in fact track 9 is being
  250.  * played.
  251.  * Solution: Clear subcode buffer when needed. Avoid reading old subcode
  252.  * info.
  253.  * 
  254.  * 57    03-04-02 20:53 Leslie
  255.  * Emergency eject for CDDA Disc loading
  256.  * 
  257.  * 57    03-03-25 19:16 Leslie
  258.  * 
  259.  * 56    03-03-22 19:00 Leslie
  260.  * Fix CDDA Pause to Scan noise problem
  261.  * 
  262.  * 55    03-03-15 18:04 Leslie
  263.  * 
  264.  * 54    03-03-11 17:33 Dingming
  265.  * CDDTS bug fixing for SPDIF
  266.  * 
  267.  * 53    03-03-07 18:42 Leslie
  268.  * Fix the wrong calculation problem with CDDA playback start address
  269.  * 
  270.  * 53    3/06/03 3:12p Yarone
  271.  * Removed pach for Drive response too long - fixed in drive module
  272.  * 
  273.  * 52    03-03-04 11:44 Hannahh
  274.  * remove the customer name from all project.
  275.  * 
  276.  * 51    03-03-03 13:27 Leslie
  277.  * Update with changes
  278.  * 
  279.  * 51    03-02-27 17:57 Dingming
  280.  * bug fixing for cdts
  281.  * 
  282.  * 50    03-02-27 15:16 Leslie
  283.  * Update with ZCH change
  284.  * Fix Multi-Session CDDA problems
  285.  * 
  286.  * 49    2/26/03 9:46p Tomasp
  287.  * Synchronization with ZCH database
  288.  * 
  289.  * 49    03-02-24 13:49 Hannahh
  290.  * Replace printf to debug
  291.  * 
  292.  * 48    2/21/03 11:04a Stephaneh
  293.  * Removed useless statement
  294.  * 
  295.  * 47    2/21/03 7:16a Stephaneh
  296.  * Cleaned subcode and error recovery info when full stop
  297.  * 
  298.  * 46    03-02-19 22:07 Leslie
  299.  * 
  300.  * 46    03-02-19 15:41 Leslie
  301.  * Add GET_CDDTS_MSF_FROM_DRIVE
  302.  * 
  303.  * 45    03-02-11 11:39 Leslie
  304.  * Add Get Total Elapsed Time
  305.  * 
  306.  * 44    03-02-09 15:10 Dingming
  307.  * macro name change
  308.  * 
  309.  * 43    2/07/03 10:46p Tomasp
  310.  * - changed SW feature selection to compilation switch
  311.  * 
  312.  * 42    03-01-24 20:32 Leslie
  313.  * Cancel PlayMode/Repeat mode when entering IntroPlay Mode
  314.  * 
  315.  * 41    03-01-18 2:44 Leslie
  316.  * Change CDDA_SUPPORT_DTS_DECODING
  317.  * 
  318.  * 40    03-01-15 18:48 Dingming
  319.  * code clean up
  320.  * 
  321.  * 39    03-01-09 4:38 Leslie
  322.  * CDDA Intro playback supported
  323.  * 
  324.  * 38    12/25/02 5:56p Leslie
  325.  * Code cleanup
  326.  * 
  327.  * 37    12/09/02 6:07p Leslie
  328.  * Code cleanup
  329.  * 
  330.  * 36    11/29/02 7:55a Leslie
  331.  * Fix no track number update in fast playback
  332.  * 
  333.  * 35    11/10/02 10:09a Leslie
  334.  * Add delay for Trackchange detection in case the servo seeking is not
  335.  * stable or fast
  336.  * 
  337.  * 34    10/30/02 12:19a Leslie
  338.  * Check if event is NULL before send it
  339.  * 
  340.  * 39    6/23/02 10:33 Rinata
  341.  * fixed CDDTS - Handle changing of audio setting digital <-->analog
  342.  * 
  343.  * 38    4/06/02 18:54 Nirm
  344.  * - Added CDDA_PROHIBIT_SCAN_ACROSS_PROGRAM_ENTRIES, to allow control
  345.  * over whether or not Program-entries are scanned when in
  346.  * Program/Shuffle.
  347.  * 
  348.  * 37    3/06/02 20:01 Nirm
  349.  * - Fixed a problem in the Rendezvous and Playback-Finished detection
  350.  * mechanism, which caused false or duplicate detections;
  351.  * - Added support of Silent-Playback of Data-Tracks, via
  352.  * CDDA_SILENT_PLAYBACK_OF_DATA_TRACKS.
  353.  * 
  354.  * 36    3/06/02 11:15 Nirm
  355.  * - Code cleanup.
  356.  * 
  357.  * 35    27/05/02 18:52 Nirm
  358.  * - Cleaned-up compilation-warnings.
  359.  * 
  360.  * 34    23/05/02 18:12 Ettim
  361.  * Calling directly to OnPlaybackFinished to prevent race between
  362.  * IE_CORE_CDNAV_FINISHED and IE_CORE_TICK.
  363.  * 
  364.  * 33    20/05/02 9:58 Ettim
  365.  * Using Array_ instead of sc_read/write .. 
  366.  * 
  367.  * 32    7/05/02 16:41 Ettim
  368.  * Added PowerOnResume playback support.
  369.  * 
  370.  * 31    5/05/02 17:56 Ettim
  371.  * Added support in CDEXTRA.
  372.  * 
  373.  * 30    2/05/02 16:08 Ettim
  374.  * Setting a longer wait time in the CDDTS detection sequence.
  375.  * 
  376.  * 29    29/04/02 16:55 Nirm
  377.  * - Code cleanup.
  378.  * 
  379.  * 28    4/25/02 12:17 Rinata
  380.  * update  gcst.mCDDTSDetected according to _isValidCDDTS
  381.  * 
  382.  * 27    23/04/02 9:31 Nirm
  383.  * - Added dependency in "Config.h".
  384.  * 
  385.  * 26    22/04/02 18:34 Ettim
  386.  * Performing Mute when trying to play a data track (FFM bug CDDA:#1,#2)
  387.  * 
  388.  * 25    21/04/02 9:51 Ettim
  389.  * Using the _isValidCDDTS function to determine audio sid - CDDTS or
  390.  * CDDA. 
  391.  * 
  392.  * 24    18/04/02 11:43 Ettim
  393.  * Added CDDTS support.
  394.  * 
  395.  * 23    16/04/02 15:23 Ettim
  396.  * Integration with CDDTS. Work is still im progress.
  397.  * 
  398.  * 22    4/14/02 16:35 Rinata
  399.  * move the init of  gcst.mCDDTSDetected to CDDTS_UN_INITIALIZE to teh
  400.  * constructor of teh CDDA , for all other disc types it init to
  401.  * CDDTS_NOT_DETECTED
  402.  * 
  403.  * 21    4/14/02 15:16 Rinata
  404.  * Support DTS, CDTS
  405.  * 
  406.  * 20    12/04/02 13:42 Nirm
  407.  * - Fixed wrong indication of COP_NEXT_CHAPTER on the last Program-List
  408.  * Entry.
  409.  * 
  410.  * 19    4/01/02 19:30 Ettim
  411.  * Removed a few warning messages.
  412.  * 
  413.  * 18    25/03/02 20:59 Nirm
  414.  * Added #include.
  415.  * 
  416.  * 17    3/14/02 11:11 Ettim
  417.  * Removing from Globsdef.h variables that are used only by the CDDA
  418.  * navigator, and declaring them locally in Nav_CDDA.c 
  419.  * 
  420.  * 16    4/03/02 20:49 Nirm
  421.  * Integrated support for Full-Stop.
  422.  * 
  423.  * 15    7/02/02 16:33 Nirm
  424.  * - Fixed resumption of playback when using
  425.  * CDDA_PROHIBIT_PAUSE_ACROSS_ITEM_BOUNDARIES.
  426.  * 
  427.  * 12    1/17/02 16:39 Ettim
  428.  * removed the include for the stubs.h file
  429.  * 
  430.  * 11    1/16/02 16:16 Ettim
  431.  * Updating the macro PE_CD_SetDiscType to get only 1 argument.
  432.  * 
  433.  * 10    16/01/02 11:51 Atai
  434.  * Change debug printing
  435.  * 
  436.  * 9     1/14/02 11:15 Ettim
  437.  * 
  438.  * 8     1/13/02 18:18 Ettim
  439.  * 
  440.  * 7     9/01/02 15:43 Nirm
  441.  * Corrected Include-Paths.
  442.  ****************************************************************************************/
  443.  
  444. #include "Config.h" // Global Configuration - do not remove!
  445. #ifdef _DEBUG
  446. #define IFTRACE if (gTraceNavigator) 
  447. #include "DebugDbgMain.h"
  448. #endif
  449. #include "IncludeSysDefs.h"
  450. #include "Includemath-macro.h"
  451. #include "Kernelker_api.h"
  452. #include "KernelEventDef.h"
  453. #include "PlaycoreCoremaincoregdef.h"
  454. #include "PlaycoreDataStructuresArray.h"
  455. #include "PlaycoreNav_CDDApe_cd.h"
  456. #include "PlaycoreNav_CDDANav_CDDA.h"
  457. #include "PlaycoreNav_CDDAcdnav_err.h"
  458. #include "PlaycorePlayModeplaymode.h"
  459. #include "PlaycoreScPadscmgr.h"
  460. #include "PlaycoreTimingTiming.h"
  461. #include "PlaycoreExceptionException.h"
  462. #ifndef EXINO2 //ZKR JK0331 : for power_on_resume in EEPROM
  463. #ifdef HW_POWER_ON_RESUME
  464. #include "PlaycoreCoremainnvm_bmk.h"
  465. #endif
  466. #endif //EXINO2
  467. //Function prototypes
  468. void ForceCDTSmicrocde(BOOL enable );
  469. #ifndef EXINO2 //ZKR JK0331 : for power_on_resume in EEPROM
  470. #ifdef HW_POWER_ON_RESUME
  471. BOOL CDDANAV_NvmBmk_Match(NVM_GENERIC_BMK* pGenric_bmk);
  472. void CDDANAV_NvmBmk_Set( WORD sc_handle);
  473. void CDDANAV_NvmBmk_Play(NVM_GENERIC_BMK *pGenric_bmk);
  474. #endif
  475. #endif //EXINO2
  476. extern BOOL g_in_full_stop;
  477. extern BYTE ucDriveErrorMsgCount;//LX070303: 
  478. #ifdef D_USE_VARIABLE_FOR_LIB
  479. extern WORD cdda_skip_back_threshold;
  480. #endif
  481. ////////////////////////////////////////////////////////////////////////////////////////////////
  482. // Constants
  483. #define CDDTS_DECODING_ATTEMPT_SZ 300
  484. #define CDDTS_SEEK_MARGIN_SZ 0 //SeanLiu_0524_2004_A
  485. #define DRIVER_SEEK_MARGIN 100 //DM050603
  486. #define CDDA_TRACK_CHANGE_DETECTION_COUNTER_6 0x06
  487. #define CDDA_TRACK_CHANGE_DETECTION_COUNTER_2 0x02
  488. #define INTRO_PLAYBACK_TIME 10 //10 second
  489. #ifdef WATCHDOG_TRIGGERED_BY_FE
  490. #define CDDA_ERROR_JUMP_GAP_SECONDS 2
  491. #endif
  492. ////////////////////////////////////////////////////////////////////////////////////////////////
  493. // Macros
  494. #define SHARED_INFO gns.cdda
  495. #define CDDAMessageGap    SHARED_INFO.CDDAMessageGap
  496. #define g_pCDDANav   SHARED_INFO.g_pCDDANav
  497. #define g_bIsCDDTS   SHARED_INFO.g_bIsCDDTS
  498. #define g_hTrackInfoCache SHARED_INFO.g_hTrackInfoCache
  499. #define uPrevTrackNumber  SHARED_INFO.uPrevTrackNumber
  500. #define MARKAB_FINISH_GAP 4
  501. ////////////////////////////////////////////////////////////////////////////////////////////////
  502. // Globals
  503. #ifdef CDDA_ERROR_RECOVERY
  504. CONST DWORD g_miCDDANSPBErrorJumpTbl[CDDA_ERROR_RETRY_NUM] = 
  505. {
  506. // in term of seconds
  507. 1,
  508. 2,
  509. 4,
  510. 8,
  511. 15,
  512. 30,
  513. 45,
  514. 60,
  515. 90,
  516. 120,
  517. 150,
  518. 180,
  519. 210,
  520. 240,
  521. 270,
  522. 300,
  523. 360,
  524. 420,
  525. 600,
  526. 900
  527. };
  528. #endif
  529. /////////////////////////////////////////////////////////////////////////////////////////////////
  530. // Private Services
  531. /////////////////////////////////////////////////////////////////////////////////////////////////
  532. /////////////////////////////////////////////////////////////////////////////////////////////////
  533. // _isValidCDDTS() -
  534. // asas
  535. //
  536. // Input:
  537. // Op - The type of operation being invoked
  538. // Event - The event to route
  539. // Param - An optional parameter for the event being routed
  540. //
  541. // Output:
  542. // Zero if the routing is successful.
  543. BOOL _isValidCDDTS(DWORD dwStartAddr, DWORD uBlocksCnt)
  544. {
  545. BOOL bIsValid = FALSE;
  546. int retry_cnt=1500;
  547. dbg_printf(("_isValidCDDTSn"));
  548. if (Exception_catchAndRethrow(EXCEPTION_MEDIUM_EJECTED)) 
  549. {
  550. tr_printf(("HHHHHHn"));
  551. return FALSE;
  552. }
  553. DEC_MuteOutput(MUTE_DETECT_REQUEST, MUTE_SETTING_ON);
  554. DEC_MuteSPDIF(MUTE_DETECT_REQUEST, MUTE_SETTING_ON);
  555. DEC_SetSID(DEC_SID_TYPE_AUDIO, DEC_ASID_CD_DETECT);
  556. PE_CD_PlaySegment(NoVideo, CDDETECT_SID , dwStartAddr+(uBlocksCnt/2), //CDDTS_SEEK_MARGIN_SZ,  fix the bug for DTS-ES supporting(jump to middle of the first track to check DTS head)
  557.   MIN(CDDTS_DECODING_ATTEMPT_SZ, uBlocksCnt), eNormalSpeed, 0);
  558. while(retry_cnt > 0x0)
  559. {
  560. switch(PE_CD_GetCdDetectType())
  561. {
  562. case CD_DETECT_CDDA :
  563. bIsValid = FALSE;
  564. retry_cnt = 0x0;
  565. break;
  566. case CD_DETECT_CDTS :
  567. bIsValid = TRUE;
  568. retry_cnt = 0x0;
  569. break;
  570. default :
  571. delay_us(10000UL);
  572. retry_cnt --;
  573. }
  574. }
  575. PE_CD_AbortPlayback(TRUE);
  576. DEC_MuteOutput(MUTE_DETECT_REQUEST, MUTE_SETTING_OFF);
  577. DEC_MuteSPDIF(MUTE_DETECT_REQUEST, MUTE_SETTING_OFF);
  578. return (bIsValid);
  579. }
  580. /////////////////////////////////////////////////////////////////////////////////////////////////
  581. // Public Services
  582. /////////////////////////////////////////////////////////////////////////////////////////////////
  583. /////////////////////////////////////////////////////////////////////////////////////////////////
  584. // int CDDA_Navigator(HDLR_OP Op, EVENT Event, void *Param) -
  585. // The main router for CDDA-Navigation Events.
  586. //
  587. // Input:
  588. // Op - The type of operation being invoked
  589. // Event - The event to route
  590. // Param - An optional parameter for the event being routed
  591. //
  592. // Output:
  593. // Zero if the routing is successful.
  594. int CDDA_Navigator(HDLR_OP Op, EVENT Event, void *Param)
  595. {
  596. switch (Op) 
  597. {
  598. case HDLR_ENTER: Constructor();
  599. break;
  600. case HDLR_EXIT: Destructor();
  601. break;
  602. case HDLR_EVENT:
  603. switch (Event) 
  604. {
  605. case IE_CORE_PAUSE:
  606. OnStop(ePause);
  607. break;
  608. case IE_CORE_STOP:
  609. //IFDEF(Cdda_Macro.bCDDA_ALLOW_RESUME)
  610. OnStop((TRUE == (BOOL)Param) ? eFullStop : eStopResume);
  611. //ELSE
  612. // OnStop(eFullStop);
  613. //ENDIF //CDDA_ALLOW_RESUME
  614. break;
  615. case IE_CORE_RESTART:
  616. #ifdef EXINO2 // ZKR JK0331 : for power_on_resume in EEPROM
  617. #ifdef HW_POWER_ON_RESUME                  
  618. if(GetResumeLeadOutInfo() == gns.cdda.wTotalPlaybackTime)
  619.                      {
  620. ClearResumeLeadOutInfo();
  621. restore_CDDA_info();
  622. }
  623. else
  624. #endif //HW_POWER_ON_RESUME  
  625. #else //EXINO2
  626. #ifdef HW_POWER_ON_RESUME
  627.            
  628. ClearMarker(eResumePlayback, 0);
  629. if((TRUE == (BOOL)Param)&&(NVM_BMK_Play()))
  630. {
  631. dbg_printf(("nNVM Bookmark restart. "));
  632.                    }
  633.                
  634.    else
  635. #endif //HW_POWER_ON_RESUME                           
  636. #endif //EXINO2                       
  637. {
  638. #ifdef K1_WL
  639. //add by wl040708 for resume play after full stop
  640. if (resume_play_request)
  641.                            {
  642. memcpy(&(g_pCDDANav->m_CurrPosition), &(g_pCDDANav->m_ResumePlayback), sizeof(CDDA_Marker));
  643. resume_play_request = FALSE;
  644. }
  645. else
  646. //add by wl040708 for resume play after full stop
  647. #endif
  648. {
  649. (g_pCDDANav->m_CurrPosition).iPlaylistItem= 1;
  650. (g_pCDDANav->m_ResumePlayback).dwAddress=-1;
  651. }
  652. }
  653. // Fall-Through!
  654. case IE_CORE_PLAY:
  655. OnPlay();
  656. break;
  657. case IE_CORE_NEXT_CHAPTER:
  658. OnNextItem();
  659. break;
  660. case IE_CORE_PREVIOUS_CHAPTER:
  661. OnPreviousItem();
  662. break;
  663. case IE_CORE_GOTO_ENTRY:
  664. case IE_CORE_MENU_NUMERICAL_SELECTION:
  665. OnNumericSelection((int)Param);
  666. break;
  667. case IE_CORE_CDNAV_RENDEZVOUS:
  668. if (IE_CORE_CDNAV_RENDEZVOUS == g_pCDDANav->m_evPendingEvent) {
  669. OnRendezvousPoint((enCDDA_RendezvousType)Param);
  670. g_pCDDANav->m_evPendingEvent= 0;
  671. }
  672. break;
  673. case IE_CORE_CDNAV_FINISHED:
  674. if (IE_CORE_CDNAV_FINISHED == g_pCDDANav->m_evPendingEvent) {
  675. OnPlaybackFinished();
  676. g_pCDDANav->m_evPendingEvent= 0;
  677. }
  678. break;
  679. case IE_CORE_PM_RESET:
  680. // reset the PM mode : program,repeat, random , reset play -A-B
  681. PM_SetPlaybackMode(PM_PLAYBACK_NORMAL);
  682. PM_ClearRepeat();
  683. break;
  684. case IE_CORE_AB_REPEAT:
  685. if (0 == (int)Param) {
  686. OnCancelABRepeat();
  687. break;
  688. }
  689. if (PM_GetRepeatAB() & PM_REPEAT_AB_B) {
  690. OnCancelABRepeat();
  691. PM_SetRepeatAB(0);
  692. }
  693. else { //after set A or A-B, set repeat single, then A will never be setted for the dwStartAddress is still there. 
  694. if ((0 == PM_GetRepeatAB()))// && ((g_pCDDANav->m_PositionA).iPlaylistItem < 0))      // so I remove this condition, if this is necessary, let me know please, tonnyg
  695. {
  696. OnSetMarkerA();
  697. PM_SetRepeatAB(PM_REPEAT_AB_A);
  698. }
  699. else {
  700. OnSetMarkerB();
  701. PM_SetRepeatAB(PM_REPEAT_AB_B);
  702. }
  703. }
  704. break;
  705. case IE_CORE_SET_BOOKMARK:
  706. #ifndef EXINO2 //ZKR JK0331 : for power_on_resume in EEPROM
  707. #ifdef HW_POWER_ON_RESUME
  708. NVM_BMK_SET((int)Param);
  709. #endif
  710. #endif
  711. SetMarker(eBookmark, (WORD)Param - 1);
  712. break;
  713. case IE_CORE_GOTO_BOOKMARK:
  714. OnGoToBookmark((WORD)Param - 1);
  715. break;
  716. case IE_CORE_SCAN:
  717. // If there is a Location-Change in progress,
  718. // reschedule this event for later.
  719. if (g_pCDDANav->m_bLocationChanging) {
  720. // If currently Pausing, then first resume Playback,
  721. // otherwise the target Location will never be reached.
  722. if (PST_PAUSE == gcs.pstate)
  723. OnPlay();
  724. ie_send_ex(IE_CORE_SCAN, Param);
  725. }
  726. else
  727. OnScan((int)Param);
  728. break;
  729. case IE_CORE_TICK_ONE_SEC:
  730. //<<<Leslie_0118_2004_A: Task Force III, implement CDDA Navigator Watchdog
  731. #ifdef CDDA_ERROR_RECOVERY
  732. #ifdef WATCHDOG_TRIGGERED_BY_FE
  733. if ( ( PST_PLAY == gcs.pstate ) || ( PST_SCAN == gcs.pstate ) ){
  734. if ( PE_CD_CheckAudioBufferFullness() )
  735. {
  736. (g_pCDDANav->m_ErrorRecoveryInfo).ucRetryCount = 0;
  737. }
  738. }
  739. #endif
  740. #endif
  741. //Leslie_0118_2004_A>>>
  742. break;
  743. case IE_CORE_TICK_200:
  744. OnTick();
  745. break;
  746. case IE_CORE_SEAMLESS_MODE_CHANGE:
  747. OnModeChange();
  748. break;
  749. case IE_CORE_GOTO_TIME:
  750. OnGotoTime((ULONG)Param);
  751. #ifdef EXINO2
  752. ie_send(IE_UI_REFRESH_TIME);
  753. #endif
  754. break;
  755. case IE_CORE_GOTO_DISC_TIME:
  756. #ifdef D_ENABLE_DISC_TIMESEARCH
  757. OnGotoDiscTime((ULONG)Param);
  758. #endif
  759. break;
  760. case IE_CORE_CDNAV_INTRO:
  761. OnIntro();//rollback to reopen the introductive function //mikex 03-08-12: close the introductive function
  762. break;
  763. //#ifndef NO_WATCHDOG
  764. #ifdef WATCHDOG_TRIGGERED_BY_FE
  765. case IE_CORE_DRIVE_READ_FAIL:
  766. #ifdef CDDA_ERROR_RECOVERY
  767. //<<<Leslie_0118_2004_A: Task Force III, implement CDDA Navigator Watchdog
  768. if ((PST_PLAY != gcs.pstate) && (PST_SCAN != gcs.pstate)){
  769. tr_printf(("Return from IE_CORE_DRIVE_READ_FAIL, since not in PLAY or SCAN Staten"));
  770. return;
  771. }
  772. dbg_printf(("CDDA_Nav: DriveDriver_ReadFail encountered.n"));
  773. if ( (g_pCDDANav->m_ErrorRecoveryInfo).ucRetryCount > CDDA_ERROR_RETRY_NUM ){
  774. (g_pCDDANav->m_ErrorRecoveryInfo).ucRetryCount = 0;
  775. tr_printf(("Retry time expires, stop the playbackn"));
  776. OnStop(eFullStop );
  777. break;
  778. }
  779. if ( ( PST_SCAN == gcs.pstate ) && ( ( g_pCDDANav->m_iScanSpeed) < 0 ) ){
  780. if ( ( PE_CD_GetCurrentLocation() > (g_pCDDANav->m_ErrorRecoveryInfo).dwParam ) 
  781. && ( (g_pCDDANav->m_ErrorRecoveryInfo).ucRetryCount > 0 ) ){
  782. }else
  783. (g_pCDDANav->m_ErrorRecoveryInfo).dwParam = PE_CD_GetCurrentLocation();
  784. }else
  785. (g_pCDDANav->m_ErrorRecoveryInfo).dwParam = PE_CD_GetCurrentLocation();
  786. tr_printf(("Stuck at point %lx, Retry Count %02xn",
  787. (g_pCDDANav->m_ErrorRecoveryInfo).dwParam,  (g_pCDDANav->m_ErrorRecoveryInfo).ucRetryCount));
  788. PerformErrorRecovery();
  789. (g_pCDDANav->m_ErrorRecoveryInfo).ucRetryCount++;
  790. //Leslie_0118_2004_A>>>
  791. #else
  792. dbg_printf(("CDDA_Nav: DriveDriver_ReadFail encountered.n"));
  793. // Force Error-Recovery
  794. // (g_pCDDANav->m_ErrorRecoveryInfo).uTimeout= 1;
  795. (g_pCDDANav->m_ErrorRecoveryInfo).dwParam= PE_CD_GetCurrentLocation();
  796. PerformErrorRecovery();
  797. #endif
  798. break;
  799. #endif//WATCHDOG_TRIGGERED_BY_FE
  800. //#endif //NO_WATCHDOG
  801. case EVENT_CLASS_CORE:
  802. #ifdef _DEBUG
  803. OnStatusReport();
  804. #endif //_DEBUG
  805. break;
  806. default:
  807. dbg_printf(("CDDA_Nav: Unexpected Event %xn",Event & 0xFF));
  808. break;
  809. }
  810. break;
  811. default:
  812. dbg_printf((" CDDA_Nav: Unknown Operation requested %dn", Op));
  813. break;
  814. }
  815. return 0;
  816. }
  817. /////////////////////////////////////////////////////////////////////////////////////////////////
  818. // Private Services
  819. /////////////////////////////////////////////////////////////////////////////////////////////////
  820. /////////////////////////////////////////////////////////////////////////////////////////////////
  821. // void Constructor() -
  822. // A Constructor for a CDDA-Navigator instance.
  823. //
  824. // Input:
  825. // None
  826. //
  827. // Output:
  828. // None. The Navigator is constructed.
  829. //
  830. // Remarks:
  831. // This method constructs a new CDDA-Navigator, whose internal data and status
  832. // are kept in the CDDA_Nav structure passed to the method.
  833. #ifndef D_NO_DECODE_ENCRYPT_CDDA
  834. extern BOOL bIsCopyControlCDDA;
  835. #endif
  836. static void Constructor()
  837. {
  838. int iTrack, iSlot, iEntriesCnt;
  839. TrackInfo tiFirstTrack, tiLastTrack;
  840. BOOL bFirstCDDATrackFound = FALSE;
  841. INT8 iDataTrackCnt = 0;
  842. dbg_printf(("CDDA Nav Constructor()n"));
  843. dbg_printf(("--> Size of CDDA Navigator is: %dn", (int)sizeof(S_CDDA_GLOBALS)));
  844. #ifndef EXINO2 //ZKR JK0331 : for power_on_resume in EEPROM
  845. #ifdef HW_POWER_ON_RESUME
  846. NVM_BMK_Hook(BMK_CDDA, CDDANAV_NvmBmk_Match, CDDANAV_NvmBmk_Set, CDDANAV_NvmBmk_Play);
  847. NVM_BMK_Verify();
  848. #endif
  849. #endif
  850. CDDAMessageGap.MARKABReachGap = 0;
  851. //configure the disc type to CDDA by default
  852. PE_CD_SetDiscType(DEC_DISC_TYPE_CDDA);
  853. iEntriesCnt= PE_CD_GetTracksCnt();
  854. #ifndef D_NO_DECODE_ENCRYPT_CDDA
  855. if(bIsCopyControlCDDA)
  856. iEntriesCnt--;
  857. #endif
  858. // Cache the entire TOC information, for later use
  859. g_hTrackInfoCache= Array_construct(iEntriesCnt, sizeof(TrackInfo), NULL);
  860. if (NULL == g_hTrackInfoCache) {
  861. dbg_printf(("Failed to allocate resources for the Tracks-Info Cache.n"));
  862. return;
  863. }
  864. for (iTrack=1; iTrack <= iEntriesCnt; iTrack++) {
  865. if (! PE_CD_GetTrackInfo(iTrack, &tiFirstTrack)) {
  866. dbg_printf(("Failed to retrieve Track information for Track #%d.n", iTrack));
  867. Array_destruct(g_hTrackInfoCache);
  868. g_hTrackInfoCache= NULL;
  869. return;
  870. }
  871. Array_setAt(g_hTrackInfoCache, (iTrack - 1), (BYTE *)&tiFirstTrack);
  872. }
  873. //Allocating the SVCD Navigator struct
  874. g_pCDDANav = (CDDA_Nav_Info *)malloc(sizeof(CDDA_Nav_Info));
  875. if (NULL == g_pCDDANav) {
  876. dbg_printf(("Failed to allocate resources for the CDDA Navigator struct.n"));
  877. return;
  878. }
  879. //initializing the rand seed
  880. srand((UINT16)timing_get_clock());
  881. #ifdef CDTEXT_SUPPORT
  882. // Read disc's CDTEXT name if available
  883. SHARED_INFO.pDiscCDText= (UINT32)PE_CD_GetCDTEXTInfo(0);
  884. #ifdef _DEBUG
  885. if (SHARED_INFO.pDiscCDText) {
  886. dbg_printf(("Disc name: %sn", SHARED_INFO.pDiscCDText));
  887. }
  888. #endif //_DEBUG
  889. #endif //CDTEXT_SUPPORT
  890. // Initialize the default Program-List to a sequencial playback of the entire disc
  891. PM_InitializeProgramList();
  892. SET_COP_MASK(0xFFFFFFFFL);
  893. CLEAR_COP_MASK(COP_SLOW | COP_STEP | COP_ZOOM | COP_PANNING |
  894.    COP_ROOT_MENU | COP_AUDIO_CHANGE | COP_SUBPIC_CHANGE | COP_ANGLE_CHANGE |
  895.    COP_RETURN);
  896. // Search for the First CDDA Track on this Disc, and initialize the Program-List
  897. // to play sequencially from that Track.
  898. g_pCDDANav->m_uFirstCDDA_Track= 1;
  899. for (iTrack=1, iSlot=1; iTrack <= iEntriesCnt; iTrack++) 
  900. {
  901. #ifdef CDDA_SILENT_PLAYBACK_OF_DATA_TRACKS
  902. PM_SetProgramListEntry((WORD)iSlot++, (WORD)iTrack);
  903. g_pCDDANav->m_uLastCDDA_Track = (WORD)iTrack;
  904. #else
  905. UINT8  uTrackCtrlField;
  906. UINT32 uDummy;
  907. if (! PE_CD_GetTrackTOC(iTrack, &uTrackCtrlField, &uDummy, &uDummy)) {
  908. tr_printf(("FATAL: Failed to collect TOC info for Track #%dn", iTrack));
  909. continue;
  910. }
  911. if (((uTrackCtrlField & 0x0F) == 0x4) 
  912. #ifndef D_NO_DECODE_ENCRYPT_CDDA
  913. && (!bIsCopyControlCDDA)
  914. #endif
  915. ) {
  916. #ifdef D_CDDA_ADD_DATATRACK_IN_PROGM_LIST
  917. // Stivenz_1102_2004: No need m_uFirstCDDA_Track if we also set data track;
  918. iDataTrackCnt++;  
  919. #else
  920. // This is a Data Track - Skip it, assuming that the next one will be
  921. // a CDDA Track.
  922. if (! bFirstCDDATrackFound) {
  923. g_pCDDANav->m_uFirstCDDA_Track= (iTrack + 1);
  924. bFirstCDDATrackFound = TRUE;
  925. }
  926. #endif  // #ifdef D_CDDA_ADD_DATATRACK_IN_PROGM_LIST
  927. }
  928. else {
  929. // This is a CDDA Track - add it to the Program-List
  930. // <<<Stiven_1101_2004: Set track-num of the nearest audio track as the track-num of data track
  931. #ifdef D_CDDA_ADD_DATATRACK_IN_PROGM_LIST
  932. while(iDataTrackCnt!=0)
  933. {
  934. // Set track-num of first audio-track we meet as the track-num of all data-track we have counted just now.
  935. PM_SetProgramListEntry((WORD)iSlot++, (WORD)iTrack);
  936. iDataTrackCnt--;
  937. }
  938. #else
  939. // Stivenz_1102_2004: No need if we also set data track;
  940. if (! bFirstCDDATrackFound) {
  941. g_pCDDANav->m_uFirstCDDA_Track= iTrack;
  942. bFirstCDDATrackFound = TRUE;
  943. }
  944. #endif  // #ifdef D_CDDA_ADD_DATATRACK_IN_PROGM_LIST
  945. // Stiven_1101_2004 >>>
  946. PM_SetProgramListEntry((WORD)iSlot++, (WORD)iTrack);
  947. g_pCDDANav->m_uLastCDDA_Track = (WORD)iTrack;
  948. }
  949. #endif //CDDA_SILENT_PLAYBACK_OF_DATA_TRACKS
  950. }
  951. // <<<Stiven_1101_2004: Set track-num of the nearest audio track as the track-num of data track
  952. // in case of the data tracks locate in the end of tracks.
  953. #ifdef D_CDDA_ADD_DATATRACK_IN_PROGM_LIST
  954. // If data-track locate in the end of CDDA, we set the track-num of last audio-track as it track-num
  955. iTrack -=(iDataTrackCnt+1); 
  956. while(iDataTrackCnt!=0)
  957. {
  958. PM_SetProgramListEntry((WORD)iSlot++, (WORD)iTrack);
  959. iDataTrackCnt--;
  960. }
  961. #endif
  962. // Stiven_1101_2004 >>>
  963. //reading the first track content from the table we already filled
  964. Array_getAt(g_hTrackInfoCache, (g_pCDDANav->m_uFirstCDDA_Track-1), (BYTE *)&tiFirstTrack);
  965. #ifdef CD_TRACK_CHECK_BY_DECODER
  966. // Try to identify if the Audio contents is actually CDDTS:
  967. gcst.mCDDTSDetected= CDDTS_UN_INITIALIZE;
  968. g_bIsCDDTS= FALSE;
  969. g_pCDDANav->g_bIsCDDTS_BAK = g_bIsCDDTS;
  970. //Checking to see if the current stream is a valid CDDTS stream.
  971. if (_isValidCDDTS(tiFirstTrack.dwStartAddress, tiFirstTrack.ulBlocksCnt)) 
  972. {
  973. dbg_printf(("CDDTS_SIDn"));
  974. #if (defined(DTS_DISABLE) || defined(CD_DTS_DECODE_DISABLE) )
  975. g_pCDDANav->m_eCurrAudSID= CDDA_SID;
  976. #else
  977. g_pCDDANav->m_eCurrAudSID= CDDTS_SID;
  978. #endif
  979. gcst.mCDDTSDetected= CDDTS_DETECTED;
  980.     g_bIsCDDTS= TRUE;
  981. }
  982. else
  983. {
  984. dbg_printf(("CDDA_SIDn"));
  985. g_bIsCDDTS= FALSE;
  986. g_pCDDANav->m_eCurrAudSID= CDDA_SID;
  987. gcst.mCDDTSDetected= CDDTS_NOT_DETECTED;
  988. }
  989. #else
  990. g_bIsCDDTS= FALSE;
  991. g_pCDDANav->m_eCurrAudSID= CDDA_SID;
  992. #endif //CD_TRACK_CHECK_BY_DECODER
  993. g_pCDDANav->g_bIsCDDTS_BAK = g_bIsCDDTS; //DM080902 back cddts flag
  994. // Initialize the Playback-Mode
  995. PM_SetPlaybackMode(PM_PLAYBACK_NORMAL);
  996. // Initialize the current Position to the first item on the Playlist
  997. (g_pCDDANav->m_CurrPosition).iPlaylistItem= 1;
  998. (g_pCDDANav->m_CurrPosition).dwAddress= -1;
  999. // Initialize the A->B Markers to "Non-Valid"
  1000. ClearMarker(eMarkerA, 0);
  1001. ClearMarker(eMarkerB, 0);
  1002. // Initialize the Bookmarks to "Non-Valid"
  1003. for (iSlot=0; iSlot < CDDA_MAX_BOOKMARKS; iSlot++)
  1004. ClearMarker(eBookmark, iSlot);
  1005. // Initialize the Resume-Playback position to "Restart"
  1006. ClearMarker(eResumePlayback, 0);
  1007. // No pending notifcation-requests or Mode Change
  1008. g_pCDDANav->m_uRendezvousPoint= 0;
  1009. g_pCDDANav->m_bPendingModeChange= FALSE;
  1010. g_pCDDANav->m_evPendingEvent= 0;
  1011. // Update the current Playback-Mode
  1012. g_pCDDANav->m_uCurrPlaybackMode= PM_GetPlaybackMode();
  1013. // Initialize Scanning mode to "OFF"
  1014. g_pCDDANav->m_iScanSpeed= 0;
  1015. // Initialize the settings of the Global variables
  1016. SHARED_INFO.iCurrentTime= 0;
  1017. SHARED_INFO.uCurrentTrackNumber= 1;
  1018. // Initialize the mode of sound mode DM090902
  1019. SHARED_INFO.bArtificialSoundMode = 1;
  1020. g_pCDDANav->m_bLocationChanging = FALSE;
  1021. //reading the last track info from the table we already filled
  1022. Array_getAt(g_hTrackInfoCache, (g_pCDDANav->m_uLastCDDA_Track - 1), (BYTE *)&tiLastTrack);
  1023. SHARED_INFO.wTotalPlaybackTime= (WORD)((tiLastTrack.dwStartAddress + tiLastTrack.ulBlocksCnt - tiFirstTrack.dwStartAddress) / CDDA_BLOCKS_PER_SEC);
  1024. SHARED_INFO.uTotalCDDATracksCnt = (UINT8)(g_pCDDANav->m_uLastCDDA_Track);
  1025. #ifdef CDDA_USE_ABSOLUTE_TIME
  1026. SHARED_INFO.wRemainingPlaybackTime = SHARED_INFO.wTotalPlaybackTime;
  1027. #else
  1028. SHARED_INFO.wRemainingPlaybackTime = (WORD)(tiFirstTrack.ulBlocksCnt / CDDA_BLOCKS_PER_SEC);
  1029. #endif //CDDA_USE_ABSOLUTE_TIME
  1030. #ifdef S1_GUI
  1031.     // For flt display during program play
  1032. gns.cdda.iPlaylistItemForFLT = 1;
  1033. #endif
  1034. gcs.pstate= PST_STOP; // Currently in STOP mode
  1035. // Reset the Error-Recovery mechanism
  1036. (g_pCDDANav->m_ErrorRecoveryInfo).uTimeout= 0;
  1037. #ifdef CDDA_ERROR_RECOVERY
  1038. //Leslie_0118_2004_A: Task Force III, implement CDDA Navigator Watchdog
  1039. (g_pCDDANav->m_ErrorRecoveryInfo).ucRetryCount = 0;
  1040. #endif
  1041. g_pCDDANav->ucCDDATrackChangeDetectionCounter = 0xFF;
  1042. SHARED_INFO.bIsCDDAIntroMode = 0;
  1043. return;
  1044. }
  1045. /////////////////////////////////////////////////////////////////////////////////////////////////
  1046. // void Destructor() -
  1047. // A Destructor for a CDDA-Navigator instance.
  1048. //
  1049. // Input:
  1050. // None.
  1051. //
  1052. // Output:
  1053. // None. The Navigator's structures destroyed.
  1054. //
  1055. // Remarks:
  1056. // This method destructs an existing instance of the CDDA-Navigator.
  1057. static void Destructor()
  1058. {
  1059. dbg_printf(("CDDA_Destructor()n"));
  1060. #ifdef EXINO2 // ZKR JK0331 : for power_on_resume for EEPORM
  1061. #ifdef HW_POWER_ON_RESUME
  1062. if (g_power_state == POWER_SEQUENCE_OFF_REQUESTED)
  1063. {
  1064.    if( g_in_full_stop != TRUE )
  1065. {
  1066.    if(gcs.pstate !=PST_STOP) 
  1067. SetMarker(eResumePlayback, 0);
  1068. save_CDDA_info();
  1069. SetResumeLeadOutInfo();
  1070.       }
  1071. }
  1072. #endif // HW_POWER_ON_RESUME
  1073. #else //EXINO2
  1074. #ifdef HW_POWER_ON_RESUME
  1075. NVM_BMK_UnHook();
  1076. #endif
  1077. #endif
  1078. if (PST_SCAN == gcs.pstate)
  1079. OnScan(0);
  1080. PE_CD_AbortPlayback(FALSE);
  1081. PE_CD_DisplayLogo();
  1082. gcs.pstate= PST_STOP;
  1083. g_in_full_stop = TRUE; /* forces next PLAY to be mapped to RESTART */
  1084. //free from SDRAM
  1085. if (NULL != g_hTrackInfoCache) {
  1086. Array_destruct(g_hTrackInfoCache);
  1087. g_hTrackInfoCache= NULL; 
  1088. }
  1089. if (NULL != g_pCDDANav)
  1090. free(g_pCDDANav);
  1091. #ifdef NO_ANLOG_OUTPUT_WHEN_SETTING_DTS_DIGITAL
  1092. ie_send_ex(IE_CORE_UPDATE_PS, (void *)((((DWORD)PS_UPDATE_VOLUME_SETTING)<<16) + 0x7FFF));
  1093. //set volume to be max
  1094. #endif
  1095. return;
  1096. }
  1097. /////////////////////////////////////////////////////////////////////////////////////////////////
  1098. // void SetMarker(enCDDA_MarkerType eMarkerType, WORD uBookmarkNumber) -
  1099. // Records the current playback position in the desired Marker.
  1100. //
  1101. // Input:
  1102. // eMarkerType - Identifies which Marker is to be used for recording
  1103. // uBookmarkNumber - If a Bookmark is being recorded, identifies the serial number
  1104. // of the requested Bookmark within the list of available Bookmarks
  1105. //
  1106. // Output:
  1107. // None. The requested Marker is recorded.
  1108. //
  1109. // Remarks:
  1110. // If an attempt is made to record a non-existent Bookmark, the recording is aborted.
  1111. static void SetMarker(enCDDA_MarkerType eMarkerType, WORD uBookmarkNumber)
  1112. {
  1113. CDDA_Marker *pMarker= NULL;
  1114. // Select the appropriate Marker to set
  1115. switch (eMarkerType) 
  1116. {
  1117. case eMarkerA: pMarker= &(g_pCDDANav->m_PositionA);
  1118. break;
  1119. case eMarkerB: pMarker= &(g_pCDDANav->m_PositionB);
  1120. break;
  1121. case eResumePlayback:
  1122. pMarker= &(g_pCDDANav->m_ResumePlayback);
  1123. break;
  1124. case eBookmark: if (uBookmarkNumber >= CDDA_MAX_BOOKMARKS)
  1125. pMarker= NULL;
  1126. else
  1127. pMarker= &(g_pCDDANav->m_Bookmarks[uBookmarkNumber]);
  1128. break;
  1129. }
  1130. if (NULL != pMarker) {
  1131. pMarker->iPlaylistItem= (g_pCDDANav->m_CurrPosition).iPlaylistItem;
  1132. // Record the current position
  1133. if (g_pCDDANav->m_bLocationChanging)
  1134. pMarker->dwAddress= g_pCDDANav->m_dwTargetLocation;
  1135. else
  1136. pMarker->dwAddress= PE_CD_GetDecoderCurrentLocationLBN();
  1137. }
  1138. return;
  1139. }
  1140. /////////////////////////////////////////////////////////////////////////////////////////////////
  1141. // void ClearMarker(enCDDA_MarkerType eMarkerType, WORD uBookmarkNumber) -
  1142. // Clears the desired Marker.
  1143. //
  1144. // Input:
  1145. // eMarkerType - Identifies which Marker is to be cleared
  1146. // uBookmarkNumber - If a Bookmark is being cleared, identifies the serial number
  1147. // of the requested Bookmark within the list of available Bookmarks
  1148. //
  1149. // Output:
  1150. // None. The requested Marker is cleared.
  1151. //
  1152. // Remarks:
  1153. // If an attempt is made to clear a non-existent Bookmark, the clearing is aborted.
  1154. static void ClearMarker(enCDDA_MarkerType eMarkerType, WORD uBookmarkNumber)
  1155. {
  1156. CDDA_Marker *pMarker= NULL;
  1157. // Select the appropriate Marker to set
  1158. switch (eMarkerType) 
  1159. {
  1160. case eMarkerA: pMarker= &(g_pCDDANav->m_PositionA);
  1161. break;
  1162. case eMarkerB: pMarker= &(g_pCDDANav->m_PositionB);
  1163. break;
  1164. case eResumePlayback:
  1165. pMarker= &(g_pCDDANav->m_ResumePlayback);
  1166. break;
  1167. case eBookmark: if (uBookmarkNumber >= CDDA_MAX_BOOKMARKS)
  1168. pMarker= NULL;
  1169. else
  1170. pMarker= &(g_pCDDANav->m_Bookmarks[uBookmarkNumber]);
  1171. break;
  1172. }
  1173. if (NULL != pMarker) {
  1174. pMarker->iPlaylistItem= -1;
  1175. pMarker->dwAddress= -1;
  1176. }
  1177. return;
  1178. }
  1179. /////////////////////////////////////////////////////////////////////////////////////////////////
  1180. // BOOL InvokePlayback() -
  1181. // Invokes playback of a segment/Track.
  1182. //
  1183. // Input:
  1184. // bUseMarkers - TRUE if the PositionA and PositionB Markers should be used as the
  1185. //   boundaries of the segment to play. Otherwise, FALSE.
  1186. //
  1187. // Output:
  1188. // TRUE if the playback was successfully invoked. FALSE otherwise.
  1189. //
  1190. // Remarks:
  1191. // This method can be used for one of two purposes:
  1192. // 1. To start the playback of a specific segment, when in REPEAT_AB mode;
  1193. // 2. To start playback of at least a single Track from its beginning / resume playback
  1194. //    of a Track from the last known position.
  1195. //
  1196. // When Form 1 of the call is used (via supplying bUseMarkers= TRUE), the method
  1197. // instructs the PE to play only the segment starting at m_PositionA and ending
  1198. // at m_PositionB.
  1199. //
  1200. // When From 2 of the call is used (via supplying bUseMarkers= FALSE), the method
  1201. // will start playback either from the last position where it was interrupted (this is
  1202. // indicated by a valid m_ResumePlayback Marker), or from the beginning of the Track.
  1203. //
  1204. // If there's a Linear-sequence of Tracks, then the method schedules a Rendezvous-Point 
  1205. // at the first Track-boundary in the sequence.
  1206. static BOOL InvokePlayback(void)
  1207. {                                                                                                                                    
  1208. int iCurrItem= (int)(g_pCDDANav->m_CurrPosition).iPlaylistItem;
  1209. ULONG ulTrackSize, uBlocksToPlayCnt;
  1210. DWORD dwTrackStartAddr, dwPlaybackStartAddr;
  1211. BOOL bLinearSequenceFound= FALSE;
  1212. TrackInfo tiCurrTrack;
  1213. DWORD dwFirstPlayTrackStartAddress=0,dwLastPlayTrackEndAddress = 0;
  1214. // Extract the Track-information for the current playlist-item
  1215. WORD uCurrTrackNumber= PM_GetProgramListEntry(iCurrItem);
  1216. // Reading the current track's content from the table we already filled
  1217. Array_getAt(g_hTrackInfoCache, (uCurrTrackNumber - 1), (BYTE *)&tiCurrTrack);
  1218. dwTrackStartAddr= tiCurrTrack.dwStartAddress;
  1219. ulTrackSize= tiCurrTrack.ulBlocksCnt;
  1220. // Save the Starting address of the current Track
  1221. g_pCDDANav->m_aCurrTrack[0]= dwTrackStartAddr;
  1222. g_pCDDANav->m_aCurrTrack[1]= (dwTrackStartAddr + ulTrackSize);
  1223. if (-1 == (g_pCDDANav->m_CurrPosition).dwAddress) {
  1224. dbg_printf(("Playing Item #%d from the beginning.n", iCurrItem));
  1225. g_bIsCDDTS = g_pCDDANav->g_bIsCDDTS_BAK; //DM080902 resume cddts flag
  1226. dwPlaybackStartAddr= dwTrackStartAddr;
  1227. uBlocksToPlayCnt= ulTrackSize;
  1228. //in case we use absolute time we don't want to reset the time dislpayed between tracks transition
  1229. #ifndef CDDA_USE_ABSOLUTE_TIME
  1230. // Clear the Elapsed-Time, if the Item is going to be played from its beginning
  1231. SHARED_INFO.iCurrentTime= 0;
  1232. #endif //CDDA_USE_ABSOLUTE_TIME
  1233. }
  1234. else {
  1235. dbg_printf(("Resuming playback of Item #%d.n", iCurrItem));
  1236. dwPlaybackStartAddr= (g_pCDDANav->m_CurrPosition).dwAddress;
  1237. uBlocksToPlayCnt= ulTrackSize - ((g_pCDDANav->m_CurrPosition).dwAddress - dwTrackStartAddr);
  1238. // Invalidate the Resume-Playback Marker, that was just used
  1239. (g_pCDDANav->m_CurrPosition).dwAddress= -1;
  1240. }
  1241. dwFirstPlayTrackStartAddress = dwPlaybackStartAddr;
  1242. // For CDDA, try locating Linear-Sequences within the current playlist
  1243. if (! g_bIsCDDTS) {
  1244. // At this point, it is known that at least the Current Track must be played until its end.
  1245. // Now calculate whether a linear Track-sequence exists in the playlist. If so, request a sequential
  1246. // playback of the entire linear-series, in order to allow smooth transitions between adjacent tracks.
  1247. while (iCurrItem < (int)(PM_GetProgramSize() - 1)) {
  1248. // Check if the current item and the next one are adjacent Tracks
  1249. if (PM_GetProgramListEntry(iCurrItem+1) != (1 + PM_GetProgramListEntry(iCurrItem))){ // If no adjacency found, break search
  1250. dwLastPlayTrackEndAddress = tiCurrTrack.dwStartAddress + tiCurrTrack.ulBlocksCnt;
  1251. uBlocksToPlayCnt = dwLastPlayTrackEndAddress - dwFirstPlayTrackStartAddress;
  1252. break;
  1253. }
  1254. bLinearSequenceFound= TRUE;
  1255. Array_getAt(g_hTrackInfoCache, (PM_GetProgramListEntry(iCurrItem+1) - 1), (BYTE *)&tiCurrTrack);
  1256. // // Add the entire Track to the playback sequence
  1257. // uBlocksToPlayCnt += tiCurrTrack.ulBlocksCnt;
  1258. // if ( iCurrItem == (int)(g_pCDDANav->m_CurrPosition).iPlaylistItem ){
  1259. // dwFirstPlayTrackStartAddress = tiCurrTrack.dwStartAddress;
  1260. // }
  1261. iCurrItem++;
  1262. }
  1263. if ( iCurrItem >= (int)(PM_GetProgramSize() - 1 ) ){
  1264. dwLastPlayTrackEndAddress = tiCurrTrack.dwStartAddress + tiCurrTrack.ulBlocksCnt;
  1265. uBlocksToPlayCnt = dwLastPlayTrackEndAddress - dwFirstPlayTrackStartAddress;
  1266. }
  1267. }
  1268. // Record the boundaries of the current Segment
  1269. g_pCDDANav->m_aCurrSegment[0]= dwPlaybackStartAddr;
  1270. g_pCDDANav->m_aCurrSegment[1]= (dwPlaybackStartAddr + uBlocksToPlayCnt);
  1271. // Initiate Error-Recovery from Playback-Hangup
  1272. (g_pCDDANav->m_ErrorRecoveryInfo).uTimeout= (2 * CDDA_PB_HANGUP_TIMEOUT);
  1273. (g_pCDDANav->m_ErrorRecoveryInfo).dwParam= dwPlaybackStartAddr;
  1274. #ifdef CDDA_ERROR_RECOVERY
  1275. //Leslie_0118_2004_A: Task Force III, implement CDDA Navigator Watchdog
  1276. (g_pCDDANav->m_ErrorRecoveryInfo).ucRetryCount = 0;
  1277. #endif
  1278. g_pCDDANav->m_bLocationChanging= TRUE;
  1279. g_pCDDANav->m_dwTargetLocation= dwPlaybackStartAddr;
  1280. // For CD-DTS discs, determine the validity of the stream
  1281. if (g_bIsCDDTS) 
  1282. {
  1283. if(_isValidCDDTS(dwTrackStartAddr, ulTrackSize))  //SeanLiu_0524_2004_B
  1284. {
  1285. // A valid CD-DTS stream -- decode it
  1286. #if (defined(DTS_DISABLE) || defined(CD_DTS_DECODE_DISABLE) )
  1287. g_pCDDANav->m_eCurrAudSID= CDDA_SID;
  1288. #else
  1289. g_pCDDANav->m_eCurrAudSID= CDDTS_SID;
  1290. #endif
  1291. gcst.mCDDTSDetected= CDDTS_DETECTED;
  1292. dbg_printf(("CDDTS_SIDn"));
  1293. }
  1294. else 
  1295. {
  1296. // An invalid CD-DTS stream -- treat it as a CDDA stream
  1297. g_bIsCDDTS = FALSE;
  1298. g_pCDDANav->m_eCurrAudSID= CDDA_SID;
  1299. gcst.mCDDTSDetected= CDDTS_NOT_DETECTED;
  1300. dbg_printf(("CDDA_SIDn"));
  1301. }
  1302. }
  1303. if (! PE_CD_PlaySegment(NoVideo, g_pCDDANav->m_eCurrAudSID, dwPlaybackStartAddr, uBlocksToPlayCnt,
  1304. eNormalSpeed, 0)) 
  1305. {
  1306. dbg_printf(("Failed to playback the current itemn"));
  1307. return FALSE;
  1308. }
  1309. if (bLinearSequenceFound) {
  1310. // If a Linear-Sequence was found, then schedule a Rendezvous-Point at the beginning of
  1311. // the second Item on the sequence. This notification is needed in order to keep track of 
  1312. // playlist-items transitions during the playback.
  1313. g_pCDDANav->m_uRendezvousPoint= (uCurrTrackNumber + 1);
  1314. dbg_printf(("Scheduling a Rendezvous-Point for: %dn", (uCurrTrackNumber + 1)));
  1315. }
  1316. else {
  1317. g_pCDDANav->m_uRendezvousPoint= 0;
  1318. }
  1319. if (PST_PAUSE == gcs.pstate) {
  1320. #ifdef CDDA_PROHIBIT_PAUSE_ACROSS_ITEM_BOUNDARIES)
  1321. PE_CD_PausePlayback(FALSE, g_pCDDANav->m_eCurrAudSID);
  1322. gcs.pstate= PST_PLAY;
  1323. #else
  1324. OnStop(ePause);
  1325. #endif //CDDA_PROHIBIT_PAUSE_ACROSS_ITEM_BOUNDARIES
  1326. }
  1327. if (PST_STOP == gcs.pstate)
  1328. gcs.pstate= PST_PLAY;
  1329. // Update the Global variables
  1330. SHARED_INFO.uCurrentTrackNumber= uCurrTrackNumber;
  1331. //jeanz_0411_2005 Fix bug :stop randomly when a track is finished in shuffle mode.
  1332. if(PM_IsRepeatSingle()||PM_IsPlaybackProgram(g_PlayModeInfo.iPlaybackMode) || PM_IsPlaybackShuffle(g_PlayModeInfo.iPlaybackMode))
  1333. g_pCDDANav->ucCDDATrackChangeDetectionCounter = CDDA_TRACK_CHANGE_DETECTION_COUNTER_2;
  1334. else
  1335. g_pCDDANav->ucCDDATrackChangeDetectionCounter = CDDA_TRACK_CHANGE_DETECTION_COUNTER_6;
  1336. #ifdef CDTEXT_SUPPORT
  1337. SHARED_INFO.pTrackCDText = (UINT32)PE_CD_GetCDTEXTInfo((BYTE)SHARED_INFO.uCurrentTrackNumber);
  1338. #ifdef _DEBUG
  1339. if (SHARED_INFO.pTrackCDText) {
  1340. dbg_printf(("Track #%d name: %sn", SHARED_INFO.uCurrentTrackNumber, SHARED_INFO.pTrackCDText));
  1341. }
  1342. #endif //_DEBUG
  1343. #endif //CDTEXT_SUPPORT
  1344. return TRUE;
  1345. }
  1346. /////////////////////////////////////////////////////////////////////////////////////////////////
  1347. // void CalculateRecoveryAddress() -
  1348. // Calculates a destination address for attempting Error-Recovery.
  1349. //
  1350. // Input:
  1351. // dwErrorAddress - Holds the LBN where the Error occurred.
  1352. // bForward - Indicates whether the recovery address should be in the forward
  1353. //    direction, or not.
  1354. //
  1355. // Output:
  1356. // None.
  1357. //
  1358. // Remarks:
  1359. // If the Error Address is met for the first time, Recovery will be attempted from the
  1360. // exact same place.
  1361. // For successive occurrences of the Error, a Linear offset is used to advance through
  1362. // the Segment.
  1363. #define LINEAR_ERROR_RECOVERY_OFFSET 10
  1364. static DWORD CalculateRecoveryAddress(DWORD dwErrorAddress, BOOL bForward)
  1365. {
  1366. static DWORD dwLastError= 0;
  1367. static UINT8 uOccurrences= 0;
  1368. // Check if this is the first time that we've seen this Address
  1369. if (dwErrorAddress != dwLastError) {
  1370. uOccurrences= 0; // Restart the mechanism for this Address
  1371. dwLastError= dwErrorAddress;
  1372. }
  1373. // Begin Calculation of the Recovery Address
  1374. if (1 == ++uOccurrences) {
  1375. // At the first attempt, always try to replay the original segment
  1376. return dwErrorAddress;
  1377. }
  1378. // Use a fixed linear offset for Recovery
  1379. if (bForward)
  1380. return (dwErrorAddress + LINEAR_ERROR_RECOVERY_OFFSET + (75L * uOccurrences));
  1381. else
  1382. return (dwErrorAddress - LINEAR_ERROR_RECOVERY_OFFSET - (75L * uOccurrences));
  1383. }
  1384. /////////////////////////////////////////////////////////////////////////////////////////////////
  1385. // void PerformErrorRecovery() -
  1386. // Performs Error-Recovery, if needed.
  1387. //
  1388. // Input:
  1389. // None.
  1390. //
  1391. // Output:
  1392. // None.
  1393. //
  1394. // Remarks:
  1395. // This function is expected to be called periodically in order to detecet an Error situation.
  1396. // In response, this function will attempt to return the system to natural flow, if possible.
  1397. static void PerformErrorRecovery()
  1398. {
  1399. BOOL bRecoveryNeeded= FALSE;
  1400. BOOL bRecoveryAddressValid, bForwardDirection;
  1401. DWORD dwCurrentLocation;
  1402. DWORD dwRecoveryAddress;
  1403. ULONG ulBlocksCnt;
  1404. #ifndef WATCHDOG_TRIGGERED_BY_FE
  1405. // Get the Current Location, depending on the current Audio-SID
  1406. if (CDDA_SID == g_pCDDANav->m_eCurrAudSID)
  1407. dwCurrentLocation= PE_CD_GetDecoderCurrentLocationLBN();
  1408. else
  1409. dwCurrentLocation= PE_CD_GetCurrentLocation();
  1410. // Check if there's need to activate Error-Recovery, by checking if the Timeout has expired.
  1411. if (((g_pCDDANav->m_ErrorRecoveryInfo).uTimeout <= 0) ||
  1412. (0 != --(g_pCDDANav->m_ErrorRecoveryInfo).uTimeout))
  1413. return;
  1414. // Make sure that the current state is either Play or Scan, otherwise there can be no
  1415. // Playback-Hangup.
  1416. if ((PST_PLAY != gcs.pstate) && (PST_SCAN != gcs.pstate))
  1417. return;
  1418. // Take care of Playback-Hangup:
  1419. // Establish the current Direction of Playback/Scanning
  1420. bForwardDirection= ( (PST_PLAY == gcs.pstate) || ((PST_SCAN == gcs.pstate) && (g_pCDDANav->m_iScanSpeed > 0)) );
  1421. // Determine the need for Recovery
  1422. if (g_pCDDANav->m_bLocationChanging) {
  1423. // If this point is reached while the Location is changing, then there is need
  1424. // for recovery.
  1425. bRecoveryNeeded= TRUE;
  1426. // Calculate the expected Recovery-Address
  1427. dwRecoveryAddress= CalculateRecoveryAddress(g_pCDDANav->m_dwTargetLocation, bForwardDirection);
  1428. g_pCDDANav->m_dwTargetLocation= dwRecoveryAddress;
  1429. dbg_printf(("Possible Playback-Hangup (Location-Change) -- Recovering...n"));
  1430. dbg_printf(("Curr= %08lx, param= %08lxn", dwCurrentLocation, dwRecoveryAddress));
  1431. }
  1432. else {
  1433. // Calculate the expected Recovery-Address
  1434. dwRecoveryAddress= CalculateRecoveryAddress((g_pCDDANav->m_ErrorRecoveryInfo).dwParam, bForwardDirection);
  1435. // Recovery necessity is determined by the relation between the Current-Location, and
  1436. // the last good known location, as held in the Recovery-Info Parameter.
  1437. if (bForwardDirection)
  1438. bRecoveryNeeded= (dwCurrentLocation <= (g_pCDDANav->m_ErrorRecoveryInfo).dwParam);
  1439. else
  1440. bRecoveryNeeded= (dwCurrentLocation >= (g_pCDDANav->m_ErrorRecoveryInfo).dwParam);
  1441. #ifdef _DEBUG
  1442. if (bRecoveryNeeded) {
  1443. dbg_printf(("Possible Playback-Hangup (%s) -- Recovering...n",
  1444.   (bForwardDirection ? "Forward" : "Backwards Scan")));
  1445. dbg_printf(("Curr= %08lx, param= %08lxn", dwCurrentLocation, dwRecoveryAddress));
  1446. }
  1447. #endif //_DEBUG
  1448. }
  1449. // Calculate the validity of the Recovery-Address, according to the Direction
  1450. // of playback/scanning. In addition, calculate the required amount of Blocks
  1451. // to play, in case the Recovery-Address is valid.
  1452. if (bForwardDirection) {
  1453. bRecoveryAddressValid= (dwRecoveryAddress < g_pCDDANav->m_aCurrSegment[1]);
  1454. ulBlocksCnt= (g_pCDDANav->m_aCurrSegment[1] - dwRecoveryAddress);
  1455. }
  1456. else {
  1457. bRecoveryAddressValid= (dwRecoveryAddress > g_pCDDANav->m_aCurrSegment[0]);
  1458. ulBlocksCnt= (dwRecoveryAddress - g_pCDDANav->m_aCurrSegment[0]);
  1459. }
  1460. // Perform the actual recovery-attempt, if needed
  1461. if (bRecoveryNeeded) {
  1462. // Abort the current opertion, while maintaining Standby Mode
  1463. PE_CD_AbortPlayback(TRUE);
  1464. // Invoke the appropriate recovery method
  1465. if (bRecoveryAddressValid) {
  1466. // The Recovery Address is within the legal range: try to recover
  1467. (g_pCDDANav->m_ErrorRecoveryInfo).dwParam= dwRecoveryAddress;
  1468. if ( PST_SCAN == gcs.pstate ){
  1469. PE_CD_SetScan(TRUE, g_pCDDANav->m_eCurrAudSID, g_pCDDANav->m_iScanSpeed);
  1470. }
  1471. PE_CD_PlaySegment(NoVideo, g_pCDDANav->m_eCurrAudSID, dwRecoveryAddress, ulBlocksCnt,
  1472.   ((PST_SCAN == gcs.pstate) ? eSearch : eNormalSpeed),
  1473.   g_pCDDANav->m_iScanSpeed);
  1474. //<<<TorranceF_1028_2005 Use to mute cd when scand
  1475. //#ifdef CDDA_MUTE_ON_SCAN
  1476.                      if ((CdMedia_Macro.bCDDA_MUTE_ON_SCAN)&&(PST_SCAN == gcs.pstate ))
  1477.                      {
  1478. tr_printf(("Mute the audio output for CDDA Watchdogn"));
  1479. PE_CD_SetMute(TRUE);
  1480.   
  1481. }
  1482. //#endif
  1483. }
  1484. else {
  1485. // The Recovery-Address breaches the legal range: emulate a Playback-Finished
  1486. // Event, so that navigation can carry on as if no error occurred.
  1487. ie_send(IE_CORE_CDNAV_FINISHED);
  1488. }
  1489. }
  1490. else {
  1491. // So far so good - there's progress. Register the Current Location.
  1492.       if (dwCurrentLocation != drv_msf2lbn(0,0,0))  //ZCO LC041403: Ignore 00:00:00 values when subcode buffer is just cleared andb not yet updated with valid values.
  1493. (g_pCDDANav->m_ErrorRecoveryInfo).dwParam= dwCurrentLocation;
  1494. }
  1495. // Reschedule the next check
  1496. (g_pCDDANav->m_ErrorRecoveryInfo).uTimeout= CDDA_PB_HANGUP_TIMEOUT;
  1497. #else//WATCHDOG_TRIGGERED_BY_FE
  1498. #ifndef CDDA_ERROR_RECOVERY
  1499. if ((PST_PLAY != gcs.pstate) && (PST_SCAN != gcs.pstate))
  1500. return;
  1501. #endif
  1502. // Take care of Playback-Hangup:
  1503. // Establish the current Direction of Playback/Scanning
  1504. bForwardDirection= ( (PST_PLAY == gcs.pstate) || ((PST_SCAN == gcs.pstate) && (g_pCDDANav->m_iScanSpeed > 0)) );
  1505. #ifdef CDDA_ERROR_RECOVERY
  1506. //<<<Leslie_0118_2004_A: Task Force III, implement CDDA Navigator Watchdog
  1507. if ( bForwardDirection )
  1508. dwRecoveryAddress = (g_pCDDANav->m_ErrorRecoveryInfo).dwParam 
  1509. + g_miCDDANSPBErrorJumpTbl[(g_pCDDANav->m_ErrorRecoveryInfo).ucRetryCount] * CDDA_BLOCKS_PER_SEC;
  1510. else
  1511. dwRecoveryAddress = (g_pCDDANav->m_ErrorRecoveryInfo).dwParam 
  1512. - g_miCDDANSPBErrorJumpTbl[(g_pCDDANav->m_ErrorRecoveryInfo).ucRetryCount] * CDDA_BLOCKS_PER_SEC;
  1513. //Leslie_0118_2004_A>>>
  1514. #else
  1515. if ( bForwardDirection )
  1516. dwRecoveryAddress = (g_pCDDANav->m_ErrorRecoveryInfo).dwParam 
  1517. + (DWORD)(CDDA_ERROR_JUMP_GAP_SECONDS*CDDA_BLOCKS_PER_SEC);
  1518. else
  1519. dwRecoveryAddress = (g_pCDDANav->m_ErrorRecoveryInfo).dwParam 
  1520. - (DWORD)(CDDA_ERROR_JUMP_GAP_SECONDS*CDDA_BLOCKS_PER_SEC);
  1521. #endif
  1522. dbg_printf(("Possible Playback-Hangup (%s) -- Recovering...n",
  1523.   (bForwardDirection ? "Forward" : "Backwards Scan")));
  1524. // dbg_printf(("Curr= %08lx, param= %08lxn", dwCurrentLocation, dwRecoveryAddress));
  1525. // Calculate the validity of the Recovery-Address, according to the Direction
  1526. // of playback/scanning. In addition, calculate the required amount of Blocks
  1527. // to play, in case the Recovery-Address is valid.
  1528. if (bForwardDirection) {
  1529. bRecoveryAddressValid= (dwRecoveryAddress < g_pCDDANav->m_aCurrSegment[1]);
  1530. ulBlocksCnt= (g_pCDDANav->m_aCurrSegment[1] - dwRecoveryAddress);
  1531. }
  1532. else {
  1533. bRecoveryAddressValid= (dwRecoveryAddress > g_pCDDANav->m_aCurrSegment[0]);
  1534. ulBlocksCnt= (dwRecoveryAddress - g_pCDDANav->m_aCurrSegment[0]);
  1535. }
  1536. // Perform the actual recovery-attempt, if needed
  1537. // Abort the current opertion, while maintaining Standby Mode
  1538. PE_CD_AbortPlayback(TRUE);
  1539. // Invoke the appropriate recovery method
  1540. if (bRecoveryAddressValid) {
  1541. #ifdef CDDA_ERROR_RECOVERY
  1542. tr_printf(("Error Retry address valid, doing retry now at %lxn", dwRecoveryAddress ) );
  1543. #else
  1544. tr_printf(("Error Retry address valid, doing retry nown"));
  1545. #endif
  1546. if ( PST_SCAN == gcs.pstate ){
  1547. PE_CD_SetScan(TRUE, g_pCDDANav->m_eCurrAudSID, g_pCDDANav->m_iScanSpeed);
  1548. }
  1549. PE_CD_PlaySegment(NoVideo, g_pCDDANav->m_eCurrAudSID, dwRecoveryAddress, ulBlocksCnt,
  1550.   ((PST_SCAN == gcs.pstate) ? eSearch : eNormalSpeed),
  1551.   g_pCDDANav->m_iScanSpeed);
  1552. //#ifdef CDDA_MUTE_ON_SCAN
  1553. //<<<TorranceF_1028_2005 Use to mute cd when scand
  1554.                if ((CdMedia_Macro.bCDDA_MUTE_ON_SCAN)&&(PST_SCAN == gcs.pstate))
  1555.                {
  1556. tr_printf(("Mute the audio output for CDDA Watchdogn"));
  1557. PE_CD_SetMute(TRUE);
  1558.      
  1559. }
  1560. //#endif
  1561. }
  1562. else {
  1563. // The Recovery-Address breaches the legal range: emulate a Playback-Finished
  1564. // Event, so that navigation can carry on as if no error occurred.
  1565. #ifndef CDDA_ERROR_RECOVERY
  1566. tr_printf(("Error Retry out of range, current playback finishedn"));
  1567. #else
  1568. //<<<Leslie_0118_2004_A: Task Force III, implement CDDA Navigator Watchdog
  1569. (g_pCDDANav->m_ErrorRecoveryInfo).ucRetryCount = 0;
  1570. g_pCDDANav->m_evPendingEvent= IE_CORE_CDNAV_FINISHED;
  1571. //Leslie_0118_2004_A>>>
  1572. #endif
  1573. ie_send(IE_CORE_CDNAV_FINISHED);
  1574. }
  1575. #endif
  1576. return;
  1577. }
  1578. /////////////////////////////////////////////////////////////////////////////////////////////////
  1579. // void ScanTrack(WORD uTrackNumber) -
  1580. // Scans a single Track.
  1581. //
  1582. // Input:
  1583. // uTrackNumber - Holds the Track number to scan.
  1584. //
  1585. // Output:
  1586. // None.
  1587. //
  1588. // Remarks:
  1589. // This function schedules playback of a single Track.
  1590. // The assumption is, that this function is called from within a Scanning mode, so
  1591. // that there is no need to call OnScan() again.
  1592. // The function cancels any pending Rendezvous points, hence confining the entire
  1593. // Scanning mechanism to the OnPlaybackFinished() event handler.
  1594. static void ScanTrack(WORD uTrackNumber)
  1595. {
  1596. DWORD dwTrackStartAddress;
  1597. ULONG ulTrackSize;
  1598. TrackInfo tiTrack;
  1599. //reading the track info
  1600. Array_getAt(g_hTrackInfoCache, (uTrackNumber - 1), (BYTE *)&tiTrack);
  1601. dwTrackStartAddress = tiTrack.dwStartAddress;
  1602. //<<<ML0714 add for scanning in intro mode
  1603. if((TRUE == SHARED_INFO.bIsCDDAIntroMode)&&(g_pCDDANav->m_iScanSpeed < 0))
  1604. ulTrackSize = INTRO_PLAYBACK_TIME*CDDA_BLOCKS_PER_SEC;
  1605. else
  1606. //>>>ML0714 add for scan in intro mode
  1607. ulTrackSize = tiTrack.ulBlocksCnt;
  1608. // Purge any Rendezvous point (unneeded for Track scan)
  1609. g_pCDDANav->m_uRendezvousPoint= 0;
  1610. // Update Current-Track and Scanning-related information
  1611. //<<<ML0714 add for scan in intro mode
  1612. if((TRUE == SHARED_INFO.bIsCDDAIntroMode)&&(g_pCDDANav->m_iScanSpeed > 0))
  1613. // Clear the Elapsed-Time, if the Item is going to be scanned from the beginning
  1614. SHARED_INFO.iCurrentTime= 0;
  1615. //>>>ML0714 add for scanning in intro mode
  1616. g_pCDDANav->m_aCurrTrack[0]= dwTrackStartAddress;
  1617. g_pCDDANav->m_aCurrTrack[1]= (dwTrackStartAddress + ulTrackSize);
  1618. g_pCDDANav->m_aCurrSegment[0]= g_pCDDANav->m_aCurrTrack[0];
  1619. g_pCDDANav->m_aCurrSegment[1]= g_pCDDANav->m_aCurrTrack[1];
  1620. //jeanz_0411_2005 Fix bug :stop randomly when a track is finished in shuffle mode.
  1621. if(PM_IsRepeatSingle()||PM_IsPlaybackProgram(g_PlayModeInfo.iPlaybackMode) || PM_IsPlaybackShuffle(g_PlayModeInfo.iPlaybackMode))
  1622. g_pCDDANav->ucCDDATrackChangeDetectionCounter = CDDA_TRACK_CHANGE_DETECTION_COUNTER_2; //ZCO LC041003
  1623. else
  1624. g_pCDDANav->ucCDDATrackChangeDetectionCounter = CDDA_TRACK_CHANGE_DETECTION_COUNTER_6;
  1625. // Initiate Error-Recovery
  1626. (g_pCDDANav->m_ErrorRecoveryInfo).uTimeout= (2 * CDDA_PB_HANGUP_TIMEOUT);
  1627. #ifdef CDDA_ERROR_RECOVERY
  1628. //Leslie_0118_2004_A: Task Force III, implement CDDA Navigator Watchdog
  1629. (g_pCDDANav->m_ErrorRecoveryInfo).ucRetryCount = 0;
  1630. #endif
  1631. if (g_pCDDANav->m_iScanSpeed > 0)
  1632. (g_pCDDANav->m_ErrorRecoveryInfo).dwParam= g_pCDDANav->m_aCurrSegment[0];
  1633. else
  1634. (g_pCDDANav->m_ErrorRecoveryInfo).dwParam= g_pCDDANav->m_aCurrSegment[1];
  1635. if (CDDTS_SID != g_pCDDANav->m_eCurrAudSID)
  1636. g_pCDDANav->m_bLocationChanging= TRUE;
  1637. g_pCDDANav->m_dwTargetLocation= (g_pCDDANav->m_ErrorRecoveryInfo).dwParam;
  1638. PE_CD_SetScan(TRUE, g_pCDDANav->m_eCurrAudSID, g_pCDDANav->m_iScanSpeed);
  1639. #ifdef EXINO2
  1640.     // navigator should update track/time information earlier during scan. 
  1641.     SHARED_INFO.uCurrentTrackNumber = uTrackNumber;
  1642.     if (g_pCDDANav->m_iScanSpeed > 0)
  1643. SHARED_INFO.iCurrentTime = 0;
  1644. #endif // EXINO2
  1645. if (! PE_CD_PlaySegment(NoVideo, g_pCDDANav->m_eCurrAudSID, dwTrackStartAddress, ulTrackSize,
  1646. eSearch, g_pCDDANav->m_iScanSpeed)) 
  1647. {
  1648. dbg_printf(("FATAL: ScanTrack() Failed to Scan Track.n"));
  1649. }
  1650. //#ifdef CDDA_MUTE_ON_SCAN
  1651. //<<<TorranceF_1028_2005 Use to mute cd when scand
  1652.        if (CdMedia_Macro.bCDDA_MUTE_ON_SCAN)
  1653.        {
  1654. PE_CD_SetMute(TRUE);
  1655.         }
  1656. //#else
  1657. #ifdef CDDTS_MUTE_ON_SCAN
  1658. if (g_pCDDANav->m_eCurrAudSID == CDDTS_SID)
  1659. // Force Mute, since the Playback is about to be re-invoked
  1660. PE_CD_SetMute(TRUE);
  1661. #endif //CDDTS_MUTE_ON_SCAN
  1662. //#endif //CDDA_MUTE_ON_SCAN
  1663. return;
  1664. }
  1665. static void CancelRepeatModes(BYTE uModesMask)
  1666. {
  1667. BOOL bRepeatModeChanged= FALSE;
  1668. // Cancel "Repeat Single" if it is in effect
  1669. if ((uModesMask & PM_REPEAT_SINGLE) && PM_IsRepeatSingle()) {
  1670. PM_SetRepeatSingle(FALSE);
  1671. bRepeatModeChanged= TRUE;
  1672. }
  1673. // Cancel "Repeat All" if it is in effect
  1674. if ((uModesMask & PM_REPEAT_ALL) && PM_IsRepeatAll()) {
  1675. PM_SetRepeatAll(FALSE);
  1676. bRepeatModeChanged= TRUE;
  1677. }
  1678. // Cancel "Repeat A-B" if it is in effect
  1679. if ((uModesMask & PM_REPEAT_AB_MASK) && (0 != PM_GetRepeatAB())) {
  1680. PM_SetRepeatAB(0);
  1681. OnCancelABRepeat();
  1682. bRepeatModeChanged= TRUE;
  1683. }
  1684. if (bRepeatModeChanged)
  1685. ie_send(IE_UI_STATE_CHANGE);
  1686. return;
  1687. }
  1688. /////////////////////////////////////////////////////////////////////////////////////////////////
  1689. // Event Handlers
  1690. /////////////////////////////////////////////////////////////////////////////////////////////////
  1691. // void OnTick() -
  1692. // Handles an IE_CORE_TICK_200 Event.
  1693. //
  1694. // Input:
  1695. // None
  1696. //
  1697. // Output:
  1698. // None.
  1699. //
  1700. // Remarks:
  1701. // This method is responsible for issuing either IE_CORE_CDNAV_RENDEZVOUS or 
  1702. // IE_CORE_CDNAV_FINISHED. The method checks if a notification of either kind was scheduled,
  1703. // and if it was - then a comparison is made between the current location and the scheduled
  1704. // location.
  1705. // If there is a match (within a reasonable threshold range), the appropriate event is
  1706. // sent.
  1707. //
  1708. // A notification of type IE_CORE_CDNAV_FINISHED has precedence over IE_CORE_CDNAV_RENDEZVOUS,
  1709. // and is always checked first.
  1710. static void OnTick()
  1711. {
  1712. TrackInfo tiCurrTrack;
  1713. BYTE ucCtrlField, ucTrackNumber;
  1714.     DWORD dwCurrLocation;
  1715. BOOL bTrackTransitionDetected= FALSE;
  1716. EVENT evEvent= 0;
  1717. void *EventParam= 0;
  1718. #ifdef GET_CDDTS_MSF_FROM_DRIVE
  1719. DWORD dwCDDTSCurrLocation;
  1720. //Getting MSF from Drive for CDDTS disc, since I64 STEP_A ADP is not abloe to get sub code from bitstream
  1721. if ( g_bIsCDDTS )
  1722. dwCDDTSCurrLocation = PE_CD_GetCurrentLocation();
  1723. #endif//GET_CDDTS_MSF_FROM_DRIVE
  1724. #ifdef CDDA_GETTIME_FROM_DRIVER
  1725. dwCurrLocation= PE_CD_GetCurrentLocation();
  1726. #else
  1727. dwCurrLocation= PE_CD_GetDecoderCurrentLocationLBN();
  1728. #endif
  1729. #ifdef S1_GUI
  1730. gns.cdda.iPlaylistItemForFLT= (g_pCDDANav->m_CurrPosition).iPlaylistItem;
  1731. #endif
  1732. // Update the global Location variable and the Elapsed-Time, provided that there is
  1733. // no Location-Change in progress
  1734.   if ((PST_PAUSE != gcs.pstate) && (PST_STOP != gcs.pstate) && 
  1735. (! g_pCDDANav->m_bLocationChanging)) 
  1736. {
  1737. int iSign;
  1738. UINT8 uMinute, uSecond, uFrame;
  1739. // Calculate the elapsed-time according to the current MSF, as
  1740. // reported from the Decoder via Sub-Code Q
  1741. // Get Total Elapsed Time
  1742. if ( ( g_pCDDANav->m_aCurrTrack[0] <= dwCurrLocation ) && ( dwCurrLocation <= g_pCDDANav->m_aCurrTrack[1] ) )
  1743. gns.cdda.wTotalElapsedTime = (WORD)(dwCurrLocation/CDDA_BLOCKS_PER_SEC);
  1744. else
  1745. gns.cdda.wTotalElapsedTime = (WORD)(g_pCDDANav->m_aCurrTrack[0]/CDDA_BLOCKS_PER_SEC);
  1746. #ifdef CDDA_USE_ABSOLUTE_TIME
  1747. #ifdef CDDA_GETTIME_FROM_DRIVER
  1748. SHARED_INFO.iCurrentTime= dwCurrLocation;
  1749. #else
  1750. if (PE_CD_GetDecoderCurrentLocationMSF(eAbsoluteLocation, 
  1751. &uMinute, &uSecond, &uFrame, &iSign))
  1752. {
  1753. int iCurrentTime= (60 * uMinute) + uSecond;
  1754. SHARED_INFO.iCurrentTime= iCurrentTime;
  1755. }
  1756. #endif//CDDA_GETTIME_FROM_DRIVER
  1757. #else//CDDA_USE_ABSOLUTE_TIME
  1758. #ifdef CDDA_GETTIME_FROM_DRIVER
  1759. {
  1760. tiCurrTrack.ulBlocksCnt = 0;
  1761. Array_getAt(g_hTrackInfoCache, (SHARED_INFO.uCurrentTrackNumber - 1), (BYTE *)&tiCurrTrack);
  1762. SHARED_INFO.iCurrentTime= (dwCurrLocation - tiCurrTrack.dwStartAddress)/CDDA_BLOCKS_PER_SEC;
  1763. }
  1764. #else
  1765. if (PE_CD_GetDecoderCurrentLocationMSF(eRelativeLocation, 
  1766. &uMinute, &uSecond, &uFrame, &iSign))
  1767. {
  1768. int iCurrentTime= (int)(iSign * ((60 * uMinute) + uSecond));
  1769. if (iSign < 0)
  1770. iCurrentTime--;
  1771. if( iCurrentTime < 0)
  1772. iCurrentTime = 0;
  1773. SHARED_INFO.iCurrentTime= iCurrentTime;
  1774. }
  1775. #endif//CDDA_GETTIME_FROM_DRIVER
  1776. #endif //CDDA_USE_ABSOLUTE_TIME
  1777. //updating the remaining time
  1778. #ifdef CDDA_USE_ABSOLUTE_TIME
  1779. SHARED_INFO.wRemainingPlaybackTime = SHARED_INFO.wTotalPlaybackTime - (WORD)(SHARED_INFO.iCurrentTime);
  1780. #else
  1781. tiCurrTrack.ulBlocksCnt = 0;
  1782. Array_getAt(g_hTrackInfoCache, (SHARED_INFO.uCurrentTrackNumber - 1), (BYTE *)&tiCurrTrack);
  1783. SHARED_INFO.wRemainingPlaybackTime = (WORD)((WORD)(tiCurrTrack.ulBlocksCnt / CDDA_BLOCKS_PER_SEC) - (WORD)(SHARED_INFO.iCurrentTime));
  1784. #endif //CDDA_USE_ABSOLUTE_TIME
  1785. #ifdef GET_CDDTS_MSF_FROM_DRIVE
  1786. if ( g_bIsCDDTS ){
  1787. tiCurrTrack.ulBlocksCnt = 0;
  1788. Array_getAt(g_hTrackInfoCache, (SHARED_INFO.uCurrentTrackNumber - 1), (BYTE *)&tiCurrTrack);
  1789. SHARED_INFO.iCurrentTime = (int)((dwCDDTSCurrLocation - tiCurrTrack.dwStartAddress )/(DWORD)CDDA_BLOCKS_PER_SEC);
  1790. SHARED_INFO.wRemainingPlaybackTime = (WORD)( (tiCurrTrack.dwStartAddress + (DWORD)tiCurrTrack.ulBlocksCnt- dwCDDTSCurrLocation)/(DWORD)CDDA_BLOCKS_PER_SEC);
  1791. //<<<ML 051003 for cddts,get time from driver
  1792. if (dwCurrLocation < tiCurrTrack.dwStartAddress || dwCurrLocation > tiCurrTrack.dwStartAddress+tiCurrTrack.ulBlocksCnt)
  1793. {
  1794. if ((1 == SHARED_INFO.uCurrentTrackNumber) && ((PST_SCAN == gcs.pstate) &&(g_pCDDANav->m_iScanSpeed < 0)))
  1795. {
  1796. dwCurrLocation = tiCurrTrack.dwStartAddress;
  1797. }
  1798. else
  1799. {
  1800. bTrackTransitionDetected= TRUE;
  1801. for (ucTrackNumber=1;ucTrackNumber<=PE_CD_GetTracksCnt();ucTrackNumber++)
  1802. {
  1803. TrackInfo Track;
  1804. DWORD o_pStartAddr;
  1805. ULONG o_pSize;
  1806.   PE_CD_GetTrackTOC(ucTrackNumber, &ucCtrlField, &o_pStartAddr, &o_pSize);
  1807.   if( dwCurrLocation >= o_pStartAddr && dwCurrLocation < ( o_pStartAddr + o_pSize ))
  1808. break;
  1809. }
  1810. if (ucTrackNumber > PE_CD_GetTracksCnt())
  1811. ucTrackNumber = 1;
  1812. }
  1813. }
  1814. SHARED_INFO.ucCurrentTrackInfo= ucCtrlField;
  1815. // Update the S/PDIF Audio information
  1816. PE_CD_UpdateAudioSPDIF();
  1817. //>>>ML 051003 for cddts,get time from driver
  1818. }
  1819. #endif//GET_CDDTS_MSF_FROM_DRIVE
  1820. // Update Track information
  1821. #ifdef CDDA_GETTIME_FROM_DRIVER
  1822. {
  1823. if (dwCurrLocation < tiCurrTrack.dwStartAddress || dwCurrLocation > tiCurrTrack.dwStartAddress+tiCurrTrack.ulBlocksCnt)
  1824. {
  1825. if ((1 == SHARED_INFO.uCurrentTrackNumber) && ((PST_SCAN == gcs.pstate) &&(g_pCDDANav->m_iScanSpeed < 0)))
  1826. {
  1827. #ifndef CDDA_WRAP_AROUND_ON_PROGRAM_EDGES
  1828. dwCurrLocation = tiCurrTrack.dwStartAddress;
  1829. #endif
  1830. }
  1831. else
  1832. {
  1833. bTrackTransitionDetected= TRUE;
  1834. for (ucTrackNumber=1;ucTrackNumber<=PE_CD_GetTracksCnt();ucTrackNumber++)
  1835. {
  1836. TrackInfo Track;
  1837. DWORD o_pStartAddr;
  1838. ULONG o_pSize;
  1839.   PE_CD_GetTrackTOC(ucTrackNumber, &ucCtrlField, &o_pStartAddr, &o_pSize);
  1840.  if( dwCurrLocation >= o_pStartAddr && dwCurrLocation < ( o_pStartAddr + o_pSize ))
  1841. break;
  1842. }
  1843. if (ucTrackNumber > PE_CD_GetTracksCnt())
  1844. ucTrackNumber = 1;
  1845. }
  1846. }
  1847. #ifdef CDDA_SILENT_PLAYBACK_OF_DATA_TRACKS
  1848. //checking if the current track is a data track, meaning it should not be played
  1849. if ((ucCtrlField & 0x0D) == 0x04) {
  1850. PE_CD_SetMute(TRUE);
  1851. }
  1852. else {
  1853. PE_CD_SetMute(FALSE);
  1854. }
  1855. #endif //CDDA_SILENT_PLAYBACK_OF_DATA_TRACKS
  1856. SHARED_INFO.ucCurrentTrackInfo= ucCtrlField;
  1857. // Update the S/PDIF Audio information
  1858. PE_CD_UpdateAudioSPDIF();
  1859. }
  1860. #else//#ifdef CDDA_GETTIME_FROM_DRIVER
  1861. if (PE_CD_GetDecoderCurrentTrackInfo(&ucCtrlField, &ucTrackNumber)) {
  1862. // Detect a Track-transition
  1863. if ( ((WORD)ucTrackNumber != SHARED_INFO.uCurrentTrackNumber) && (0 != ucTrackNumber) )
  1864. {
  1865. PE_CD_ResetDecoderCurrentLocationMSF(); //ZCO LC040303: Clear old subcode info.         
  1866. if (( g_pCDDANav->ucCDDATrackChangeDetectionCounter != 0xFF ) && ( g_pCDDANav->ucCDDATrackChangeDetectionCounter-- == 0 )){
  1867. bTrackTransitionDetected= TRUE;
  1868. }
  1869. }
  1870. #ifdef EXINO2
  1871.         // When repeat single, playback the next track a short time in specific disc.
  1872. if( PM_IsRepeatSingle() && PE_CD_GetCurrentLocation()  >  g_pCDDANav->m_aCurrTrack[1]  )
  1873. {
  1874. PE_CD_SetMute(TRUE);
  1875. bTrackTransitionDetected= TRUE; 
  1876. }
  1877. #endif
  1878. #ifdef CDDA_SILENT_PLAYBACK_OF_DATA_TRACKS
  1879. //checking if the current track is a data track, meaning it should not be played
  1880. if ((ucCtrlField & 0x0D) == 0x04) {
  1881. PE_CD_SetMute(TRUE);
  1882. }
  1883. else {
  1884. PE_CD_SetMute(FALSE);
  1885. }
  1886. #endif //CDDA_SILENT_PLAYBACK_OF_DATA_TRACKS
  1887. SHARED_INFO.ucCurrentTrackInfo= ucCtrlField;
  1888. // Update the S/PDIF Audio information
  1889. PE_CD_UpdateAudioSPDIF();
  1890. }
  1891. #endif//CDDA_GETTIME_FROM_DRIVER
  1892. }
  1893. // Check for normal Finish condition
  1894. // ZCO SH021903:Added condition "&& (gns.cdda.iCurrentTime != 0)" to avoid system sending
  1895. // "Playback finishied" event, when drive is just starting to play new track.
  1896. // Wrong phenomenon happens when from NSPB, user press Stop twice and quickly press PLAY to restart NSPB
  1897. // <<< SEC shKang050804 : because gns.cdda.iCurrentTime is zero, cannot go to the next track in shuffle mode.
  1898. // So check the gns.cdda.iCurrentTime only for normal playback mode.
  1899. #ifdef EXINO2
  1900. if (  ((PST_PLAY == gcs.pstate) && PE_CD_IsPlaybackFinished() && 
  1901. ((gns.cdda.iCurrentTime != 0 && PM_IsPlaybackNormal(PM_GetPlaybackMode())) || (!PM_IsPlaybackNormal(PM_GetPlaybackMode()))) )
  1902.    ||((PST_SCAN == gcs.pstate) && PE_CD_IsPlaybackFinished())
  1903.    ||((PST_PLAY == gcs.pstate) && (INTRO_PLAYBACK_TIME == gns.cdda.iCurrentTime) && ((TRUE == SHARED_INFO.bIsCDDAIntroMode)))
  1904.            ||((PST_SCAN == gcs.pstate) && (INTRO_PLAYBACK_TIME <= SHARED_INFO.iCurrentTime) && ((TRUE == SHARED_INFO.bIsCDDAIntroMode)))//ML0714 add for scanning in intro mode
  1905. #else // EXINO2
  1906. if (  ((PST_PLAY == gcs.pstate) && PE_CD_IsPlaybackFinished() && (gns.cdda.iCurrentTime != 0)) 
  1907.    ||((PST_SCAN == gcs.pstate) && PE_CD_IsPlaybackFinished())
  1908.    ||((PST_PLAY == gcs.pstate) && (INTRO_PLAYBACK_TIME == gns.cdda.iCurrentTime) && ((TRUE == SHARED_INFO.bIsCDDAIntroMode)))
  1909.            ||((PST_SCAN == gcs.pstate) && (INTRO_PLAYBACK_TIME <= SHARED_INFO.iCurrentTime) && ((TRUE == SHARED_INFO.bIsCDDAIntroMode)))//ML0714 add for scanning in intro mode
  1910. #endif // EXINO2
  1911. // SEC shKang050804 >>>
  1912. {
  1913. if (IE_CORE_CDNAV_FINISHED != g_pCDDANav->m_evPendingEvent) {
  1914. #ifdef WATCHDOG_TRIGGERED_BY_FE
  1915. if ( ucDriveErrorMsgCount > 0 )
  1916. return;
  1917. #endif
  1918. g_pCDDANav->m_evPendingEvent= IE_CORE_CDNAV_FINISHED;
  1919. ie_send(IE_CORE_CDNAV_FINISHED);
  1920. usleep(50000UL);
  1921. }
  1922. #ifndef WATCHDOG_TRIGGERED_BY_FE
  1923. // Call for Error-Recovery, if needed
  1924. PerformErrorRecovery();
  1925. #endif
  1926. return;
  1927. }
  1928. // Check if there is a Location-Change in progress
  1929. if (g_pCDDANav->m_bLocationChanging) {
  1930. DWORD dwTargetRangeLow, dwTargetRangeHigh;
  1931. // Check whether the Location-Change has been completed
  1932. if ((PST_SCAN == gcs.pstate) && (g_pCDDANav->m_iScanSpeed < 0)) {
  1933. // Backwards Scanning
  1934. dwTargetRangeLow= (g_pCDDANav->m_dwTargetLocation - CDDA_POSITION_TOLERANCE + 
  1935.    (g_pCDDANav->m_iScanSpeed * CDDA_BLOCKS_PER_SEC*2));
  1936. dwTargetRangeHigh= g_pCDDANav->m_dwTargetLocation;
  1937. }
  1938. else {
  1939. // Normal playback or Forward Scanning
  1940. dwTargetRangeLow= g_pCDDANav->m_dwTargetLocation;
  1941. dwTargetRangeHigh= (g_pCDDANav->m_dwTargetLocation + CDDA_POSITION_TOLERANCE + 
  1942. (g_pCDDANav->m_iScanSpeed * CDDA_BLOCKS_PER_SEC));
  1943. }
  1944. // If the Location-Change has finished, then signal this. Otherwise,
  1945. // nothing else to do.
  1946. #ifdef CDDA_PAUSE_ENABLED_FOR_SCAN
  1947. if (dwCurrLocation >= dwTargetRangeLow)
  1948. g_pCDDANav->m_bLocationChanging= FALSE;
  1949. #else      
  1950. if ((dwCurrLocation >= dwTargetRangeLow) && (dwCurrLocation < dwTargetRangeHigh))
  1951. g_pCDDANav->m_bLocationChanging= FALSE;
  1952. #endif         
  1953. else {
  1954. #ifndef WATCHDOG_TRIGGERED_BY_FE
  1955. // Call for Error-Recovery, if needed
  1956. PerformErrorRecovery();
  1957. return;
  1958. #endif
  1959. }
  1960. }
  1961. // Update the COP_MASK with regard to the Next-Chapter operation
  1962. SET_COP_MASK(COP_NEXT_CHAPTER);
  1963. // Update the COP_MASK with regard to the Pre-Chapter operation
  1964. SET_COP_MASK(COP_PREVIOUS_CHAPTER);
  1965. #ifndef CDDA_WRAP_AROUND_ON_PROGRAM_EDGES
  1966. if (! PM_IsRepeatAll() && 
  1967. ((g_pCDDANav->m_CurrPosition).iPlaylistItem == (PM_GetProgramSize() - 1))) 
  1968. {
  1969. // If the Current-Item is the last one on the Program-List, then Next is not allowed
  1970. CLEAR_COP_MASK(COP_NEXT_CHAPTER);
  1971. }
  1972. //angieh_0324_2004:For Alco,support previous func when play the first track.
  1973. #ifndef SKIP_TO_THE_BEGINING
  1974. if (! PM_IsRepeatAll() && 
  1975. ((g_pCDDANav->m_CurrPosition).iPlaylistItem == 1))
  1976. {
  1977. // If the Current-Item is the first one on the Program-List, then Pre is not allowed
  1978. CLEAR_COP_MASK(COP_PREVIOUS_CHAPTER);
  1979. }
  1980. #endif //CDDA_WRAP_AROUND_ON_PROGRAM_EDGES
  1981. #endif //CDDA_WRAP_AROUND_ON_PROGRAM_EDGES
  1982. // Check for a Position-Rendezvous condition, or a special Finish condition.
  1983. // Take care of A-B Repeat
  1984. if (PM_GetRepeatAB() & PM_REPEAT_AB_B) {
  1985. if ((PST_SCAN == gcs.pstate) && (g_pCDDANav->m_iScanSpeed < 0)) {
  1986. // Handle a Backwards-scan (in this case, look for Position-A, rather than Position-B)
  1987. if ((dwCurrLocation <= (g_pCDDANav->m_PositionA).dwAddress) &&
  1988. ((g_pCDDANav->m_CurrPosition).iPlaylistItem == (g_pCDDANav->m_PositionA).iPlaylistItem))
  1989. {
  1990. evEvent= IE_CORE_CDNAV_RENDEZVOUS;
  1991. EventParam= (void *)ePositionA;
  1992. }
  1993. }
  1994. else if (((g_pCDDANav->m_PositionB).dwAddress < dwCurrLocation) &&
  1995.  ((g_pCDDANav->m_CurrPosition).iPlaylistItem == (g_pCDDANav->m_PositionB).iPlaylistItem))
  1996. {
  1997. // For Forward-scan, of Normal speed playback, look for Position-B
  1998. if (0 == CDDAMessageGap.MARKABReachGap)
  1999. {
  2000. evEvent= IE_CORE_CDNAV_RENDEZVOUS;
  2001. EventParam= (void *)ePositionB;
  2002. CDDAMessageGap.MARKABReachGap = MARKAB_FINISH_GAP;
  2003. }
  2004. }
  2005. if (CDDAMessageGap.MARKABReachGap > 0)
  2006. CDDAMessageGap.MARKABReachGap--;
  2007. }
  2008. else if (PM_GetRepeatAB() & PM_REPEAT_AB_A) {
  2009. // Only Position-A is set:
  2010. // If the Current position precedes Position-A (e.g. during Backwards-scan),
  2011. // then cancel the setting.
  2012. if (((dwCurrLocation + DRIVER_SEEK_MARGIN) <= (g_pCDDANav->m_PositionA).dwAddress) &&
  2013. ((g_pCDDANav->m_CurrPosition).iPlaylistItem == (g_pCDDANav->m_PositionA).iPlaylistItem))
  2014. {
  2015. CancelRepeatModes(PM_REPEAT_AB_MASK);
  2016. core_report_error( IE_UI_REPORT_ERROR, (void *)CDNAV_ERR_REPEAT_AB_PROHIBIT );
  2017. }
  2018. else
  2019. {
  2020. if((g_pCDDANav->m_CurrPosition).iPlaylistItem != (g_pCDDANav->m_PositionA).iPlaylistItem)
  2021. {
  2022. CancelRepeatModes(PM_REPEAT_AB_MASK);
  2023. }
  2024. }
  2025. }
  2026. #ifdef CDDA_DEEMPHASIS_ENABLE
  2027. if(uPrevTrackNumber != gns.cdda.uCurrentTrackNumber)
  2028. {
  2029. UINT8  uTrackCtrlField;
  2030. UINT32 uDummy;
  2031. uPrevTrackNumber = gns.cdda.uCurrentTrackNumber;
  2032.   PE_CD_GetTrackTOC(uPrevTrackNumber, &ucCtrlField, &uDummy, &uDummy); 
  2033. #ifndef EXINO2  //ZKR ML220404 S1 Deemphisis set
  2034. if (ucCtrlField&0x10)
  2035. PE_CD_SetDeemphasis(TRUE);
  2036. else
  2037. PE_CD_SetDeemphasis(FALSE);
  2038. #else
  2039. #ifdef DAC_DSD1608
  2040. if (ucCtrlField&0x01)
  2041. PE_CD_SetDeemphasis(TRUE);
  2042. else
  2043. PE_CD_SetDeemphasis(FALSE);
  2044. #endif
  2045. #endif
  2046. }
  2047. #endif
  2048. // Take care of End-of-Item (Track Transition)
  2049. if (bTrackTransitionDetected) {
  2050. // Check if there is a Rendezvous-point scheduled for the new Track
  2051. if (ucTrackNumber == g_pCDDANav->m_uRendezvousPoint) {
  2052. // Report a Rendezvous only if the current Playback Mode is neither Program
  2053. // nor Shuffle (in which cases, the playback should be terminated immediately).
  2054. if (PM_IsPlaybackProgram(g_pCDDANav->m_uCurrPlaybackMode) || 
  2055. PM_IsPlaybackShuffle(g_pCDDANav->m_uCurrPlaybackMode))
  2056. {
  2057. evEvent= IE_CORE_CDNAV_FINISHED;
  2058. }
  2059. else {
  2060. evEvent= IE_CORE_CDNAV_RENDEZVOUS;
  2061. EventParam= (void *)eEndOfItem;
  2062. }
  2063. }
  2064. else {
  2065. // There was no Rendezvous-point shceduled
  2066. if ((PST_PLAY == gcs.pstate) && 
  2067. (PM_IsPlaybackProgram(g_pCDDANav->m_uCurrPlaybackMode) || 
  2068.  PM_IsPlaybackShuffle(g_pCDDANav->m_uCurrPlaybackMode)))
  2069. {
  2070. // For Normal playback during Program or Shuffle, there's need to
  2071. // terminate playback immediately.
  2072. //<<<LX102502: Track number is not udpated during drive seek, still holding previous track no.
  2073. //need to double check it
  2074. dbg_printf(("ucTrackNumber = %02x, SHARED_INFO.uCurrentTrackNumber = %02xn", ucTrackNumber, SHARED_INFO.uCurrentTrackNumber));
  2075. if ( ucTrackNumber == ( SHARED_INFO.uCurrentTrackNumber + 1 ) ){
  2076. evEvent= IE_CORE_CDNAV_FINISHED;
  2077. }else
  2078. dbg_printf(("Not issue playback finished during seekingn"));
  2079. //LX102502>>>
  2080. }
  2081. else if (PST_SCAN == gcs.pstate) {
  2082. // For Scanning, check the current Playback-Mode
  2083. if (PM_IsRepeatSingle()) {
  2084. // For Repeat-Single terminate playback immediately
  2085. evEvent= IE_CORE_CDNAV_FINISHED;
  2086. }
  2087. else {
  2088. // For any other Playback-Mode, just update the global information (i.e.
  2089. // the new Track Number) - this cannot be done elsewhere, because Track
  2090. // Transition might occur before the actual end of the Track as reported
  2091. // in the TOC (when the Index field is 00).
  2092. SHARED_INFO.uCurrentTrackNumber= ucTrackNumber;
  2093. g_pCDDANav->ucCDDATrackChangeDetectionCounter = CDDA_TRACK_CHANGE_DETECTION_COUNTER_6;
  2094. #ifdef CDTEXT_SUPPORT
  2095. SHARED_INFO.pTrackCDText= (UINT32)PE_CD_GetCDTEXTInfo(ucTrackNumber);
  2096. #ifdef _DEBUG
  2097. if (SHARED_INFO.pTrackCDText) {
  2098. dbg_printf(("Track #%d name: %sn", SHARED_INFO.uCurrentTrackNumber, SHARED_INFO.pTrackCDText));
  2099. }
  2100. #endif //_DEBUG
  2101. #endif //CDTEXT_SUPPORT
  2102. }
  2103. }
  2104. #ifdef EXINO2
  2105.             // in disc repeat, final song play-> fist song play -> second play -> stop VFD bug fixed
  2106. else if((PST_PLAY == gcs.pstate) &&PM_IsRepeatAll() )
  2107. {
  2108. g_pCDDANav->ucCDDATrackChangeDetectionCounter = CDDA_TRACK_CHANGE_DETECTION_COUNTER_6;
  2109. }
  2110. #endif
  2111. }
  2112. }
  2113. // Send any Event needed, as long as it is not already pending
  2114. if ( (evEvent != g_pCDDANav->m_evPendingEvent) && ( 0 != evEvent ) ){//LX102902: Not send 0 event to RTOS
  2115. g_pCDDANav->m_evPendingEvent= evEvent;
  2116. ie_send_ex(evEvent, EventParam);
  2117. }
  2118. #ifndef WATCHDOG_TRIGGERED_BY_FE
  2119. // Call for Error-Recovery, if needed
  2120. PerformErrorRecovery();
  2121. #endif
  2122. return;
  2123. }
  2124. /////////////////////////////////////////////////////////////////////////////////////////////////
  2125. // void OnPlay() -
  2126. // Handles an IE_CORE_PLAY Event.
  2127. //
  2128. // Input:
  2129. // None.
  2130. //
  2131. // Output:
  2132. // None.
  2133. static void OnPlay()
  2134. {
  2135. dbg_printf(("OnPlay()n"));
  2136. if(! IS_COP_ENABLE( COP_SETUP ))   //kz 07082002
  2137. SET_COP_MASK( COP_SETUP);
  2138. // Make sure that there's really need to invoke playback
  2139. if (PST_PLAY == gcs.pstate) {
  2140. dbg_printf(("Already in Playback state. Ignoredn"));
  2141. return;
  2142. }
  2143. #ifdef CDDA_DISPLAY_BACKGROUND_DURING_PLAYBACK
  2144. // Display the Background, if needed
  2145. if (PST_STOP == gcs.pstate)
  2146. PE_CD_DisplayBackground(TRUE);
  2147. #endif //CDDA_DISPLAY_BACKGROUND_DURING_PLAYBACK
  2148. if (PST_PAUSE == gcs.pstate) {
  2149. PE_CD_PausePlayback(FALSE, g_pCDDANav->m_eCurrAudSID);
  2150. gcs.pstate= PST_PLAY;
  2151. return;
  2152. }
  2153. if (PST_SCAN == gcs.pstate) {
  2154. // Resume Normal playback, from the current location
  2155. (g_pCDDANav->m_CurrPosition).dwAddress= PE_CD_GetDecoderCurrentLocationLBN();
  2156. PE_CD_AbortPlayback(TRUE); // Maintain Standby mode
  2157. // Cancel the on-going Scan
  2158. OnScan(0);
  2159. gcs.pstate= PST_PLAY;
  2160. if (! InvokePlayback()) {
  2161. dbg_printf(("Failed to resume Normal-Speed Playback.n"));
  2162. gcs.pstate= PST_STOP;
  2163. }
  2164. return;
  2165. }
  2166. // Check if the playback needs to be resumed from a previously recorded position
  2167. if (-1 != (g_pCDDANav->m_ResumePlayback).dwAddress) {
  2168. dbg_printf(("Resuming playbackn"));
  2169. memcpy(&(g_pCDDANav->m_CurrPosition), &(g_pCDDANav->m_ResumePlayback), sizeof(CDDA_Marker));
  2170. ClearMarker(eResumePlayback, 0); // Mark that this Marker has been used
  2171. }
  2172. gcs.pstate= PST_PLAY;
  2173. if (! InvokePlayback()) {
  2174. dbg_printf(("Error: Failed to invoke playbackn"));
  2175. gcs.pstate= PST_STOP;
  2176. }
  2177. return;
  2178. }
  2179. /////////////////////////////////////////////////////////////////////////////////////////////////
  2180. // void OnPlaybackFinished() -
  2181. // Handles an IE_CORE_CDNAV_FINISHED Event.
  2182. //
  2183. // Input:
  2184. //
  2185. // Output:
  2186. // None.
  2187. //
  2188. // Remarks:
  2189. // An Event of type PLAYBACK_FINISHED is encountered when the PE has finished presenting
  2190. // the entire segemnt which was previously requested by a call to InvokePlayback().
  2191. // This happens at the end of a linear-Track-sequence.
  2192. //
  2193. // This method is responsible for selecting the next linear-Track-sequence to play, or 
  2194. // rewinding to the beginning of the Playlist (if the last item has been reached).
  2195. static void OnPlaybackFinished()
  2196. {
  2197. BOOL bCancelOngoingScanning;
  2198. dbg_printf(("OnPlaybackFinished()n"));
  2199. // Force a Full-Stop, just in case
  2200. PE_CD_AbortPlayback(TRUE); // Maintain Standby mode
  2201. // Cancel Error-Recovery
  2202. (g_pCDDANav->m_ErrorRecoveryInfo).uTimeout= 0;
  2203. #ifdef CDDA_ERROR_RECOVERY
  2204. //Leslie_0118_2004_A: Task Force III, implement CDDA Navigator Watchdog
  2205. (g_pCDDANav->m_ErrorRecoveryInfo).ucRetryCount = 0;
  2206. #endif
  2207. // Determine whether or not ongoing Scanning should be cancelled
  2208. if (PM_IsPlaybackProgram(g_pCDDANav->m_uCurrPlaybackMode) || 
  2209. PM_IsPlaybackShuffle(g_pCDDANav->m_uCurrPlaybackMode)) 
  2210. {
  2211. #ifdef CDDA_PROHIBIT_SCAN_ACROSS_PROGRAM_ENTRIES
  2212. // For Program or Shuffle Playback, always cancel any ongoing Scanning
  2213. bCancelOngoingScanning= TRUE;
  2214. #else
  2215. bCancelOngoingScanning= FALSE;
  2216. #endif //CDDA_PROHIBIT_SCAN_ACROSS_PROGRAM_ENTRIES
  2217. }
  2218. else 
  2219. {
  2220. #ifdef CDDA_PROHIBIT_SCAN_ACROSS_TRACK_BOUNDARIES
  2221. bCancelOngoingScanning= TRUE;
  2222. #else
  2223. bCancelOngoingScanning= FALSE;
  2224. #endif //CDDA_PROHIBIT_SCAN_ACROSS_TRACK_BOUNDARIES
  2225. }
  2226. // Take care of Backwards Scanning
  2227. if ((PST_SCAN == gcs.pstate) && (g_pCDDANav->m_iScanSpeed < 0)) {
  2228. if (bCancelOngoingScanning) {
  2229. // Stop Scanning, and resume Normal playback
  2230. OnScan(0);
  2231. gcs.pstate= PST_PLAY;
  2232. if (! InvokePlayback()) {
  2233. dbg_printf(("Failed to playback the next itemn"));
  2234. gcs.pstate= PST_STOP;
  2235. }
  2236. ie_send(IE_UI_STATE_CHANGE);
  2237. }
  2238. else {
  2239. // Continue Scanning, if appropriate
  2240. if ((1 == (g_pCDDANav->m_CurrPosition).iPlaylistItem) || PM_IsRepeatSingle()) {
  2241. // If this is the first item, or if there's need to repeat
  2242. // the current Track, then resume normal playback from the beginning.
  2243. OnScan(0);
  2244. gcs.pstate= PST_PLAY;
  2245. if (! InvokePlayback()) {
  2246. dbg_printf(("Failed to playback the next itemn"));
  2247. gcs.pstate= PST_STOP;
  2248. }
  2249. ie_send(IE_UI_STATE_CHANGE);
  2250. }
  2251. else {
  2252. // Switch to the previous Item on the Program-List, while scanning
  2253. WORD wCurrentTrackNumber= PM_GetProgramListEntry(--((g_pCDDANav->m_CurrPosition).iPlaylistItem));
  2254. ScanTrack(wCurrentTrackNumber);
  2255. }
  2256. }
  2257. return;
  2258. }
  2259. // Take care of Forward Playback/Scanning
  2260. if ((PST_SCAN == gcs.pstate) && bCancelOngoingScanning) {
  2261. OnScan(0);
  2262. gcs.pstate= PST_PLAY;
  2263. ie_send(IE_UI_STATE_CHANGE);
  2264. }
  2265. // Check for a pending Playback-Mode change
  2266. if (g_pCDDANav->m_bPendingModeChange)
  2267. g_pCDDANav->m_bPendingModeChange= FALSE;
  2268. // Check if the Playback-Mode is "Single Repeat". If so, reschedule playback of the 
  2269. // current Playlist-Item again. This check is essential for the special case where the last
  2270. // item on a Linear-Sequence or Playlist needs to be repeated.
  2271. if (PM_IsRepeatSingle()) {
  2272. // Resume Normal playback, if scanning
  2273. if (PST_SCAN == gcs.pstate) {
  2274. OnScan(0);
  2275. gcs.pstate= PST_PLAY;
  2276. ie_send(IE_UI_STATE_CHANGE);
  2277. }
  2278. if (! InvokePlayback()) {
  2279. dbg_printf(("Error: Failed to invoke playbackn"));
  2280. gcs.pstate= PST_STOP;
  2281. }
  2282. return;
  2283. }
  2284. // Check if the end of the Playlist has been reached. If so, then rewind the
  2285. // Playlist. If the Playback-Mode is REPEAT_ALL, then also re-invoke the playback.
  2286. if (++((g_pCDDANav->m_CurrPosition).iPlaylistItem) > (int)(PM_GetProgramSize() - 1)) {
  2287. (g_pCDDANav->m_CurrPosition).iPlaylistItem= 1;
  2288. // Cancel AB-Repeat, in case only Position-A was set
  2289. CancelRepeatModes(PM_REPEAT_AB_MASK);
  2290. // If the current playback-mode is not "Repeat All", then don't re-invoke the playback
  2291. if (! PM_IsRepeatAll()
  2292. //jeanz_2004_0916 For cdda repeat program
  2293. #ifdef D_REPEAT_PROGRAM_MODE
  2294. && (PM_GetPlaybackMode() != PM_PLAYBACK_PROGRAM)  
  2295. #endif
  2296. ) {
  2297. OnStop(eFullStop);
  2298. ie_send(IE_UI_STATE_CHANGE);
  2299. return;
  2300. }
  2301. // Resume Normal playback, if Scanning
  2302. if (PST_SCAN == gcs.pstate) {
  2303. OnScan(0);
  2304. gcs.pstate= PST_PLAY;
  2305. ie_send(IE_UI_STATE_CHANGE);
  2306. }
  2307. }
  2308. // Extract the Track-information for the current playlist-item
  2309. SHARED_INFO.uCurrentTrackNumber = PM_GetProgramListEntry((g_pCDDANav->m_CurrPosition).iPlaylistItem);
  2310. // Invoke playback of the next item(s) on the playlist
  2311. if (PST_SCAN == gcs.pstate) {
  2312. // Schedule a forward-scan of the current Item
  2313. ScanTrack(PM_GetProgramListEntry((g_pCDDANav->m_CurrPosition).iPlaylistItem));
  2314. }
  2315. else {
  2316. // Play-back the current Item from its beginning
  2317. gcs.pstate= PST_PLAY;
  2318. if (! InvokePlayback()) {
  2319. dbg_printf(("Failed to play-back the next itemn"));
  2320. gcs.pstate= PST_STOP;
  2321. }
  2322. }
  2323. return;
  2324. }
  2325. /////////////////////////////////////////////////////////////////////////////////////////////////
  2326. // OnStop(enCDDA_StopType eType) -
  2327. // Handles an IE_CORE_PAUSE or IE_CORE_STOP or IE_CORE_FULL_STOP Event.
  2328. //
  2329. // Input:
  2330. // eType - The type of requested Stop
  2331. //
  2332. // Output:
  2333. // None.
  2334. static void OnStop(enCDDA_StopType eType)
  2335. {
  2336. dbg_printf(("OnStop()n"));
  2337. switch (eType) 
  2338. {
  2339. case ePause:
  2340. dbg_printf(("OnPause()n"));
  2341. if (PST_SCAN == gcs.pstate) {
  2342. // First, cancel Scanning
  2343. // OnScan(0);
  2344. // Now, Abort playback
  2345. PE_CD_AbortPlayback(TRUE);
  2346. //#ifdef CDDA_MUTE_ON_SCAN
  2347. // Force Mute, since the Playback is about to be re-invoked
  2348.       if (CdMedia_Macro.bCDDA_MUTE_ON_SCAN)
  2349.             {
  2350. PE_CD_SetMute(TRUE);
  2351.              }
  2352. //#else
  2353. #ifdef CDDTS_MUTE_ON_SCAN
  2354. if (g_pCDDANav->m_eCurrAudSID == CDDTS_SID)
  2355. // Force Mute, since the Playback is about to be re-invoked
  2356. PE_CD_SetMute(TRUE);
  2357. #endif //CDDTS_MUTE_ON_SCAN
  2358. //#endif //CDDA_MUTE_ON_SCAN
  2359. // And now, re-invoke Playback from the same position, to allow resuming
  2360. // of the Playback later.
  2361. (g_pCDDANav->m_CurrPosition).dwAddress= PE_CD_GetDecoderCurrentLocationLBN();
  2362. PE_CD_SetScan(FALSE, g_pCDDANav->m_eCurrAudSID, 0);
  2363. if (! InvokePlayback()) {
  2364. dbg_printf(("Failed to re-invoke Playback.n"));
  2365. }
  2366. }
  2367. PE_CD_PausePlayback(TRUE, g_pCDDANav->m_eCurrAudSID);
  2368. #ifdef CDDA_MUTE_ON_SCAN
  2369. // Cancel existing Mute, if any
  2370. // if ( !g_bIsCDDTS ){
  2371. // tr_printf(("Cancel Mute from Scan to Pausen"));
  2372. // PE_CD_SetMute(FALSE);
  2373. // }
  2374. #else
  2375. #ifdef CDDTS_MUTE_ON_SCAN
  2376. if (g_pCDDANav->m_eCurrAudSID == CDDTS_SID)
  2377. // Force Mute, since the Playback is about to be re-invoked
  2378. PE_CD_SetMute(FALSE);
  2379. #endif //CDDTS_MUTE_ON_SCAN
  2380. #endif //CDDA_MUTE_ON_SCAN
  2381. gcs.pstate= PST_PAUSE;
  2382. break;
  2383. case eStopResume:
  2384. dbg_printf(("Stopping playback. Current-position recorded:%dn",eType));
  2385. case eFullStop:
  2386. g_pCDDANav->m_uRendezvousPoint= 0; // Purge pending notification requests
  2387. if (eStopResume == eType)
  2388. {
  2389. #ifdef D_CD_GRAPHIC_ENABLED
  2390. //let CDG stop resume from current track instead of first track
  2391. if( gcst.mCDGDetected )
  2392. ClearMarker(eResumePlayback, 0);
  2393. else
  2394. #endif
  2395. SetMarker(eResumePlayback, 0);
  2396. }
  2397. else 
  2398. {
  2399. #ifndef K1_WL
  2400. ClearMarker(eResumePlayback, 0);
  2401. #endif
  2402. //add by wl033004 for set the play mode to normal after full stop
  2403. #ifdef K1_WL
  2404. if ( PM_IsPlaybackProgram(PM_GetPlaybackMode()) || PM_IsPlaybackIntro(PM_GetPlaybackMode())
  2405. #ifdef D_ENABLE_SHUFFLE_MODE
  2406. || PM_IsPlaybackShuffle(PM_GetPlaybackMode())
  2407. #endif
  2408. )
  2409. {
  2410. PM_SetPlaybackMode(PM_PLAYBACK_NORMAL);
  2411.   mode_set_private_program_size(0);
  2412. OnModeChange();
  2413. }
  2414. #endif
  2415. //add by wl033004 for set the play mode to normal after full stop
  2416. // Rewind the Current-Position to the Program-Beginning
  2417. (g_pCDDANav->m_CurrPosition).iPlaylistItem= 1;
  2418. (g_pCDDANav->m_CurrPosition).dwAddress= -1;
  2419. // <<< ZCO SH021903:Clean Error recovery info after full stop
  2420. // Limit also wrong behavior of system when restart NSPB after pressing twice STOP and then quickly PLAY.
  2421. g_pCDDANav->m_dwTargetLocation = -1;
  2422. // ZCO SH021903 >>>
  2423. // ZCO SH021903:Reset subcode info after a full stop
  2424. // Avoid system reading outdated subcode information.
  2425. PE_CD_ResetDecoderCurrentLocationMSF();
  2426. #ifdef EXINO2
  2427. g_in_full_stop = TRUE;
  2428. #endif // EXINO2
  2429. }
  2430. PE_CD_AbortPlayback((eStopResume == eType) ? TRUE : FALSE);
  2431. if (PST_STOP != gcs.pstate) {
  2432. PE_CD_SetScan(FALSE, g_pCDDANav->m_eCurrAudSID, 0);
  2433. // Cancel Scanning
  2434. if (PST_SCAN == gcs.pstate)
  2435. OnScan(0);
  2436. gcs.pstate= PST_STOP;
  2437. // Cancel any current Repeat-Modes
  2438. if (eStopResume != eType) //BT0407: only full stop cancel repeat mode
  2439. CancelRepeatModes(PM_REPEAT_SINGLE | PM_REPEAT_ALL | PM_REPEAT_AB_MASK);
  2440. // Cancel pending Mode-Changes
  2441. g_pCDDANav->m_bPendingModeChange= FALSE;
  2442. // Display the Logo
  2443. PE_CD_DisplayLogo();
  2444. }
  2445. SHARED_INFO.bIsCDDAIntroMode = FALSE;
  2446. break;
  2447. }
  2448. // Disable Error-Recovery
  2449. (g_pCDDANav->m_ErrorRecoveryInfo).uTimeout= 0;
  2450. (g_pCDDANav->m_ErrorRecoveryInfo).dwParam= 0;
  2451. #ifdef CDDA_ERROR_RECOVERY
  2452. //Leslie_0118_2004_A: Task Force III, implement CDDA Navigator Watchdog
  2453. (g_pCDDANav->m_ErrorRecoveryInfo).ucRetryCount = 0;
  2454. #endif
  2455. return;
  2456. }
  2457. /////////////////////////////////////////////////////////////////////////////////////////////////
  2458. // void OnRendezvousPoint() -
  2459. // Handles an IE_CORE_CDNAV_RENDEZVOUS Event.
  2460. //
  2461. // Input:
  2462. // None.
  2463. // Output:
  2464. // None.
  2465. //
  2466. // Remarks:
  2467. // An Event of type RENDEZVOUS_POINT is encountered when the PE has reached a predefined
  2468. // point in the playback, which was previously determined by InvokePlayback().
  2469. // This happens only on the boundaries of two sequencial Tracks/Play-Items, or when reaching
  2470. // Position-A/B when in "Repeat A->B" Playback-Mode.
  2471. //
  2472. // When such an event occurs, there's need to either repeat the current Item (if
  2473. // the Playback-Mode is REPEAT_SINGLE), or to continue playback of the next item.
  2474. // In the latter, there's no need to repeat the request from the PE, but there is need
  2475. // to update the internal value of m_iCurrPlaylistItem and to schedule a new Rendezvous-Point,
  2476. // if appropriate.
  2477. //
  2478. // If the event occurs within the context of a "Repeat A->B" Playback-Mode, then there's need
  2479. // to check whether Position-A/B has been reached. If yes, the playback is restarted from Position-A.
  2480. // Otherwise, if Position-B is located within the next item, an appropriate Rendezvous-Point is set.
  2481. static void OnRendezvousPoint(enCDDA_RendezvousType eType)
  2482. {
  2483. dbg_printf(("OnRendezvousPoint()n"));
  2484. if ((ePositionA == eType) || (ePositionB == eType)) {
  2485. dbg_printf(("Position%c encountered.n", (ePositionA == eType) ? 'A' : 'B'));
  2486. PE_CD_AbortPlayback(TRUE); // Maintain Standby mode
  2487. // Rewind to Position-A
  2488. memcpy(&(g_pCDDANav->m_CurrPosition), &(g_pCDDANav->m_PositionA), sizeof(CDDA_Marker));
  2489. // Eliminate any on-going Scanning
  2490. if (PST_SCAN == gcs.pstate) {
  2491. OnScan(0);
  2492. gcs.pstate= PST_PLAY;
  2493. }
  2494. // Restart playback from Position-A
  2495. if (! InvokePlayback()) {
  2496. dbg_printf(("Failed to playback the current listn"));
  2497. gcs.pstate= PST_STOP;
  2498. }
  2499. //Give proper time to loader to fucus
  2500. usleep(50000UL);
  2501. return;
  2502. }
  2503. // this is for eType == EndOfItem
  2504. g_pCDDANav->m_uRendezvousPoint= 0; // Purge pending notification requests
  2505. // Check if the Playback-Mode is "Single Repeat". If so, abort the current playback and
  2506. // reschedule playback of the current Playlist-Item again.
  2507. if (PM_IsRepeatSingle()) {
  2508. PE_CD_AbortPlayback(TRUE); // Maintain Standby mode
  2509. // Cancel "Repeat AB" if it is in effect
  2510. CancelRepeatModes(PM_REPEAT_AB_MASK);
  2511. if (! InvokePlayback()) {
  2512. dbg_printf(("Error: Failed to invoke playbackn"));
  2513. gcs.pstate= PST_STOP;
  2514. }
  2515. return;
  2516. }
  2517. // Check for a pending Playback-Mode change
  2518. if (g_pCDDANav->m_bPendingModeChange) {
  2519. // Force a playback-mode change by pretending that a Linear-Sequence has ended playback
  2520. g_pCDDANav->m_bPendingModeChange= FALSE;
  2521. OnPlaybackFinished();
  2522. return;
  2523. }
  2524. // The Playback-Mode is either "Normal", or "Repeat A->B" provided that Position-B is not within the next item.
  2525. // Therefore, continue playback of the next item on the Playlist, and if it's not the last
  2526. // within a linear-sequence, reschedule a Rendezvous-Point.
  2527. if (PM_GetProgramListEntry((g_pCDDANav->m_CurrPosition).iPlaylistItem+1) == 
  2528. (1 + PM_GetProgramListEntry((g_pCDDANav->m_CurrPosition).iPlaylistItem)))
  2529. {
  2530. TrackInfo tiCurrTrack;
  2531. DWORD dwCurrTrackStartAddress;
  2532. ULONG ulCurrTrackSize;
  2533. WORD uCurrTrackNumber= PM_GetProgramListEntry((g_pCDDANav->m_CurrPosition).iPlaylistItem+1);
  2534. // Update Current-Track information
  2535. Array_getAt(g_hTrackInfoCache, (uCurrTrackNumber - 1), (BYTE *)&tiCurrTrack);
  2536. dwCurrTrackStartAddress = tiCurrTrack.dwStartAddress;
  2537. ulCurrTrackSize = tiCurrTrack.ulBlocksCnt;
  2538. g_pCDDANav->m_aCurrTrack[0]= dwCurrTrackStartAddress;
  2539. g_pCDDANav->m_aCurrTrack[1]= (dwCurrTrackStartAddress + ulCurrTrackSize);
  2540. // Schedule a new Rendezvous-point for the beginning of the next Item (Track)
  2541. g_pCDDANav->m_uRendezvousPoint= (uCurrTrackNumber + 1);
  2542. dbg_printf(("Scheduling a Rendezvous-Point for: %dn", (uCurrTrackNumber + 1)));
  2543. // Update the global information
  2544. SHARED_INFO.uCurrentTrackNumber= uCurrTrackNumber;
  2545. //jeanz_0411_2005 Fix bug :stop randomly when a track is finished in shuffle mode.
  2546. if(PM_IsRepeatSingle()||PM_IsPlaybackProgram(g_PlayModeInfo.iPlaybackMode) || PM_IsPlaybackShuffle(g_PlayModeInfo.iPlaybackMode))
  2547. g_pCDDANav->ucCDDATrackChangeDetectionCounter = CDDA_TRACK_CHANGE_DETECTION_COUNTER_2;
  2548. else
  2549. g_pCDDANav->ucCDDATrackChangeDetectionCounter = CDDA_TRACK_CHANGE_DETECTION_COUNTER_6;
  2550. #ifdef CDTEXT_SUPPORT
  2551. SHARED_INFO.pTrackCDText= (UINT32)PE_CD_GetCDTEXTInfo((BYTE)SHARED_INFO.uCurrentTrackNumber);
  2552. #ifdef _DEBUG
  2553. if (SHARED_INFO.pTrackCDText) {
  2554. dbg_printf(("Track #%d name: %sn", SHARED_INFO.uCurrentTrackNumber, SHARED_INFO.pTrackCDText));
  2555. }
  2556. #endif //_DEBUG
  2557. #endif //CDTEXT_SUPPORT
  2558. }
  2559. (g_pCDDANav->m_CurrPosition).iPlaylistItem++;
  2560. return;
  2561. }
  2562. static void OnModeChange()
  2563. {
  2564. dbg_printf(("OnModeChangen"));
  2565. // Find-out what kind of mode has changed: the Playback-Mode or the Repeat-Mode
  2566. // If the change is not in Playback-Mode, then nothing to do.
  2567. if (g_pCDDANav->m_uCurrPlaybackMode == PM_GetPlaybackMode()) {
  2568. dbg_printf(("No Playback-Mode change detected.n"));
  2569. return;
  2570. }
  2571. // In case of a Playback-Mode change, cancel all current Repeat Modes
  2572. CancelRepeatModes(PM_REPEAT_SINGLE | PM_REPEAT_ALL | PM_REPEAT_AB_MASK);
  2573. core_clear_bookmark_info( 0 ); // clear all bookmarks
  2574. // Detect a transition of type: Non-Shuffle -> Shuffle
  2575. if (! PM_IsPlaybackShuffle(g_pCDDANav->m_uCurrPlaybackMode) && PM_IsPlaybackShuffle(PM_GetPlaybackMode())) {
  2576. dbg_printf(("Non_Shuffle -> Shufflen"));
  2577. // If the current Playback-Status is other than Stopped, shuffle the Program-List while
  2578. // keeping the current item as the first item
  2579. if ( gcs.pstate == PST_STOP && g_in_full_stop == TRUE)
  2580. PM_ShuffleProgramList(FALSE, 0);
  2581. else
  2582. {
  2583. PM_ShuffleProgramList(TRUE, (g_pCDDANav->m_CurrPosition).iPlaylistItem);
  2584. g_pCDDANav->m_ResumePlayback.iPlaylistItem = 1;
  2585. }
  2586. // Now set the Current-Item to Item #1
  2587. (g_pCDDANav->m_CurrPosition).iPlaylistItem= 1;
  2588. g_pCDDANav->m_bPendingModeChange= TRUE;
  2589. }
  2590. // Detect a transition of type: Non-Normal -> Normal
  2591. if (! PM_IsPlaybackNormal(g_pCDDANav->m_uCurrPlaybackMode) && PM_IsPlaybackNormal(PM_GetPlaybackMode())) {
  2592. UINT16 uEntriesCnt;
  2593. WORD uEntry;
  2594. WORD uCurrTrack= (WORD) PM_GetProgramListEntry((g_pCDDANav->m_CurrPosition).iPlaylistItem);
  2595. dbg_printf(("Non_Normal -> Normaln"));
  2596. // Rebuild the Normal Program-List (sequential playback of the Tracks)
  2597. PM_InitializeProgramList();
  2598. //uEntriesCnt= (UINT16)PE_CD_GetTracksCnt();
  2599. uEntriesCnt = (UINT16)g_pCDDANav->m_uLastCDDA_Track;
  2600. // Initialize the Program-List to sequencial playback
  2601. for (uEntry= g_pCDDANav->m_uFirstCDDA_Track; uEntry <= uEntriesCnt; uEntry++)
  2602. PM_SetProgramListEntry((WORD)(uEntry - g_pCDDANav->m_uFirstCDDA_Track + 1), (WORD)uEntry);
  2603. // Now update the Current Item to point at the Entry holding the current-Track,
  2604. // if playback is currently in progress
  2605. if ( gcs.pstate == PST_STOP && g_in_full_stop == TRUE)
  2606. (g_pCDDANav->m_CurrPosition).iPlaylistItem= 1;
  2607. else
  2608. {
  2609. (g_pCDDANav->m_CurrPosition).iPlaylistItem= (uCurrTrack - g_pCDDANav->m_uFirstCDDA_Track + 1);
  2610. g_pCDDANav->m_ResumePlayback.iPlaylistItem = g_pCDDANav->m_CurrPosition.iPlaylistItem;
  2611. }
  2612. }
  2613. // Detect a transition of type: Non-Program -> Program
  2614. if (! PM_IsPlaybackProgram(g_pCDDANav->m_uCurrPlaybackMode) && PM_IsPlaybackProgram(PM_GetPlaybackMode())) {
  2615. dbg_printf(("Non-Program ->Program n"));
  2616. (g_pCDDANav->m_CurrPosition).iPlaylistItem= 1;
  2617. //if (PST_STOP != gcs.pstate) {
  2618. PE_CD_AbortPlayback(TRUE); // Maintain Standby mode
  2619. if(PST_SCAN == gcs.pstate)
  2620. OnScan(0);
  2621. gcs.pstate= PST_PLAY;
  2622. if (! InvokePlayback()) {
  2623. dbg_printf(("Failed to re-invoke playback after playback-mode changen"));
  2624. gcs.pstate= PST_STOP;
  2625. }
  2626. //}
  2627. //ML0703 remove this condition for cdda's program play being set in pst_stop state
  2628. }
  2629. // Update the current Playback-Mode
  2630. g_pCDDANav->m_uCurrPlaybackMode= PM_GetPlaybackMode();
  2631. return;
  2632. }
  2633. /////////////////////////////////////////////////////////////////////////////////////////////////
  2634. // void OnSetMarkerA() -
  2635. // Handles an event of setting the first Marker for an A->B Repeat sequence.
  2636. //
  2637. // Input:
  2638. // None.
  2639. // Output:
  2640. // None.
  2641. //
  2642. // Remarks:
  2643. // The method calls for the setting of the MarkerA Marker.
  2644. static void OnSetMarkerA()
  2645. {
  2646. dbg_printf(("OnSetMarkAn"));
  2647. SetMarker(eMarkerA, 0);
  2648. return;
  2649. }
  2650. /////////////////////////////////////////////////////////////////////////////////////////////////
  2651. // void OnSetMarkerB() -
  2652. // Handles an event of setting the second Marker for an A->B Repeat sequence.
  2653. //
  2654. // Input:
  2655. // None.
  2656. //
  2657. // Output:
  2658. // None.
  2659. //
  2660. // Remarks:
  2661. // The method calls for the setting of the MarkerB Marker, and then it initiates the
  2662. // REPEAT_AB Play-Mode.
  2663. static void OnSetMarkerB()
  2664. {
  2665. dbg_printf(("OnSetMarkB()n"));
  2666. // First, record the current position as MarkerB and stop playback
  2667. SetMarker(eMarkerB, 0);
  2668. // Prohibit an A-B Segment of less than 1 Second
  2669. if (((g_pCDDANav->m_PositionB).dwAddress - (g_pCDDANav->m_PositionA).dwAddress) < 2*CDDA_BLOCKS_PER_SEC)
  2670. {
  2671. // Force a 1 Second gap between Point-A and Point-B
  2672. (g_pCDDANav->m_PositionB).dwAddress= (g_pCDDANav->m_PositionA).dwAddress + 2*CDDA_BLOCKS_PER_SEC;
  2673. }
  2674. // Stop Playback
  2675. PE_CD_AbortPlayback(TRUE); // Maintain Standby mode
  2676. // Move the Current-Position to Point-A
  2677. memcpy(&(g_pCDDANav->m_CurrPosition), &(g_pCDDANav->m_PositionA), sizeof(CDDA_Marker));
  2678. // Invoke A-B Repeat, and start Playback
  2679. PM_SetRepeatAB(PM_REPEAT_AB_B);
  2680. // Schedule a playback using the Markers just set
  2681. if (! InvokePlayback()) {
  2682. dbg_printf(("Error: Failed to invoke playbackn"));
  2683. gcs.pstate= PST_STOP;
  2684. }
  2685. ie_send(IE_UI_STATE_CHANGE);
  2686. return;
  2687. }
  2688. /////////////////////////////////////////////////////////////////////////////////////////////////
  2689. // void OnCancelABRepeat() -
  2690. // Handles an event of cancelling the current REPEAT_AB Play-Mode.
  2691. //
  2692. // Input:
  2693. // None.
  2694. //
  2695. // Output:
  2696. // None.
  2697. //
  2698. // Remarks:
  2699. // The method aborts the current Play-Mode by clearing both MarkerA and MarkerB, and
  2700. // removing the REPEAT_AB Bit from the Play-Mode mask.
  2701. // In addition, the method will re-sechedule a Rendezvous-Point, if needed,
  2702. // in order to assure correct playback of the following items.
  2703. static void OnCancelABRepeat()
  2704. {
  2705. dbg_printf(("OnCancelABRepeat()n"));
  2706. // Clear the current setting of both markers
  2707. ClearMarker(eMarkerA, 0);
  2708. ClearMarker(eMarkerB, 0);
  2709. PM_SetRepeatAB(0);
  2710. ie_send(IE_UI_STATE_CHANGE);
  2711. return;
  2712. }
  2713. /////////////////////////////////////////////////////////////////////////////////////////////////
  2714. // void OnGoToBookmark(WORD uBookmarkNumber) -
  2715. // Handles an event of jumping to a certain point in the disc and starting playback
  2716. // from that point.
  2717. //
  2718. // Input:
  2719. // uBookmarkNumber - The serial number of the Bookmark to use as a destination,
  2720. // assuming that it was previously set during an event.
  2721. //
  2722. // Output:
  2723. // None.
  2724. //
  2725. // Remarks:
  2726. // The method performs a unconditional jump to the point in the Disc that is marked
  2727. // by the requested Bookmark. This Bookmark should have been set earlier, during
  2728. // the handling of an event of type IE_CORE_SETBOOKMARK.
  2729. static void OnGoToBookmark(WORD uBookmarkNumber)
  2730. {
  2731. dbg_printf(("OnGoToBookmark(%d)n", uBookmarkNumber));
  2732. // Cancel pending Mode-Changes
  2733. g_pCDDANav->m_bPendingModeChange= FALSE;
  2734. // Make sure that the requested Bookmark is still valid
  2735. if ((uBookmarkNumber >= CDDA_MAX_BOOKMARKS) ||
  2736. (-1 == (g_pCDDANav->m_Bookmarks[uBookmarkNumber]).iPlaylistItem)) {
  2737. dbg_printf(("Bookmark #%d",(int)uBookmarkNumber));
  2738. dbg_printf((" is invalid. Ignored.n"));
  2739. return;
  2740. }
  2741. // Stop any ongoing playback
  2742. PE_CD_AbortPlayback(TRUE); // Maintain Standby mode
  2743. // Cancel any current Repeat-Modes
  2744. CancelRepeatModes(PM_REPEAT_SINGLE | PM_REPEAT_ALL | PM_REPEAT_AB_MASK);
  2745. g_pCDDANav->m_uRendezvousPoint= 0;
  2746. // Set the Current-Position to hold the selected Bookmark
  2747. memcpy(&(g_pCDDANav->m_CurrPosition), &(g_pCDDANav->m_Bookmarks[uBookmarkNumber]), sizeof(CDDA_Marker));
  2748. if (PST_SCAN == gcs.pstate) {
  2749. // Cancel the on-going Scan
  2750. OnScan(0);
  2751. }
  2752. if (PST_STOP != gcs.pstate) {
  2753. // Cancel pending Mode-Changes
  2754. g_pCDDANav->m_bPendingModeChange= FALSE;
  2755. // Display the Logo
  2756. PE_CD_DisplayLogo();
  2757. }
  2758. gcs.pstate= PST_PLAY;
  2759. if (! InvokePlayback()) {
  2760. dbg_printf(("Failed to playback current listn"));
  2761. gcs.pstate= PST_STOP;
  2762. }
  2763. return;
  2764. }
  2765. static void OnScan(int iSpeed)
  2766. {
  2767. WORD uCurrentTrackNumber;
  2768. ULONG ulBlocksCnt= 0;
  2769. DWORD dwCurrLocation;
  2770. TrackInfo tiCurrTrack;
  2771. dbg_printf(("OnScan(%d)n", iSpeed));
  2772. if ((PST_PLAY != gcs.pstate) && (PST_SCAN != gcs.pstate) && (PST_PAUSE != gcs.pstate)) {
  2773. dbg_printf(("Cannot scan during a stop. Ignoredn"));
  2774. return;
  2775. }
  2776. //CL, avoid driver jump to a unknown area
  2777. if ((iSpeed < 0) && (1 == SI_CDDA_TRACK_NUM) && (0 == SI_CDDA_ELAPSED_TIME))
  2778. return;
  2779. // Record the current Scanning-speed
  2780. g_pCDDANav->m_iScanSpeed= iSpeed;//((iSpeed >= 0) ? iSpeed : (iSpeed - 1));
  2781. if (0 == iSpeed) 
  2782. {
  2783. // Cancel the Scanning
  2784. PE_CD_SetScan(FALSE, g_pCDDANav->m_eCurrAudSID, 0);
  2785. //#ifdef CDDA_MUTE_ON_SCAN
  2786.              if (CdMedia_Macro.bCDDA_MUTE_ON_SCAN)
  2787.              {
  2788.              PE_CD_SetMute(TRUE);
  2789. if (PS_GET_ANALOG_AUDIO_SETTING()!=NO_ANALOG_AUDIO)
  2790.       {
  2791. ;//DEC_EX_MUTEOff();//tecobest gxd 20051028
  2792.        }
  2793.         }
  2794. //#else
  2795. #ifdef CDDTS_MUTE_ON_SCAN)
  2796. if (g_pCDDANav->m_eCurrAudSID == CDDTS_SID)
  2797. // Force Mute, since the Playback is about to be re-invoked
  2798. PE_CD_SetMute(FALSE);
  2799. #endif
  2800. //#endif //CDDA_MUTE_ON_SCAN
  2801. return;
  2802. }
  2803. //#ifdef CDDA_MUTE_ON_SCAN
  2804.        if((CdMedia_Macro.bCDDA_MUTE_ON_SCAN)&&(PST_PAUSE == gcs.pstate))
  2805.        {
  2806. tr_printf(("Mute on Pause to Scann"));
  2807. PE_CD_SetMute(TRUE);
  2808. }
  2809. //#endif
  2810. //ML 042303 
  2811. //For everytime call this function,reset the current position,no matter whether it is already PST_SCAN or not.
  2812. // Record the current position
  2813. dwCurrLocation= PE_CD_GetDecoderCurrentLocationLBN();
  2814. PE_CD_AbortPlayback(TRUE); // Maintain Standby mode
  2815. // Start actual Scanning
  2816. gcs.pstate= PST_SCAN;
  2817. PE_CD_SetScan(TRUE, g_pCDDANav->m_eCurrAudSID, g_pCDDANav->m_iScanSpeed);
  2818. // Extract information on the current Track
  2819. uCurrentTrackNumber= PM_GetProgramListEntry((g_pCDDANav->m_CurrPosition).iPlaylistItem);
  2820. //pCurrTrack= &g_aTrackInfoCache[uCurrentTrackNumber-1];
  2821. Array_getAt(g_hTrackInfoCache, (uCurrentTrackNumber - 1), (BYTE *)&tiCurrTrack);
  2822. // Cancel any pending Rendezvous point (since the Track is going to be scanned
  2823. // until its end).
  2824. g_pCDDANav->m_uRendezvousPoint= 0;
  2825. // Continue playback according to the Scanning-Direction
  2826. if (iSpeed > 0) {
  2827. ulBlocksCnt= ((tiCurrTrack.dwStartAddress + tiCurrTrack.ulBlocksCnt) - dwCurrLocation);
  2828. g_pCDDANav->m_aCurrSegment[0]= dwCurrLocation;
  2829. g_pCDDANav->m_aCurrSegment[1]= (dwCurrLocation + ulBlocksCnt);
  2830. }
  2831. else {
  2832. ulBlocksCnt= (dwCurrLocation - tiCurrTrack.dwStartAddress);
  2833. g_pCDDANav->m_aCurrSegment[0]= tiCurrTrack.dwStartAddress;
  2834. g_pCDDANav->m_aCurrSegment[1]= dwCurrLocation;
  2835. }
  2836. // Record Current-Track information
  2837. g_pCDDANav->m_aCurrTrack[0]= tiCurrTrack.dwStartAddress;
  2838. g_pCDDANav->m_aCurrTrack[1]= (tiCurrTrack.dwStartAddress + tiCurrTrack.ulBlocksCnt);
  2839. // Set-up the Error-Recovery Information
  2840. (g_pCDDANav->m_ErrorRecoveryInfo).uTimeout= CDDA_PB_HANGUP_TIMEOUT;
  2841. (g_pCDDANav->m_ErrorRecoveryInfo).dwParam= dwCurrLocation;
  2842. #ifdef CDDA_ERROR_RECOVERY
  2843. //Leslie_0118_2004_A: Task Force III, implement CDDA Navigator Watchdog
  2844. (g_pCDDANav->m_ErrorRecoveryInfo).ucRetryCount = 0;
  2845. #endif
  2846. if (! PE_CD_PlaySegment(NoVideo, g_pCDDANav->m_eCurrAudSID, g_pCDDANav->m_aCurrSegment[0], ulBlocksCnt,
  2847. eSearch, g_pCDDANav->m_iScanSpeed)) 
  2848. {
  2849. dbg_printf(("Failed to re-invoke playbackn"));
  2850. gcs.pstate= PST_STOP;
  2851. return;
  2852. }
  2853. //#ifdef CDDA_MUTE_ON_SCAN
  2854.              if(CdMedia_Macro.bCDDA_MUTE_ON_SCAN)
  2855.               {
  2856. PE_CD_SetMute(TRUE);
  2857. //DEC_EX_MUTEOn();//tecobest gxd 20051020
  2858.               }
  2859. //#else
  2860. #ifdef CDDTS_MUTE_ON_SCAN)
  2861. if (g_pCDDANav->m_eCurrAudSID == CDDTS_SID)
  2862. // Force Mute, since the Playback is about to be re-invoked
  2863. PE_CD_SetMute(TRUE);
  2864. #endif
  2865. //#endif //CDDA_MUTE_ON_SCAN
  2866. return;
  2867. }
  2868. /////////////////////////////////////////////////////////////////////////////////////////////////
  2869. // void OnNextItem() -
  2870. // Handles an event of selecting the next item in the Play-List.
  2871. //
  2872. // Input:
  2873. // None.
  2874. //
  2875. // Output:
  2876. // None.
  2877. //
  2878. // Remarks:
  2879. // The method jumps to the next item on the Play-List, if the current item is not
  2880. // already the last item on the list.
  2881. static void OnNextItem()
  2882. {
  2883. dbg_printf(("OnNext()n"));
  2884. // Check the current Playback-Status. If in Stop-mode, then resume playback.
  2885. if (PST_STOP == gcs.pstate) {
  2886. // Resume playback from the Item's beginning
  2887. (g_pCDDANav->m_ResumePlayback).dwAddress= -1;
  2888. OnPlay();
  2889. return;
  2890. }
  2891. // Cancel any Scanning
  2892. if (PST_SCAN == gcs.pstate) {
  2893. OnScan(0);
  2894. gcs.pstate= PST_PLAY;
  2895. }
  2896. #ifdef EXINO2
  2897. if (PST_PAUSE == gcs.pstate) {
  2898. gcs.pstate= PST_PLAY; // Cancel pause
  2899. }
  2900. #endif
  2901. // Take care of A-B Repeat
  2902. if (PM_GetRepeatAB() & PM_REPEAT_AB_B) {
  2903. // If the Current Playlist Item contains Position-B, then cancel A-B Repeat (A-B Loop
  2904. // scope has been exceeded).
  2905. if ((g_pCDDANav->m_CurrPosition).iPlaylistItem == (g_pCDDANav->m_PositionB).iPlaylistItem)
  2906. CancelRepeatModes(PM_REPEAT_AB_MASK);
  2907. }
  2908. // Take care of the last Item on the Playlist
  2909. if ((g_pCDDANav->m_CurrPosition).iPlaylistItem == (int)(PM_GetProgramSize() - 1)) 
  2910. {
  2911. #ifdef CDDA_WRAP_AROUND_ON_PROGRAM_EDGES)
  2912. // Set the Current Item to Zero, so that the first Item on the Play-List
  2913. // will be used (i.e. a wrap-around is performed).
  2914. g_pCDDANav->m_CurrPosition.iPlaylistItem= 0;
  2915. #else
  2916. // Wrap-around if Repeat-All is on
  2917. if (PM_IsRepeatAll()) {
  2918. g_pCDDANav->m_CurrPosition.iPlaylistItem= 0;
  2919. }
  2920. else 
  2921. if(PM_IsRepeatSingle())
  2922. {
  2923. ;         //add this though we prohibit skipf at the last track upper already.
  2924. }
  2925. else
  2926. {
  2927. dbg_printf(("Already playing the last item on the playlist. Ignoredn"));
  2928. return;
  2929. }
  2930. #endif //CDDA_WRAP_AROUND_ON_PROGRAM_EDGES
  2931. }
  2932. // Clear the Resume Marker and Rendezvous point
  2933. ClearMarker(eResumePlayback, 0);
  2934. g_pCDDANav->m_uRendezvousPoint= 0;
  2935. // Cancel pending Mode-Changes
  2936. g_pCDDANav->m_bPendingModeChange= FALSE;
  2937. // Select the next Item
  2938. #ifndef EXINO2
  2939. if(!PM_IsRepeatSingle())                       // if repeat track, return to current track start
  2940. #endif
  2941. (g_pCDDANav->m_CurrPosition).iPlaylistItem++;
  2942. if (PST_STOP != gcs.pstate) {
  2943. // Stop the current playback, and re-invoke playback at the next item
  2944. PE_CD_AbortPlayback(TRUE); // Maintain Standby mode
  2945. if (! InvokePlayback()) {
  2946. dbg_printf(("Error: Failed to invoke playbackn"));
  2947. gcs.pstate= PST_STOP;
  2948. }
  2949. }
  2950. return;
  2951. }
  2952. /////////////////////////////////////////////////////////////////////////////////////////////////
  2953. // void OnPreviousItem() -
  2954. // Handles an event of selecting the Previous item in the Play-List.
  2955. //
  2956. // Input:
  2957. // None.
  2958. //
  2959. // Output:
  2960. // None.
  2961. //
  2962. // Remarks:
  2963. // The method jumps to the previous item on the Play-List, if the current item is not
  2964. // already the first item on the list.
  2965. static void OnPreviousItem()
  2966. {
  2967. int iTimeFromTrackStart = 0;
  2968. dbg_printf(("OnPrevious()n"));
  2969. // Check the current Playback-Status. If in Stop-mode, then resume playback.
  2970. if (PST_STOP == gcs.pstate) {
  2971. // Resume playback from the Item's beginning
  2972. (g_pCDDANav->m_ResumePlayback).dwAddress= -1;
  2973. OnPlay();
  2974. return;
  2975. }
  2976. // Cancel any Scanning
  2977. if (PST_SCAN == gcs.pstate) {
  2978. OnScan(0);
  2979. gcs.pstate= PST_PLAY;
  2980. }
  2981. #ifdef EXINO2
  2982.     // Cancelled pause because of forward skip doing. 
  2983. if (PST_PAUSE == gcs.pstate) {
  2984. gcs.pstate= PST_PLAY;
  2985. }
  2986. #endif
  2987. #ifdef CDDA_USE_ABSOLUTE_TIME
  2988. {
  2989. TrackInfo tiCurrTrack;
  2990. PE_CD_GetTrackInfo(gns.cdda.uCurrentTrackNumber, &tiCurrTrack);
  2991. iTimeFromTrackStart = gns.cdda.iCurrentTime - (tiCurrTrack.dwStartAddress / CDDA_BLOCKS_PER_SEC); 
  2992. }
  2993. #else
  2994. iTimeFromTrackStart = gns.cdda.iCurrentTime;
  2995. #endif //CDDA_USE_ABSOLUTE_TIME
  2996. //<<<<<angieh_0324_2004:For Alco,support previous func when play the first track.
  2997. #ifdef SKIP_TO_THE_BEGINING
  2998. if ((iTimeFromTrackStart <= CDDA_SKIP_BACK_THRESHOLD) || (1 == g_pCDDANav->m_CurrPosition.iPlaylistItem))
  2999. #else
  3000. #ifdef D_USE_VARIABLE_FOR_LIB
  3001. if (iTimeFromTrackStart <= cdda_skip_back_threshold)
  3002. #else
  3003. if (iTimeFromTrackStart <= CDDA_SKIP_BACK_THRESHOLD)
  3004. #endif
  3005. #endif
  3006. //angieh_0324_2004>>>>>
  3007. {
  3008. // Take care of the first Item on the Playlist
  3009. if (1 == g_pCDDANav->m_CurrPosition.iPlaylistItem) {
  3010. // Cancel A-B Repeat (if any)
  3011. CancelRepeatModes(PM_REPEAT_AB_MASK);
  3012. #ifdef CDDA_WRAP_AROUND_ON_PROGRAM_EDGES
  3013. // Set the Current Item to one past the Last item on the Play-List (i.e.
  3014. // wrap-around is performed).
  3015. g_pCDDANav->m_CurrPosition.iPlaylistItem= PM_GetProgramSize()-1;
  3016. #else
  3017. g_pCDDANav->m_CurrPosition.iPlaylistItem= 1;
  3018. //dbg_printf(("Currently playing the first item on the Playlist. Ignored.n"));
  3019. //return;      //kz 07092002
  3020. #endif //CDDA_WRAP_AROUND_ON_PROGRAM_EDGES
  3021. }
  3022.       else //kz 07092002
  3023. // Select the previous Item
  3024. #ifdef EXINO2
  3025.        // if current elapsed time is smaller than 4sec, go to the top of the current track.
  3026.        if(/*!PM_IsRepeatSingle() && */SI_CDDA_ELAPSED_TIME < 4 ) // if repeat track, return to current track start
  3027. #else
  3028. if(!PM_IsRepeatSingle())                       // if repeat track, return to current track start
  3029. #endif
  3030. g_pCDDANav->m_CurrPosition.iPlaylistItem--;
  3031. }
  3032. // Take care of A-B Repeat
  3033. if (PM_GetRepeatAB() & PM_REPEAT_AB_B) {
  3034. // If the Previous Playlist Item contains Position-A, then cancel A-B Repeat (A-B Loop
  3035. // scope has been exceeded).
  3036. if ((g_pCDDANav->m_CurrPosition).iPlaylistItem == (g_pCDDANav->m_PositionA).iPlaylistItem)
  3037. CancelRepeatModes(PM_REPEAT_AB_MASK);
  3038. }
  3039. // Clear the Resume Marker and Rendezvous point
  3040. ClearMarker(eResumePlayback, 0);
  3041. g_pCDDANav->m_uRendezvousPoint= 0;
  3042. // Cancel pending Mode-Changes
  3043. g_pCDDANav->m_bPendingModeChange= FALSE;
  3044. if (PST_STOP != gcs.pstate) {
  3045. // Stop the current playback, and re-invoke playback at the next item
  3046. PE_CD_AbortPlayback(TRUE); // Maintain Standby mode
  3047. if (! InvokePlayback()) {
  3048. dbg_printf(("ERROR: Failed to invoke playback.n"));
  3049. gcs.pstate= PST_STOP;
  3050. }
  3051. }
  3052. return;
  3053. }
  3054. /////////////////////////////////////////////////////////////////////////////////////////////////
  3055. // void OnNumericSelection(ULONG ulSelectedTrackNumber) -
  3056. // Handles either a IE_CORE_GOTO_ENTRY or a IE_CORE_MENU_NUMERICAL_SELECTION Event.
  3057. //
  3058. // Input:
  3059. // ulSelectedTrackNumber - Holds the serial number of the Track to play.
  3060. //
  3061. // Output:
  3062. // None.
  3063. //
  3064. // Remarks:
  3065. // The method stops the current playback (if any), and jumps unconditionally to play
  3066. // the selected Program-List Entry.
  3067. // already the first item on the list.
  3068. static void OnNumericSelection(ULONG ulSelectedTrackNumber)
  3069. {
  3070. //WORD uLastTrackNumber= PE_CD_GetTracksCnt();
  3071. WORD uLastTrackNumber= g_pCDDANav->m_uLastCDDA_Track;
  3072. dbg_printf(("OnNumericSelection(%d)n", ulSelectedTrackNumber));
  3073. // Verify that the selected number is legal
  3074. if ((ulSelectedTrackNumber < g_pCDDANav->m_uFirstCDDA_Track) || 
  3075. (ulSelectedTrackNumber > uLastTrackNumber)) 
  3076. {
  3077. dbg_printf(("Illegal Track-number selected. Ignored.n"));
  3078. return;
  3079. }
  3080. if (! PM_IsPlaybackNormal(PM_GetPlaybackMode())) {
  3081. #ifdef bCDDA_PROHIBIT_NUMERIC_SELECTION_FOR_PROGRAM
  3082. dbg_printf(("Numeric-Selection is not allowed for Program or Shuffle. Ignored.n"));
  3083. return;
  3084. #else //CDDA_PROHIBIT_NUMERIC_SELECTION_FOR_PROGRAM
  3085. // Force transition to Normal playback mode
  3086. PM_SetPlaybackMode(PM_PLAYBACK_NORMAL);
  3087. OnModeChange();
  3088. /* NirM 11/07/2001
  3089. WORD uCurrTrackNumber;
  3090. // 
  3091. dbg_printf(("Numeric selection in non-normal playmode.n"));
  3092. PM_InitializeProgramList(0);
  3093. PM_SetPlaybackMode(PM_PLAYBACK_NORMAL);
  3094. for (uCurrTrackNumber= g_pCDDANav->m_uFirstCDDA_Track; uCurrTrackNumber <= ulLastTrack; uCurrTrackNumber++ ) {
  3095. PM_SetProgramListEntry((WORD)(uCurrTrackNumber - g_pCDDANav->m_uFirstCDDA_Track + 1), uCurrTrackNumber);
  3096. }
  3097. */
  3098. #endif //CDDA_PROHIBIT_NUMERIC_SELECTION_FOR_PROGRAM
  3099. }
  3100. PE_CD_AbortPlayback(TRUE); // Maintain Standby mode
  3101. ClearMarker(eResumePlayback, 0);
  3102. // Cancel any current Repeat-Modes
  3103. CancelRepeatModes(PM_REPEAT_SINGLE | PM_REPEAT_ALL | PM_REPEAT_AB_MASK);
  3104. // Cancel any Scanning
  3105. if (PST_SCAN == gcs.pstate)
  3106. OnScan(0);
  3107. // Purge any pending Rendezvous point or Mode-Change
  3108. g_pCDDANav->m_uRendezvousPoint= 0;
  3109. g_pCDDANav->m_bPendingModeChange= FALSE;
  3110. // Set the Current Item to the equivalent of the selected Track (Playback mode is Normal)
  3111. (g_pCDDANav->m_CurrPosition).iPlaylistItem= (int)(ulSelectedTrackNumber - g_pCDDANav->m_uFirstCDDA_Track + 1);
  3112. (g_pCDDANav->m_CurrPosition).dwAddress= -1;
  3113. // Invoke playback of the selected Item
  3114. gcs.pstate= PST_PLAY;
  3115. if (! InvokePlayback()) {
  3116. dbg_printf(("Failed to invoke playback a SelectionList Item.n"));
  3117. gcs.pstate= PST_STOP;
  3118. }
  3119. return;
  3120. }
  3121. //////////////////////////////////////////////////////////////////////////////////
  3122. // Function name : OnGotoTime
  3123. //
  3124. // Purpose : Start playing the disc from a given time value.
  3125. //
  3126. // Input Parameters : 
  3127. // ULONG ulTime - time in seconds from the beginning of the current track
  3128. // or beginning of the disc - depends on whether an absolute
  3129. // time is used or a relative one (the default).
  3130. //
  3131. // Return Value : static void 
  3132. //
  3133. // Description : Calculating the new address and the new item number to play.
  3134. //   In case a relative time is used:
  3135. // - Start address is from the beginning of the current track.
  3136. // - Providing the start address is valid, the new item to 
  3137. // play is the the current play item.
  3138. //   In case an absolute time is used:
  3139. // - Start address is from the beginning of the disc.
  3140. // - The new item to play is found by searching the TOC table 
  3141. // that was initialzed in the constructor.
  3142. //////////////////////////////////////////////////////////////////////////////////
  3143. static void OnGotoTime(ULONG ulTime)
  3144. {
  3145. DWORD dwStartAddress;
  3146. #ifdef CDDA_USE_ABSOLUTE_TIME
  3147. UINT16 uTracksCount, uCurrTrackNumber;
  3148. #endif //CDDA_USE_ABSOLUTE_TIME
  3149. dbg_printf(("OnGotoTime(%ld)n", ulTime));
  3150. #ifdef CDDA_USE_ABSOLUTE_TIME
  3151. //setting the start address from the beginning of the disc
  3152. dwStartAddress = (ulTime * CDDA_BLOCKS_PER_SEC);
  3153. //Make sure that the requested time is within cd bounderies
  3154. if (ulTime > gns.cdda.wTotalPlaybackTime) {
  3155. dbg_printf(("Illegal Time requested.n"));
  3156. return;
  3157. }
  3158. // Rebuild the Normal Program-List (sequential playback of the Tracks)
  3159. PM_InitializeProgramList();
  3160. uTracksCount = (UINT16)g_pCDDANav->m_uLastCDDA_Track;
  3161. // Initialize the Program-List to sequencial playback
  3162. for (uCurrTrackNumber = g_pCDDANav->m_uFirstCDDA_Track; uCurrTrackNumber <= uTracksCount; uCurrTrackNumber++)
  3163. PM_SetProgramListEntry((WORD)(uCurrTrackNumber - g_pCDDANav->m_uFirstCDDA_Track + 1), (WORD)uCurrTrackNumber);
  3164. //setting the current play item according to the address by searching the TOC we
  3165. //created in the constructor
  3166. uCurrTrackNumber = 0;
  3167. while (uCurrTrackNumber <  (uTracksCount - 1))
  3168. {
  3169. TrackInfo tiCurrTrack;
  3170. Array_getAt(g_hTrackInfoCache, (uCurrTrackNumber - 1), (BYTE *)&tiCurrTrack);
  3171. // checking if the start address is within the current track bounderies
  3172. if ((dwStartAddress >= tiCurrTrack.dwStartAddress) &&
  3173. (dwStartAddress <= (tiCurrTrack.dwStartAddress + tiCurrTrack.ulBlocksCnt)))
  3174. {
  3175. (g_pCDDANav->m_CurrPosition).iPlaylistItem = uCurrTrackNumber;
  3176. break;
  3177. }
  3178. uCurrTrackNumber++;
  3179. }
  3180. //in case shuffle mode was on
  3181. if (PM_IsPlaybackShuffle(g_pCDDANav->m_uCurrPlaybackMode))
  3182. {
  3183. //cancle shuffle
  3184. PM_SetPlaybackMode(PM_PLAYBACK_NORMAL);
  3185. //sending the ui an event for state changed
  3186. ie_send(IE_UI_STATE_CHANGE);
  3187. // Update the current Playback-Mode
  3188. g_pCDDANav->m_uCurrPlaybackMode= PM_GetPlaybackMode();
  3189. }
  3190. #else //CDDA_USE_ABSOLUTE_TIME
  3191. //Setting the start address relativly to the current track
  3192. dwStartAddress= (g_pCDDANav->m_aCurrTrack[0] + (ulTime * CDDA_BLOCKS_PER_SEC));
  3193. // Make sure that the requested Time is within the boundaries of the current Track
  3194. if (dwStartAddress > g_pCDDANav->m_aCurrTrack[1]) {
  3195. dbg_printf(("Illegal Time requested.n"));
  3196. core_report_error( IE_UI_REPORT_ERROR, (void *) CDNAV_ERR_PROHIBITED_UOP );
  3197. return;
  3198. }
  3199. //Setting the new item to be the current played item
  3200. //(g_pCDDANav->m_CurrPosition).iPlaylistItem = gns.cdda.uCurrentTrackNumber;
  3201. #endif //CDDA_USE_ABSOLUTE_TIME
  3202. PE_CD_AbortPlayback(TRUE); // Maintain Standby mode
  3203. ClearMarker(eResumePlayback, 0);
  3204. // Cancel any current Repeat-Modes
  3205. CancelRepeatModes(PM_REPEAT_SINGLE | PM_REPEAT_ALL | PM_REPEAT_AB_MASK);
  3206. if (PST_SCAN == gcs.pstate)
  3207. OnScan(0);
  3208. g_pCDDANav->m_uRendezvousPoint= 0;
  3209. g_pCDDANav->m_bPendingModeChange= FALSE;
  3210. (g_pCDDANav->m_CurrPosition).dwAddress= dwStartAddress;
  3211. gcs.pstate= PST_PLAY;
  3212. if (! InvokePlayback()) {
  3213. dbg_printf(("Failed to invoke playback a SelectionList Item.n"));
  3214. gcs.pstate= PST_STOP;
  3215. }
  3216. return;
  3217. }
  3218. #ifdef D_ENABLE_DISC_TIMESEARCH
  3219. /////////////////////////////////////////////////////////////////////////////////////////////////
  3220. // static void OnGotoDiscTime(ULONG ulTime) -
  3221. // Handles an IE_CORE_GOTO_DISC_TIME Event.
  3222. //
  3223. // Input:
  3224. // ulTime - The absolute time, within the Whole Disc, to jump to.
  3225. //
  3226. // Output:
  3227. // None. The playback is resumed from the requested time, if possible.
  3228. //
  3229. // Remarks:
  3230. // None.
  3231. static void OnGotoDiscTime(ULONG ulTime)
  3232. {
  3233. TrackInfo Track;
  3234. DWORD dwStartAddress;
  3235. WORD uCurrTrackNumber= 1, uLastTrack = PE_CD_GetTracksCnt();
  3236. BOOL done = 0;
  3237. dbg_printf(("OnGotoDiscTime(%ld)n", ulTime));
  3238. if (! PE_CD_GetTrackInfo(uCurrTrackNumber, &Track)){
  3239. dbg_printf(("Failed to access the TOC for Track %d.n", (int)uCurrTrackNumber));
  3240. return;
  3241. }
  3242. dwStartAddress = ulTime*CDDA_BLOCKS_PER_SEC + Track.dwStartAddress;
  3243. if ( !PE_CD_GetTrackInfo(uLastTrack, &Track)){
  3244. dbg_printf(("Failed to access the TOC for Track %d.n", (int)uLastTrack));
  3245. return;
  3246. }
  3247. if ( dwStartAddress > ( Track.dwStartAddress + Track.ulBlocksCnt ) ){
  3248. dbg_printf(("Search time is out of lead out area.n"));
  3249. core_report_error( IE_UI_REPORT_ERROR, (void *) CDNAV_ERR_PROHIBITED_UOP );
  3250. return;
  3251. }
  3252. uCurrTrackNumber = 0;
  3253. while( ( uCurrTrackNumber <= uLastTrack ) && ( !done ) ){
  3254. uCurrTrackNumber ++;
  3255. if(!PE_CD_GetTrackInfo(uCurrTrackNumber, &Track)){
  3256. dbg_printf(("Failed to access the TOC for Track %d.n", (int)uCurrTrackNumber));
  3257. return;
  3258. }
  3259. if ( ( dwStartAddress >= Track.dwStartAddress ) && ( dwStartAddress < ( Track.dwStartAddress + Track.ulBlocksCnt ) ) ){
  3260. g_pCDDANav->m_CurrPosition.iPlaylistItem = uCurrTrackNumber;
  3261. g_pCDDANav->m_CurrPosition.dwAddress = dwStartAddress;
  3262. SHARED_INFO.uCurrentTrackNumber = g_pCDDANav->m_CurrPosition.iPlaylistItem;
  3263. done = 1;
  3264. }
  3265. }
  3266. //we must cancel all the playmode and scan, initilaize the playlist
  3267. OnScan(0);
  3268. CancelRepeatModes((PM_REPEAT_SINGLE | PM_REPEAT_ALL | PM_REPEAT_AB_MASK));
  3269. PM_InitializeProgramList();
  3270. PM_SetPlaybackMode(PM_PLAYBACK_NORMAL);
  3271. //<<<MikeX_0917_2003_A: don't add the data track into the program list
  3272. for(uCurrTrackNumber = 1; uCurrTrackNumber <= uLastTrack; uCurrTrackNumber++ ){
  3273. UINT8  uTrackCtrlField;
  3274. UINT32 uDummy;
  3275. if (! PE_CD_GetTrackTOC(uCurrTrackNumber, &uTrackCtrlField, &uDummy, &uDummy)) {
  3276. tr_printf(("FATAL: Failed to collect TOC info for Track #%dn", uCurrTrackNumber));
  3277. continue;
  3278. }
  3279. if ((uTrackCtrlField & 0x0F) != 0x4)
  3280. {
  3281. // This is a CDDA Track - add it to the Program-List
  3282. PM_SetProgramListEntry((WORD)uCurrTrackNumber, (WORD)uCurrTrackNumber);
  3283. g_pCDDANav->m_uLastCDDA_Track = (WORD)uCurrTrackNumber;
  3284. }
  3285. }//MikeX_0917_2003_A>>>
  3286. // Clear all Markers and Bookmarks
  3287. ClearMarker(eResumePlayback, 0);
  3288. ClearMarker(eMarkerA, 0);
  3289. ClearMarker(eMarkerB, 0);
  3290. if ( gcs.pstate != PST_STOP ){
  3291. PE_CD_AbortPlayback(TRUE); // Maintain standby
  3292. }
  3293. if (!InvokePlayback()){
  3294. dbg_printf(("Can't invoke playback for Disc Time Search.n"));
  3295. }
  3296. return;
  3297. }
  3298. #endif
  3299. //////////////////////////////////////////////////////////////////////////////////
  3300. // Function name : CDDA_IsCDDTS
  3301. // Purpose : return if CDDTS was detect   
  3302. // Input Parameters : none     
  3303. // Return Value : g_bIsCDDTS   
  3304. //////////////////////////////////////////////////////////////////////////////////
  3305. BOOL CDDA_IsCDDTS(void)
  3306. {
  3307. if(g_disc_type == DEC_DISC_TYPE_CDDA)
  3308. return g_bIsCDDTS;
  3309. else
  3310. return FALSE;
  3311. }
  3312. //////////////////////////////////////////////////////////////////////////////////
  3313. // Function name : OnIntro
  3314. //
  3315. // Input Parameters : void
  3316. //
  3317. // Return Value : void 
  3318. //
  3319. // Description : Begin to start intro playback or stop it.
  3320. //////////////////////////////////////////////////////////////////////////////////
  3321. void OnIntro(void)
  3322. {
  3323. if (TRUE != SHARED_INFO.bIsCDDAIntroMode)
  3324. {
  3325. dbg_printf(("Cancel Playmode/Repeat moden"));
  3326. PM_SetPlaybackMode(0);
  3327. PM_ClearRepeat();
  3328. OnModeChange();
  3329. SHARED_INFO.bIsCDDAIntroMode = TRUE;
  3330. (g_pCDDANav->m_CurrPosition).iPlaylistItem = 1;
  3331. ClearMarker(eResumePlayback, 0);
  3332. OnPlay();
  3333. }
  3334. return;
  3335. }
  3336. #ifdef _DEBUG
  3337. static void OnStatusReport()
  3338. {
  3339. dbg_printf(("Status Report for CDDA-Navigator:n"));
  3340. dbg_printf(("tTotal number of items on Playlist: %dn", (int)(PM_GetProgramSize()-1)));
  3341. dbg_printf(("tCurrent Playlist item: %dn", (int)(g_pCDDANav->m_CurrPosition).iPlaylistItem));
  3342. return;
  3343. }
  3344. #endif //_DEBUG
  3345. #ifdef EXINO2
  3346. BOOL get_intro_mode(void)
  3347. {
  3348. return SHARED_INFO.bIsCDDAIntroMode;
  3349. }
  3350. // SEC BK.LIM070203>>>
  3351. // <<< SEC BK.LIM070203: porting  from exino code
  3352. BOOL CDDA_Nav_Check_UOP(EVENT Event, void *Param)
  3353. {
  3354. BOOL bIsNextOp = FALSE;
  3355. DWORD dwCurrentLocation = PE_CD_GetCurrentLocation();
  3356. switch(Event){
  3357. case IE_CORE_NEXT_CHAPTER:
  3358. bIsNextOp = TRUE;
  3359. case IE_CORE_PREVIOUS_CHAPTER:
  3360. if ( gcs.pstate == PST_STOP )
  3361. return FALSE;
  3362. if ((( (g_pCDDANav->m_CurrPosition).iPlaylistItem  == ( PM_GetProgramSize() - 1 )) && (bIsNextOp )) ||
  3363. (( (g_pCDDANav->m_CurrPosition).iPlaylistItem == 1 ) && ( !bIsNextOp) && ( (dwCurrentLocation - g_pCDDANav->m_aCurrTrack[0]) <= 225) ) )//ZORAN LX010402
  3364.     if ( !PM_IsPlaybackShuffle(PM_GetPlaybackMode()))  //Added by Billt 081602
  3365.                 return FALSE;  //Added by Billt 081602
  3366. return TRUE;
  3367. default:
  3368. return FALSE;
  3369. }
  3370. }
  3371. // SEC BK.LIM070203>>>
  3372. #endif // EXINO2
  3373. #ifdef EXINO2 // ZKR JK0331 : for power_on_resume in EEPROM
  3374. #ifdef HW_POWER_ON_RESUME
  3375. static WORD GetResumeLeadOutInfo(void)
  3376. {
  3377. WORD wLeadOut;
  3378. if (eeprom_read(CDDA_LeadOut_Info_ADDR, (BYTE *)&wLeadOut, sizeof(WORD) ))
  3379. return wLeadOut;
  3380. else
  3381. tr_printf(("Error on reading Lead Out info from EEPROM when do CDDA power on resume n"));
  3382. //dbg_printf(("Error on reading Lead Out info from EEPROM when do CDDA power on resume n"));
  3383. }
  3384. static void SetResumeLeadOutInfo(void)
  3385. {
  3386. if (eeprom_write (CDDA_LeadOut_Info_ADDR, (BYTE *)&((gns.cdda).wTotalPlaybackTime), sizeof(WORD) ))
  3387. return;
  3388. else
  3389. tr_printf(("Error on writing Lead Out info to EEPROMn"));
  3390. //dbg_printf(("Error on writing Lead Out info to EEPROMn"));
  3391. }
  3392. void ClearResumeLeadOutInfo(void)
  3393. {
  3394. WORD wLeadOut;
  3395. wLeadOut = 0x0000;
  3396. // <<< ZKR GL021302 : Use eeprom_write()
  3397. //if (eeprom_read(CDDA_LeadOut_Info_ADDR, (BYTE *)&wLeadOut, sizeof(WORD) ))
  3398. if (eeprom_write(CDDA_LeadOut_Info_ADDR, (BYTE *)&wLeadOut, sizeof(WORD) ))
  3399. // ZKR GL021302 >>>
  3400. return;
  3401. else
  3402. tr_printf(("Error on cleanning CDDA Lead Out info from EEPROM when eject tray n"));
  3403. //dbg_printf(("Error on cleanning CDDA Lead Out info from EEPROM when eject tray n"));
  3404. }
  3405. void save_CDDA_info(void)
  3406. {
  3407. g_pCDDANav->m_ResumePlayback.iPlaylistItem = SHARED_INFO.uCurrentTrackNumber;
  3408. eeprom_write(PonCDDA, (BYTE *)&g_pCDDANav->m_ResumePlayback, sizeof(CDDA_Marker));
  3409. }
  3410. void restore_CDDA_info(void)
  3411. {
  3412. eeprom_read(PonCDDA, (BYTE *)&g_pCDDANav->m_ResumePlayback, sizeof(CDDA_Marker));
  3413. }
  3414. #endif//HW_POWER_ON_RESUME
  3415. #else //EXINO2
  3416. #ifdef HW_POWER_ON_RESUME
  3417. BOOL CDDANAV_NvmBmk_Match(NVM_GENERIC_BMK* pGenric_bmk)
  3418. {
  3419. if (gns.cdda.wTotalPlaybackTime != pGenric_bmk->marker.cdda.wLeadOut)
  3420. return FALSE;
  3421. return TRUE;
  3422. }
  3423. void CDDANAV_NvmBmk_Set( WORD sc_handle)
  3424. {
  3425. WORD wSCTmp;
  3426. BYTE b_temp;
  3427. int i, offset;
  3428. NVM_GENERIC_BMK* pGenric_bmk;
  3429. offset = (int)&pGenric_bmk->marker.cdda.wLeadOut - (int)pGenric_bmk;
  3430. sc_SetBytes(sc_handle, offset, sizeof(WORD), (BYTE *)&gns.cdda.wTotalPlaybackTime);
  3431. if(gcs.pstate !=PST_STOP) 
  3432. SetMarker(eResumePlayback, 0);
  3433. g_pCDDANav->m_ResumePlayback.iPlaylistItem = SHARED_INFO.uCurrentTrackNumber;
  3434. offset = (int)&pGenric_bmk->marker.cdda.m_ResumePlayback - (int)pGenric_bmk;
  3435. sc_SetBytes(sc_handle, offset, sizeof(CDDA_Marker), (BYTE *)&g_pCDDANav->m_ResumePlayback);
  3436. return;
  3437. }
  3438. void CDDANAV_NvmBmk_Play(NVM_GENERIC_BMK *pGenric_bmk)
  3439. {
  3440. g_pCDDANav->m_ResumePlayback = pGenric_bmk->marker.cdda.m_ResumePlayback;
  3441. return;
  3442. }
  3443. #endif //HW_POWER_ON_RESUME
  3444. #endif //EXINO2
  3445. #ifdef EXINO2
  3446. // Check valid time or not for flt displaying correctly.
  3447. BOOL IS_CDDA_Elapsed_time_valid(void)
  3448. {
  3449. DWORD dwCurrentLocation = PE_CD_GetCurrentLocation();
  3450. return ((dwCurrentLocation >=g_pCDDANav->m_aCurrTrack[0])
  3451. && (dwCurrentLocation <= g_pCDDANav->m_aCurrTrack[1]));
  3452. }
  3453. int get_CDDA_ScanSpeed(void)
  3454. {
  3455. return g_pCDDANav->m_iScanSpeed;
  3456. }
  3457. #endif
  3458.