DirectShow DirectShow 튜토리얼 시크 바의 처리   [목차열람] [주소복사] [슬롯비우기]
시크 바의 처리
 
Microsoft DirectX 9.0

시크 바의 처리

여기에서는, 미디어 player 애플리케이션에 시크 바를 처리 하는 방법을 설명한다. 시크 바는 트랙 바 컨트롤로서 처리 된다. DirectShow 에서의 시크의 개요에 대해서는, 「필터 그래프의 시크」를 참조할것.

애플리케이션의 기동시에, 트랙 바를 초기화한다.

void InitSlider(HWND hwnd) 
{
   // 트랙 바의 범위를 초기화하지만, 사용자가 파일을
    // 열 때까지 컨트롤을 무효로 한다.
    hScroll = GetDlgItem(hwnd, IDC_SLIDER1);
    EnableWindow(hScroll, FALSE);
    SendMessage(hScroll, TBM_SETRANGE, TRUE, MAKELONG(0, 100));
}

트랙 바는, 사용자가 미디어 파일을 열 때까지 무효이다. 트랙 바의 범위는 0 에서 100 이 된다. 파일의 재생중에, 애플리케이션은 재생 위치를 파일의 시간폭에 대한 퍼센티지로서 계산해, 거기에 응해 트랙 바를 업데이트 한다. 예를 들어, 트랙 바의 위치 "50" 은 항상 파일의 중앙에 상당한다.

사용자가 파일을 열 때,RenderFile 를 사용해 파일 재생 그래프를 생성 한다. 이 그래프 생성에 대응하는 코드는, 「파일의 재생법」으로 나타나고 있다. 다음에, 필터 그래프 매니저에 IMediaSeeking 인터페이스의 유무를 문의해 인터페이스 포인터를 저장 한다.

IMediaSeeking *g_pSeek = 0;
hr = pGraph->QueryInterface(IID_IMediaSeeking, (void**) &g_pSeek);

파일이 시크 가능한가 어떤가를 판단하려면 ,IMediaSeeking::CheckCapabilities 메서드 또는 IMediaSeeking::GetCapabilities 메서드를 호출한다. 이러한 메서드는 거의 같은 처리를 하지만, 의미들이 약간 다르다. 다음의 예에서는,CheckCapabilites 를 사용한다.

// 소스가 시크 가능한가 어떤가를 조사한다.
BOOL  bCanSeek = FALSE;
DWORD caps = AM_SEEKING_CanSeekAbsolute | AM_SEEKING_CanGetDuration; 
bCanSeek = (S_OK == pSeek->CheckCapabilities(&caps));
if (bCanSeek)
{
    // 트랙 바를 유효하게 한다.
    EnableWindow(hScroll, TRUE);

    // 파일의 시간폭을 얻어온다.
    pSeek->GetDuration(&g_rtTotalTime);
}

AM_SEEKING_CanSeekAbsolute 플래그로 소스 파일이 시크 가능한가 어떤가를 조사해 AM_SEEKING_CanGetDuration 플래그로 파일의 시간폭을 선행해 확인할 수 있을지 어떨지를 조사하고 있다. 양쪽 모두의 능력이 지원 되고 있는 경우, 애플리케이션은 트랙 바를 유효하게 해, 파일의 시간폭을 얻어온다.

그래프가 시크 가능한 경우, 애플리케이션은 재생중에 타이머를 사용해 트랙 바의 위치를 업데이트 한다. 필터 그래프를 실행해 파일을 재생하는 경우는,SetTimer 등의 Windows 타이머 함수를 1 개 호출해 바다거북 겨이삭띠를 시작 한다. 타이머의 더 자세한 정보는, Platform SDK 의 「Timers」를 참조할것.

void StartPlayback(HWND hwnd) 
{
    pControl->Run();
    if (bCanSeek)
    {
        StopTimer(); // 낡은 타이머가 아직 액티브하게 안 되게 한다.
        nTimerID = SetTimer(hwnd, IDT_TIMER1, TICK_FREQ, (TIMERPROC) NULL);
        if (nTimerID == 0)
        {
            /* 에러 처리.  */
        }
    }
}

void StopTimer() 
{
    if (wTimerID != 0)
    {
        KillTimer(g_hwnd, wTimerID);
        wTimerID = 0;
    }
}

바다거북 겨이삭띠를 사용해 트랙 바의 위치를 업데이트 한다. IMediaSeeking::GetCurrentPosition 를 호출해, 현재의 재생 위치를 취득해, 그 위치를 파일의 시간폭에 대한 퍼센티지로서 계산한다.

case WM_TIMER:
    if (wParam == IDT_TIMER1)
    {
        // 실제로 시크 할 수 없는 한, 타이머는 실행하지 않는다.
        ASSERT(bCanSeek == TRUE);

        REFERENCE_TIME timeNow;
        if (SUCCEEDED(pSeek->GetCurrentPosition(&timeNow)))
        {
            long sliderTick = (long)((timeNow * 100) / g_rtTotalTime);
            SendMessage( hScroll, TBM_SETPOS, TRUE, sliderTick );
        }
    }
    break;

사용자는, 트랙 바를 이동해 파일을 시크 하는 일도 가능하다. 사용자가 트랙 바 컨트롤을 드러그 또는 클릭 하면, 애플리케이션은 WM_HSCROLL 이벤트를 받는다. wParam 파라미터의 하위 워드는, 트랙 바 통지 메시지이다. 예를 들어, 트랙 바 액션의 종료시에는 TB_ENDTRACK 가 송신되어 사용자가 트랙 바를 드러그중은 계속적으로 TB_THUMBTRACK 가 송신된다. 다음 코드는, WM_HSCROLL 메시지를 처리하는 방법의 1 개를 나타내고 있다.

static OAFilterState state;
static BOOL bStartOfScroll = TRUE;

case WM_HSCROLL:
    short int userReq = LOWORD(wParam);
    if (userReq == TB_ENDTRACK || userReq == TB_THUMBTRACK)
    {
        DWORD dwPosition  = SendMessage(hTrackbar, TBM_GETPOS, 0, 0);
        // 스크롤 액션이 시작되면 포즈 한다.
        if (bStartOfScroll) 
        {
            pControl->GetState(10, &state);
            bStartOfScroll = FALSE;
            pControl->Pause();
        }
        // 위치를 계속해 갱신한다.
        REFERENCE_TIME newTime = (g_rtTotalTime/100) * dwPosition;
        pSeek->SetPositions(&newTime, AM_SEEKING_AbsolutePositioning,
            NULL, AM_SEEKING_NoPositioning);

        // 마지막에 상태를 복원한다.
        if (userReq == TB_ENDTRACK)
        {
            if (state == State_Stopped)
                pControl->Stop();
            else if (state == State_Running) 
                pControl->Run();
            bStartOfScroll = TRUE;
        }
    }
}

사용자가 트랙 바를 드러그 하면, 애플리케이션은 TB_THUMBTRACK 메시지를 받아들여, 받은 각 메시지에 대해서 1 개씩, 시크 커멘드를 발행한다. 시크 조작을 할 수 있는 한 쾌적하게 실행하기 위해서, 애플리케이션은 그래프를 포즈 한다. 그래프를 포즈 상태로 하면 재생이 정지하지만, 비디오 윈도우는 확실히 업데이트 된다. 애플리케이션은, TB_ENDTRACK 메시지를 받아들이면 그래프를 원 상태에 복원한다.

↑TOP