www.pudn.com > mediator15src.zip > mediator.cpp


/* 
 * mediator.cpp 
 * Copyright (C) 2001-2002 Arno Hornberger  
 * 
 * This file is part of MPEG Mediator, a free MPEG stream converter. 
 * 
 * MPEG Mediator is free software; you can redistribute it and/or modify 
 * it under the terms of the GNU General Public License as published by 
 * the Free Software Foundation; either version 2 of the License, or 
 * (at your option) any later version. 
 * 
 * MPEG Mediator is distributed in the hope that it will be useful, 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 * GNU General Public License for more details. 
 * 
 * You should have received a copy of the GNU General Public License 
 * along with this program; if not, write to the Free Software 
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
 */ 
 
#include  
#include  
#include  
#include  
#include  
#include  
#include  
 
#include "resource.h" 
 
#include "mpegstream.h" 
#include "except.h" 
#include "output.h" 
#include "progress.h" 
 
#define WM_DONE (WM_USER + 0) 
 
#define IDC_TRACKBAR 50000 
#define IDM_AC3_0    50100 
#define IDM_AC3_7    50107 
#define IDM_MPA_0    50108 
#define IDM_MPA_1F   50139 
#define IDM_LPCM_0   50140 
#define IDM_LPCM_7   50147 
 
#define IDM_NOAUDIO  50150 
 
#define IDM_PLUGIN_0 50156 
#define IDM_PLUGIN_F 50171 
 
#define TRACKBAR_HEIGHT 27 
#define INIT_WIDTH      600 
#define INIT_HEIGHT     400 
 
extern bool mmx_available(); 
extern VOID ConverterThread(PVOID pvoid); 
extern VOID AudioExtractionThread(PVOID pvoid); 
 
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); 
BOOL CALLBACK PropertiesDlgProc(HWND, UINT, WPARAM, LPARAM); 
BOOL CALLBACK AboutDlgProc(HWND, UINT, WPARAM, LPARAM); 
BOOL CALLBACK FramesDlgProc(HWND, UINT, WPARAM, LPARAM); 
BOOL CALLBACK OpenDlgProc(HWND, UINT, WPARAM, LPARAM); 
BOOL CALLBACK ProgressDlgProc(HWND, UINT, WPARAM, LPARAM); 
BOOL CALLBACK AudioProgressDlgProc(HWND, UINT, WPARAM, LPARAM); 
 
void UpdateMenu(); 
void AdjustWindow(); 
void UpdateTrackbarState(); 
void UncheckAudioTracks(); 
void AddPluginsToMenu(); 
void UncheckPlugins(); 
int PopFileSaveDlg(char *filename, char *defextension); 
 
HBITMAP CreateBitmapObjectFromDibFile(HDC hdc, PTSTR szFileName); 
 
HWND hMainWnd; 
HWND hProgressDlg; 
HWND hAudioProgressDlg; 
HINSTANCE hInstance; 
HBITMAP hWallpaper; 
VideoFrame frame_buffer; 
 
Progress progress; 
 
extern Plugins plugins; 
extern compStdParms stdParms; 
 
MPEGStream stream;      // main application object 
char outfilename[256]; 
char audiofilename[256]; 
int total_frames;       // frames to convert 
bool exportyv12; 
bool allframes; 
 
void ReportProblem(HWND hWnd, const char *component, const char *problem) 
{ 
  char szMessage[200]; 
 
  if (component) { 
    sprintf(szMessage, "Component '%s' reports the following problem:\n%s", 
            component, problem); 
    MessageBox(hWnd, szMessage, "MPEG Mediator", MB_ICONEXCLAMATION); 
  } 
  else 
    MessageBox(hWnd, problem, "MPEG Mediator", MB_ICONEXCLAMATION); 
} 
 
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInstance, 
                   PSTR szCmdLine, int iCmdShow) 
{ 
  MSG msg; 
  WNDCLASS wndclass; 
  char *szAppName = "MPEG Mediator"; 
  HDC hdc; 
  HACCEL hAccel; 
 
  if (!mmx_available()) { 
    ReportProblem(NULL, 0, "This program requires an MMX-enhanced CPU."); 
    return 0; 
  } 
 
  hInstance = hInst; 
  wndclass.style = CS_HREDRAW | CS_VREDRAW; 
  wndclass.lpfnWndProc = WndProc; 
  wndclass.cbClsExtra = 0; 
  wndclass.cbWndExtra = 0; 
  wndclass.hInstance = hInstance; 
  wndclass.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON)); 
  wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); 
  wndclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); 
  wndclass.lpszMenuName = MAKEINTRESOURCE(IDR_MAINMENU); 
  wndclass.lpszClassName = szAppName; 
 
  if (!RegisterClass(&wndclass)) 
  { 
    MessageBox(NULL, TEXT("This program needs Windows NT or higher."), 
               szAppName, MB_ICONERROR); 
    return 0; 
  } 
 
  hMainWnd = CreateWindow(szAppName, TEXT("MPEG Mediator"), 
    WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, 
    CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 
    NULL, NULL, hInstance, NULL); 
 
  CreateWindow(TRACKBAR_CLASS, NULL, 
    WS_CHILD | WS_VISIBLE | WS_DISABLED | TBS_NOTICKS | TBS_BOTH, 
    0, 100, 300, TRACKBAR_HEIGHT, hMainWnd, (HMENU)IDC_TRACKBAR, 
    hInstance, NULL); 
 
  AdjustWindow(); 
  AddPluginsToMenu(); 
 
  ShowWindow(hMainWnd, iCmdShow); 
 
  hdc = GetDC(hMainWnd); 
  hWallpaper = CreateBitmapObjectFromDibFile(hdc, "wallpaper.bmp"); 
  ReleaseDC(hMainWnd, hdc); 
 
  UpdateWindow(hMainWnd); 
 
  hAccel = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDR_ACCELERATOR1)); 
   
  while (GetMessage(&msg, NULL, 0, 0)) 
  { 
    if ((hProgressDlg == 0 || !IsDialogMessage(hProgressDlg, &msg)) && 
        (hAudioProgressDlg == 0 || !IsDialogMessage(hAudioProgressDlg, &msg)) ) 
    { 
      if (!TranslateAccelerator(hMainWnd, hAccel, &msg)) 
      {       
        TranslateMessage(&msg); 
        DispatchMessage(&msg); 
      } 
    } 
  } 
 
  if (hWallpaper) 
    DeleteObject(hWallpaper); 
 
  return msg.wParam; 
} 
 
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 
{ 
  BITMAP bitmap; 
  FILE *file; 
  static BITMAPINFO bmi; 
  HMENU hMenu; 
  PAINTSTRUCT ps; 
  static int cxClient, cyClient; 
  int i, j; 
  char sztemp[80]; 
 
  switch (message) 
  { 
    case WM_CREATE: 
      LoadPlugins(); 
      outfilename[0] = 0; 
      audiofilename[0] = 0; 
			exportyv12 = false; 
      return 0; 
    case WM_COMMAND: 
      switch (LOWORD(wParam)) 
      { 
        case IDM_OPEN: 
          if (DialogBox(hInstance, MAKEINTRESOURCE(IDD_OPEN), hwnd, OpenDlgProc)) 
          { 
            UpdateMenu(); 
            AdjustWindow(); 
            UpdateTrackbarState(); 
            InvalidateRect(hwnd, NULL, TRUE); 
          } 
          return 0; 
        case IDM_CLOSE: 
          if (stream.IsOpen()) 
          { 
            stream.Close(); 
            UpdateMenu(); 
            AdjustWindow(); 
            UpdateTrackbarState(); 
            InvalidateRect(hwnd, NULL, TRUE); 
          } 
          return 0; 
        case IDM_PROPERTIES: 
          DialogBox(hInstance, MAKEINTRESOURCE(IDD_PROPERTIES), 
                        hwnd, PropertiesDlgProc); 
          return 0; 
        case IDM_EXIT: 
          if (stream.IsOpen()) 
            stream.Close(); 
          DestroyWindow(hMainWnd); 
          return 0; 
        case IDM_EXPORTYV12: 
          exportyv12 = !exportyv12; 
 
          hMenu = GetMenu(hMainWnd); 
          CheckMenuItem(hMenu, IDM_EXPORTYV12, exportyv12 ? MF_CHECKED : MF_UNCHECKED); 
          return 0; 
        case IDM_PLUGINS_CONFIGURE: 
          compGetFilePrefsRec fileprefs; 
 
          fileprefs.compilerPrefs = plugins.plugins[plugins.current].compilerPrefs; 
          plugins.plugins[plugins.current].CompileEntry(compGetFilePrefs, &stdParms, (long)&fileprefs, 0); 
          plugins.plugins[plugins.current].compilerPrefs = fileprefs.compilerPrefs; 
 
          return 0; 
        case IDM_PLUGINS_SETOUTPUTFILE: 
          PopFileSaveDlg(outfilename, 0); 
          return 0; 
				case IDM_NOAUDIO: 
          hMenu = GetMenu(hMainWnd); 
					stream.SelectAudioTrack(MPEGStream::AUDIO_NONE, 0); 
          UncheckAudioTracks(); 
          CheckMenuItem(hMenu, LOWORD(wParam), MF_CHECKED); 
					EnableMenuItem(hMenu, IDM_EXTRACTAUDIO, MF_GRAYED); 
					return 0; 
				case IDM_ASPECTRATIO_11: 
        case IDM_ASPECTRATIO_43: 
        case IDM_ASPECTRATIO_169: 
        case IDM_ASPECTRATIO_2211: 
          { 
            PostProcess::Config *cfg = stream.GetPostProcessor()->GetConfig(); 
             
            hMenu = GetMenu(hMainWnd); 
            CheckMenuItem(hMenu, IDM_ASPECTRATIO_11, MF_UNCHECKED); 
            CheckMenuItem(hMenu, IDM_ASPECTRATIO_43, MF_UNCHECKED); 
            CheckMenuItem(hMenu, IDM_ASPECTRATIO_169, MF_UNCHECKED); 
            CheckMenuItem(hMenu, IDM_ASPECTRATIO_2211, MF_UNCHECKED); 
            CheckMenuItem(hMenu, LOWORD(wParam), MF_CHECKED); 
           
            cfg->Reset(LOWORD(wParam) - IDM_ASPECTRATIO_11 + 1); 
 
						stream.AdjustFrameDimensions(&frame_buffer); 
						stream.GetFrame(&frame_buffer, true); 
 
            AdjustWindow(); 
            InvalidateRect(hwnd, NULL, TRUE); 
            return 0; 
          } 
        case IDM_RESIZE_DECWIDTH: 
          { 
            PostProcess::Config *cfg = stream.GetPostProcessor()->GetConfig(); 
             
            cfg->DecreaseResizeWidth(); 
 
						stream.GetFrame(&frame_buffer, true); 
            InvalidateRect(hwnd, NULL, TRUE); 
            return 0; 
          } 
        case IDM_RESIZE_INCWIDTH: 
          { 
            PostProcess::Config *cfg = stream.GetPostProcessor()->GetConfig(); 
             
            cfg->IncreaseResizeWidth(); 
 
						stream.GetFrame(&frame_buffer, true); 
            InvalidateRect(hwnd, NULL, TRUE); 
            return 0; 
          } 
        case IDM_RESIZE_DECHEIGHT: 
          { 
            PostProcess::Config *cfg = stream.GetPostProcessor()->GetConfig(); 
             
            cfg->DecreaseResizeHeight(); 
 
						stream.GetFrame(&frame_buffer, true); 
            InvalidateRect(hwnd, NULL, TRUE); 
            return 0; 
          } 
        case IDM_RESIZE_INCHEIGHT: 
          { 
            PostProcess::Config *cfg = stream.GetPostProcessor()->GetConfig(); 
             
            cfg->IncreaseResizeHeight(); 
 
						stream.GetFrame(&frame_buffer, true); 
            InvalidateRect(hwnd, NULL, TRUE); 
            return 0; 
          } 
        case IDM_RESIZE_LOCKRATIO: 
          { 
            PostProcess::Config *cfg = stream.GetPostProcessor()->GetConfig(); 
 
            CheckMenuItem(GetMenu(hMainWnd), IDM_RESIZE_LOCKRATIO, 
              cfg->ToggleAspectRatioLock() ? MF_CHECKED : MF_UNCHECKED); 
 
						stream.GetFrame(&frame_buffer, true); 
            InvalidateRect(hwnd, NULL, TRUE); 
            return 0; 
          } 
        case IDM_CROP_DECWIDTH: 
          { 
            PostProcess::Config *cfg = stream.GetPostProcessor()->GetConfig(); 
             
            cfg->DecreaseCropWidth(); 
 
						stream.AdjustFrameDimensions(&frame_buffer); 
						stream.GetFrame(&frame_buffer, true); 
            AdjustWindow(); 
            InvalidateRect(hwnd, NULL, TRUE); 
 
            sprintf(sztemp, "MPEG Mediator [%d x %d]", cfg->GetCropWidth(), cfg->GetCropHeight());  
            SetWindowText(hwnd, sztemp);  
            KillTimer(hwnd, 1); 
            SetTimer(hwnd, 1, 2000, 0); 
            return 0; 
          } 
        case IDM_CROP_INCWIDTH: 
          { 
            PostProcess::Config *cfg = stream.GetPostProcessor()->GetConfig(); 
             
            cfg->IncreaseCropWidth(); 
 
						stream.AdjustFrameDimensions(&frame_buffer); 
						stream.GetFrame(&frame_buffer, true); 
            AdjustWindow(); 
            InvalidateRect(hwnd, NULL, TRUE); 
 
            sprintf(sztemp, "MPEG Mediator [%d x %d]", cfg->GetCropWidth(), cfg->GetCropHeight());  
            SetWindowText(hwnd, sztemp);  
            KillTimer(hwnd, 1); 
            SetTimer(hwnd, 1, 2000, 0); 
            return 0; 
          } 
        case IDM_CROP_DECHEIGHT: 
          { 
            PostProcess::Config *cfg = stream.GetPostProcessor()->GetConfig(); 
             
            cfg->DecreaseCropHeight(); 
 
						stream.AdjustFrameDimensions(&frame_buffer); 
						stream.GetFrame(&frame_buffer, true); 
            AdjustWindow(); 
            InvalidateRect(hwnd, NULL, TRUE); 
 
            sprintf(sztemp, "MPEG Mediator [%d x %d]", cfg->GetCropWidth(), cfg->GetCropHeight());  
            SetWindowText(hwnd, sztemp);  
            KillTimer(hwnd, 1); 
            SetTimer(hwnd, 1, 2000, 0); 
            return 0; 
          } 
        case IDM_CROP_INCHEIGHT: 
          { 
            PostProcess::Config *cfg = stream.GetPostProcessor()->GetConfig(); 
             
            cfg->IncreaseCropHeight(); 
 
						stream.AdjustFrameDimensions(&frame_buffer); 
						stream.GetFrame(&frame_buffer, true); 
            AdjustWindow(); 
            InvalidateRect(hwnd, NULL, TRUE); 
 
            sprintf(sztemp, "MPEG Mediator [%d x %d]", cfg->GetCropWidth(), cfg->GetCropHeight());  
            SetWindowText(hwnd, sztemp);  
            KillTimer(hwnd, 1); 
            SetTimer(hwnd, 1, 2000, 0); 
            return 0; 
          } 
        case IDM_DEINTERLACING_AUTO: 
        case IDM_DEINTERLACING_ON: 
        case IDM_DEINTERLACING_OFF: 
          stream.SetDeinterlacing(LOWORD(wParam) - IDM_DEINTERLACING_AUTO); 
 
          hMenu = GetMenu(hMainWnd); 
          CheckMenuItem(hMenu, IDM_DEINTERLACING_AUTO, MF_UNCHECKED); 
          CheckMenuItem(hMenu, IDM_DEINTERLACING_ON, MF_UNCHECKED); 
          CheckMenuItem(hMenu, IDM_DEINTERLACING_OFF, MF_UNCHECKED); 
          CheckMenuItem(hMenu, LOWORD(wParam), MF_CHECKED); 
 
          if (stream.IsOpen()) 
          { 
						stream.GetFrame(&frame_buffer, true); 
            InvalidateRect(hwnd, NULL, TRUE); 
          } 
          return 0; 
        case IDM_INVERSETELECINE: 
          hMenu = GetMenu(hMainWnd); 
					stream.SetIVTC(!stream.GetIVTC()); 
          CheckMenuItem(hMenu, IDM_INVERSETELECINE, stream.GetIVTC() ? MF_CHECKED : MF_UNCHECKED); 
					return 0; 
				case IDM_STARTCONVERSION: 
				case IDM_CONVERTNFRAMES: 
          if (strlen(outfilename) == 0) { 
            ReportProblem(NULL, 0, "No output file selected"); 
            return 0; 
          } 
 
          if ((plugins.plugins[plugins.current].inforec.fileType == 'LSVA') ||  
							(LOWORD(wParam) == IDM_CONVERTNFRAMES)) 
          { 
            if (DialogBox(hInstance, MAKEINTRESOURCE(IDD_FRAMES), hwnd, FramesDlgProc) == FALSE) 
              return 0; 
						allframes = false; 
          } 
          else { 
            total_frames = 500000; 
						allframes = true; 
					} 
 
          try { 
            stream.BeginConversion(); 
          } 
          catch (Except &e) { 
            ReportProblem(hwnd, e.Who(), e.What()); 
            return 0; 
          } 
 
          hMenu = GetMenu(hMainWnd); 
          for (i = 0; i < 6; i++) 
            EnableMenuItem(hMenu, i, MF_BYPOSITION | MF_GRAYED); 
 
          DrawMenuBar(hMainWnd); 
          EnableWindow(GetDlgItem(hMainWnd, IDC_TRACKBAR), FALSE); 
 
          hProgressDlg = CreateDialog(hInstance, 
              MAKEINTRESOURCE(IDD_PROGRESS), hwnd, ProgressDlgProc); 
          InvalidateRect(hwnd, NULL, TRUE); 
          return 0; 
        case IDM_EXTRACTAUDIO: 
          if (!PopFileSaveDlg(audiofilename, "wav")) 
            return 0; 
           
          file = fopen(audiofilename, "rb"); 
          if (file) 
          { 
            fclose(file); 
            if (MessageBox(hwnd, "Output file already exists. Continue anyway?", 
                           "MPEG Mediator", MB_YESNO) != IDYES) 
              return 0; 
          } 
 
          try { 
            stream.BeginConversion(); 
          } 
          catch (Except &e) { 
            ReportProblem(hwnd, e.Who(), e.What()); 
            return 0; 
          } 
 
          hMenu = GetMenu(hMainWnd); 
          for (i = 0; i < 6; i++) 
            EnableMenuItem(hMenu, i, MF_BYPOSITION | MF_GRAYED); 
 
          DrawMenuBar(hMainWnd); 
          EnableWindow(GetDlgItem(hMainWnd, IDC_TRACKBAR), FALSE); 
 
          hAudioProgressDlg = CreateDialog(hInstance, 
              MAKEINTRESOURCE(IDD_AUDIOPROGRESS), hwnd, AudioProgressDlgProc); 
           
          return 0; 
        case IDM_HOMEPAGE: 
          ShellExecute(NULL, "open", "http://www.mpeg-mediator.com", NULL, NULL, SW_SHOWNORMAL); 
          return 0; 
        case IDM_ABOUT: 
          DialogBox(hInstance, MAKEINTRESOURCE(IDD_ABOUT), 
                        hwnd, AboutDlgProc); 
          return 0; 
        default: 
          hMenu = GetMenu(hMainWnd); 
          try 
          { 
            if ((LOWORD(wParam) >= IDM_AC3_0) && (LOWORD(wParam) <= IDM_AC3_7)) 
            { 
              stream.SelectAudioTrack(MPEGStream::AUDIO_AC3, LOWORD(wParam) - IDM_AC3_0); 
              UncheckAudioTracks(); 
              CheckMenuItem(hMenu, LOWORD(wParam), MF_CHECKED); 
							EnableMenuItem(hMenu, IDM_EXTRACTAUDIO, MF_ENABLED); 
            } 
            else if ((LOWORD(wParam) >= IDM_MPA_0) && (LOWORD(wParam) <= IDM_MPA_1F)) 
            { 
              stream.SelectAudioTrack(MPEGStream::AUDIO_MPEG, LOWORD(wParam) - IDM_MPA_0); 
              UncheckAudioTracks(); 
              CheckMenuItem(hMenu, LOWORD(wParam), MF_CHECKED); 
							EnableMenuItem(hMenu, IDM_EXTRACTAUDIO, MF_ENABLED); 
            } 
            else if ((LOWORD(wParam) >= IDM_LPCM_0) && (LOWORD(wParam) <= IDM_LPCM_7)) 
            { 
              stream.SelectAudioTrack(MPEGStream::AUDIO_LPCM, LOWORD(wParam) - IDM_LPCM_0); 
              UncheckAudioTracks(); 
              CheckMenuItem(hMenu, LOWORD(wParam), MF_CHECKED); 
							EnableMenuItem(hMenu, IDM_EXTRACTAUDIO, MF_ENABLED); 
            } 
          } 
          catch (Except &e) { 
            stream.Close(); 
            ReportProblem(hMainWnd, e.Who(), e.What()); 
            UpdateMenu(); 
            AdjustWindow(); 
            UpdateTrackbarState(); 
            InvalidateRect(hwnd, NULL, TRUE); 
            UpdateWindow(hwnd); 
          } 
 
          if ((LOWORD(wParam) >= IDM_PLUGIN_0) && (LOWORD(wParam) <= IDM_PLUGIN_F)) 
          { 
            UncheckPlugins(); 
            plugins.current = LOWORD(wParam) - IDM_PLUGIN_0; 
            CheckMenuItem(hMenu, LOWORD(wParam), MF_CHECKED); 
 
						if (plugins.plugins[plugins.current].extended_api) 
						{ 
							EnableMenuItem(hMenu, IDM_EXPORTYV12, MF_ENABLED); 
							CheckMenuItem(hMenu, IDM_EXPORTYV12, MF_CHECKED); 
 
							exportyv12 = true; 
						} 
						else 
						{ 
							EnableMenuItem(hMenu, IDM_EXPORTYV12, MF_GRAYED); 
							CheckMenuItem(hMenu, IDM_EXPORTYV12, MF_UNCHECKED); 
 
							exportyv12 = false; 
						} 
					} 
      } 
      break; 
    case WM_DONE: 
      stream.EndConversion(); 
      hMenu = GetMenu(hMainWnd); 
 
      for (i = 0; i < 6; i++) 
        EnableMenuItem(hMenu, i, MF_BYPOSITION | MF_ENABLED); 
 
      DrawMenuBar(hMainWnd); 
      EnableWindow(GetDlgItem(hMainWnd, IDC_TRACKBAR), TRUE); 
 
      try { 
        stream.Seek(stream.GetStartPos()); 
				stream.GetFrame(&frame_buffer, true); 
      } 
      catch (Except &e) { 
        stream.Close(); 
        ReportProblem(hMainWnd, e.Who(), e.What()); 
        UpdateMenu(); 
        AdjustWindow(); 
        UpdateTrackbarState(); 
      } 
 
      InvalidateRect(hwnd, NULL, TRUE); 
      return 0; 
    case WM_HSCROLL: 
      if ((int)LOWORD(wParam) != SB_ENDSCROLL) 
        return 0; 
      if (!(stream.IsOpen())) 
        return 0; 
 
      try { 
        stream.Seek((__int64)SendMessage((HWND)lParam, TBM_GETPOS, 0, 0) * 2048); 
				stream.GetFrame(&frame_buffer, true); 
      } 
      catch (Except &e) { 
        stream.Close(); 
        ReportProblem(hMainWnd, e.Who(), e.What()); 
        UpdateMenu(); 
        AdjustWindow(); 
        UpdateTrackbarState(); 
      } 
      InvalidateRect(hwnd, NULL, TRUE); 
      return 0; 
    case WM_SIZE: 
      cxClient = LOWORD(lParam); 
      cyClient = HIWORD(lParam); 
      MoveWindow(GetDlgItem(hwnd, IDC_TRACKBAR), 0, 
        cyClient - TRACKBAR_HEIGHT, cxClient, TRACKBAR_HEIGHT, TRUE); 
      return 0; 
    case WM_PAINT: 
      { 
        PostProcess::Config *cfg; 
        HDC hdc; 
  
        hdc = BeginPaint(hwnd, &ps); 
 
        if (stream.IsOpen() && (hProgressDlg == 0)) 
        { 
          cfg = stream.GetPostProcessor()->GetConfig(); 
 
          bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 
          bmi.bmiHeader.biWidth = cfg->GetCropWidth(); 
          bmi.bmiHeader.biHeight= cfg->GetCropHeight(); 
          bmi.bmiHeader.biPlanes = 1; 
          bmi.bmiHeader.biBitCount = 24; 
          bmi.bmiHeader.biCompression = BI_RGB; 
 
          SetDIBitsToDevice(hdc, 0, 0, cfg->GetCropWidth(), cfg->GetCropHeight(), 
            0, 0, 0, cfg->GetCropHeight(), frame_buffer.GetRGB24Representation(), 
						&bmi, DIB_RGB_COLORS); 
        } 
        else if (hWallpaper) 
        { 
          GetObject(hWallpaper, sizeof(BITMAP), &bitmap); 
          HDC hdcMem = CreateCompatibleDC(hdc); 
          SelectObject(hdcMem, hWallpaper); 
          for (i = 0; i < cyClient; i += bitmap.bmHeight) 
            for (j = 0; j < cxClient; j += bitmap.bmWidth) 
              BitBlt(hdc, j, i, bitmap.bmWidth, bitmap.bmHeight, hdcMem, 
                     0, 0, SRCCOPY); 
 
          DeleteDC(hdcMem); 
        } 
        EndPaint(hwnd, &ps); 
        return 0; 
      } 
    case WM_TIMER: 
      KillTimer(hwnd, 1); 
      SetWindowText(hwnd, "MPEG Mediator"); 
      return 0; 
    case WM_CLOSE: 
      if (hProgressDlg || hAudioProgressDlg) { 
        ReportProblem(hwnd, 0, "Cannot exit while being busy"); 
        return 0; 
      } 
      if (stream.IsOpen()) 
        stream.Close(); 
 
      DestroyWindow(hwnd); 
      return 0; 
    case WM_DESTROY: 
      UnloadPlugins(); 
      PostQuitMessage(0); 
      return 0; 
  } 
  return DefWindowProc(hwnd, message, wParam, lParam); 
} 
 
BOOL CALLBACK OpenDlgProc(HWND hDlg, UINT message, 
                          WPARAM wParam, LPARAM lParam) 
{ 
	using namespace std; 
   
	HDROP hDrop; 
  unsigned int iFiles; 
  static char szFilename[256]; 
  static char szDlgFile[400]; 
	static bool bSort = true; 
  char *str; 
  unsigned int i; 
  int iPathEnd; 
  LONG iCurSel; 
  static OPENFILENAME ofn; 
  static const char *errors[] = { 
    "MPEG-Stream is empty", 
    "Packetized Elementary Streams not supported", 
    "Transport Streams not supported", 
    "No MPEG-Video stream" 
  }; 
  static const char *szFilter = 
    "MPEG video files (*.mpg;*.mpeg;*.vob;*.m1v;*.m2v;*.mpv)\0*.mpg;*.mpeg;*.vob;*.m1v;*.m2v;*.mpv\0" 
    "All files (*.*)\0*.*\0"; 
 
  switch (message) 
  { 
    case WM_INITDIALOG: 
			CheckDlgButton(hDlg, IDC_SORTFILES, bSort ? BST_CHECKED : BST_UNCHECKED); 
      return TRUE; 
    case WM_COMMAND: 
      switch (LOWORD(wParam)) 
      { 
        case IDOK: 
          iFiles = SendDlgItemMessage(hDlg, IDC_FILES, LB_GETCOUNT, 0, 0); 
          if (iFiles == 0) { 
            EndDialog(hDlg, FALSE); 
            return TRUE; 
          } 
 
          if (stream.IsOpen()) 
            stream.Close(); 
 
          for (i = 0; i < iFiles; i++) { 
            SendDlgItemMessage(hDlg, IDC_FILES, LB_GETTEXT, (WPARAM)i, (LPARAM)szFilename); 
            stream.AddFilename(szFilename); 
          } 
 
          try { 
            i = stream.Open(); 
            if (i != 0) 
              ReportProblem(hDlg, 0, errors[i - 1]); 
						else 
						{ 
							stream.AdjustFrameDimensions(&frame_buffer); 
							stream.GetFrame(&frame_buffer, true); 
						} 
					} 
          catch (Except &e) { 
            ReportProblem(hDlg, e.Who(), e.What()); 
            stream.Close(); 
          } 
          EndDialog(hDlg, TRUE); 
          return TRUE; 
        case IDCANCEL: 
          EndDialog(hDlg, FALSE); 
          return TRUE; 
        case IDC_ADD: 
          szDlgFile[0] = '\0'; 
          ofn.lStructSize = sizeof(OPENFILENAME); 
          ofn.hwndOwner = hDlg; 
          ofn.lpstrFilter = szFilter ; 
          ofn.nMaxFile = 400; 
          ofn.lpstrFile = szDlgFile; 
          ofn.Flags = OFN_HIDEREADONLY | OFN_FILEMUSTEXIST | 
                      OFN_EXPLORER | OFN_ALLOWMULTISELECT; 
          if (GetOpenFileName(&ofn)) { 
            iPathEnd = (int)strlen(szDlgFile); 
            strcpy(szFilename, szDlgFile); 
            if (strlen(&szDlgFile[iPathEnd + 1]) == 0) 
						{ 
							if (bSort) 
								SendDlgItemMessage(hDlg, IDC_FILES, LB_ADDSTRING, 0, (LPARAM)szFilename); 
							else 
								SendDlgItemMessage(hDlg, IDC_FILES, LB_INSERTSTRING, -1, (LPARAM)szFilename); 
						} 
						else { 
              str = &szDlgFile[iPathEnd + 1]; 
              if (szFilename[iPathEnd - 1] != '\\') 
                szFilename[iPathEnd++] = '\\'; 
 
              while (strlen(str) > 0) { 
                strcpy(&szFilename[iPathEnd], str); 
                 
								if (bSort) 
									SendDlgItemMessage(hDlg, IDC_FILES, LB_ADDSTRING, 0, (LPARAM)szFilename); 
								else 
									SendDlgItemMessage(hDlg, IDC_FILES, LB_INSERTSTRING, -1, (LPARAM)szFilename); 
								 
								str += strlen(str) + 1; 
						  } 
            } 
          } 
          return TRUE; 
				case IDC_REMOVE: 
          iCurSel = SendDlgItemMessage(hDlg, IDC_FILES, LB_GETCURSEL, 0, 0); 
          if (iCurSel != LB_ERR) 
            SendDlgItemMessage(hDlg, IDC_FILES, LB_DELETESTRING, (WPARAM)iCurSel, 0); 
          return TRUE; 
        case IDC_REMOVEALL: 
          SendDlgItemMessage(hDlg, IDC_FILES, LB_RESETCONTENT, 0, 0); 
          return TRUE; 
				case IDC_SORTFILES: 
					bSort = (IsDlgButtonChecked(hDlg, IDC_SORTFILES) == BST_CHECKED) ? true : false; 
					if (bSort) 
					{					 
						if ((iFiles = SendDlgItemMessage(hDlg, IDC_FILES, LB_GETCOUNT, 0, 0)) == 0) 
	            return TRUE; 
 
						vector filenames; 
		 
						for (i = 0; i < iFiles; i++) { 
							SendDlgItemMessage(hDlg, IDC_FILES, LB_GETTEXT, (WPARAM)i, (LPARAM)szFilename); 
							filenames.push_back(string(szFilename)); 
						} 
 
						SendDlgItemMessage(hDlg, IDC_FILES, LB_RESETCONTENT, 0, 0); 
 
						for (i = 0; i < iFiles; i++) 
              SendDlgItemMessage(hDlg, IDC_FILES, LB_ADDSTRING, 0, (LPARAM)filenames[i].c_str()); 
					} 
					return TRUE; 
      } 
      break; 
    case WM_DROPFILES: 
      hDrop = (HDROP)wParam; 
      iFiles = DragQueryFile(hDrop, 0xffffffff, NULL, 256); 
      for (i = 0; i < iFiles; i++) { 
        DragQueryFile(hDrop, i, szFilename, 256); 
 
				if (bSort) 
					SendDlgItemMessage(hDlg, IDC_FILES, LB_ADDSTRING, 0, (LPARAM)szFilename); 
				else 
					SendDlgItemMessage(hDlg, IDC_FILES, LB_INSERTSTRING, -1, (LPARAM)szFilename); 
      } 
      return TRUE; 
  } 
  return FALSE; 
} 
 
int PopFileSaveDlg(char *filename, char *defextension) 
{ 
  static OPENFILENAME ofn; 
  static const char *szFilter = "All files (*.*)\0*.*\0"; 
 
  ofn.lStructSize = sizeof(OPENFILENAME); 
  ofn.hwndOwner = hMainWnd; 
  ofn.lpstrFilter = szFilter; 
  ofn.nMaxFile = 256; 
  ofn.lpstrFile = filename; 
  ofn.lpstrDefExt = defextension; 
  ofn.Flags = OFN_HIDEREADONLY; 
 
  return GetSaveFileName(&ofn); 
} 
 
BOOL CALLBACK PropertiesDlgProc(HWND hDlg, UINT message, 
                                WPARAM wParam, LPARAM lParam) 
{ 
  PostProcess::Config *cfg = stream.GetPostProcessor()->GetConfig(); 
  char szBuffer[80]; 
  int i; 
 
  static const char *szRateStrings[] = 
  { 
    "23.976", "24", "25", "29.97", "30", "50", "59.94", "60" 
  }; 
  static const char *szMPEG1AspectStrings[] = 
  { 
    "1.0", "0.6735", "0.7031", "0.7615", "0.8055", 
    "0.8437", "0.8935", "0.9157", "0.9815", "1.0255", 
    "1.0695", "1.0950", "1.1575", "1.2015" 
  }; 
  static const char *szMPEG2AspectStrings[] = 
  { 
    "1:1 (Square Pixels)", 
    "4:3", 
    "16:9 (Widescreen)", 
    "2.21:1", 
  }; 
 
  static const char *szAudioStrings[] = 
  { 
    "n/a", "AC-3", "MPEG", "LPCM" 
  }; 
 
  switch (message) 
  { 
    case WM_INITDIALOG: 
      if (stream.GetStreamType() == MPEGStream::MPEG2_PROGRAM) 
        SetDlgItemText(hDlg, IDC_STREAMTYPE, "MPEG-2 Program Stream"); 
      else if (stream.GetStreamType() == MPEGStream::MPEG1_PROGRAM) 
        SetDlgItemText(hDlg, IDC_STREAMTYPE, "MPEG-1 Program Stream"); 
      else 
        SetDlgItemText(hDlg, IDC_STREAMTYPE, "Video Elementary Stream"); 
 
      sprintf(szBuffer, "%I64d bytes", stream.GetStreamSize()); 
      SetDlgItemText(hDlg, IDC_STREAMSIZE, szBuffer); 
 
      if (stream.IsMPEG2Video()) 
        SetDlgItemText(hDlg, IDC_VIDEOTYPE, "MPEG-2"); 
      else 
        SetDlgItemText(hDlg, IDC_VIDEOTYPE, "MPEG-1"); 
 
      sprintf(szBuffer, "%d x %d", cfg->GetSourceWidth(), cfg->GetSourceHeight()); 
      SetDlgItemText(hDlg, IDC_RESOLUTION, szBuffer); 
 
      i = stream.GetFramerateCode(); 
 
      if ((i < 1) || (i > 8)) 
        sprintf(szBuffer, "unknown"); 
      else 
        sprintf(szBuffer, "%s fps", szRateStrings[i - 1]); 
 
      SetDlgItemText(hDlg, IDC_FRAMERATE, szBuffer); 
 
      i = stream.GetAspectratioCode(); 
 
      if ((i < 1) || (i > 14)) 
        sprintf(szBuffer, "unknown"); 
      else if (stream.IsMPEG2Video()) { 
        if (i > 4) 
          sprintf(szBuffer, "unknown"); 
        else 
          sprintf(szBuffer, "%s", szMPEG2AspectStrings[i - 1]); 
      } 
      else 
        sprintf(szBuffer, "%s", szMPEG1AspectStrings[i - 1]); 
 
      SetDlgItemText(hDlg, IDC_ASPECTRATIO, szBuffer); 
 
      i = stream.GetAudioType(); 
      SetDlgItemText(hDlg, IDC_AUDIOTYPE, szAudioStrings[i]); 
      if (i == MPEGStream::AUDIO_NONE) 
      { 
        SetDlgItemText(hDlg, IDC_CHANNELS, szAudioStrings[0]); 
        SetDlgItemText(hDlg, IDC_SAMPLERATE, szAudioStrings[0]); 
        SetDlgItemText(hDlg, IDC_SAMPLERESOLUTION, szAudioStrings[0]); 
      } 
      else 
      { 
        if (i == MPEGStream::AUDIO_AC3) 
          SetDlgItemText(hDlg, IDC_CHANNELS, stream.GetAC3ChannelString()); 
        else 
        { 
          if (stream.IsStereo()) 
            SetDlgItemText(hDlg, IDC_CHANNELS, "2 (Stereo)"); 
          else 
            SetDlgItemText(hDlg, IDC_CHANNELS, "1 (Mono)"); 
        } 
        sprintf(szBuffer, "%d Hz", stream.GetSampleRate()); 
        SetDlgItemText(hDlg, IDC_SAMPLERATE, szBuffer); 
        SetDlgItemText(hDlg, IDC_SAMPLERESOLUTION, "16 bit"); 
      } 
      return TRUE; 
    case WM_COMMAND: 
      switch (LOWORD(wParam)) 
      { 
        case IDOK: 
        case IDCANCEL: 
          EndDialog(hDlg, FALSE); 
          return TRUE; 
      } 
  } 
  return FALSE; 
} 
 
BOOL CALLBACK AboutDlgProc(HWND hDlg, UINT message, 
                           WPARAM wParam, LPARAM lParam) 
{ 
  switch (message) 
  { 
    case WM_COMMAND: 
      switch (LOWORD(wParam)) 
      { 
        case IDOK: 
        case IDCANCEL: 
          EndDialog(hDlg, TRUE); 
          return TRUE; 
      } 
  } 
  return FALSE; 
} 
 
BOOL CALLBACK FramesDlgProc(HWND hDlg, UINT message, 
                            WPARAM wParam, LPARAM lParam) 
{ 
  unsigned int l; 
   
  switch (message) 
  { 
    case WM_COMMAND: 
      switch (LOWORD(wParam)) 
      { 
        case IDOK: 
          l = GetDlgItemInt(hDlg, IDC_FRAMES, 0, FALSE); 
          if (l > 0) { 
            total_frames = (int)l; 
            EndDialog(hDlg, TRUE); 
          } 
          return TRUE; 
        case IDCANCEL: 
          EndDialog(hDlg, FALSE); 
          return TRUE; 
      } 
  } 
  return FALSE; 
} 
 
void TimePrint(char *szBuffer, int nSeconds) 
{ 
  int hours = nSeconds / (60 * 60); 
  int minutes = (nSeconds / 60) % 60; 
  int seconds = nSeconds % 60; 
 
  sprintf(szBuffer, "%02d:%02d:%02d", hours, minutes, seconds); 
} 
 
BOOL CALLBACK ProgressDlgProc(HWND hDlg, UINT message, 
                              WPARAM wParam, LPARAM lParam) 
{ 
	static HANDLE hThread = 0; 
  char sztemp[256]; 
  int nseconds; 
  static double frame_duration; 
	static bool bThreadSuspended = false; 
 
  switch (message) 
  { 
    case WM_INITDIALOG: 
      InitializeCriticalSection(&progress.cs); 
      progress.hEvent = CreateEvent(0, FALSE, FALSE, 0); 
      progress.bytes_done = 0; 
      progress.total_bytes = stream.GetStreamSize() - stream.GetStartPos(); 
      progress.audio_frame = 0; 
      progress.video_frame = 0; 
      progress.abort = false; 
      progress.seconds_passed = 0; 
 
      SendDlgItemMessage(hDlg, IDC_RENDERFRAME, CB_RESETCONTENT, 0, 0); 
      SendDlgItemMessage(hDlg, IDC_RENDERFRAME, CB_ADDSTRING, 0, (LPARAM)"no Frames");  
      SendDlgItemMessage(hDlg, IDC_RENDERFRAME, CB_ADDSTRING, 0, (LPARAM)"every Frame");  
      SendDlgItemMessage(hDlg, IDC_RENDERFRAME, CB_ADDSTRING, 0, (LPARAM)"every 2nd Frame");  
      SendDlgItemMessage(hDlg, IDC_RENDERFRAME, CB_ADDSTRING, 0, (LPARAM)"every 4th Frame");  
      SendDlgItemMessage(hDlg, IDC_RENDERFRAME, CB_ADDSTRING, 0, (LPARAM)"every 8th Frame");  
      SendDlgItemMessage(hDlg, IDC_RENDERFRAME, CB_ADDSTRING, 0, (LPARAM)"every 16th Frame");  
      SendDlgItemMessage(hDlg, IDC_RENDERFRAME, CB_ADDSTRING, 0, (LPARAM)"every 32nd Frame");  
			 
			progress.display_video = 0; 
      SendDlgItemMessage(hDlg, IDC_RENDERFRAME, CB_SETCURSEL, progress.display_video, 0); 
 
      SetDlgItemText(hDlg, IDC_OUTPUTFILE, outfilename); 
      SetDlgItemText(hDlg, IDC_VIDEOFRAME, ""); 
      SetDlgItemText(hDlg, IDC_AUDIOFRAME, ""); 
      SetDlgItemText(hDlg, IDC_TIMEELAPSED, ""); 
      SetDlgItemText(hDlg, IDC_TIMEREMAINING, ""); 
      SetDlgItemText(hDlg, IDC_VIDEOTIME, ""); 
      SetDlgItemText(hDlg, IDC_AUDIOTIME, ""); 
      SetDlgItemText(hDlg, IDC_PROGRESSPERCENT, ""); 
 
	    SetDlgItemText(hDlg, IDC_PAUSE, "Pause"); 
      bThreadSuspended = false; 
       
      if (allframes) 
        SendDlgItemMessage(hDlg, IDC_PROGRESS, PBM_SETRANGE32, 0, 
          (int)(progress.total_bytes / 2048)); 
      else 
        SendDlgItemMessage(hDlg, IDC_PROGRESS, PBM_SETRANGE32, 0, total_frames); 
 
      frame_duration = stream.GetFinalFrameDuration(); 
 
      hThread = (HANDLE)_beginthread(ConverterThread, 0, 0); 
 
      SetTimer(hDlg, 1, 1000, NULL); 
      return TRUE; 
    case WM_CLOSE: 
      progress.abort = true; 
      if (bThreadSuspended) 
				ResumeThread(hThread); 
      return TRUE; 
    case WM_TIMER: 
      if (WaitForSingleObject(progress.hEvent, 0) == WAIT_OBJECT_0) 
        DestroyWindow(hDlg); 
      else 
      { 
				if (bThreadSuspended) 
					return TRUE; 
         
				EnterCriticalSection(&progress.cs); 
 
        if (allframes) 
          SendDlgItemMessage(hDlg, IDC_PROGRESS, PBM_SETPOS, 
                             (int)(progress.bytes_done / 2048), 0); 
        else 
          SendDlgItemMessage(hDlg, IDC_PROGRESS, PBM_SETPOS, 
                             progress.video_frame, 0); 
 
        sprintf(sztemp, "%d", progress.video_frame); 
        SetDlgItemText(hDlg, IDC_VIDEOFRAME, sztemp); 
        sprintf(sztemp, "%d", progress.audio_frame); 
        SetDlgItemText(hDlg, IDC_AUDIOFRAME, sztemp); 
 
        TimePrint(sztemp, (int)(progress.video_frame * frame_duration)); 
        SetDlgItemText(hDlg, IDC_VIDEOTIME, sztemp); 
        TimePrint(sztemp, (int)(progress.audio_frame * frame_duration)); 
        SetDlgItemText(hDlg, IDC_AUDIOTIME, sztemp); 
 
        if (allframes) 
          sprintf(sztemp, "%.1f%%", (double)progress.bytes_done * 100.0 / progress.total_bytes); 
        else 
          sprintf(sztemp, "%.1f%%", (double)progress.video_frame * 100.0 / total_frames); 
         
        SetDlgItemText(hDlg, IDC_PROGRESSPERCENT, sztemp); 
 
        if (progress.video_frame > 1) 
        { 
          progress.seconds_passed++; 
 
          TimePrint(sztemp, progress.seconds_passed); 
          SetDlgItemText(hDlg, IDC_TIMEELAPSED, sztemp); 
 
          if (allframes) 
            nseconds = (int)((progress.total_bytes * progress.seconds_passed) / progress.bytes_done) - 
              progress.seconds_passed; 
          else 
            nseconds = (int)((total_frames * progress.seconds_passed) / progress.video_frame) - 
              progress.seconds_passed; 
 
          TimePrint(sztemp, nseconds); 
          SetDlgItemText(hDlg, IDC_TIMEREMAINING, sztemp); 
        } 
        LeaveCriticalSection(&progress.cs); 
      } 
      return TRUE; 
    case WM_COMMAND: 
      switch (LOWORD(wParam)) 
      { 
        case IDOK: 
        case IDCANCEL: 
          progress.abort = true; 
          if (bThreadSuspended) 
		    		ResumeThread(hThread); 
          return TRUE; 
        case IDC_RENDERFRAME: 
	        EnterCriticalSection(&progress.cs); 
          progress.display_video = (int)SendDlgItemMessage(hDlg, IDC_RENDERFRAME, CB_GETCURSEL, 0, 0); 
					if (progress.display_video == 0) 
	          InvalidateRect(hMainWnd, NULL, TRUE); 
	        LeaveCriticalSection(&progress.cs); 
          return TRUE; 
				case IDC_PAUSE: 
					bThreadSuspended = !bThreadSuspended; 
					if (bThreadSuspended) 
					{ 
						SuspendThread(hThread); 
				    SetDlgItemText(hDlg, IDC_PAUSE, "Continue"); 
					} 
					else 
					{ 
						ResumeThread(hThread); 
				    SetDlgItemText(hDlg, IDC_PAUSE, "Pause"); 
					} 
					return TRUE; 
			} 
      return FALSE; 
    case WM_DESTROY: 
      KillTimer(hDlg, 1); 
      hProgressDlg = 0; 
      CloseHandle(progress.hEvent); 
      DeleteCriticalSection(&progress.cs); 
      SendMessage(hMainWnd, WM_DONE, 0, 0); 
      return TRUE; 
  } 
  return FALSE; 
} 
 
BOOL CALLBACK AudioProgressDlgProc(HWND hDlg, UINT message, 
            WPARAM wParam, LPARAM lParam) 
{ 
  switch (message) 
  { 
    case WM_INITDIALOG: 
      InitializeCriticalSection(&progress.cs); 
      progress.hEvent = CreateEvent(0, FALSE, FALSE, 0); 
      progress.bytes_done = 0; 
      progress.total_bytes = stream.GetStreamSize() - stream.GetStartPos(); 
      progress.abort = false; 
 
      SendDlgItemMessage(hDlg, IDC_AUDIOPROGRESS, PBM_SETRANGE32, 0, 
        (int)(progress.total_bytes / 2048)); 
 
      _beginthread(AudioExtractionThread, 0, 0); 
 
      SetTimer(hDlg, 1, 1000, NULL); 
      return TRUE; 
    case WM_CLOSE: 
      progress.abort = true; 
      return TRUE; 
    case WM_TIMER: 
      if (WaitForSingleObject(progress.hEvent, 0) == WAIT_OBJECT_0) 
        DestroyWindow(hDlg); 
      else 
      { 
        EnterCriticalSection(&progress.cs); 
        SendDlgItemMessage(hDlg, IDC_AUDIOPROGRESS, PBM_SETPOS, 
          (int)(progress.bytes_done / 2048), 0); 
        LeaveCriticalSection(&progress.cs); 
      } 
      return TRUE; 
    case WM_COMMAND: 
      switch (LOWORD(wParam)) 
      { 
        case IDOK: 
        case IDCANCEL: 
          progress.abort = true; 
          return TRUE; 
      } 
      return FALSE; 
    case WM_DESTROY: 
      KillTimer(hDlg, 1); 
      hAudioProgressDlg = 0; 
      CloseHandle(progress.hEvent); 
      DeleteCriticalSection(&progress.cs); 
      SendMessage(hMainWnd, WM_DONE, 0, 0); 
      return TRUE; 
  } 
  return FALSE; 
} 
 
void UncheckAudioTracks() 
{ 
  static MENUITEMINFO info; 
  HMENU hMenu, hAudioMenu; 
  int items, i; 
 
  hMenu = GetMenu(hMainWnd); 
  info.cbSize = sizeof(MENUITEMINFO); 
  info.fMask  = MIIM_SUBMENU; 
  GetMenuItemInfo(hMenu, 2, TRUE, &info); 
  hAudioMenu = info.hSubMenu; 
 
  items = GetMenuItemCount(hAudioMenu); 
 
  for (i = 0; i < items; i++) 
    CheckMenuItem(hAudioMenu, i, MF_BYPOSITION | MF_UNCHECKED); 
} 
 
void UpdateMenu() 
{ 
  PostProcess::Config *cfg; 
  static MENUITEMINFO info; 
  HMENU hMenu, hAudioMenu; 
  char label[30]; 
  int audiotype, track; 
  int i, count; 
 
  hMenu = GetMenu(hMainWnd); 
  info.cbSize = sizeof(MENUITEMINFO); 
  info.fMask  = MIIM_SUBMENU; 
  GetMenuItemInfo(hMenu, 2, TRUE, &info); 
  hAudioMenu = info.hSubMenu; 
 
  if (stream.IsOpen()) 
  { 
    EnableMenuItem(hMenu, IDM_CLOSE, MF_ENABLED); 
    EnableMenuItem(hMenu, IDM_PROPERTIES, MF_ENABLED); 
 
    if (plugins.count > 0) 
      EnableMenuItem(hMenu, IDM_PLUGINS_CONFIGURE, MF_ENABLED); 
 
    EnableMenuItem(hMenu, IDM_RESIZECROP, MF_ENABLED); 
 
    if (plugins.count > 0) { 
      EnableMenuItem(hMenu, IDM_STARTCONVERSION, MF_ENABLED); 
      EnableMenuItem(hMenu, IDM_CONVERTNFRAMES, MF_ENABLED); 
		} 
 
    EnableMenuItem(hMenu, IDM_ASPECTRATIO_11, MF_ENABLED); 
    EnableMenuItem(hMenu, IDM_ASPECTRATIO_43, MF_ENABLED); 
    EnableMenuItem(hMenu, IDM_ASPECTRATIO_169, MF_ENABLED); 
    EnableMenuItem(hMenu, IDM_ASPECTRATIO_2211, MF_ENABLED); 
 
    CheckMenuItem(hMenu, IDM_ASPECTRATIO_11, MF_UNCHECKED); 
    CheckMenuItem(hMenu, IDM_ASPECTRATIO_43, MF_UNCHECKED); 
    CheckMenuItem(hMenu, IDM_ASPECTRATIO_169, MF_UNCHECKED); 
    CheckMenuItem(hMenu, IDM_ASPECTRATIO_2211, MF_UNCHECKED); 
 
    i = stream.GetAspectratioCode(); 
    if ((i < 1) || (i > 4)) 
      i = 1; 
 
    CheckMenuItem(hMenu, IDM_ASPECTRATIO_11 + i - 1, MF_CHECKED); 
 
    EnableMenuItem(hMenu, IDM_RESIZE_DECWIDTH, MF_ENABLED); 
    EnableMenuItem(hMenu, IDM_RESIZE_INCWIDTH, MF_ENABLED); 
    EnableMenuItem(hMenu, IDM_RESIZE_DECHEIGHT, MF_ENABLED); 
    EnableMenuItem(hMenu, IDM_RESIZE_INCHEIGHT, MF_ENABLED); 
    EnableMenuItem(hMenu, IDM_RESIZE_LOCKRATIO, MF_ENABLED); 
 
    cfg = stream.GetPostProcessor()->GetConfig(); 
 
    CheckMenuItem(hMenu, IDM_RESIZE_LOCKRATIO, cfg->IsAspectRatioLocked() ? MF_CHECKED : MF_UNCHECKED); 
 
    EnableMenuItem(hMenu, IDM_CROP_DECWIDTH, MF_ENABLED); 
    EnableMenuItem(hMenu, IDM_CROP_INCWIDTH, MF_ENABLED); 
    EnableMenuItem(hMenu, IDM_CROP_DECHEIGHT, MF_ENABLED); 
    EnableMenuItem(hMenu, IDM_CROP_INCHEIGHT, MF_ENABLED); 
 
		if (stream.IsTelecined()) { 
			EnableMenuItem(hMenu, IDM_INVERSETELECINE, MF_ENABLED); 
			CheckMenuItem(hMenu, IDM_INVERSETELECINE, stream.GetIVTC() ? MF_CHECKED : MF_UNCHECKED); 
		} 
		else { 
			EnableMenuItem(hMenu, IDM_INVERSETELECINE, MF_GRAYED); 
			CheckMenuItem(hMenu, IDM_INVERSETELECINE, MF_UNCHECKED); 
		} 
 
		while (RemoveMenu(hAudioMenu, 0, MF_BYPOSITION)); 
 
    audiotype = stream.GetAudioType(); 
    track = stream.GetAudioTrack(); 
 
    info.fMask = MIIM_TYPE | MIIM_ID; 
    info.fType = MFT_STRING; 
    info.dwTypeData = label; 
 
    count = 0; 
    for (i = 0; i < 8; i++) { 
      if (stream.HasAudioTrack(MPEGStream::AUDIO_AC3, i)) { 
        sprintf(label, "AC-3, Track %d", i); 
        info.wID = IDM_AC3_0 + i; 
        InsertMenuItem(hAudioMenu, count, TRUE, &info); 
        if ((audiotype == MPEGStream::AUDIO_AC3) && (i == track)) 
          CheckMenuItem(hAudioMenu, count, MF_BYPOSITION | MF_CHECKED); 
        count++; 
      } 
    } 
    for (i = 0; i < 32; i++) { 
      if (stream.HasAudioTrack(MPEGStream::AUDIO_MPEG, i)) { 
        sprintf(label, "MPEG, Track %d", i); 
        info.wID = IDM_MPA_0 + i; 
        InsertMenuItem(hAudioMenu, count, TRUE, &info); 
        if ((audiotype == MPEGStream::AUDIO_MPEG) && (i == track)) 
          CheckMenuItem(hAudioMenu, count, MF_BYPOSITION | MF_CHECKED); 
        count++; 
      } 
    } 
    for (i = 0; i < 16; i++) { 
      if (stream.HasAudioTrack(MPEGStream::AUDIO_LPCM, i)) { 
        sprintf(label, "LPCM, Track %d", i); 
        info.wID = IDM_LPCM_0 + i; 
        InsertMenuItem(hAudioMenu, count, TRUE, &info); 
        if ((audiotype == MPEGStream::AUDIO_LPCM) && (i == track)) 
          CheckMenuItem(hAudioMenu, count, MF_BYPOSITION | MF_CHECKED); 
        count++; 
      } 
    } 
    if (count == 0) { 
      info.fMask = MIIM_TYPE | MIIM_STATE; 
      info.fType = MFT_STRING; 
      info.fState = MFS_GRAYED; 
      info.dwTypeData = ""; 
      InsertMenuItem(hAudioMenu, 0, TRUE, &info); 
      EnableMenuItem(hMenu, IDM_EXTRACTAUDIO, MF_GRAYED); 
    } 
    else { 
			info.fMask = MIIM_TYPE; 
			info.fType = MFT_SEPARATOR; 
      InsertMenuItem(hAudioMenu, count++, TRUE, &info); 
			 
		  info.fMask = MIIM_TYPE | MIIM_ID; 
	    info.fType = MFT_STRING; 
			info.wID = IDM_NOAUDIO; 
      info.dwTypeData = "No Audio"; 
      InsertMenuItem(hAudioMenu, count, TRUE, &info); 
 
      EnableMenuItem(hMenu, IDM_EXTRACTAUDIO, MF_ENABLED); 
		} 
	} 
  else 
  { 
    EnableMenuItem(hMenu, IDM_CLOSE, MF_GRAYED); 
    EnableMenuItem(hMenu, IDM_PROPERTIES, MF_GRAYED); 
    EnableMenuItem(hMenu, IDM_PLUGINS_CONFIGURE, MF_GRAYED); 
    EnableMenuItem(hMenu, IDM_RESIZECROP, MF_GRAYED); 
    EnableMenuItem(hMenu, IDM_STARTCONVERSION, MF_GRAYED); 
    EnableMenuItem(hMenu, IDM_CONVERTNFRAMES, MF_GRAYED); 
    EnableMenuItem(hMenu, IDM_EXTRACTAUDIO, MF_GRAYED); 
 
    EnableMenuItem(hMenu, IDM_ASPECTRATIO_11, MF_GRAYED); 
    EnableMenuItem(hMenu, IDM_ASPECTRATIO_43, MF_GRAYED); 
    EnableMenuItem(hMenu, IDM_ASPECTRATIO_169, MF_GRAYED); 
    EnableMenuItem(hMenu, IDM_ASPECTRATIO_2211, MF_GRAYED); 
 
    CheckMenuItem(hMenu, IDM_ASPECTRATIO_11, MF_UNCHECKED); 
    CheckMenuItem(hMenu, IDM_ASPECTRATIO_43, MF_UNCHECKED); 
    CheckMenuItem(hMenu, IDM_ASPECTRATIO_169, MF_UNCHECKED); 
    CheckMenuItem(hMenu, IDM_ASPECTRATIO_2211, MF_UNCHECKED); 
 
    EnableMenuItem(hMenu, IDM_RESIZE_DECWIDTH, MF_GRAYED); 
    EnableMenuItem(hMenu, IDM_RESIZE_INCWIDTH, MF_GRAYED); 
    EnableMenuItem(hMenu, IDM_RESIZE_DECHEIGHT, MF_GRAYED); 
    EnableMenuItem(hMenu, IDM_RESIZE_INCHEIGHT, MF_GRAYED); 
    EnableMenuItem(hMenu, IDM_RESIZE_LOCKRATIO, MF_GRAYED); 
 
    CheckMenuItem(hMenu, IDM_RESIZE_LOCKRATIO, MF_UNCHECKED); 
 
    EnableMenuItem(hMenu, IDM_CROP_DECWIDTH, MF_GRAYED); 
    EnableMenuItem(hMenu, IDM_CROP_INCWIDTH, MF_GRAYED); 
    EnableMenuItem(hMenu, IDM_CROP_DECHEIGHT, MF_GRAYED); 
    EnableMenuItem(hMenu, IDM_CROP_INCHEIGHT, MF_GRAYED); 
 
		EnableMenuItem(hMenu, IDM_INVERSETELECINE, MF_GRAYED); 
    CheckMenuItem(hMenu, IDM_INVERSETELECINE, MF_UNCHECKED); 
 
    while (RemoveMenu(hAudioMenu, 0, MF_BYPOSITION)); 
 
    info.fMask = MIIM_TYPE | MIIM_STATE; 
    info.fType = MFT_STRING; 
    info.fState = MFS_GRAYED; 
    info.dwTypeData = ""; 
    InsertMenuItem(hAudioMenu, 0, TRUE, &info); 
  } 
} 
 
void AddPluginsToMenu() 
{ 
  static MENUITEMINFO info; 
  HMENU hMenu, hPluginMenu; 
 
  hMenu = GetMenu(hMainWnd); 
  info.cbSize = sizeof(MENUITEMINFO); 
  info.fMask  = MIIM_SUBMENU; 
  GetMenuItemInfo(hMenu, 1, TRUE, &info); 
  hPluginMenu = info.hSubMenu; 
 
  info.fMask = MIIM_TYPE | MIIM_ID; 
  info.fType = MFT_STRING; 
 
  for (int i = 0; i < plugins.count; i++) 
  { 
    info.dwTypeData = plugins.plugins[i].inforec.compilerName; 
    info.wID = IDM_PLUGIN_0 + i; 
    InsertMenuItem(hPluginMenu, i, TRUE, &info); 
    if (i == plugins.current) 
		{ 
      CheckMenuItem(hPluginMenu, i, MF_BYPOSITION | MF_CHECKED); 
			if (plugins.plugins[i].extended_api) 
			{ 
		    EnableMenuItem(hMenu, IDM_EXPORTYV12, MF_ENABLED); 
				CheckMenuItem(hMenu, IDM_EXPORTYV12, MF_CHECKED); 
				exportyv12 = true; 
			} 
			else 
				exportyv12 = false; 
		} 
	} 
} 
 
void UncheckPlugins() 
{ 
  static MENUITEMINFO info; 
  HMENU hMenu, hPluginMenu; 
 
  hMenu = GetMenu(hMainWnd); 
  info.cbSize = sizeof(MENUITEMINFO); 
  info.fMask  = MIIM_SUBMENU; 
  GetMenuItemInfo(hMenu, 1, TRUE, &info); 
  hPluginMenu = info.hSubMenu; 
 
  for (int i = 0; i < plugins.count; i++) 
    CheckMenuItem(hPluginMenu, i, MF_BYPOSITION | MF_UNCHECKED); 
} 
 
void AdjustWindow() 
{ 
  PostProcess::Config *cfg; 
  RECT rect, wrect, crect; 
  int delta; 
 
  if (!stream.IsOpen()) { 
    SetRect(&rect, 0, 0, INIT_WIDTH, TRACKBAR_HEIGHT + INIT_HEIGHT); 
    SetRect(&wrect, 0, 0, INIT_WIDTH, TRACKBAR_HEIGHT + INIT_HEIGHT); 
  } 
  else 
  { 
    cfg = stream.GetPostProcessor()->GetConfig(); 
    SetRect(&rect, 0, 0, cfg->GetCropWidth(), TRACKBAR_HEIGHT + cfg->GetCropHeight()); 
    SetRect(&wrect, 0, 0, cfg->GetCropWidth(), TRACKBAR_HEIGHT + cfg->GetCropHeight()); 
  } 
 
  GetClientRect(hMainWnd, &crect); 
 
  // adjust size of window if necessary 
 
  if ((rect.right != crect.right) || 
      (rect.bottom != crect.bottom)) 
  { 
    AdjustWindowRect(&wrect, GetWindowLong(hMainWnd, GWL_STYLE), TRUE); 
    OffsetRect(&wrect, -wrect.left, -wrect.top); 
    SetWindowPos(hMainWnd, HWND_TOP, 0, 0, 
                 wrect.right, wrect.bottom, SWP_NOMOVE); 
 
    // handle menu-wraps (not perfect for weird cases (3-times wrap)) 
    GetClientRect(hMainWnd, &crect); 
    delta = rect.bottom - crect.bottom; 
 
    GetWindowRect(hMainWnd, &wrect); 
    SetWindowPos(hMainWnd, HWND_TOP, 0, 0, wrect.right - wrect.left, 
                 wrect.bottom - wrect.top + delta, SWP_NOMOVE); 
  } 
} 
 
void UpdateTrackbarState() 
{ 
  if (stream.IsOpen()) 
  { 
    EnableWindow(GetDlgItem(hMainWnd, IDC_TRACKBAR), TRUE); 
    SendDlgItemMessage(hMainWnd, IDC_TRACKBAR, TBM_SETRANGEMIN, 
      (WPARAM)FALSE, 0); 
    SendDlgItemMessage(hMainWnd, IDC_TRACKBAR, TBM_SETRANGEMAX, 
      (WPARAM)FALSE, (long)(stream.GetStreamSize() / 2048)); 
    SendDlgItemMessage(hMainWnd, IDC_TRACKBAR, TBM_SETPOS, 
      (WPARAM)TRUE, (LPARAM)0); 
  } 
  else 
  { 
    SendDlgItemMessage(hMainWnd, IDC_TRACKBAR, TBM_SETPOS, 
      (WPARAM)TRUE, (LPARAM)0); 
    EnableWindow(GetDlgItem(hMainWnd, IDC_TRACKBAR), FALSE); 
  } 
} 
 
HBITMAP CreateBitmapObjectFromDibFile(HDC hdc, PTSTR szFileName) 
{ 
  BITMAPFILEHEADER *pbmfh; 
  BOOL bSuccess; 
  DWORD dwFileSize, dwHighSize, dwBytesRead; 
  HANDLE hFile; 
  HBITMAP hBitmap; 
 
  hFile = CreateFile(szFileName, GENERIC_READ, FILE_SHARE_READ, NULL, 
                     OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL); 
 
  if (hFile == INVALID_HANDLE_VALUE) 
    return NULL; 
 
  dwFileSize = GetFileSize(hFile, &dwHighSize); 
 
  if (dwHighSize) 
  { 
    CloseHandle(hFile); 
    return NULL; 
  } 
 
  pbmfh = (BITMAPFILEHEADER *)malloc(dwFileSize); 
 
  if (!pbmfh) 
  { 
    CloseHandle(hFile); 
    return NULL; 
  } 
 
  bSuccess = ReadFile(hFile, pbmfh, dwFileSize, &dwBytesRead, NULL); 
  CloseHandle(hFile); 
 
  if (!bSuccess || (dwBytesRead != dwFileSize) 
                || (pbmfh->bfType != *(WORD *)"BM") 
                || (pbmfh->bfSize != dwFileSize)) 
  { 
    free(pbmfh); 
    return NULL; 
  } 
 
  hBitmap = CreateDIBitmap(hdc, 
                           (BITMAPINFOHEADER *)(pbmfh + 1), 
                           CBM_INIT, 
                           (BYTE *)pbmfh + pbmfh->bfOffBits, 
                           (BITMAPINFO *)(pbmfh + 1), 
                           DIB_RGB_COLORS); 
  free(pbmfh); 
 
  return hBitmap; 
}