CLTEXT.CPP
  //========================================================================= 
  // 
  //  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY 
  //  KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE 
  //  IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR 
  //  PURPOSE. 
  // 
  // Copyright (c) 1996 - 1997  Microsoft Corporation.  All Rights Reserved. 
  // 
  //========================================================================= 
 
  #include <windows.h> 
  #include <streams.h> 
  #include <strmif.h> 
  #include <cutlist.h> 
  #include <stdio.h> 
  #include "cltext.h" 
 
  ICutListGraphBuilder  *pCLGraphBuilder  = NULL; 
  IStandardCutList      *pVideoCL         = NULL; 
  IStandardCutList      *pAudioCL         = NULL; 
  IGraphBuilder         *pigb             = NULL; 
  IMediaControl         *pimc             = NULL; 
  IMediaEventEx         *pimex            = NULL; 
  IVideoWindow          *pivw             = NULL; 
  IMediaSeeking         *pims             = NULL; 
 
  IFileClip             *pVidFileClip[MAX_CLIPS]; 
  IFileClip             *pAudFileClip[MAX_CLIPS]; 
  IAMCutListElement       *pVidCLElem[MAX_CLIPS]; 
  IAMCutListElement       *pAudCLElem[MAX_CLIPS]; 
 
  HRESULT hr; 
 
  int nVidElems, nAudElems; 
 
  void CutlistFromTextfile () 
 
    { // CutlistFromTextfile // 
 
      WCHAR wFile[MAX_PATH];  // file name 
 
      // Initialize video and audio file clips and elements to NULL 
      // so we can easily free objects later. 
      for (int x = 0; x < MAX_CLIPS; ++x) 
 
        {  
          pVidFileClip[x] = NULL;  
          pAudFileClip[x] = NULL;  
            pVidCLElem[x] = NULL;  
            pAudCLElem[x] = NULL;  
        }; 
 
      // Create cutlist graph builder object 
      hr = CoCreateInstance(CLSID_CutListGraphBuilder, NULL,  
                            CLSCTX_INPROC, IID_ICutListGraphBuilder,  
                            (void**)&pCLGraphBuilder); 
 
      if (FAILED(hr)) 
        { // CoCreateInstance of CutListGraphBuiler failed 
          MBOX("CoCreateInstance of CutListGraphBuiler failed"); 
          TearDownTheGraph(); 
          return; 
        } // CoCreateInstance of CutListGraphBuiler failed 
 
      // Create simple (standard) cutlist object for video 
      hr = CoCreateInstance(CLSID_SimpleCutList, NULL,  
                            CLSCTX_INPROC, IID_IStandardCutList,  
                            (void**)&pVideoCL); 
      if (FAILED(hr)) 
        { // CoCreateInstance of video CutlistFromTextfile failed 
          MBOX("CoCreateInstance of video CLSID_SimpleCutList failed"); 
          TearDownTheGraph(); 
          return; 
        } // CoCreateInstance of video CLSID_SimpleCutList failed 
 
      // Create simple (standard) cutlist object for audio 
      hr = CoCreateInstance(CLSID_SimpleCutList, NULL,  
                            CLSCTX_INPROC, IID_IStandardCutList,  
                            (void**)&pAudioCL); 
 
      if (FAILED(hr)) 
        { // CoCreateInstance of audio CutlistFromTextfile failed 
          MBOX("CoCreateInstance of audio CLSID_SimpleCutList failed"); 
          TearDownTheGraph(); 
          return; 
        } // CoCreateInstance of audio CutlistFromTextfile failed 
 
      // Create the individual clips and add them to the cutlist 
      nVidElems = nAudElems = 0; 
      for (x = 0; x < gTheSet.nNumClips; ++x) 
 
        { // Individual clips 
 
          MultiByteToWideChar(CP_ACP, 0,  
                              gTheSet.List[x].szFilename,  
                              -1, wFile, MAX_PATH ); 
 
          // Create a video clip object and give it the file and stream  
          // to read from. 
          // SetFileAndStream will fail if we call it from a video clip  
          // object and the clip is not a video clip. 
          hr = CoCreateInstance(CLSID_VideoFileClip, NULL,  
                                CLSCTX_INPROC, IID_IFileClip,  
                                (void**)&pVidFileClip[nVidElems]); 
 
          hr = pVidFileClip[nVidElems]->SetFileAndStream(wFile, 0); 
 
          if (SUCCEEDED(hr)) 
 
            { // Create video cut and add the clip (element) to the cutlist 
 
              hr = pVidFileClip[nVidElems]->CreateCut(&pVidCLElem[nVidElems],  
                      gTheSet.List[x].start*SCALE,  
                      gTheSet.List[x].stop*SCALE,  
                      0,  
                      (gTheSet.List[x].stop-gTheSet.List[x].start)*SCALE,  
                      0); 
 
              if (SUCCEEDED(hr)) 
 
                { // Add the element to the cutlist 
 
                  hr = pVideoCL->AddElement(pVidCLElem[nVidElems], CL_DEFAULT_TIME, CL_DEFAULT_TIME); 
 
                  if (SUCCEEDED(hr)) 
                    ++nVidElems; 
 
                  else 
 
                    { // AddElement failed so release associated objects 
 
                      HELPER_RELEASE(pVidCLElem[nVidElems]); 
                      HELPER_RELEASE(pVidFileClip[nVidElems]); 
                      MBOX("AddElement (video) failed!"); 
 
                    } // AddElement failed so release associated objects 
 
                } // Add the element to the cutlist 
 
              else MBOX("CreateCut (video) failed!"); 
 
            } // Create video cut 
 
          else 
 
            { // Problems creating video stream 
 
              HELPER_RELEASE(pVidFileClip[nVidElems]); 
              MBOX("SetFileAndStream (video) failed!"); 
 
            } // Problems creating video stream 
 
          // Create an audio clip object and give it the file and stream  
          // to read from. 
          // SetFileAndStream will fail if we call it from an audio clip  
          // object and the clip is not an audio clip 
          hr = CoCreateInstance(CLSID_AudioFileClip, NULL,  
                                CLSCTX_INPROC, IID_IFileClip,  
                                (void**)&pAudFileClip[nAudElems]); 
 
          hr = pAudFileClip[nAudElems]->SetFileAndStream(wFile, 0); 
 
          if (SUCCEEDED(hr)) 
 
            { // Create audio cut and add the clip (element) to the cutlist 
 
            hr = pAudFileClip[nAudElems]->CreateCut(&pAudCLElem[nAudElems],  
                      gTheSet.List[x].start*SCALE,  
                      gTheSet.List[x].stop*SCALE,  
                      0,  
                      (gTheSet.List[x].stop-gTheSet.List[x].start)*SCALE,  
                      0); 
 
              if (SUCCEEDED(hr)) 
 
                { // Add the element to the cutlist 
 
                  hr = pAudioCL->AddElement(pAudCLElem[nAudElems], 
                                            CL_DEFAULT_TIME,  
                                            CL_DEFAULT_TIME); 
 
                  if (SUCCEEDED(hr)) 
                    ++nAudElems; 
 
                  else 
 
                    { // AddElement failed so release associated objects 
 
                      HELPER_RELEASE(pAudCLElem[nAudElems]); 
                      HELPER_RELEASE(pAudFileClip[nAudElems]); 
                      MBOX("AddElement (audio) failed!"); 
 
                    } // AddElement failed so release associated objects 
 
                } // Add the element to the cutlist 
 
              else MBOX("CreateCut (audio) failed!"); 
 
            } // Create audio cut 
 
          else 
           
            { // Problems creating audio stream 
 
              HELPER_RELEASE(pAudFileClip[nAudElems]); 
              MBOX("SetFileAndStream (audio) failed!"); 
 
            } // Problems creating audio stream 
 
        } // Individual clips 
 
      // Add the video cutlist to the filter graph 
      hr = pCLGraphBuilder->AddCutList(pVideoCL, NULL); 
 
      if (FAILED(hr)) // AddCutList (video) failed 
          MBOX("AddCutList (video) failed"); 
 
      // Add the audio cutlist to the filter graph 
      hr = pCLGraphBuilder->AddCutList(pAudioCL, NULL); 
 
      if (FAILED(hr)) // AddCutList (audio) failed 
          MBOX("AddCutList (audio) failed"); 
 
      if ((!gTheSet.nNumClips) || (!pVideoCL) && (!pAudioCL)) 
 
        { // Clean up 
 
          TearDownTheGraph(); 
          return; 
 
        } // Clean up 
 
      // Let the filter graph manager construct the the appropriate graph  
      // automatically 
      hr = pCLGraphBuilder->Render(); 
 
      if (FAILED(hr)) 
        { // Problems rendering the graph 
          if (!AMGetErrorText(hr, gszScratch, 2048)) 
            MBOX("Problems rendering the graph!"); 
          else  
            MBOX(gszScratch); 
          TearDownTheGraph(); 
          return; 
        } // Problems rendering the graph 
 
      // Retrieve the filter graph and useful interfaces 
      hr = pCLGraphBuilder->GetFilterGraph(&pigb); 
 
      if (FAILED(hr)) 
        { // Problems retrieving the graph pointer 
          if (!AMGetErrorText(hr, gszScratch, 2048)) 
            MBOX("Problems retrieving the graph pointer!"); 
          else  
            MBOX(gszScratch); 
          TearDownTheGraph(); 
          return; 
        } // Problems retrieving the graph pointer 
 
      // QueryInterface for some basic interfaces 
      pigb->QueryInterface(IID_IMediaControl, (void **)&pimc); 
      pigb->QueryInterface(IID_IMediaEventEx, (void **)&pimex); 
      pigb->QueryInterface(IID_IVideoWindow, (void **)&pivw); 
      pigb->QueryInterface(IID_IMediaSeeking, (void **)&pims); 
 
      // Decrement the ref count on the filter graph 
      pigb->Release(); 
 
      // Prepare to play in the main application window's client area 
 
      RECT rc; 
      GetClientRect(ghApp, &rc); 
      hr = pivw->put_Owner((OAHWND)ghApp); 
      hr = pivw->put_WindowStyle(WS_CHILD|WS_CLIPSIBLINGS); 
      hr = pivw->SetWindowPosition(rc.left, rc.top, rc.right, rc.bottom); 
 
      hr = pims->SetTimeFormat(&TIME_FORMAT_MEDIA_TIME); 
      hr = pims->GetDuration(&glTotalLength); 
 
      SetScrollRange(ghApp, SB_HORZ, 0, 100, TRUE); 
  
      //Ready to rumble... 
      pimc->Run(); 
 
    } // CutlistFromTextfile // 
 
  void TearDownTheGraph (void) 
 
      { // TearDownTheGraph // 
 
        if (gTimerNum) 
          timeKillEvent(gTimerNum); 
 
        if (pimc) 
          pimc->Stop(); 
 
        if (pivw) 
 
          { // Hide the playback window first thing 
 
            pivw->put_Visible(OAFALSE); 
            pivw->put_Owner(NULL); 
 
          } // 
 
        HELPER_RELEASE(pimex); 
        HELPER_RELEASE(pimc); 
        HELPER_RELEASE(pivw); 
        HELPER_RELEASE(pims); 
 
        // Remove the video cutlist from the filter graph to free resources 
        if (pCLGraphBuilder && pVideoCL) 
          pCLGraphBuilder->RemoveCutList(pVideoCL); 
 
        // Remove the audio cutlist from the filter graph to free resources 
        if (pCLGraphBuilder && pAudioCL) 
          pCLGraphBuilder->RemoveCutList(pAudioCL); 
 
        for (int x = 0; x < nAudElems; ++x) 
 
          { // Release audio objects 
 
            HELPER_RELEASE(pAudCLElem[x]); 
            HELPER_RELEASE(pAudFileClip[x]); 
 
          } // Release audio objects 
 
        for (x = 0; x < nVidElems; ++x) 
 
          { // Release video objects 
 
            HELPER_RELEASE(pVidCLElem[x]); 
            HELPER_RELEASE(pVidFileClip[x]); 
 
          } // Release video objects 
 
        HELPER_RELEASE(pVideoCL); 
        HELPER_RELEASE(pAudioCL);       
        HELPER_RELEASE(pCLGraphBuilder); 
 
        gTheSet.nNumClips = 0; 
 
      } // TearDownTheGraph // 
 
  BOOL GetCliplistTxtFilename (LPSTR szName) 
 
    {   // GetCliplistTxtFilename // 
 
        OPENFILENAME ofn; 
 
        ofn.lStructSize       = sizeof(OPENFILENAME); 
        ofn.hwndOwner         = ghApp; 
        ofn.lpstrFilter       = NULL; 
        ofn.lpstrFilter       = "Text Files (clip list) (*.txt)\0*.txt\0\0\0"; 
        ofn.lpstrCustomFilter = NULL; 
        ofn.nFilterIndex      = 1; 
        *szName               = 0; 
        ofn.lpstrFile         = szName; 
        ofn.nMaxFile          = MAX_PATH; 
        ofn.lpstrInitialDir   = NULL; 
        ofn.lpstrTitle        = NULL; 
        ofn.lpstrFileTitle    = NULL; 
        ofn.lpstrDefExt       = "TXT"; 
        ofn.Flags             = OFN_FILEMUSTEXIST | OFN_READONLY | OFN_PATHMUSTEXIST; 
 
        return GetOpenFileName((LPOPENFILENAME)&ofn); 
 
    }   // GetCliplistTxtFilename // 
 
  LRESULT CALLBACK WndMainProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 
 
    { // WndMainProc // 
 
      LONGLONG l; 
 
      switch(message) 
 
        { // Window msgs handling 
 
          case WM_COMMAND: 
 
            switch(wParam) 
 
              {  // Program menu option 
 
                case ID_FILE_EXIT: 
                  if (gTheSet.nNumClips) 
                    TearDownTheGraph(); 
                  PostQuitMessage(0); 
                  break; 
 
                case ID_CUTLIST_PLAY: 
                  l = 0; 
                  hr = pimc->Stop(); 
                  hr = pims->SetPositions(&l, AM_SEEKING_AbsolutePositioning, NULL, AM_SEEKING_NoPositioning); 
                  hr = pimc->Run(); 
                  break; 
 
              }  // Program menu option 
 
            break; 
 
          case WM_HSCROLL: 
 
            if (SB_THUMBPOSITION == LOWORD(wParam)) 
 
              { // Seeking via horiz. scroll 
 
                l = (glTotalLength * (LONGLONG)HIWORD(wParam))/100; 
                pimc->Stop(); 
                hr = pims->SetPositions(&l, AM_SEEKING_AbsolutePositioning, NULL, AM_SEEKING_NoPositioning); 
                pimc->Run(); 
 
              } // Seeking via horiz. scroll 
             
          break; 
 
          case WM_EXITSIZEMOVE: 
 
            RECT rc; 
            GetClientRect(ghApp, &rc); 
            if (pivw) 
              pivw->SetWindowPosition(rc.left, rc.top, rc.right, rc.bottom); 
            break; 
 
          case WM_SIZE: 
            if ((SIZE_RESTORED == wParam) || (SIZE_MAXIMIZED == wParam)) 
              PostMessage(ghApp, WM_EXITSIZEMOVE, 0, 0); 
            break; 
 
          case WM_DESTROY: 
            if (gTheSet.nNumClips) 
              TearDownTheGraph(); 
            PostQuitMessage(0); 
            break; 
 
          default: 
            return DefWindowProc(hWnd, message, wParam, lParam); 
           
        } // Window msgs handling 
 
      return FALSE; 
 
      }  // WndMainProc // 
 
  void ReadTextFile (LPCSTR cFilename) 
 
    { // ReadTextFile // 
 
      FILE  *fp; 
      TCHAR cString[MAX_PATH]; 
 
      if (!(fp = fopen(cFilename, "rt"))) 
        return; // File not found! 
 
      while (!feof(fp) && (gTheSet.nNumClips < MAX_CLIPS)) 
 
        { // Parse individual lines 
 
          ZeroMemory(cString, MAX_PATH); 
          fgets(cString, MAX_PATH, fp); 
 
          if (lstrlen(cString) && (cString[0] != TCHAR(';'))) 
 
            { // Decipher filename, start, stop times 
 
              int i = lstrlen(cString); 
 
              while (i && (cString[i] != TCHAR(','))) --i; 
              gTheSet.List[gTheSet.nNumClips].stop = atol(&cString[i+1]); --i; 
              while (i && (cString[i] != TCHAR(','))) --i; 
              gTheSet.List[gTheSet.nNumClips].start = atol(&cString[i+1]); 
              cString[i] = TCHAR('\0'); 
              lstrcpy(gTheSet.List[gTheSet.nNumClips].szFilename, cString); 
              gTheSet.nNumClips += 1; 
 
            } // Deciphering 
 
        } // Parse individual lines 
 
      fclose(fp); 
 
    } // ReadTextFile // 
 
  void CALLBACK TimerProc (UINT uID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2) 
   
    { // TimerProc // 
 
      LONGLONG lPos; 
 
      if (pims) 
        pims->GetCurrentPosition(&lPos); 
      lPos = (lPos * 100)/glTotalLength; 
      SetScrollPos(ghApp, SB_HORZ, (int)lPos, TRUE); 
 
    } // TimerProc // 
 
  int PASCAL WinMain(HINSTANCE hInstC, HINSTANCE hInstP, LPSTR lpCmdLine, int nCmdShow) 
 
    { // WinMain // 
   
      MSG msg; 
      WNDCLASS wc; 
 
      // OLE subsystem requires applications to initialize things first! 
      CoInitialize(NULL); 
 
      ZeroMemory(&wc, sizeof wc); 
      wc.lpfnWndProc = WndMainProc; 
      ghInst = wc.hInstance = hInstC; 
      wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); 
      wc.lpszClassName = CLASSNAME; 
      wc.hCursor = LoadCursor(NULL, IDC_ARROW); 
      wc.hIcon = LoadIcon(hInstC, MAKEINTRESOURCE(IDI_CUTLIST)); 
      RegisterClass(&wc); 
 
      RECT rc; 
 
      GetWindowRect(GetDesktopWindow(), &rc); 
      rc.right >>= 1; 
      rc.bottom >>= 1; 
 
      ghApp = CreateWindow(CLASSNAME, 
      APPLICATIONNAME, 
      WS_OVERLAPPEDWINDOW|WS_HSCROLL, 
      rc.right-200, 
      rc.bottom-200, 
      400, 
      400, 
      0, 
      0, 
      ghInst, 
      0); 
       
      SetMenu(ghApp, ghMenu = LoadMenu(hInstC, MAKEINTRESOURCE(IDR_MENU1))); 
 
      ShowWindow(ghApp, SW_NORMAL); 
      UpdateWindow(ghApp); 
 
      ZeroMemory(&gTheSet, sizeof gTheSet); 
 
      // Text-file 
 
      TCHAR szFilename[MAX_PATH]; 
 
      if (lstrlen(lpCmdLine)) 
        ReadTextFile(lpCmdLine); 
      else 
        if (GetCliplistTxtFilename(szFilename)) 
          ReadTextFile(szFilename); 
        else 
          return FALSE; 
 
      if (gTheSet.nNumClips) 
        CutlistFromTextfile(); 
 
      // Establish a callback-based tracking timer 
      gTimerNum = 0; 
      if (nVidElems || nAudElems) 
        gTimerNum = timeSetEvent(125, 0, TimerProc, 0, TIME_PERIODIC); 
 
      while (GetMessage(&msg,NULL,0,0)) 
 
      {  // Message loop 
 
         TranslateMessage(&msg); 
         DispatchMessage(&msg); 
 
      }  // Message loop 
 
      DestroyMenu(ghMenu); 
 
      // Finished with OLE subsystem 
      CoUninitialize(); 
 
      return msg.wParam; 
 
  } // WinMain //