/***************************************************************************** * * This program 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. * * This program 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 * * $Id: interface.c 624 2006-02-01 17:48:42Z picard $ * * The Core Pocket Media Player * Copyright (c) 2004-2005 Gabor Kovacs * ****************************************************************************/ #include "../../common/common.h" #include "../win.h" #include "interface.h" #include "resource.h" #include "openfile_win32.h" #include "../about.h" #include "../benchresult.h" #include "../mediainfo.h" #include "../settings.h" #include "playlst.h" #include "../skin.h" #include "../../config.h" #define CORETHEQUE_UI_ID FOURCC('C','T','Q','U') #if defined(TARGET_WINCE) || defined(TARGET_WIN32) #ifndef STRICT #define STRICT #endif #include #if _MSC_VER > 1000 #pragma warning(disable : 4201) #endif #include #define REG_INITING 0x2400 #define TIMER_CLIPPING 500 #define TIMER_INITING 501 #define TIMER_SLEEP 502 #define TIMER_KEYINSEEK 503 #define TIMER_SLIDERINSEEK 504 #define TIMER_SLIDERINVOL 505 #define TIMER_CLIPPING2 506 #define TIMER_TITLESCROLL 507 #define SLIDERINSEEK_CYCLE 250 #define SLIDERINVOL_CYCLE 100 #define KEYINSEEK_START 1000 #define KEYINSEEK_REPEAT 500 #define CLIPPING_CYCLE 200 #define INITING_CYCLE 3000 #define SLEEP_CYCLE 5000 #define CLIPPING2_CYCLE 200 #define TITLESCROLL_CYCLE 150 #define TITLESCROLL_WAIT (4000/TITLESCROLL_CYCLE) #define TRACKMAX 30000 #define TRACKHEIGHT 16 #define TRACKTHUMB 12 #define TITLEHEIGHT 16 #define TITLEFONT 11 #define VOLMINWIDTH 35 #define VOLTHUMB 12 #define IF_AUDIO 50000 #define IF_VIDEO 51000 #define IF_VIDEOACCEL 52000 #define IF_CHAPTER 53000 #define IF_STREAM_AUDIO 54000 #define IF_STREAM_VIDEO 55000 #define IF_STREAM_SUBTITLE 56000 static int HotKey[] = { IF_FILE_OPENFILE, IF_FILE_PLAYLIST, IF_PLAY, IF_PLAYPAUSE, IF_PLAY_FULLSCREEN, IF_STOP, IF_MOVE_FFWD, IF_MOVE_BACK, IF_NEXT, IF_PREV, IF_PREV_SMART, IF_NEXT2, IF_PREV_SMART2, IF_FASTFORWARD, IF_OPTIONS_VOLUME_UP, IF_OPTIONS_VOLUME_DOWN, IF_OPTIONS_VOLUME_UP_FINE, IF_OPTIONS_VOLUME_DOWN_FINE, IF_OPTIONS_MUTE, IF_OPTIONS_EQUALIZER, IF_OPTIONS_FULLSCREEN, IF_OPTIONS_ZOOM_FIT, IF_OPTIONS_ZOOM_IN, IF_OPTIONS_ZOOM_OUT, IF_OPTIONS_ROTATE, IF_OPTIONS_BRIGHTNESS_UP, IF_OPTIONS_BRIGHTNESS_DOWN, IF_OPTIONS_CONTRAST_UP, IF_OPTIONS_CONTRAST_DOWN, IF_OPTIONS_SATURATION_UP, IF_OPTIONS_SATURATION_DOWN, IF_OPTIONS_TOGGLE_VIDEO, IF_OPTIONS_TOGGLE_AUDIO, //!SUBTITLE IF_OPTIONS_TOGGLE_SUBTITLE, IF_OPTIONS_AUDIO_STEREO_TOGGLE, IF_OPTIONS_SCREEN, IF_FILE_EXIT, }; #define HOTKEYCOUNT (sizeof(HotKey)/sizeof(int)) typedef struct intface { win Win; DWORD ThreadId; player* Player; node* Color; node* Equalizer; WNDPROC DefTrackProc; WNDPROC DefVolProc; HWND WndTrack; HWND WndTitle; HWND WndVol; HWND WndVolBack; int TrackThumb; RECT ClientRect; rect SkinViewport; rect SkinArea; rect Viewport; int InSkin; bool_t InVol; bool_t InSeek; bool_t Capture; bool_t ForceFullScreen; bool_t TrackBar; bool_t TitleBar; bool_t TaskBar; bool_t Buttons; bool_t Focus; bool_t Clipping; bool_t Overlap; bool_t VolResizeNeeded; bool_t VolResizeNeeded2; bool_t Exited; POINT Offset; bool_t Bench; bool_t Wait; bool_t CmdLineMode; int Vol; int HotKey[HOTKEYCOUNT]; // refresh states int TrackSetPos; int TrackPos; bool_t Play; bool_t FFwd; bool_t FullScreen; bool_t Mute; HFONT TitleFont; int TitleFontSize; tick_t TitleTime; int TitleTimeWidth; int TitleNameWidth; int TitleNameSize; int TitleNameOffset; int ScrollMode; bool_t UpdateScroll; int TitleDurWidth; int TitleBorder; int TitleTop; int TitleWidth; int TitleHeight; HBRUSH TitleBrush; rgbval_t TitleFace; rgbval_t TitleText; tchar_t TitleName[256]; tchar_t TitleDur[32]; int MenuPreAmp; int MenuStreams; int MenuAStream; int MenuVStream; int MenuSubStream; array VOutput; array AOutput; bool_t AllKeys; bool_t AllKeysWarning; int SkinNo; skin Skin[MAX_SKIN]; tchar_t SkinPath[MAXPATH]; } intface; static void ResizeVolume(intface* p) { if (p->WndVolBack) { RECT rv; RECT r; POINT o; int Width; int i; GetClientRect(p->Win.WndTB,&r); if (r.leftWin.WndTB,TB_GETRECT,IF_OPTIONS_MUTE,(LPARAM)&rv); #if defined(TARGET_WINCE) if (p->Win.ToolBarHeight) // decrease width by 'X' button on right r.right = max(r.left,r.right-(rv.right-rv.left)); #endif Width = r.right-rv.right; if (Width < 16) Width = 16; i = WinUnitToPixelX(&p->Win,50); if (Width > i) Width = i; o.x = o.y = 0; if (!p->Win.ToolBarHeight) ClientToScreen(p->Win.WndTB,&o); MoveWindow(p->WndVolBack,rv.right+o.x,o.y+1,Width,r.bottom-1,TRUE); GetClientRect(p->WndVolBack,&r); i = WinUnitToPixelX(&p->Win,2); MoveWindow(p->WndVol,-i,0,r.right+2*i,r.bottom,TRUE); SendMessage(p->WndVol, TBM_SETTHUMBLENGTH,WinUnitToPixelY(&p->Win,VOLTHUMB),0); } } } static bool_t Toggle(intface* p,int Param,int Force); static void UpdateVolume(intface* p); static void UpdateClipping(intface* p,bool_t Suggest,bool_t HotKey); static void ShowVol(intface* p,bool_t Show) { if (p->WndVolBack && !p->Win.ToolBarHeight) { if (Show) SetWindowPos(p->WndVolBack,HWND_TOPMOST,0,0,0,0,SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_SHOWWINDOW); else ShowWindow(p->WndVolBack,SW_HIDE); if (p->VolResizeNeeded2>1) p->VolResizeNeeded2=1; } } static void Resize(intface* p) { RECT r; bool_t Rotated = IsOrientationChanged(); DEBUG_MSG(DEBUG_VIDEO,T("Resize begin")); if (Rotated) { p->Player->Set(p->Player,PLAYER_ROTATEBEGIN,NULL,0); p->Player->Set(p->Player,PLAYER_RESETVIDEO,NULL,0); if (!p->Win.ToolBarHeight) { p->VolResizeNeeded2 = 1; // toolbar position may change later if (p->WndVolBack && IsWindowVisible(p->WndVolBack)) { ShowVol(p,0); p->VolResizeNeeded2 = 2; } } else p->VolResizeNeeded = 1; if (p->Win.FullScreen) PostMessage(p->Win.Wnd,MSG_PLAYER,PLAYER_FULLSCREEN,0); } p->Offset.x = 0; p->Offset.y = 0; ClientToScreen(p->Win.Wnd,&p->Offset); if (!p->Win.FullScreen) { #if !defined(TARGET_WINCE) && defined(MAXIMIZE_FULLSCREEN) WINDOWPLACEMENT Place; Place.length = sizeof(Place); GetWindowPlacement(p->Win.Wnd,&Place); if (Place.showCmd != SW_MAXIMIZE) #endif { GetClientRect(p->Win.Wnd,&r); if (r.right != p->ClientRect.right || r.bottom != p->ClientRect.bottom) { bool_t Skin = p->Skin[p->SkinNo].Valid; int TrackThumb; int TrackHeight = 0; p->TitleHeight = 0; p->ClientRect = r; r.top += p->Win.ToolBarHeight; if (p->WndTrack) { TrackHeight = WinUnitToPixelY(&p->Win,TRACKHEIGHT); r.bottom -= TrackHeight; MoveWindow(p->WndTrack,r.left,r.bottom,r.right,TrackHeight,TRUE); TrackThumb = WinUnitToPixelY(&p->Win,TRACKTHUMB); if (p->TrackThumb != TrackThumb) { p->TrackThumb = TrackThumb; // avoid calling this regulary because it shows the trackbar SendMessage(p->WndTrack, TBM_SETTHUMBLENGTH,TrackThumb,0); } } if (p->WndTitle) { p->TitleTimeWidth = 0; p->TitleFontSize = TITLEFONT; p->TitleFont = WinFont(&p->Win,&p->TitleFontSize,0); p->TitleHeight = WinUnitToPixelY(&p->Win,TITLEHEIGHT); p->TitleBorder = WinUnitToPixelX(&p->Win,3); p->TitleWidth = r.right - r.left; if (Skin) { skinitem* i = &p->Skin[p->SkinNo].Item[SKIN_TITLE]; p->TitleWidth = i->Rect.Width; p->TitleHeight = i->Rect.Height; MoveWindow(p->WndTitle,r.left + i->Rect.x,r.top + i->Rect.y,p->TitleWidth,p->TitleHeight,TRUE); } else { if (p->Win.ToolBarHeight) { r.bottom -= p->TitleHeight; MoveWindow(p->WndTitle,r.left,r.bottom,p->TitleWidth,p->TitleHeight,TRUE); } else { MoveWindow(p->WndTitle,r.left,r.top,p->TitleWidth,p->TitleHeight,TRUE); r.top += p->TitleHeight; } } p->TitleTop = (p->TitleHeight-WinUnitToPixelY(&p->Win,p->TitleFontSize))/2; } p->SkinArea.x = r.left; p->SkinArea.y = r.top; p->SkinArea.Width = r.right - r.left; p->SkinArea.Height = r.bottom - r.top;\ if (!Skin) p->SkinViewport = p->SkinArea; else { p->SkinViewport = p->Skin[p->SkinNo].Item[SKIN_VIEWPORT].Rect; p->SkinViewport.x += p->SkinArea.x; p->SkinViewport.y += p->SkinArea.y; } if (p->Win.ToolBarHeight && !p->VolResizeNeeded) ResizeVolume(p); } p->Viewport = p->SkinViewport; p->Viewport.x += p->Offset.x; p->Viewport.y += p->Offset.y; p->Player->Set(p->Player,PLAYER_SKIN_VIEWPORT,&p->Viewport,sizeof(rect)); p->Player->Set(p->Player,PLAYER_UPDATEVIDEO,NULL,0); if (p->VolResizeNeeded) { ResizeVolume(p); p->VolResizeNeeded = 0; } } } else { GetClientRect(p->Win.Wnd,&r); p->Viewport.x = r.left + p->Offset.x; p->Viewport.y = r.top + p->Offset.y; p->Viewport.Width = r.right - r.left; p->Viewport.Height = r.bottom - r.top; } if (Rotated) p->Player->Set(p->Player,PLAYER_ROTATEEND,NULL,0); DEBUG_MSG4(DEBUG_VIDEO,T("Resize end %d,%d,%d,%d"),p->Viewport.x,p->Viewport.y,p->Viewport.Width,p->Viewport.Height); } static BOOL CALLBACK EnumCheck(HWND Wnd, LPARAM lParam ) { intface* p = (intface*) lParam; RECT r; if (Wnd == p->Win.Wnd) return 0; if (IsWindowVisible(Wnd)) { GetWindowRect(Wnd,&r); if (p->Viewport.x < r.right && p->Viewport.x + p->Viewport.Width > r.left && p->Viewport.y < r.bottom && p->Viewport.y + p->Viewport.Height > r.top) { p->Overlap = 1; return 0; } } return 1; } static void UpdateHotKey(intface* p,bool_t State,bool_t NoKeep) { int i; if (!p->AllKeys) { for (i=0;iHotKey[i]) { if (State) { if (!WinEssentialKey(p->HotKey[i])) WinRegisterHotKey(&p->Win,HotKey[i],p->HotKey[i]); } else if (NoKeep || !(p->HotKey[i] & HOTKEY_KEEP)) WinUnRegisterHotKey(&p->Win,HotKey[i]); else if (WinEssentialKey(p->HotKey[i])) //essential keys -> register in the background WinRegisterHotKey(&p->Win,HotKey[i],p->HotKey[i]); } } else { WinAllKeys(State); if (!State && !NoKeep) for (i=0;iHotKey[i] & HOTKEY_KEEP) WinRegisterHotKey(&p->Win,HotKey[i],p->HotKey[i]); } } static void UpdateSleepTimer(intface* p) { #if defined(TARGET_WINCE) if (p->Play>0 || p->FFwd>0) { SleepTimerReset(); SetTimer(p->Win.Wnd,TIMER_SLEEP,SLEEP_CYCLE,NULL); } else KillTimer(p->Win.Wnd,TIMER_SLEEP); #endif } static void UpdateTitleScroll(intface* p) { if (p->Focus && p->TitleNameSize < p->TitleNameWidth) { if (p->TitleNameOffset >= p->TitleNameWidth - p->TitleNameSize) p->TitleNameOffset = p->TitleNameWidth - p->TitleNameSize; SetTimer(p->Win.Wnd,TIMER_TITLESCROLL,TITLESCROLL_CYCLE,NULL); } else { p->TitleNameOffset = 0; p->ScrollMode = 0; KillTimer(p->Win.Wnd,TIMER_TITLESCROLL); } } static void TitleScroll(intface* p) { if (p->ScrollModeScrollMode; else if (p->ScrollMode==TITLESCROLL_WAIT) { p->TitleNameOffset += 3; if (p->TitleNameOffset >= p->TitleNameWidth - p->TitleNameSize) { p->TitleNameOffset = p->TitleNameWidth - p->TitleNameSize; ++p->ScrollMode; } InvalidateRect(p->WndTitle,NULL,1); } else if (p->ScrollModeScrollMode; else { p->TitleNameOffset -= 3; if (p->TitleNameOffset<=0) { p->TitleNameOffset=0; p->ScrollMode = 0; } InvalidateRect(p->WndTitle,NULL,1); } UpdateTitleScroll(p); } static bool_t ShowVideo(intface* p) { bool_t b = p->Focus; if (!b) p->Player->Get(p->Player,PLAYER_SHOWINBACKGROUND,&b,sizeof(b)); return b; } static void UpdateClippingTimer(intface* p) { if (p->Clipping && ShowVideo(p)) SetTimer(p->Win.Wnd,TIMER_CLIPPING,CLIPPING_CYCLE,NULL); else KillTimer(p->Win.Wnd,TIMER_CLIPPING); } static bool_t IsOverlay(intface* p) { bool_t b = 0; p->Player->Get(p->Player,PLAYER_VIDEO_OVERLAY,&b,sizeof(b)); return b; } static bool_t IsOverlapped(intface* p) { if (!p->Win.FullScreen || p->Wait) { // check for overlapping top-level windows p->Overlap = 0; EnumWindows(EnumCheck,(LPARAM)p); if (p->Overlap) return 1; } return 0; } static void UpdateClipping(intface* p,bool_t Suggest,bool_t HotKey) { if (p->Clipping != Suggest) { KillTimer(p->Win.Wnd,TIMER_CLIPPING2); if (!Suggest && IsOverlapped(p)) return; // overlapping window -> clipping still needed p->Clipping = Suggest; p->Player->Set(p->Player,PLAYER_CLIPPING,&p->Clipping,sizeof(bool_t)); if (HotKey) UpdateHotKey(p,!p->Clipping,0); UpdateClippingTimer(p); } } static void RefreshButton(intface* p,int No,bool_t* State,int Id,int Off,int On) { int i; bool_t b; if (p->Player->Get(p->Player,No,&b,sizeof(b)) != ERR_NONE) b = -1; switch (No) { case PLAYER_PLAY: i = SKIN_PLAY; break; case PLAYER_FFWD: i = SKIN_FFWD; break; case PLAYER_MUTE: i = SKIN_MUTE; break; case PLAYER_FULLSCREEN: i = SKIN_FULLSCREEN; break; case PLAYER_REPEAT: i = SKIN_REPEAT; break; default: i = -1; break; } if (i>=0 && p->Skin[p->SkinNo].Item[i].Pushed != b) { p->Skin[p->SkinNo].Item[i].Pushed = b; SkinDrawItem(p->Skin+p->SkinNo,p->Win.Wnd,i,&p->SkinArea); } if (State && b != *State) { if (b == -1 || *State == -1) SendMessage(p->Win.WndTB,TB_ENABLEBUTTON,Id,MAKELPARAM(b!=-1,0)); *State = b; if (b != -1) { SendMessage(p->Win.WndTB,TB_CHECKBUTTON,Id,MAKELPARAM(b,0)); if (On>=0) SendMessage(p->Win.WndTB,TB_CHANGEBITMAP,Id,MAKELPARAM(p->Win.BitmapNo+(b?On:Off),0)); } } } static void SetTrackThumb(HWND Wnd, bool_t State) { int Style = GetWindowLong(Wnd,GWL_STYLE); if ((Style & TBS_NOTHUMB) != (State?0:TBS_NOTHUMB)) { Style ^= TBS_NOTHUMB; SetWindowLong(Wnd,GWL_STYLE,Style); } } static void UpdateTitleTime(intface* p) { if (p->WndTitle) { tick_t Time; if (p->Player->Get(p->Player,PLAYER_POSITION,&Time,sizeof(tick_t)) == ERR_NONE) { Time = (Time / TICKSPERSEC) * TICKSPERSEC; if (Time<0) Time=0; } else Time = -1; if (Time != p->TitleTime) { RECT r; r.left = p->TitleWidth - p->TitleTimeWidth - p->TitleDurWidth - p->TitleBorder; r.right = r.left + p->TitleTimeWidth; r.top = 0; r.bottom = p->TitleHeight; p->TitleTime = Time; InvalidateRect(p->WndTitle,&r,0); } } } static void UpdateMenuBool(intface* p,int MenuId,int Param) { bool_t b = 0; WinMenuEnable(&p->Win,1,MenuId,p->Player->Get(p->Player,Param,&b,sizeof(b)) != ERR_NOT_SUPPORTED); WinMenuCheck(&p->Win,1,MenuId,b); } static void UpdateMenuInt(intface* p,int MenuId,int Param,int Value) { int v = 0; WinMenuEnable(&p->Win,1,MenuId,p->Player->Get(p->Player,Param,&v,sizeof(v)) != ERR_NOT_SUPPORTED); WinMenuCheck(&p->Win,1,MenuId,v==Value); } static void UpdateMenuFrac(intface* p,int MenuId,int Param,int Num,int Den) { fraction f = {0,0}; WinMenuEnable(&p->Win,1,MenuId,p->Player->Get(p->Player,Param,&f,sizeof(f)) != ERR_NOT_SUPPORTED); WinMenuCheck(&p->Win,1,MenuId,f.Num*Den==f.Den*Num); } static void UpdateMenu(intface* p) { packetformat PacketFormat; node* AOutput; bool_t Stereo; bool_t b; int* i; int No,Id; int PreAmp; bool_t Accel; tchar_t Name[20+1]; int ACurrent = -1; int VCurrent = -1; int SubCurrent = -1; // remove old chapters if (!WinMenuEnable(&p->Win,0,IF_FILE_CHAPTERS_NONE,0)) { WinMenuInsert(&p->Win,0,IF_CHAPTER+1,IF_FILE_CHAPTERS_NONE,LangStr(INTERFACE_ID,IF_FILE_CHAPTERS_NONE)); for (No=1;NoWin,0,IF_CHAPTER+No)) break; } // add new chapters for (No=1;NoPlayer,No,Name,TSIZEOF(Name))>=0;++No) WinMenuInsert(&p->Win,0,IF_FILE_CHAPTERS_NONE,IF_CHAPTER+No,Name); if (No>1) WinMenuDelete(&p->Win,0,IF_FILE_CHAPTERS_NONE); else WinMenuEnable(&p->Win,0,IF_FILE_CHAPTERS_NONE,0); // remove old streams if (p->MenuVStream >= 0) { WinMenuInsert(&p->Win,1,p->MenuVStream,IF_OPTIONS_VIDEO_STREAM_NONE, LangStr(INTERFACE_ID,IF_OPTIONS_VIDEO_STREAM_NONE)); for (No=0;NoMenuStreams;++No) WinMenuDelete(&p->Win,1,IF_STREAM_VIDEO+No); } if (p->MenuAStream >= 0) { WinMenuInsert(&p->Win,1,p->MenuAStream,IF_OPTIONS_AUDIO_STREAM_NONE, LangStr(INTERFACE_ID,IF_OPTIONS_AUDIO_STREAM_NONE)); for (No=0;NoMenuStreams;++No) WinMenuDelete(&p->Win,1,IF_STREAM_AUDIO+No); } if (p->MenuSubStream >= 0) for (No=0;NoMenuStreams;++No) WinMenuDelete(&p->Win,1,IF_STREAM_SUBTITLE+No); // add new streams p->MenuStreams = 0; p->MenuAStream = -1; p->MenuVStream = -1; p->MenuSubStream = -1; for (No=0;PlayerGetStream(p->Player,No,&PacketFormat,Name,TSIZEOF(Name),NULL);++No) switch (PacketFormat.Type) { case PACKET_VIDEO: p->MenuVStream = IF_STREAM_VIDEO+No; WinMenuInsert(&p->Win,1,IF_OPTIONS_VIDEO_STREAM_NONE,IF_STREAM_VIDEO+No,Name); break; case PACKET_AUDIO: p->MenuAStream = IF_STREAM_AUDIO+No; WinMenuInsert(&p->Win,1,IF_OPTIONS_AUDIO_STREAM_NONE,IF_STREAM_AUDIO+No,Name); break; case PACKET_SUBTITLE: p->MenuSubStream = IF_STREAM_SUBTITLE+No; WinMenuInsert(&p->Win,1,IF_OPTIONS_SUBTITLE_STREAM_NONE,IF_STREAM_SUBTITLE+No,Name); break; } p->MenuStreams = No; p->Player->Get(p->Player,PLAYER_VSTREAM,&VCurrent,sizeof(int)); p->Player->Get(p->Player,PLAYER_ASTREAM,&ACurrent,sizeof(int)); p->Player->Get(p->Player,PLAYER_SUBSTREAM,&SubCurrent,sizeof(int)); if (p->MenuVStream<0) WinMenuEnable(&p->Win,1,IF_OPTIONS_VIDEO_STREAM_NONE,0); else { WinMenuCheck(&p->Win,1,IF_STREAM_VIDEO+VCurrent,1); WinMenuDelete(&p->Win,1,IF_OPTIONS_VIDEO_STREAM_NONE); } if (p->MenuAStream<0) WinMenuEnable(&p->Win,1,IF_OPTIONS_AUDIO_STREAM_NONE,0); else { WinMenuCheck(&p->Win,1,IF_STREAM_AUDIO+ACurrent,1); WinMenuDelete(&p->Win,1,IF_OPTIONS_AUDIO_STREAM_NONE); } if (SubCurrent >= MAXSTREAM) SubCurrent = -1; WinMenuEnable(&p->Win,1,IF_OPTIONS_SUBTITLE_STREAM_NONE,p->MenuSubStream>=0); WinMenuCheck(&p->Win,1,IF_OPTIONS_SUBTITLE_STREAM_NONE,SubCurrent<0); if (SubCurrent>=0) WinMenuCheck(&p->Win,1,IF_STREAM_SUBTITLE+SubCurrent,1); UpdateMenuFrac(p,IF_OPTIONS_ASPECT_AUTO,PLAYER_ASPECT,0,1); UpdateMenuFrac(p,IF_OPTIONS_ASPECT_SQUARE,PLAYER_ASPECT,1,1); UpdateMenuFrac(p,IF_OPTIONS_ASPECT_4_3_SCREEN,PLAYER_ASPECT,-4,3); UpdateMenuFrac(p,IF_OPTIONS_ASPECT_4_3_NTSC,PLAYER_ASPECT,10,11); UpdateMenuFrac(p,IF_OPTIONS_ASPECT_4_3_PAL,PLAYER_ASPECT,12,11); UpdateMenuFrac(p,IF_OPTIONS_ASPECT_16_9_SCREEN,PLAYER_ASPECT,-16,9); UpdateMenuFrac(p,IF_OPTIONS_ASPECT_16_9_NTSC,PLAYER_ASPECT,40,33); UpdateMenuFrac(p,IF_OPTIONS_ASPECT_16_9_PAL,PLAYER_ASPECT,16,11); UpdateMenuFrac(p,IF_OPTIONS_ZOOM_FIT_SCREEN,PLAYER_FULL_ZOOM,0,1); UpdateMenuFrac(p,IF_OPTIONS_ZOOM_FIT_110,PLAYER_FULL_ZOOM,-11,10); UpdateMenuFrac(p,IF_OPTIONS_ZOOM_FIT_120,PLAYER_FULL_ZOOM,-12,10); UpdateMenuFrac(p,IF_OPTIONS_ZOOM_FIT_130,PLAYER_FULL_ZOOM,-13,10); UpdateMenuFrac(p,IF_OPTIONS_ZOOM_FILL_SCREEN,PLAYER_FULL_ZOOM,-4,SCALE_ONE); UpdateMenuFrac(p,IF_OPTIONS_ZOOM_STRETCH_SCREEN,PLAYER_FULL_ZOOM,-3,SCALE_ONE); UpdateMenuFrac(p,IF_OPTIONS_ZOOM_50,PLAYER_FULL_ZOOM,1,2); UpdateMenuFrac(p,IF_OPTIONS_ZOOM_100,PLAYER_FULL_ZOOM,1,1); UpdateMenuFrac(p,IF_OPTIONS_ZOOM_150,PLAYER_FULL_ZOOM,3,2); UpdateMenuFrac(p,IF_OPTIONS_ZOOM_200,PLAYER_FULL_ZOOM,2,1); UpdateMenuBool(p,IF_OPTIONS_VIDEO_ZOOM_SMOOTH50,PLAYER_SMOOTH50); UpdateMenuBool(p,IF_OPTIONS_VIDEO_ZOOM_SMOOTHALWAYS,PLAYER_SMOOTHALWAYS); WinMenuCheck(&p->Win,1,IF_OPTIONS_VIEW_TITLEBAR,p->TitleBar); WinMenuCheck(&p->Win,1,IF_OPTIONS_VIEW_TRACKBAR,p->TrackBar); WinMenuCheck(&p->Win,1,IF_OPTIONS_VIEW_TASKBAR,p->TaskBar); //UpdateMenuInt(p,IF_OPTIONS_AUDIO_QUALITY_LOW,PLAYER_AUDIO_QUALITY,0); //UpdateMenuInt(p,IF_OPTIONS_AUDIO_QUALITY_MEDIUM,PLAYER_AUDIO_QUALITY,1); //UpdateMenuInt(p,IF_OPTIONS_AUDIO_QUALITY_HIGH,PLAYER_AUDIO_QUALITY,2); if (p->Player->Get(p->Player,PLAYER_PREAMP,&PreAmp,sizeof(PreAmp)) != ERR_NONE) PreAmp = 0; if (PreAmp != p->MenuPreAmp) { p->MenuPreAmp = PreAmp; stprintf_s(Name,TSIZEOF(Name),LangStr(INTERFACE_ID,IF_OPTIONS_AUDIO_PREAMP),PreAmp); WinMenuDelete(&p->Win,1,IF_OPTIONS_AUDIO_PREAMP); WinMenuInsert(&p->Win,1,IF_OPTIONS_AUDIO_PREAMP_INC,IF_OPTIONS_AUDIO_PREAMP,Name); } UpdateMenuInt(p,IF_OPTIONS_VIDEO_QUALITY_LOWEST,PLAYER_VIDEO_QUALITY,0); UpdateMenuInt(p,IF_OPTIONS_VIDEO_QUALITY_LOW,PLAYER_VIDEO_QUALITY,1); UpdateMenuInt(p,IF_OPTIONS_VIDEO_QUALITY_NORMAL,PLAYER_VIDEO_QUALITY,2); UpdateMenuInt(p,IF_OPTIONS_ROTATE_GUI,PLAYER_FULL_DIR,-1); UpdateMenuInt(p,IF_OPTIONS_ROTATE_0,PLAYER_FULL_DIR,0); UpdateMenuInt(p,IF_OPTIONS_ROTATE_90,PLAYER_FULL_DIR,DIR_SWAPXY | DIR_MIRRORLEFTRIGHT); UpdateMenuInt(p,IF_OPTIONS_ROTATE_270,PLAYER_FULL_DIR,DIR_SWAPXY | DIR_MIRRORUPDOWN); UpdateMenuInt(p,IF_OPTIONS_ROTATE_180,PLAYER_FULL_DIR,DIR_MIRRORUPDOWN | DIR_MIRRORLEFTRIGHT); UpdateMenuFrac(p,IF_OPTIONS_SPEED_10,PLAYER_PLAY_SPEED,1,10); UpdateMenuFrac(p,IF_OPTIONS_SPEED_25,PLAYER_PLAY_SPEED,1,4); UpdateMenuFrac(p,IF_OPTIONS_SPEED_50,PLAYER_PLAY_SPEED,1,2); UpdateMenuFrac(p,IF_OPTIONS_SPEED_80,PLAYER_PLAY_SPEED,8,10); UpdateMenuFrac(p,IF_OPTIONS_SPEED_90,PLAYER_PLAY_SPEED,9,10); UpdateMenuFrac(p,IF_OPTIONS_SPEED_100,PLAYER_PLAY_SPEED,1,1); UpdateMenuFrac(p,IF_OPTIONS_SPEED_110,PLAYER_PLAY_SPEED,11,10); UpdateMenuFrac(p,IF_OPTIONS_SPEED_120,PLAYER_PLAY_SPEED,12,10); UpdateMenuFrac(p,IF_OPTIONS_SPEED_150,PLAYER_PLAY_SPEED,3,2); UpdateMenuFrac(p,IF_OPTIONS_SPEED_200,PLAYER_PLAY_SPEED,2,1); UpdateMenuFrac(p,IF_OPTIONS_SPEED_BENCHMARK,PLAYER_PLAY_SPEED,0,1); UpdateMenuBool(p,IF_PLAY,PLAYER_PLAY); WinMenuEnable(&p->Win,1,IF_OPTIONS_VIDEO_DITHER,p->Color->Get(p->Color,COLOR_DITHER,&b,sizeof(b)) != ERR_NOT_SUPPORTED); WinMenuCheck(&p->Win,1,IF_OPTIONS_VIDEO_DITHER,b); UpdateMenuInt(p,IF_OPTIONS_AUDIO_STEREO,PLAYER_STEREO,STEREO_NORMAL); UpdateMenuInt(p,IF_OPTIONS_AUDIO_STEREO_SWAPPED,PLAYER_STEREO,STEREO_SWAPPED); UpdateMenuInt(p,IF_OPTIONS_AUDIO_STEREO_JOINED,PLAYER_STEREO,STEREO_JOINED); UpdateMenuInt(p,IF_OPTIONS_AUDIO_STEREO_LEFT,PLAYER_STEREO,STEREO_LEFT); UpdateMenuInt(p,IF_OPTIONS_AUDIO_STEREO_RIGHT,PLAYER_STEREO,STEREO_RIGHT); UpdateMenuBool(p,IF_OPTIONS_FULLSCREEN,PLAYER_FULLSCREEN); UpdateMenuBool(p,IF_OPTIONS_REPEAT,PLAYER_REPEAT); UpdateMenuBool(p,IF_OPTIONS_SHUFFLE,PLAYER_SHUFFLE); p->Equalizer->Get(p->Equalizer,EQUALIZER_ENABLED,&b,sizeof(b)); WinMenuCheck(&p->Win,1,IF_OPTIONS_EQUALIZER,b); p->Player->Get(p->Player,PLAYER_VIDEO_ACCEL,&Accel,sizeof(Accel)); p->Player->Get(p->Player,PLAYER_VOUTPUTID,&Id,sizeof(Id)); WinMenuCheck(&p->Win,1,IF_OPTIONS_VIDEO_TURNOFF,!Id); for (No=0,i=ARRAYBEGIN(p->VOutput,int);i!=ARRAYEND(p->VOutput,int);++i,++No) { WinMenuCheck(&p->Win,1,IF_VIDEO+No,*i==Id && !Accel); WinMenuCheck(&p->Win,1,IF_VIDEOACCEL+No,*i==Id && Accel); } p->Player->Get(p->Player,PLAYER_AOUTPUTID,&Id,sizeof(Id)); WinMenuCheck(&p->Win,1,IF_OPTIONS_AUDIO_TURNOFF,!Id); for (No=0,i=ARRAYBEGIN(p->AOutput,int);i!=ARRAYEND(p->AOutput,int);++i,++No) WinMenuCheck(&p->Win,1,IF_AUDIO+No,*i==Id); Stereo = 1; p->Player->Get(p->Player,PLAYER_AOUTPUT,&AOutput,sizeof(AOutput)); if (AOutput && AOutput->Get(AOutput,OUT_INPUT|PIN_FORMAT,&PacketFormat,sizeof(PacketFormat))==ERR_NONE && PacketFormat.Type == PACKET_AUDIO && PacketFormat.Format.Audio.Channels<2) Stereo = 0; WinMenuEnable(&p->Win,1,IF_OPTIONS_AUDIO_STEREO,Stereo); WinMenuEnable(&p->Win,1,IF_OPTIONS_AUDIO_STEREO_SWAPPED,Stereo); WinMenuEnable(&p->Win,1,IF_OPTIONS_AUDIO_STEREO_JOINED,Stereo); WinMenuEnable(&p->Win,1,IF_OPTIONS_AUDIO_STEREO_LEFT,Stereo); WinMenuEnable(&p->Win,1,IF_OPTIONS_AUDIO_STEREO_RIGHT,Stereo); } static void UpdatePosition(intface* p); static int Delta(intface* p,node* Node,int Param,int d,int Min,int Max) { int State; if (Node && Node->Get(Node,Param,&State,sizeof(State))==ERR_NONE) { State += d; if (State < Min) State = Min; if (State > Max) State = Max; Node->Set(Node,Param,&State,sizeof(State)); if (Param == PLAYER_VOLUME) { if (State > Min) Toggle(p,PLAYER_MUTE,0); UpdateVolume(p); } } return State; } static bool_t IsCoverAtr(player *Player) { node* Format; int CoverArt; int VStream; return Player->Get(Player,PLAYER_FORMAT,&Format,sizeof(Format))==ERR_NONE && Format && Format->Get(Format,FORMAT_COVERART,&CoverArt,sizeof(CoverArt))==ERR_NONE && Player->Get(Player,PLAYER_VSTREAM,&VStream,sizeof(VStream))==ERR_NONE && VStream==CoverArt; } static bool_t ToggleFullScreen(intface* p,int Force,int CoverArtFullScreen) { bool_t State = 0; if (p->Player->Get(p->Player,PLAYER_FULLSCREEN,&State,sizeof(State))==ERR_NONE) { node* VOutput; bool_t Primary; packetformat Format; if (State==Force) return State; State = !State; if (p->Player->Get(p->Player,PLAYER_VOUTPUT,&VOutput,sizeof(VOutput))!=ERR_NONE || !VOutput || VOutput->Get(VOutput,VOUT_PRIMARY,&Primary,sizeof(Primary))!=ERR_NONE || !Primary || (!CoverArtFullScreen && IsCoverAtr(p->Player)) || (!p->ForceFullScreen && VOutput->Get(VOutput,OUT_INPUT|PIN_FORMAT,&Format,sizeof(Format))!=ERR_NONE) || (!p->ForceFullScreen && !Format.Format.Video.Width)) State = 0; UpdatePosition(p); // before returning from fullscreen if (!State) { p->Player->Set(p->Player,PLAYER_FULLSCREEN,&State,sizeof(State)); p->Player->Set(p->Player,PLAYER_UPDATEVIDEO,NULL,0); RefreshButton(p,PLAYER_FULLSCREEN,&p->FullScreen,IF_OPTIONS_FULLSCREEN,-1,-1); } if (p->Skin[p->SkinNo].Valid) p->Skin[p->SkinNo].Hidden = State; if (p->WndTrack) ShowWindow(p->WndTrack,State ? SW_HIDE:SW_SHOWNA); if (p->WndTitle) ShowWindow(p->WndTitle,State ? SW_HIDE:SW_SHOWNA); WinSetFullScreen(&p->Win,State); if (p->Win.WndTB) UpdateWindow(p->Win.WndTB); ShowVol(p,!State); // called after WinSetFullScreen so TOPMOST is over taskbar if (State) { p->Player->Set(p->Player,PLAYER_FULLSCREEN,&State,sizeof(State)); p->Player->Set(p->Player,PLAYER_UPDATEVIDEO,NULL,0); RefreshButton(p,PLAYER_FULLSCREEN,&p->FullScreen,IF_OPTIONS_FULLSCREEN,-1,-1); } } return State; } static bool_t Toggle(intface* p,int Param,int Force) { bool_t State = 0; if (p->Player->Get(p->Player,Param,&State,sizeof(State))==ERR_NONE) { assert(Param != PLAYER_FULLSCREEN); if (State==Force) return State; State = !State; p->Player->Set(p->Player,Param,&State,sizeof(State)); if (Param == PLAYER_PLAY) RefreshButton(p,PLAYER_PLAY,&p->Play,IF_PLAY,0,1); else if (Param == PLAYER_FFWD) RefreshButton(p,PLAYER_FFWD,&p->FFwd,IF_FASTFORWARD,4,1); else RefreshButton(p,Param,NULL,0,0,0); } return State; } static bool_t IsAutoRun(intface* p, const tchar_t* CmdLine) { while (IsSpace(*CmdLine)) ++CmdLine; return tcsnicmp(CmdLine,T("-autorun"),8)==0; } static void EnumDir(const tchar_t* Path,const tchar_t* Exts,player* Player) { streamdir DirItem; stream* Stream = GetStream(Path,1); if (Stream) { int Result = Stream->EnumDir(Stream,Path,Exts,1,&DirItem); while (Result == ERR_NONE) { tchar_t FullPath[MAXPATH]; AbsPath(FullPath,TSIZEOF(FullPath),DirItem.FileName,Path); if (DirItem.Size < 0) EnumDir(FullPath,Exts,Player); else if (DirItem.Type == FTYPE_AUDIO || DirItem.Type == FTYPE_VIDEO) { int n; Player->Get(Player,PLAYER_LIST_COUNT,&n,sizeof(n)); Player->Set(Player,PLAYER_LIST_URL+n,FullPath,sizeof(FullPath)); } Result = Stream->EnumDir(Stream,NULL,NULL,0,&DirItem); } NodeDelete((node*)Stream); } } void ProcessCmdLine( intface* p, const tchar_t* CmdLine) { int n; tchar_t URL[MAXPATH]; if (IsAutoRun(p,CmdLine)) { // search for media files on SD card tchar_t Base[MAXPATH]; int* i; array List; tchar_t* s; int ExtsLen = 1024; tchar_t* Exts = malloc(ExtsLen*sizeof(tchar_t)); if (!Exts) return; Exts[0]=0; NodeEnumClass(&List,FORMAT_CLASS); for (i=ARRAYBEGIN(List,int);i!=ARRAYEND(List,int);++i) { const tchar_t* s = LangStr(*i,NODE_EXTS); if (s[0]) { if (Exts[0]) tcscat_s(Exts,ExtsLen,T(";")); tcscat_s(Exts,ExtsLen,s); } } ArrayClear(&List); n = 0; p->Player->Set(p->Player,PLAYER_LIST_COUNT,&n,sizeof(n)); GetModuleFileName(GetModuleHandle(NULL),Base,MAXPATH); s = tcsrchr(Base,'\\'); if (s) *s=0; s = tcsrchr(Base,'\\'); if (s) *s=0; EnumDir(Base,Exts,p->Player); free(Exts); } else { while (IsSpace(*CmdLine)) ++CmdLine; if (*CmdLine == '"') { tchar_t* ch = tcschr(++CmdLine,'"'); if (ch) *ch=0; } tcscpy_s(URL,TSIZEOF(URL),CmdLine); p->CmdLineMode = 1; n = 1; p->Player->Set(p->Player,PLAYER_LIST_COUNT,&n,sizeof(n)); PlayerAdd(p->Player,0,URL,NULL); } n = 0; p->Player->Set(p->Player,PLAYER_LIST_CURRIDX,&n,sizeof(n)); if (!IsWindowEnabled(p->Win.Wnd)) Toggle(p,PLAYER_PLAY,0); } void SetTrackPos(intface* p,int x) { fraction Percent; RECT r,rt; int Adj; if (p->TrackSetPos == x) return; p->TrackSetPos = x; SendMessage(p->WndTrack,TBM_GETCHANNELRECT,0,(LONG)&r); SendMessage(p->WndTrack,TBM_GETTHUMBRECT,0,(LONG)&rt); Adj = (rt.right-rt.left) >> 1; r.left += Adj; r.right -= (rt.right-rt.left)-Adj; if (x > 32768) x -= 65536; if (r.right <= r.left) r.right = r.left+1; if (x < r.left) x = r.left; if (x > r.right) x = r.right; x = Scale(TRACKMAX,x-r.left,r.right-r.left); Percent.Num = x; Percent.Den = TRACKMAX; p->Player->Set(p->Player,PLAYER_PERCENT,&Percent,sizeof(Percent)); } LRESULT CALLBACK TitleProc(HWND WndTitle, UINT Msg, WPARAM wParam, LPARAM lParam) { intface* p = (intface*) WinGetObject(WndTitle); if (p) { PAINTSTRUCT Paint; RECT r; tchar_t Time[32]; switch (Msg) { case WM_ERASEBKGND: GetClientRect(WndTitle,&r); FillRect((HDC)wParam,&r,p->TitleBrush ? p->TitleBrush:GetSysColorBrush(COLOR_BTNFACE)); break; case WM_SIZE: p->UpdateScroll = 1; break; case WM_LBUTTONDOWN: break; case WM_MOUSEMOVE: break; case WM_LBUTTONUP: break; case WM_PAINT: BeginPaint(WndTitle,&Paint); SelectObject(Paint.hdc,p->TitleFont); SetBkColor(Paint.hdc,p->TitleFace); SetTextColor(Paint.hdc,p->TitleText); #if !defined(TARGET_WINCE) SetTextAlign(Paint.hdc,TA_LEFT); #endif if (!p->TitleTimeWidth) { SIZE Size; tchar_t* s; tchar_t Dur[32]; tick_t Duration; tchar_t TitleName[256]; node* Format; if (p->Player->Get(p->Player,PLAYER_FORMAT,&Format,sizeof(Format)) == ERR_NONE && !Format) p->TitleTime = -1; p->Player->Get(p->Player,PLAYER_TITLE,TitleName,sizeof(TitleName)); if (tcscmp(p->TitleName,TitleName)!=0) { tcscpy_s(p->TitleName,TSIZEOF(p->TitleName),TitleName); GetTextExtentPoint(Paint.hdc,p->TitleName,tcslen(p->TitleName),&Size); p->TitleNameWidth = Size.cx; p->TitleNameOffset = 0; p->ScrollMode = 0; p->UpdateScroll = 1; } s = Dur; Dur[0] = 0; if (p->Player->Get(p->Player,PLAYER_DURATION,&Duration,sizeof(Duration)) == ERR_NONE && Duration>=0) { TickToString(Dur,TSIZEOF(Dur),Duration,0,0,1); if (p->TitleTime<0) p->TitleTime = 0; } else s = T("0:00:00"); GetTextExtentPoint(Paint.hdc,s,tcslen(s),&Size); p->TitleTimeWidth = Size.cx; p->TitleDurWidth = 0; p->TitleDur[0] = 0; if (Dur[0]) { stprintf_s(p->TitleDur,TSIZEOF(p->TitleDur),T("/%s"),Dur); GetTextExtentPoint(Paint.hdc,p->TitleDur,tcslen(p->TitleDur),&Size); p->TitleDurWidth = Size.cx; p->UpdateScroll = 1; } } if (p->TitleTime>=0) TickToString(Time,TSIZEOF(Time),p->TitleTime,0,0,1); else Time[0] = 0; r.top = p->TitleTop; r.bottom = p->TitleHeight - p->TitleTop; r.left = p->TitleBorder; r.right = p->TitleWidth - p->TitleTimeWidth - p->TitleDurWidth - p->TitleBorder * 2; p->TitleNameSize = r.right - r.left; if (p->UpdateScroll) { p->UpdateScroll = 0; UpdateTitleScroll(p); } ExtTextOut(Paint.hdc,r.left-p->TitleNameOffset,r.top,ETO_CLIPPED,&r,p->TitleName,tcslen(p->TitleName),NULL); r.left = r.right + p->TitleBorder; r.right = r.left + p->TitleTimeWidth; //SetBkColor(Paint.hdc,0xFFFFFF); ExtTextOut(Paint.hdc,r.left,r.top,ETO_CLIPPED|ETO_OPAQUE,&r,Time,tcslen(Time),NULL); //SetBkColor(Paint.hdc,0x00FF00); if (p->TitleDurWidth) { r.left = r.right; r.right = r.left + p->TitleDurWidth; ExtTextOut(Paint.hdc,r.left,r.top,ETO_CLIPPED,&r,p->TitleDur,tcslen(p->TitleDur),NULL); } EndPaint(WndTitle,&Paint); break; } } return DefWindowProc(WndTitle,Msg,wParam,lParam); } static void SetKeyInSeek(intface* p) { bool_t First = !p->InSeek; p->InSeek = 1; p->Player->Set(p->Player,PLAYER_INSEEK,&p->InSeek,sizeof(p->InSeek)); SetTimer(p->Win.Wnd,TIMER_KEYINSEEK,First?KEYINSEEK_START:KEYINSEEK_REPEAT,NULL); } static void StopSeek(intface* p) { p->InSeek = 0; p->Player->Set(p->Player,PLAYER_INSEEK,&p->InSeek,sizeof(p->InSeek)); KillTimer(p->Win.Wnd,TIMER_KEYINSEEK); if (p->Capture) { ReleaseCapture(); p->Capture = 0; KillTimer(p->Win.Wnd,TIMER_SLIDERINSEEK); } } LRESULT CALLBACK TrackProc(HWND WndTrack, UINT Msg, WPARAM wParam, LPARAM lParam) { intface* p = (intface*) WinGetObject(WndTrack); if (Msg == WM_LBUTTONDOWN) { p->InSeek = 1; p->Capture = 1; p->TrackSetPos = -1; p->Player->Set(p->Player,PLAYER_INSEEK,&p->InSeek,sizeof(p->InSeek)); SetTrackPos(p,LOWORD(lParam)); SetCapture(WndTrack); SetTimer(p->Win.Wnd,TIMER_SLIDERINSEEK,SLIDERINSEEK_CYCLE,NULL); return 0; } if (Msg == WM_MOUSEMOVE) { if (p->InSeek && (wParam & MK_LBUTTON)) SetTrackPos(p,LOWORD(lParam)); return 0; } if (Msg == WM_LBUTTONUP) { if (p->InSeek) { SetTrackPos(p,LOWORD(lParam)); StopSeek(p); } return 0; } return CallWindowProc(p->DefTrackProc,WndTrack,Msg,wParam,lParam); } void UpdateVol(intface* p) { if (p->Vol >= 0) { SendMessage(p->WndVol,TBM_SETPOS,1,p->Vol); p->Player->Set(p->Player,PLAYER_VOLUME,&p->Vol,sizeof(p->Vol)); p->Vol = -1; if (p->Skin[p->SkinNo].Valid) SkinUpdate(&p->Skin[p->SkinNo],p->Player,p->Win.Wnd,&p->SkinArea); } } void SetVolPos(intface* p,int x) { RECT r; int Adj; SendMessage(p->WndVol,TBM_GETCHANNELRECT,0,(LONG)&r); Adj = WinUnitToPixelX(&p->Win,VOLTHUMB)/4; r.left += Adj; r.right -= Adj; if (x > 32768) x -= 65536; if (r.right <= r.left) r.right = r.left+1; if (x < r.left) x = r.left; if (x > r.right) x = r.right; p->Vol = (100*(x-r.left))/(r.right-r.left); } LRESULT CALLBACK VolBackProc(HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam) { //DEBUG_MSG1(DEBUG_WIN,T("MSG %04x"),Msg); switch (Msg) { #if defined(TARGET_WINCE) case WM_CTLCOLORSTATIC: return (LRESULT) GetSysColorBrush(COLOR_BTNFACE); #endif } return DefWindowProc(Wnd,Msg,wParam,lParam); } LRESULT CALLBACK VolProc(HWND WndVol, UINT Msg, WPARAM wParam, LPARAM lParam) { intface* p = (intface*) WinGetObject(WndVol); switch (Msg) { case WM_MOUSEMOVE: if ((wParam & MK_LBUTTON)==0) break; case WM_LBUTTONDOWN: case WM_LBUTTONDBLCLK: SetVolPos(p,LOWORD(lParam)); if (!p->InVol) { p->InVol = 1; SetForegroundWindow(p->Win.Wnd); SetCapture(WndVol); SetTimer(p->Win.Wnd,TIMER_SLIDERINVOL,SLIDERINVOL_CYCLE,NULL); UpdateVol(p); } return 0; case WM_LBUTTONUP: if (!p->InVol) SetForegroundWindow(p->Win.Wnd); else { p->InVol = 0; ReleaseCapture(); KillTimer(p->Win.Wnd,TIMER_SLIDERINVOL); } SetVolPos(p,LOWORD(lParam)); UpdateVol(p); return 0; } return CallWindowProc(p->DefVolProc,WndVol,Msg,wParam,lParam); } void CreateDeviceMenu(intface* p) { int No; int *i; NodeEnumClass(&p->VOutput,VOUT_CLASS); NodeEnumClass(&p->AOutput,AOUT_CLASS); for (No=0,i=ARRAYBEGIN(p->VOutput,int);i!=ARRAYEND(p->VOutput,int);++i,++No) { if (VOutIDCT(*i)) { tchar_t s[256]; stprintf_s(s,TSIZEOF(s),LangStr(INTERFACE_ID,IF_OPTIONS_VIDEO_ACCEL),LangStr(*i,NODE_NAME)); WinMenuInsert(&p->Win,1,IF_OPTIONS_VIDEO_TURNOFF,IF_VIDEOACCEL+No,s); } WinMenuInsert(&p->Win,1,IF_OPTIONS_VIDEO_TURNOFF,IF_VIDEO+No,LangStr(*i,NODE_NAME)); } for (No=0,i=ARRAYBEGIN(p->AOutput,int);i!=ARRAYEND(p->AOutput,int);++i,++No) WinMenuInsert(&p->Win,1,IF_OPTIONS_AUDIO_TURNOFF,IF_AUDIO+No,LangStr(*i,NODE_NAME)); } static menudef MenuDef[] = { { 0,INTERFACE_ID, IF_FILE }, { 1,INTERFACE_ID, IF_FILE_OPENFILE }, { 1,INTERFACE_ID, IF_FILE_CORETHEQUE }, { 1,INTERFACE_ID, IF_FILE_PLAYLIST }, { 1,-1,-1 }, { 1,INTERFACE_ID, IF_PLAY }, { 1,INTERFACE_ID, IF_NEXT }, { 1,INTERFACE_ID, IF_PREV }, { 1,-1,-1 }, { 1,INTERFACE_ID, IF_FILE_CHAPTERS }, { 2,INTERFACE_ID, IF_FILE_CHAPTERS_NONE }, { 1,INTERFACE_ID, IF_FILE_MEDIAINFO }, { 1,INTERFACE_ID, IF_FILE_BENCHMARK }, { 1,INTERFACE_ID, IF_FILE_ABOUT }, { 1,-1,-1 }, { 1,INTERFACE_ID, IF_FILE_EXIT }, { 0,INTERFACE_ID, IF_OPTIONS }, { 1,INTERFACE_ID, IF_OPTIONS_SPEED }, { 2,INTERFACE_ID, IF_OPTIONS_SPEED_10 }, { 2,INTERFACE_ID, IF_OPTIONS_SPEED_25 }, { 2,INTERFACE_ID, IF_OPTIONS_SPEED_50 }, { 2,INTERFACE_ID, IF_OPTIONS_SPEED_80 }, { 2,INTERFACE_ID, IF_OPTIONS_SPEED_90 }, { 2,INTERFACE_ID, IF_OPTIONS_SPEED_100 }, { 2,INTERFACE_ID, IF_OPTIONS_SPEED_110 }, { 2,INTERFACE_ID, IF_OPTIONS_SPEED_120 }, { 2,INTERFACE_ID, IF_OPTIONS_SPEED_150 }, { 2,INTERFACE_ID, IF_OPTIONS_SPEED_200 }, { 1,INTERFACE_ID, IF_OPTIONS_VIEW, MENU_SMALL }, { 2,INTERFACE_ID, IF_OPTIONS_ZOOM }, #if !defined(SH3) { 3,INTERFACE_ID, IF_OPTIONS_ZOOM_FIT_SCREEN }, { 3,INTERFACE_ID, IF_OPTIONS_ZOOM_FILL_SCREEN }, { 3,INTERFACE_ID, IF_OPTIONS_ZOOM_STRETCH_SCREEN }, { 3,INTERFACE_ID, IF_OPTIONS_ZOOM_FIT_110 }, { 3,INTERFACE_ID, IF_OPTIONS_ZOOM_FIT_120 }, { 3,INTERFACE_ID, IF_OPTIONS_ZOOM_FIT_130 }, { 3,INTERFACE_ID, IF_OPTIONS_ZOOM_50 }, #endif { 3,INTERFACE_ID, IF_OPTIONS_ZOOM_100 }, #if !defined(SH3) { 3,INTERFACE_ID, IF_OPTIONS_ZOOM_150 }, #endif { 3,INTERFACE_ID, IF_OPTIONS_ZOOM_200 }, #if !defined(SH3) { 2,INTERFACE_ID, IF_OPTIONS_ASPECT }, { 3,INTERFACE_ID, IF_OPTIONS_ASPECT_AUTO }, { 3,INTERFACE_ID, IF_OPTIONS_ASPECT_SQUARE }, { 3,INTERFACE_ID, IF_OPTIONS_ASPECT_4_3_SCREEN }, { 3,INTERFACE_ID, IF_OPTIONS_ASPECT_4_3_NTSC }, { 3,INTERFACE_ID, IF_OPTIONS_ASPECT_4_3_PAL }, { 3,INTERFACE_ID, IF_OPTIONS_ASPECT_16_9_SCREEN }, { 3,INTERFACE_ID, IF_OPTIONS_ASPECT_16_9_NTSC }, { 3,INTERFACE_ID, IF_OPTIONS_ASPECT_16_9_PAL }, #endif { 2,INTERFACE_ID, IF_OPTIONS_ORIENTATION }, { 3,INTERFACE_ID, IF_OPTIONS_ORIENTATION_FULLSCREEN }, { 3,INTERFACE_ID, IF_OPTIONS_ROTATE_GUI }, { 3,INTERFACE_ID, IF_OPTIONS_ROTATE_0 }, { 3,INTERFACE_ID, IF_OPTIONS_ROTATE_90 }, { 3,INTERFACE_ID, IF_OPTIONS_ROTATE_270 }, { 3,INTERFACE_ID, IF_OPTIONS_ROTATE_180 }, { 2,INTERFACE_ID, IF_OPTIONS_VIEW, MENU_NOTSMALL }, { 3,INTERFACE_ID, IF_OPTIONS_VIEW_TITLEBAR }, { 3,INTERFACE_ID, IF_OPTIONS_VIEW_TRACKBAR }, { 3,INTERFACE_ID, IF_OPTIONS_VIEW_TASKBAR }, { 1,INTERFACE_ID, IF_OPTIONS_VIDEO }, #if !defined(SH3) && !defined(MIPS) { 2,INTERFACE_ID, IF_OPTIONS_VIDEO_ZOOM_SMOOTH50 }, { 2,INTERFACE_ID, IF_OPTIONS_VIDEO_ZOOM_SMOOTHALWAYS }, { 2,INTERFACE_ID, IF_OPTIONS_VIDEO_DITHER }, #endif { 2,INTERFACE_ID, IF_OPTIONS_VIDEO_QUALITY }, { 3,INTERFACE_ID, IF_OPTIONS_VIDEO_QUALITY_LOWEST }, { 3,INTERFACE_ID, IF_OPTIONS_VIDEO_QUALITY_LOW }, { 3,INTERFACE_ID, IF_OPTIONS_VIDEO_QUALITY_NORMAL }, { 2,-1,-1 }, { 2,INTERFACE_ID, IF_OPTIONS_VIDEO_DEVICE, MENU_SMALL|MENU_GRAYED }, { 3,INTERFACE_ID, IF_OPTIONS_VIDEO_TURNOFF }, { 2,-1,-1 }, { 2,INTERFACE_ID, IF_OPTIONS_VIDEO_STREAM, MENU_SMALL|MENU_GRAYED }, { 3,INTERFACE_ID, IF_OPTIONS_VIDEO_STREAM_NONE }, { 1,INTERFACE_ID, IF_OPTIONS_AUDIO }, { 2,INTERFACE_ID, IF_OPTIONS_AUDIO_CHANNELS, MENU_SMALL }, { 3,INTERFACE_ID, IF_OPTIONS_AUDIO_STEREO }, { 3,INTERFACE_ID, IF_OPTIONS_AUDIO_STEREO_SWAPPED }, { 3,INTERFACE_ID, IF_OPTIONS_AUDIO_STEREO_JOINED }, { 3,INTERFACE_ID, IF_OPTIONS_AUDIO_STEREO_LEFT }, { 3,INTERFACE_ID, IF_OPTIONS_AUDIO_STEREO_RIGHT }, // { 2,-1,-1 }, // { 2,INTERFACE_ID, IF_OPTIONS_AUDIO_QUALITY }, // { 3,INTERFACE_ID, IF_OPTIONS_AUDIO_QUALITY_LOW }, // { 3,INTERFACE_ID, IF_OPTIONS_AUDIO_QUALITY_MEDIUM }, // { 3,INTERFACE_ID, IF_OPTIONS_AUDIO_QUALITY_HIGH }, { 2,-1,-1 }, { 2,INTERFACE_ID, IF_OPTIONS_AUDIO_PREAMP_DEC }, { 2,INTERFACE_ID, IF_OPTIONS_AUDIO_PREAMP }, { 2,INTERFACE_ID, IF_OPTIONS_AUDIO_PREAMP_INC }, { 2,-1,-1 }, { 2,INTERFACE_ID, IF_OPTIONS_AUDIO_DEVICE, MENU_SMALL|MENU_GRAYED }, { 3,INTERFACE_ID, IF_OPTIONS_AUDIO_TURNOFF }, { 2,-1,-1 }, { 2,INTERFACE_ID, IF_OPTIONS_AUDIO_STREAM, MENU_SMALL|MENU_GRAYED }, { 3,INTERFACE_ID, IF_OPTIONS_AUDIO_STREAM_NONE }, //!SUBTITLE { 1,INTERFACE_ID, IF_OPTIONS_SUBTITLE_STREAM, MENU_GRAYED }, //!SUBTITLE { 2,INTERFACE_ID, IF_OPTIONS_SUBTITLE_STREAM_NONE }, { 1,-1,-1 }, { 1,INTERFACE_ID, IF_OPTIONS_REPEAT }, { 1,INTERFACE_ID, IF_OPTIONS_SHUFFLE }, { 1,INTERFACE_ID, IF_OPTIONS_EQUALIZER }, { 1,INTERFACE_ID, IF_OPTIONS_FULLSCREEN }, #if defined(CONFIG_SKIN) { 1,INTERFACE_ID, IF_OPTIONS_SKIN }, #endif { 1,-1,-1 }, { 1,INTERFACE_ID, IF_OPTIONS_SETTINGS }, MENUDEF_END }; void CreateButtons(intface* p) { if (QueryPlatform(PLATFORM_TYPENO) != TYPE_SMARTPHONE) { bool_t FullScreenButton = 1; RECT r,rv; WinBitmap(&p->Win,IDB_TOOLBAR16,IDB_TOOLBAR32,10); WinAddButton(&p->Win,-1,-1,NULL,0); WinAddButton(&p->Win,IF_PLAY,0,NULL,1); WinAddButton(&p->Win,IF_FASTFORWARD,4,NULL,1); WinAddButton(&p->Win,IF_STOP,5,NULL,0); WinAddButton(&p->Win,-1,-1,NULL,0); WinAddButton(&p->Win,IF_OPTIONS_FULLSCREEN,6,NULL,1); WinAddButton(&p->Win,IF_OPTIONS_MUTE,7,NULL,1); GetClientRect(p->Win.WndTB,&r); SendMessage(p->Win.WndTB,TB_GETRECT,IF_OPTIONS_MUTE,(LPARAM)&rv); if (r.right-rv.right < VOLMINWIDTH) { WinDeleteButton(&p->Win,IF_FASTFORWARD); SendMessage(p->Win.WndTB,TB_GETRECT,IF_OPTIONS_MUTE,(LPARAM)&rv); if (r.right-rv.right < VOLMINWIDTH) { WinDeleteButton(&p->Win,IF_OPTIONS_FULLSCREEN); FullScreenButton = 0; } } WinMenuDelete(&p->Win,0,IF_PLAY); if (FullScreenButton) WinMenuDelete(&p->Win,1,IF_OPTIONS_FULLSCREEN); WinMenuDelete(&p->Win,1,IF_OPTIONS_MUTE); } } static void UpdateVolume(intface* p) { int x; if (p->Skin[p->SkinNo].Valid) SkinUpdate(&p->Skin[p->SkinNo],p->Player,p->Win.Wnd,&p->SkinArea); if (p->WndVol) { bool_t Enable = p->Player->Get(p->Player,PLAYER_VOLUME,&x,sizeof(x))==ERR_NONE; EnableWindow(p->WndVol,Enable); SetTrackThumb(p->WndVol,Enable); if (Enable) SendMessage(p->WndVol,TBM_SETPOS,1,x); } RefreshButton(p,PLAYER_MUTE,&p->Mute,IF_OPTIONS_MUTE,7,8); } static void CreateVolumeTrack(intface* p) { if (QueryPlatform(PLATFORM_TYPENO) != TYPE_SMARTPHONE) { WNDCLASS WinClass; memset(&WinClass,0,sizeof(WinClass)); WinClass.style = CS_HREDRAW | CS_VREDRAW; WinClass.lpfnWndProc = (WNDPROC) VolBackProc; WinClass.cbClsExtra = 0; WinClass.cbWndExtra = 0; WinClass.hInstance = p->Win.Module; WinClass.hCursor = WinCursorArrow(); WinClass.hbrBackground = GetSysColorBrush(COLOR_BTNFACE); WinClass.lpszMenuName = 0; WinClass.lpszClassName = T("VolumeBack"); RegisterClass(&WinClass); p->WndVolBack = CreateWindowEx( WS_EX_TOPMOST, WinClass.lpszClassName, Context()->ProgramName, (p->Win.ToolBarHeight ? WS_CHILD:WS_POPUP) | WS_VISIBLE | TBS_HORZ|TBS_BOTH|TBS_NOTICKS|TBS_FIXEDLENGTH, 200, 0, 40, 20, (p->Win.ToolBarHeight ? p->Win.WndTB:p->Win.Wnd), NULL, p->Win.Module, NULL ); p->WndVol = CreateWindowEx( 0, TRACKBAR_CLASS, NULL, WS_CHILD | WS_VISIBLE | TBS_HORZ|TBS_BOTH|TBS_NOTICKS|TBS_FIXEDLENGTH, 0, 0, 40, 20, p->WndVolBack, NULL, p->Win.Module, NULL ); p->DefVolProc = (WNDPROC)GetWindowLong(p->WndVol,GWL_WNDPROC); SetWindowLong(p->WndVol,GWL_WNDPROC,(LONG)VolProc); WinSetObject(p->WndVol,&p->Win); SendMessage(p->WndVol, TBM_SETRANGE, FALSE,MAKELONG(0,100)); SendMessage(p->WndVol, TBM_SETPAGESIZE,0,10); SendMessage(p->WndVol, TBM_SETLINESIZE,0,10); ResizeVolume(p); UpdateVolume(p); } } static int UpdateTitleBar(intface* p,bool_t DoResize) { if (p->TitleBar && !p->WndTitle && p->Win.Wnd) { WNDCLASS WinClass; memset(&WinClass,0,sizeof(WinClass)); WinClass.style = CS_HREDRAW | CS_VREDRAW; WinClass.lpfnWndProc = (WNDPROC) TitleProc; WinClass.cbClsExtra = 0; WinClass.cbWndExtra = 0; WinClass.hInstance = p->Win.Module; WinClass.hCursor = WinCursorArrow(); WinClass.hbrBackground = NULL; WinClass.lpszMenuName = 0; WinClass.lpszClassName = T("TitleBar"); RegisterClass(&WinClass); p->WndTitle = CreateWindowEx( 0, WinClass.lpszClassName, T("Time"), WS_CHILD | WS_VISIBLE, 0, 0, 200, 20, p->Win.Wnd, NULL, p->Win.Module, NULL ); WinSetObject(p->WndTitle,&p->Win); p->ClientRect.right = -1; if (DoResize) Resize(p); } if (!p->TitleBar && p->WndTitle) { DestroyWindow(p->WndTitle); p->WndTitle = NULL; p->ClientRect.right = -1; if (DoResize) Resize(p); } return ERR_NONE; } static NOINLINE void UpdateTrackPos(intface* p) { if (p->Skin[p->SkinNo].Valid) SkinUpdate(p->Skin+p->SkinNo,p->Player,p->Win.Wnd,&p->SkinArea); if (p->WndTrack) { fraction f; int TrackPos; if (p->Player->Get(p->Player,PLAYER_PERCENT,&f,sizeof(fraction)) == ERR_NONE) TrackPos = Scale(TRACKMAX,f.Num,f.Den); else TrackPos = -1; if (TrackPos != p->TrackPos) { if (TrackPos == -1) { SetTrackThumb(p->WndTrack,0); EnableWindow(p->WndTrack,0); } if (p->TrackPos == -1) { SetTrackThumb(p->WndTrack,1); EnableWindow(p->WndTrack,1); } p->TrackPos = TrackPos; SendMessage(p->WndTrack,TBM_SETPOS,1,TrackPos); } } } static int UpdateTrackBar(intface* p,bool_t DoResize) { bool_t TrackBar = p->TrackBar && !p->Skin[p->SkinNo].Valid; if (TrackBar && !p->WndTrack && p->Win.Wnd) { p->WndTrack = CreateWindowEx( 0, TRACKBAR_CLASS, T("Time"), WS_CHILD | WS_VISIBLE | TBS_HORZ|TBS_BOTH|TBS_NOTICKS|TBS_FIXEDLENGTH, 0, 0, 200, 20, p->Win.Wnd, NULL, p->Win.Module, NULL ); p->DefTrackProc = (WNDPROC)GetWindowLong(p->WndTrack,GWL_WNDPROC); SetWindowLong(p->WndTrack,GWL_WNDPROC,(LONG)TrackProc); WinSetObject(p->WndTrack,&p->Win); SendMessage(p->WndTrack, TBM_SETRANGE, FALSE,MAKELONG(0,TRACKMAX)); SendMessage(p->WndTrack, TBM_SETPAGESIZE,0,TRACKMAX/20); SendMessage(p->WndTrack, TBM_SETLINESIZE,0,TRACKMAX/100); p->TrackPos = 0; UpdateTrackPos(p); p->ClientRect.right = -1; if (DoResize) Resize(p); } if (!TrackBar && p->WndTrack) { DestroyWindow(p->WndTrack); p->WndTrack = NULL; p->ClientRect.right = -1; if (DoResize) Resize(p); } p->TrackThumb = -1; return ERR_NONE; } static void BeforeExit(intface* p) { if (Context()->Wnd) { NodeRegSaveValue(0,REG_INITING,NULL,0,TYPE_INT); NodeRegSave((node*)p); UpdateHotKey(p,0,1); if (p->WndVolBack) { DestroyWindow(p->WndVolBack); p->WndVolBack = NULL; } Context_Wnd(NULL); } } static void ShowError2(intface* p, const tchar_t* s) { win* Win; if (p->Player) { p->Player->Set(p->Player,PLAYER_STOP,NULL,1); // full stop (no filling buffers) ToggleFullScreen(p,0,0); //ATI tweaks would have problem } UpdateClipping(p,1,1); // force clipping mode // find application foreground window Win = &p->Win; while (Win->Child) Win = Win->Child; MessageBox(Win->Wnd,s,LangStr(PLATFORM_ID,PLATFORM_ERROR),MB_OK|MB_SETFOREGROUND|MB_TOPMOST); } static void ToggleStream(intface* p,int Id,int Type,bool_t UseNone) { packetformat Format; int No,Current,First=-1; p->Player->Get(p->Player,Id,&Current,sizeof(int)); if (Current == MAXSTREAM) Current = -1; for (No=0;PlayerGetStream(p->Player,No,&Format,NULL,0,NULL);++No) if (Format.Type == Type) { if (First < 0) First = No; if (Current == No) Current = -1; else if (Current == -1) Current = No; } if (Current == -1) Current = UseNone ? MAXSTREAM:First; if (Current >= 0) { p->Player->Set(p->Player,Id,&Current,sizeof(int)); p->Player->Set(p->Player,PLAYER_RESYNC,NULL,0); } } static int UpdateTaskBar(intface* p) { if (!p->Win.FullScreen) DIASet(p->TaskBar?DIA_TASKBAR:0,DIA_TASKBAR); return ERR_NONE; } static int UpdateSkin(intface* p,bool_t Others); static int UpdateSkinFile(intface* p) { if (p->Player) { SkinFree(p->Skin,NULL); SkinLoad(p->Skin,p->Win.Wnd,p->SkinPath); UpdateSkin(p,1); } return ERR_NONE; } static int Command(intface* p,int Cmd) { node* Node; bool_t b; int i; fraction f; tick_t t; int Zero = 0; switch (Cmd) { case IF_SKIN0: p->SkinNo = 0; UpdateSkin(p,1); break; case IF_SKIN1: p->SkinNo = 1; UpdateSkin(p,1); break; case IF_OPTIONS_VOLUME_UP: Delta(p,(node*)p->Player,PLAYER_VOLUME,10,0,100); break; case IF_OPTIONS_VOLUME_DOWN: Delta(p,(node*)p->Player,PLAYER_VOLUME,-10,0,100); break; case IF_OPTIONS_VOLUME_UP_FINE: Delta(p,(node*)p->Player,PLAYER_VOLUME,3,0,100); break; case IF_OPTIONS_VOLUME_DOWN_FINE: Delta(p,(node*)p->Player,PLAYER_VOLUME,-3,0,100); break; case IF_OPTIONS_BRIGHTNESS_UP: Delta(p,p->Color,COLOR_BRIGHTNESS,6,-128,127); break; case IF_OPTIONS_BRIGHTNESS_DOWN: Delta(p,p->Color,COLOR_BRIGHTNESS,-6,-128,127); break; case IF_OPTIONS_CONTRAST_UP: Delta(p,p->Color,COLOR_CONTRAST,6,-128,127); break; case IF_OPTIONS_CONTRAST_DOWN: Delta(p,p->Color,COLOR_CONTRAST,-6,-128,127); break; case IF_OPTIONS_SATURATION_UP: Delta(p,p->Color,COLOR_SATURATION,6,-128,127); break; case IF_OPTIONS_SATURATION_DOWN: Delta(p,p->Color,COLOR_SATURATION,-6,-128,127); break; case IF_OPTIONS_SCREEN: SetDisplayPower(!GetDisplayPower(),1); break; case IF_OPTIONS_AUDIO_STEREO_TOGGLE: p->Player->Get(p->Player,PLAYER_STEREO,&i,sizeof(i)); i = i==STEREO_LEFT?STEREO_RIGHT:STEREO_LEFT; p->Player->Set(p->Player,PLAYER_STEREO,&i,sizeof(i)); break; case IF_OPTIONS_TOGGLE_VIDEO: ToggleStream(p,PLAYER_VSTREAM,PACKET_VIDEO,0); break; case IF_OPTIONS_TOGGLE_SUBTITLE: ToggleStream(p,PLAYER_SUBSTREAM,PACKET_SUBTITLE,1); break; case IF_OPTIONS_TOGGLE_AUDIO: ToggleStream(p,PLAYER_ASTREAM,PACKET_AUDIO,0); break; case IF_OPTIONS_ZOOM_IN: p->Player->Get(p->Player,PLAYER_FULL_ZOOM,&f,sizeof(f)); if (f.Num <= 0) f.Num = f.Den = 1; if (f.Den != 100) { f.Num = f.Num * 100 / f.Den; f.Den = 100; } f.Num+=5; p->Player->Set(p->Player,PLAYER_FULL_ZOOM,&f,sizeof(f)); p->Player->Set(p->Player,PLAYER_SKIN_ZOOM,&f,sizeof(f)); break; case IF_OPTIONS_ZOOM_OUT: p->Player->Get(p->Player,PLAYER_FULL_ZOOM,&f,sizeof(f)); if (f.Num <= 0) f.Num = f.Den = 1; if (f.Den != 100) { f.Num = f.Num * 100 / f.Den; f.Den = 100; } if (f.Num>5) f.Num-=5; p->Player->Set(p->Player,PLAYER_FULL_ZOOM,&f,sizeof(f)); p->Player->Set(p->Player,PLAYER_SKIN_ZOOM,&f,sizeof(f)); break; case IF_OPTIONS_ZOOM_FIT: p->Player->Get(p->Player,PLAYER_FULL_ZOOM,&f,sizeof(f)); f.Num = f.Num == -1 ? -2:-1; f.Den = 1; p->Player->Set(p->Player,PLAYER_FULL_ZOOM,&f,sizeof(f)); p->Player->Set(p->Player,PLAYER_SKIN_ZOOM,&f,sizeof(f)); break; case IF_PLAY_FULLSCREEN: if (p->Player->Get(p->Player,PLAYER_STREAMING,&b,sizeof(b))==ERR_NONE && b) ToggleFullScreen(p,-1,0); else if (!(p->Player->Get(p->Player,PLAYER_FULLSCREEN,&b,sizeof(b))==ERR_NONE && b) && !(p->Player->Get(p->Player,PLAYER_PLAY,&b,sizeof(b))==ERR_NONE && b)) { ToggleFullScreen(p,1,0); Toggle(p,PLAYER_PLAY,1); } else { Toggle(p,PLAYER_PLAY,0); ToggleFullScreen(p,0,0); } break; case IF_MOVE_FFWD: SetKeyInSeek(p); p->Player->Set(p->Player,PLAYER_MOVEFFWD,NULL,0); break; case IF_MOVE_BACK: SetKeyInSeek(p); p->Player->Set(p->Player,PLAYER_MOVEBACK,NULL,0); break; case IF_NEXT2: case IF_NEXT: p->Player->Set(p->Player,PLAYER_NEXT,NULL,0); break; case IF_PREV_SMART: case IF_PREV_SMART2: p->Player->Set(p->Player,PLAYER_PREV,NULL,1); break; case IF_PREV: p->Player->Set(p->Player,PLAYER_PREV,NULL,0); break; case IF_PLAYPAUSE: case IF_PLAY: p->Play = -1; // force button refresh Toggle(p,PLAYER_PLAY,-1); break; case IF_FASTFORWARD: p->FFwd = -1; // force button refresh Toggle(p,PLAYER_FFWD,-1); break; case IF_FILE_BENCHMARK: if (!ToggleFullScreen(p,1,0)) { if (p->WndTrack) SetTrackThumb(p->WndTrack,0); WaitBegin(); } UpdateWindow(p->Win.Wnd); t = 0; p->Player->Set(p->Player,PLAYER_BENCHMARK,&t,sizeof(t)); p->Bench = 1; break; case IF_STOP: p->Player->Set(p->Player,PLAYER_STOP,NULL,0); f.Num = 0; f.Den = 1; p->Player->Set(p->Player,PLAYER_PERCENT,&f,sizeof(f)); break; case IF_FILE_OPENFILE: p->CmdLineMode = 0; Node = NodeCreate(OPENFILE_ID); i = 0; Node->Set(Node,OPENFILE_FLAGS,&i,sizeof(i)); i = MEDIA_CLASS; Node->Set(Node,OPENFILE_CLASS,&i,sizeof(i)); UpdateHotKey(p,0,1); i = ((win*)Node)->Popup((win*)Node,&p->Win); NodeDelete(Node); if (i==2) { UpdateWindow(p->Win.Wnd); i=0; p->Player->Set(p->Player,PLAYER_LIST_CURRIDX,&i,sizeof(i)); } break; case IF_FILE_CORETHEQUE: WinPopupClass(CORETHEQUE_UI_ID,&p->Win); p->Player->Set(p->Player,PLAYER_UPDATEVIDEO,NULL,0); break; case IF_FILE_ABOUT: WinPopupClass(ABOUT_ID,&p->Win); break; case IF_OPTIONS_SETTINGS: UpdateHotKey(p,0,1); p->AllKeysWarning = 1; WinPopupClass(SETTINGS_ID,&p->Win); p->AllKeysWarning = 0; p->Player->Set(p->Player,PLAYER_UPDATEVIDEO,NULL,0); break; case IF_FILE_PLAYLIST: WinPopupClass(PLAYLIST_ID,&p->Win); break; case IF_FILE_MEDIAINFO: WinPopupClass(MEDIAINFO_ID,&p->Win); break; case IF_FILE_EXIT: // just to be sure to stop overlay update (WM_DESTROY comes after window is hidden) BeforeExit(p); DestroyWindow(p->Win.Wnd); break; case IF_OPTIONS_REPEAT: Toggle(p,PLAYER_REPEAT,-1); break; case IF_OPTIONS_SHUFFLE: Toggle(p,PLAYER_SHUFFLE,-1); break; case IF_OPTIONS_EQUALIZER: p->Equalizer->Get(p->Equalizer,EQUALIZER_ENABLED,&b,sizeof(b)); b = !b; p->Equalizer->Set(p->Equalizer,EQUALIZER_ENABLED,&b,sizeof(b)); //p->Player->Set(p->Player,PLAYER_RESYNC,NULL,0); break; case IF_OPTIONS_SKIN: Node = NodeCreate(OPENFILE_ID); if (Node) { i = OPENFLAG_SINGLE; Node->Set(Node,OPENFILE_FLAGS,&i,sizeof(i)); i = SKIN_CLASS; Node->Set(Node,OPENFILE_CLASS,&i,sizeof(i)); i = ((win*)Node)->Popup((win*)Node,&p->Win); NodeDelete(Node); if (i==1) { p->SkinPath[0] = 0; UpdateSkinFile(p); } } break; case IF_OPTIONS_FULLSCREEN: p->FullScreen = -1; // force button refresh ToggleFullScreen(p,-1,1); break; case IF_OPTIONS_MUTE: p->Mute = -1; // force button refresh if (p->Player->Get(p->Player,PLAYER_VOLUME,&i,sizeof(i))==ERR_NONE && i==0) { i = 1; p->Player->Set(p->Player,PLAYER_VOLUME,&i,sizeof(i)); } Toggle(p,PLAYER_MUTE,-1); UpdateVolume(p); break; case IF_OPTIONS_VIDEO_DITHER: p->Color->Get(p->Color,COLOR_DITHER,&b,sizeof(b)); b = !b; p->Color->Set(p->Color,COLOR_DITHER,&b,sizeof(b)); break; case IF_OPTIONS_ROTATE: p->Player->Get(p->Player,PLAYER_FULL_DIR,&i,sizeof(i)); switch (i) { case 0: i = DIR_SWAPXY | DIR_MIRRORLEFTRIGHT; break; case DIR_SWAPXY | DIR_MIRRORLEFTRIGHT: i = DIR_MIRRORUPDOWN | DIR_MIRRORLEFTRIGHT; break; case DIR_MIRRORUPDOWN | DIR_MIRRORLEFTRIGHT: i = DIR_SWAPXY | DIR_MIRRORUPDOWN; break; case DIR_SWAPXY | DIR_MIRRORUPDOWN: i = 0; break; default: i = 0; break; } p->Player->Set(p->Player,PLAYER_FULL_DIR,&i,sizeof(i)); p->Player->Get(p->Player,PLAYER_SKIN_DIR,&i,sizeof(i)); switch (i) { case 0: i = DIR_SWAPXY | DIR_MIRRORLEFTRIGHT; break; case DIR_SWAPXY | DIR_MIRRORLEFTRIGHT: i = DIR_MIRRORUPDOWN | DIR_MIRRORLEFTRIGHT; break; case DIR_MIRRORUPDOWN | DIR_MIRRORLEFTRIGHT: i = DIR_SWAPXY | DIR_MIRRORUPDOWN; break; case DIR_SWAPXY | DIR_MIRRORUPDOWN: i = 0; break; default: i = 0; break; } p->Player->Set(p->Player,PLAYER_SKIN_DIR,&i,sizeof(i)); break; case IF_OPTIONS_ROTATE_GUI: i = -1; p->Player->Set(p->Player,PLAYER_FULL_DIR,&i,sizeof(i)); break; case IF_OPTIONS_ROTATE_0: i = 0; p->Player->Set(p->Player,PLAYER_FULL_DIR,&i,sizeof(i)); break; case IF_OPTIONS_ROTATE_270: i = DIR_SWAPXY | DIR_MIRRORUPDOWN; p->Player->Set(p->Player,PLAYER_FULL_DIR,&i,sizeof(i)); break; case IF_OPTIONS_ROTATE_180: i = DIR_MIRRORUPDOWN | DIR_MIRRORLEFTRIGHT; p->Player->Set(p->Player,PLAYER_FULL_DIR,&i,sizeof(i)); break; case IF_OPTIONS_ROTATE_90: i = DIR_SWAPXY | DIR_MIRRORLEFTRIGHT; p->Player->Set(p->Player,PLAYER_FULL_DIR,&i,sizeof(i)); break; case IF_OPTIONS_ASPECT_AUTO: f.Num = 0; f.Den = 1; p->Player->Set(p->Player,PLAYER_ASPECT,&f,sizeof(f)); break; case IF_OPTIONS_ASPECT_SQUARE: f.Num = 1; f.Den = 1; p->Player->Set(p->Player,PLAYER_ASPECT,&f,sizeof(f)); break; case IF_OPTIONS_ASPECT_4_3_SCREEN: f.Num = -4; f.Den = 3; p->Player->Set(p->Player,PLAYER_ASPECT,&f,sizeof(f)); break; case IF_OPTIONS_ASPECT_4_3_NTSC: f.Num = 10; f.Den = 11; p->Player->Set(p->Player,PLAYER_ASPECT,&f,sizeof(f)); break; case IF_OPTIONS_ASPECT_4_3_PAL: f.Num = 12; f.Den = 11; p->Player->Set(p->Player,PLAYER_ASPECT,&f,sizeof(f)); break; case IF_OPTIONS_ASPECT_16_9_SCREEN: f.Num = -16; f.Den = 9; p->Player->Set(p->Player,PLAYER_ASPECT,&f,sizeof(f)); break; case IF_OPTIONS_ASPECT_16_9_NTSC: f.Num = 40; f.Den = 33; p->Player->Set(p->Player,PLAYER_ASPECT,&f,sizeof(f)); break; case IF_OPTIONS_ASPECT_16_9_PAL: f.Num = 16; f.Den = 11; p->Player->Set(p->Player,PLAYER_ASPECT,&f,sizeof(f)); break; case IF_OPTIONS_ZOOM_FIT_SCREEN: f.Num = 0; f.Den = 1; p->Player->Set(p->Player,PLAYER_FULL_ZOOM,&f,sizeof(f)); p->Player->Set(p->Player,PLAYER_SKIN_ZOOM,&f,sizeof(f)); break; case IF_OPTIONS_ZOOM_STRETCH_SCREEN: f.Num = -3; f.Den = SCALE_ONE; p->Player->Set(p->Player,PLAYER_FULL_ZOOM,&f,sizeof(f)); p->Player->Set(p->Player,PLAYER_SKIN_ZOOM,&f,sizeof(f)); break; case IF_OPTIONS_ZOOM_FILL_SCREEN: f.Num = -4; f.Den = SCALE_ONE; p->Player->Set(p->Player,PLAYER_FULL_ZOOM,&f,sizeof(f)); p->Player->Set(p->Player,PLAYER_SKIN_ZOOM,&f,sizeof(f)); break; case IF_OPTIONS_VIEW_TITLEBAR: p->TitleBar = !p->TitleBar; UpdateTitleBar(p,1); break; case IF_OPTIONS_VIEW_TASKBAR: p->TaskBar = !p->TaskBar; UpdateTaskBar(p); break; case IF_OPTIONS_VIEW_TRACKBAR: p->TrackBar = !p->TrackBar; UpdateTrackBar(p,1); break; case IF_OPTIONS_ZOOM_50: f.Num = 1; f.Den = 2; p->Player->Set(p->Player,PLAYER_FULL_ZOOM,&f,sizeof(f)); p->Player->Set(p->Player,PLAYER_SKIN_ZOOM,&f,sizeof(f)); break; case IF_OPTIONS_ZOOM_100: f.Num = 1; f.Den = 1; p->Player->Set(p->Player,PLAYER_FULL_ZOOM,&f,sizeof(f)); p->Player->Set(p->Player,PLAYER_SKIN_ZOOM,&f,sizeof(f)); break; case IF_OPTIONS_ZOOM_FIT_110: f.Num = -11; f.Den = 10; p->Player->Set(p->Player,PLAYER_FULL_ZOOM,&f,sizeof(f)); p->Player->Set(p->Player,PLAYER_SKIN_ZOOM,&f,sizeof(f)); break; case IF_OPTIONS_ZOOM_FIT_120: f.Num = -12; f.Den = 10; p->Player->Set(p->Player,PLAYER_FULL_ZOOM,&f,sizeof(f)); p->Player->Set(p->Player,PLAYER_SKIN_ZOOM,&f,sizeof(f)); break; case IF_OPTIONS_ZOOM_FIT_130: f.Num = -13; f.Den = 10; p->Player->Set(p->Player,PLAYER_FULL_ZOOM,&f,sizeof(f)); p->Player->Set(p->Player,PLAYER_SKIN_ZOOM,&f,sizeof(f)); break; case IF_OPTIONS_ZOOM_150: f.Num = 3; f.Den = 2; p->Player->Set(p->Player,PLAYER_FULL_ZOOM,&f,sizeof(f)); p->Player->Set(p->Player,PLAYER_SKIN_ZOOM,&f,sizeof(f)); break; case IF_OPTIONS_ZOOM_200: f.Num = 2; f.Den = 1; p->Player->Set(p->Player,PLAYER_FULL_ZOOM,&f,sizeof(f)); p->Player->Set(p->Player,PLAYER_SKIN_ZOOM,&f,sizeof(f)); break; case IF_OPTIONS_VIDEO_ZOOM_SMOOTH50: Toggle(p,PLAYER_SMOOTH50,-1); Toggle(p,PLAYER_SMOOTHALWAYS,0); break; case IF_OPTIONS_VIDEO_ZOOM_SMOOTHALWAYS: Toggle(p,PLAYER_SMOOTHALWAYS,-1); Toggle(p,PLAYER_SMOOTH50,0); break; case IF_OPTIONS_AUDIO_STEREO: i = STEREO_NORMAL; p->Player->Set(p->Player,PLAYER_STEREO,&i,sizeof(i)); break; case IF_OPTIONS_AUDIO_STEREO_SWAPPED: i = STEREO_SWAPPED; p->Player->Set(p->Player,PLAYER_STEREO,&i,sizeof(i)); break; case IF_OPTIONS_AUDIO_STEREO_JOINED: i = STEREO_JOINED; p->Player->Set(p->Player,PLAYER_STEREO,&i,sizeof(i)); break; case IF_OPTIONS_AUDIO_STEREO_LEFT: i = STEREO_LEFT; p->Player->Set(p->Player,PLAYER_STEREO,&i,sizeof(i)); break; case IF_OPTIONS_AUDIO_STEREO_RIGHT: i = STEREO_RIGHT; p->Player->Set(p->Player,PLAYER_STEREO,&i,sizeof(i)); break; case IF_OPTIONS_AUDIO_PREAMP_INC: p->Player->Get(p->Player,PLAYER_PREAMP,&i,sizeof(i)); i += 25; if (i>200) i=200; p->Player->Set(p->Player,PLAYER_PREAMP,&i,sizeof(i)); break; case IF_OPTIONS_AUDIO_PREAMP_DEC: p->Player->Get(p->Player,PLAYER_PREAMP,&i,sizeof(i)); i -= 25; if (i<-200) i=-200; p->Player->Set(p->Player,PLAYER_PREAMP,&i,sizeof(i)); break; case IF_OPTIONS_AUDIO_PREAMP: i = 0; p->Player->Set(p->Player,PLAYER_PREAMP,&i,sizeof(i)); break; case IF_OPTIONS_AUDIO_QUALITY_LOW: i = 0; p->Player->Set(p->Player,PLAYER_AUDIO_QUALITY,&i,sizeof(i)); break; case IF_OPTIONS_AUDIO_QUALITY_MEDIUM: i = 1; p->Player->Set(p->Player,PLAYER_AUDIO_QUALITY,&i,sizeof(i)); break; case IF_OPTIONS_AUDIO_QUALITY_HIGH: i = 2; p->Player->Set(p->Player,PLAYER_AUDIO_QUALITY,&i,sizeof(i)); break; case IF_OPTIONS_VIDEO_QUALITY_LOWEST: i = 0; p->Player->Set(p->Player,PLAYER_VIDEO_QUALITY,&i,sizeof(i)); p->Player->Set(p->Player,PLAYER_RESYNC,NULL,0); break; case IF_OPTIONS_VIDEO_QUALITY_LOW: i = 1; p->Player->Set(p->Player,PLAYER_VIDEO_QUALITY,&i,sizeof(i)); p->Player->Set(p->Player,PLAYER_RESYNC,NULL,0); break; case IF_OPTIONS_VIDEO_QUALITY_NORMAL: i = 2; p->Player->Set(p->Player,PLAYER_VIDEO_QUALITY,&i,sizeof(i)); p->Player->Set(p->Player,PLAYER_RESYNC,NULL,0); break; case IF_OPTIONS_SPEED_10: f.Num = 1; f.Den = 10; p->Player->Set(p->Player,PLAYER_PLAY_SPEED,&f,sizeof(f)); break; case IF_OPTIONS_SPEED_25: f.Num = 1; f.Den = 4; p->Player->Set(p->Player,PLAYER_PLAY_SPEED,&f,sizeof(f)); break; case IF_OPTIONS_SPEED_50: f.Num = 1; f.Den = 2; p->Player->Set(p->Player,PLAYER_PLAY_SPEED,&f,sizeof(f)); break; case IF_OPTIONS_SPEED_100: f.Num = 1; f.Den = 1; p->Player->Set(p->Player,PLAYER_PLAY_SPEED,&f,sizeof(f)); break; case IF_OPTIONS_SPEED_150: f.Num = 3; f.Den = 2; p->Player->Set(p->Player,PLAYER_PLAY_SPEED,&f,sizeof(f)); break; case IF_OPTIONS_SPEED_200: f.Num = 2; f.Den = 1; p->Player->Set(p->Player,PLAYER_PLAY_SPEED,&f,sizeof(f)); break; case IF_OPTIONS_SPEED_80: f.Num = 8; f.Den = 10; p->Player->Set(p->Player,PLAYER_PLAY_SPEED,&f,sizeof(f)); break; case IF_OPTIONS_SPEED_90: f.Num = 9; f.Den = 10; p->Player->Set(p->Player,PLAYER_PLAY_SPEED,&f,sizeof(f)); break; case IF_OPTIONS_SPEED_110: f.Num = 11; f.Den = 10; p->Player->Set(p->Player,PLAYER_PLAY_SPEED,&f,sizeof(f)); break; case IF_OPTIONS_SPEED_120: f.Num = 12; f.Den = 10; p->Player->Set(p->Player,PLAYER_PLAY_SPEED,&f,sizeof(f)); break; case IF_OPTIONS_SPEED_BENCHMARK: f.Num = 0; f.Den = 1; p->Player->Set(p->Player,PLAYER_PLAY_SPEED,&f,sizeof(f)); break; case IF_OPTIONS_VIDEO_TURNOFF: p->Player->Set(p->Player,PLAYER_VOUTPUTID,&Zero,sizeof(Zero)); break; case IF_OPTIONS_AUDIO_TURNOFF: p->Player->Set(p->Player,PLAYER_AOUTPUTID,&Zero,sizeof(Zero)); UpdateVolume(p); break; case IF_OPTIONS_SUBTITLE_STREAM_NONE: i = MAXSTREAM; p->Player->Set(p->Player,PLAYER_SUBSTREAM,&i,sizeof(i)); break; } if (Cmd >= IF_CHAPTER && Cmd < IF_CHAPTER+100) { tick_t Time = PlayerGetChapter(p->Player,Cmd-IF_CHAPTER,NULL,0); if (Time>=0) p->Player->Set(p->Player,PLAYER_POSITION,&Time,sizeof(tick_t)); } if (Cmd >= IF_STREAM_AUDIO && Cmd < IF_STREAM_AUDIO+MAXSTREAM) { i = Cmd-IF_STREAM_AUDIO; p->Player->Set(p->Player,PLAYER_ASTREAM,&i,sizeof(i)); p->Player->Set(p->Player,PLAYER_RESYNC,NULL,0); } if (Cmd >= IF_STREAM_VIDEO && Cmd < IF_STREAM_VIDEO+MAXSTREAM) { i = Cmd-IF_STREAM_VIDEO; p->Player->Set(p->Player,PLAYER_VSTREAM,&i,sizeof(i)); p->Player->Set(p->Player,PLAYER_RESYNC,NULL,0); } if (Cmd >= IF_STREAM_SUBTITLE && Cmd < IF_STREAM_SUBTITLE+MAXSTREAM) { i = Cmd-IF_STREAM_SUBTITLE; p->Player->Set(p->Player,PLAYER_SUBSTREAM,&i,sizeof(i)); p->Player->Set(p->Player,PLAYER_RESYNC,NULL,0); } if (Cmd >= IF_VIDEO && Cmd < IF_VIDEO+ARRAYCOUNT(p->VOutput,int)) { b = 0; p->Player->Set(p->Player,PLAYER_VIDEO_ACCEL,&b,sizeof(b)); p->Player->Set(p->Player,PLAYER_VOUTPUTID,ARRAYBEGIN(p->VOutput,int)+(Cmd-IF_VIDEO),sizeof(int)); } if (Cmd >= IF_VIDEOACCEL && Cmd < IF_VIDEOACCEL+ARRAYCOUNT(p->VOutput,int)) { b = 1; p->Player->Set(p->Player,PLAYER_VIDEO_ACCEL,&b,sizeof(b)); p->Player->Set(p->Player,PLAYER_VOUTPUTID,ARRAYBEGIN(p->VOutput,int)+(Cmd-IF_VIDEOACCEL),sizeof(int)); } if (Cmd >= IF_AUDIO && Cmd < IF_AUDIO+ARRAYCOUNT(p->AOutput,int)) { p->Player->Set(p->Player,PLAYER_AOUTPUTID,ARRAYBEGIN(p->AOutput,int)+(Cmd-IF_AUDIO),sizeof(int)); UpdateVolume(p); } if (p->Focus && p->Clipping) UpdateClipping(p,0,1); // maybe overlapping window is gone return ERR_INVALID_PARAM; } static int PlayerNotify(intface* p,int Id,int Value) { if (Id == PLAYER_TITLE) { p->TitleTimeWidth = 0; if (Value) p->TitleTime = -1; if (p->WndTitle && !p->FullScreen) InvalidateRect(p->WndTitle,NULL,1); // redraws timer too! if (!p->Win.FullScreen && !p->Bench && p->InSeek && p->Capture) PostMessage(p->Win.Wnd,MSG_PLAYER,PLAYER_PERCENT,Value); } else if (Id == PLAYER_PERCENT) { if (!p->Win.FullScreen && !p->Bench && (!p->InSeek || !p->Capture)) PostMessage(p->Win.Wnd,MSG_PLAYER,PLAYER_PERCENT,Value); } else PostMessage(p->Win.Wnd,MSG_PLAYER,Id,Value); return ERR_NONE; } static int ErrorNotify(intface* p,int Param,int Param2) { const tchar_t* Msg = (const tchar_t*)Param2; if (GetCurrentThreadId() != p->ThreadId) PostMessage(p->Win.Wnd,MSG_ERROR,0,(LPARAM)tcsdup(Msg)); else ShowError2(p,Msg); return ERR_NONE; } static int KeyRotate(intface* p,int Code) { int i; int Dir; if (!QueryAdvanced(ADVANCED_KEYFOLLOWDIR)) return Code; switch (Code) { case VK_UP: i=1; break; case VK_RIGHT: i=2; break; case VK_DOWN: i=3; break; case VK_LEFT: i=4; break; default: return Code; } p->Player->Get(p->Player,PLAYER_REL_DIR,&Dir,sizeof(Dir)); if (Dir & DIR_SWAPXY) i += (Dir & DIR_MIRRORUPDOWN) ? 1:3; else i += (Dir & DIR_MIRRORUPDOWN) ? 2:0; if (i>4) i-=4; switch (i) { case 1: Code = VK_UP; break; case 2: Code = VK_RIGHT; break; case 3: Code = VK_DOWN; break; case 4: Code = VK_LEFT; break; } return Code; } static void DefaultSkin(intface* p); static NOINLINE void UpdatePosition(intface* p) { UpdateTrackPos(p); UpdateTitleTime(p); } static const int SkinCmd[MAX_SKINITEM] = { 0, 0, 0, 0, 0, IF_PLAY, IF_STOP, IF_NEXT, IF_PREV, IF_OPTIONS_FULLSCREEN, IF_FASTFORWARD, IF_FILE_PLAYLIST, IF_FILE_OPENFILE, IF_OPTIONS_MUTE, IF_OPTIONS_REPEAT, IF_SKIN0, IF_SKIN1, IF_OPTIONS_ROTATE, 0, IF_PLAY_FULLSCREEN, IF_FILE_EXIT, }; static bool_t Proc(intface* p, int Msg, uint32_t wParam, uint32_t lParam, int* Result) { tick_t t; bool_t b; int i,Key; PAINTSTRUCT Paint; notify Notify; switch (Msg) { case WM_CANCELMODE: if (p->InSkin>0) { p->InSkin = 0; ReleaseCapture(); } if (p->InVol) { p->InVol = 0; ReleaseCapture(); } if (p->InSeek) StopSeek(p); if (IsOverlay(p)) { //delayed clipping (don't want to turn off overlay, just because a toolbar button was pressed) SetTimer(p->Win.Wnd,TIMER_CLIPPING2,CLIPPING2_CYCLE,NULL); break; } // no break #if !defined(TARGET_WINCE) case WM_INITMENU: #endif UpdateClipping(p,1,1); // force clipping mode break; case WM_PAINT: BeginPaint(p->Win.Wnd,&Paint); if (p->Skin[p->SkinNo].Valid) SkinDraw(&p->Skin[p->SkinNo],Paint.hdc,&p->SkinArea); p->Player->Paint(p->Player,Paint.hdc,p->Offset.x,p->Offset.y); EndPaint(p->Win.Wnd,&Paint); break; #if defined(TARGET_WINCE) case WM_CTLCOLORSTATIC: *Result = (LRESULT) GetSysColorBrush(COLOR_BTNFACE); return 1; #endif case WM_SYSCHAR: if (wParam == 13) //Alt+Enter PostMessage(p->Win.Wnd,WM_COMMAND,IF_OPTIONS_FULLSCREEN,0); break; case WM_TIMER: if (wParam == TIMER_TITLESCROLL) TitleScroll(p); if (wParam == TIMER_SLIDERINVOL) UpdateVol(p); if (wParam == TIMER_SLIDERINSEEK && !p->Win.FullScreen) UpdatePosition(p); if (wParam == TIMER_KEYINSEEK) StopSeek(p); if (wParam == TIMER_CLIPPING2 && ShowVideo(p) && !p->Clipping && IsOverlapped(p)) UpdateClipping(p,1,1); if (wParam == TIMER_CLIPPING && ShowVideo(p) && p->Clipping) UpdateClipping(p,0,1); if (wParam == TIMER_INITING) { NodeRegSaveValue(0,REG_INITING,NULL,0,TYPE_INT); KillTimer(p->Win.Wnd,TIMER_INITING); } if (wParam == TIMER_SLEEP && (p->Play>0 || p->FFwd>0)) SleepTimerReset(); break; case WM_INITMENUPOPUP: UpdateClipping(p,1,1); // force clipping mode UpdateMenu(p); break; case WM_KEYUP: #if defined(TARGET_WINCE) if (!GetDisplayPower()) SetDisplayPower(0,1); #endif Key = WinKeyState(KeyRotate(p,wParam)); for (i=0;iHotKey[i] && (p->HotKey[i] & ~HOTKEY_KEEP) == Key) return 0; if (p->AllKeys) ForwardMenuButtons(&p->Win,Msg,wParam,lParam); break; case WM_KEYDOWN: Key = WinKeyState(KeyRotate(p,wParam)); for (i=0;iHotKey[i] && (p->HotKey[i] & ~HOTKEY_KEEP) == Key) { PostMessage(p->Win.Wnd,WM_COMMAND,HotKey[i],0); return 0; } if (p->AllKeys) ForwardMenuButtons(&p->Win,Msg,wParam,lParam); break; case WM_HOTKEY: #if defined(TARGET_WINCE) if ((LOWORD(lParam) & MOD_KEYUP)) { if (!GetDisplayPower()) SetDisplayPower(0,1); } else #endif PostMessage(p->Win.Wnd,WM_COMMAND,wParam,0); *Result = 0; return 1; case WM_MOUSEMOVE: if (p->InSkin>0 && (wParam & MK_LBUTTON)) SkinMouse(&p->Skin[p->SkinNo],p->InSkin,(int16_t)LOWORD(lParam)-p->SkinArea.x,(int16_t)HIWORD(lParam)-p->SkinArea.y,p->Player,NULL,p->Win.Wnd,&p->SkinArea); return 0; case WM_LBUTTONUP: if (p->InSkin>0) { int Cmd = 0; SkinMouse(&p->Skin[p->SkinNo],p->InSkin,(int16_t)LOWORD(lParam)-p->SkinArea.x,(int16_t)HIWORD(lParam)-p->SkinArea.y,p->Player,&Cmd,p->Win.Wnd,&p->SkinArea); if (p->InSeek) StopSeek(p); p->InSkin = 0; if (p->Capture) { ReleaseCapture(); p->Capture = 0; } if (Cmd==SKIN_VOLUME) UpdateVolume(p); if (Cmd>0 && SkinCmd[Cmd]>0) Command(p,SkinCmd[Cmd]); } *Result = 0; return 1; case WM_LBUTTONDBLCLK: case WM_LBUTTONDOWN: DEBUG_MSG(DEBUG_WIN,T("LBUTTON")); if ((wParam & MK_LBUTTON) && p->Focus) { tchar_t URL[MAXPATH]; SetDisplayPower(1,0); if (p->Skin[p->SkinNo].Valid && !p->FullScreen) p->InSkin = SkinMouse(&p->Skin[p->SkinNo],0,(int16_t)LOWORD(lParam)-p->SkinArea.x,(int16_t)HIWORD(lParam)-p->SkinArea.y,p->Player,NULL,p->Win.Wnd,&p->SkinArea); else p->InSkin = -1; if (p->InSkin>0) { SetCapture(p->Win.Wnd); p->Capture = 1; if (p->InSkin == SKIN_SEEK) p->InSeek = 1; } else if (p->InSkin<0) { if (!p->FullScreen && p->Player->CommentByName(p->Player,-1,T("URL"),URL,TSIZEOF(URL))) WinShowHTML(URL); else if (p->Player->Get(p->Player,PLAYER_SINGLECLICKFULLSCREEN,&b,sizeof(b))==ERR_NONE && !b) { if (Msg == WM_LBUTTONDBLCLK) PostMessage(p->Win.Wnd,WM_COMMAND,IF_OPTIONS_FULLSCREEN,0); PostMessage(p->Win.Wnd,WM_COMMAND,IF_PLAY,0); } else PostMessage(p->Win.Wnd,WM_COMMAND,IF_PLAY_FULLSCREEN,0); } } SetForegroundWindow(p->Win.Wnd); //sometimes wince suck (triple click in opendialog) *Result = 0; return 1; case WM_MOVE: Resize(p); break; case WM_SETTINGCHANGE: if (wParam == SETTINGCHANGE_RESET) { p->Player->Set(p->Player,PLAYER_RESETVIDEO,NULL,0); if (p->VolResizeNeeded2) { ResizeVolume(p); if (p->VolResizeNeeded2>1) ShowVol(p,1); p->VolResizeNeeded2 = 0; } } break; case WM_SIZE: #ifdef MAXIMIZE_FULLSCREEN if (wParam == SIZE_MAXIMIZED) { ShowWindow(p->Win.Wnd,SW_SHOWNORMAL); ToggleFullScreen(p,1,1); } else #endif Resize(p); break; case WM_SETFOCUS: if (!p->Focus || !p->WndVolBack || (HWND)wParam != p->WndVolBack) { DEBUG_MSG(DEBUG_WIN,T("SETFOCUS")); p->Focus = 1; DIASet(0,DIA_SIP); if (p->Wait) { WaitBegin(); UpdateHotKey(p,1,0); // clipping still needed } else UpdateClipping(p,0,1); // turn off clipping when no overlapping windows UpdateClippingTimer(p); UpdateTitleScroll(p); } break; case WM_KILLFOCUS: if (!p->WndVolBack || (HWND)wParam != p->WndVolBack) { DEBUG_MSG(DEBUG_WIN,T("KILLFOCUS")); p->Focus = 0; if (!ShowVideo(p)) UpdateClipping(p,1,1); // force clipping mode if (p->Wait) WaitEnd(); } break; case WM_ACTIVATE: if (!p->WndVolBack || (HWND)lParam != p->WndVolBack) { if (LOWORD(wParam)==WA_INACTIVE) { #ifdef NDEBUG Toggle(p,PLAYER_FOREGROUND,0); ToggleFullScreen(p,0,0); // example ATI tweaks have problem #endif ShowVol(p,0); if (p->InSeek) StopSeek(p); SetDisplayPower(1,0); } else { ShowVol(p,1); UpdateVolume(p); Toggle(p,PLAYER_FOREGROUND,1); if (p->ForceFullScreen) PostMessage(p->Win.Wnd,MSG_PLAYER,PLAYER_FULLSCREEN,1); } } break; case WM_DESTROY: BeforeExit(p); PostQuitMessage(0); SkinFree(p->Skin,NULL); Context()->Error.Func = NULL; ArrayClear(&p->VOutput); ArrayClear(&p->AOutput); break; case MSG_ERROR: ShowError2(p,(const tchar_t*)lParam); free((tchar_t*)lParam); return 1; case MSG_PLAYER: switch (wParam) { case PLAYER_EXIT_AT_END: if (p->CmdLineMode) PostMessage(p->Win.Wnd,WM_COMMAND,IF_FILE_EXIT,0); break; case PLAYER_PERCENT: UpdatePosition(p); break; case PLAYER_LOADMODE: if (p->Wait != (bool_t)lParam) { p->Wait = lParam; if (p->Wait) { if (WaitBegin()) UpdateClipping(p,1,0); } else WaitEnd(); } break; case PLAYER_FULLSCREEN: p->ForceFullScreen = lParam; if (GetForegroundWindow() == p->Win.Wnd || !lParam) { ToggleFullScreen(p,lParam,1); p->ForceFullScreen = 0; } break; case PLAYER_PLAY: RefreshButton(p,PLAYER_PLAY,&p->Play,IF_PLAY,0,1); RefreshButton(p,PLAYER_FFWD,&p->FFwd,IF_FASTFORWARD,4,1); UpdateSleepTimer(p); break; case PLAYER_BENCHMARK: if (p->Bench && p->Player->Get(p->Player,PLAYER_BENCHMARK,&t,sizeof(tick_t))==ERR_NONE) { p->Bench = 0; ToggleFullScreen(p,0,0); WaitEnd(); if (p->WndTrack) SetTrackThumb(p->WndTrack,1); UpdateWindow(p->Win.Wnd); WinPopupClass(BENCHRESULT_ID,&p->Win); } break; } return 1; case WM_COPYDATA: ProcessCmdLine(p,(const tchar_t*)((COPYDATASTRUCT*)lParam)->lpData); return 1; case MSG_INIT: SetForegroundWindow(p->Win.Wnd); if (Context()->CmdLine[0] || NodeRegLoadValue(0,REG_INITING,&i,sizeof(i),TYPE_INT)) { b = 1; // last time crashed -> discard saved playlist p->Player->Set(p->Player,PLAYER_DISCARDLIST,&b,sizeof(b)); } #ifdef NDEBUG i = 1; NodeRegSaveValue(0,REG_INITING,&i,sizeof(int),TYPE_INT); SetTimer(p->Win.Wnd,TIMER_INITING,INITING_CYCLE,NULL); #endif Context_Wnd(p->Win.Wnd); if (Context()->CmdLine[0]) { p->Player->Get(p->Player,PLAYER_PLAYATOPEN_FULL,&b,sizeof(b)); if (!b) { UpdateWindow(p->Win.Wnd); //http connection may take a while if (p->Win.WndTB) UpdateWindow(p->Win.WndTB); } ProcessCmdLine(p,Context()->CmdLine); } if (LangStr(LANG_ID,LANG_DEFAULT)[0]==0 && LangStr(LANG_ID,Context()->Lang)[0]==0) ShowMessage(NULL,T("Language files (*.txt,*.tgz) are missing!")); return 1; case WM_CREATE: WinTitle(&p->Win,Context()->ProgramName); p->ThreadId = GetCurrentThreadId(); p->Player = (player*)Context()->Player; p->Color = NodeEnumObject(NULL,COLOR_ID); p->Equalizer = NodeEnumObject(NULL,EQUALIZER_ID); p->Focus = 0; p->Clipping = 0; Notify.This = p; Notify.Func = (notifyfunc)PlayerNotify; if (p->Player) p->Player->Set(p->Player,PLAYER_NOTIFY,&Notify,sizeof(Notify)); Context()->Error.This = p; Context()->Error.Func = ErrorNotify; WinMenuEnable(&p->Win,1,IF_OPTIONS_VIDEO_STREAM,0); WinMenuEnable(&p->Win,1,IF_OPTIONS_VIDEO_STREAM,0); WinMenuEnable(&p->Win,1,IF_OPTIONS_AUDIO_STREAM,0); WinMenuEnable(&p->Win,1,IF_OPTIONS_VIDEO_DEVICE,0); WinMenuEnable(&p->Win,1,IF_OPTIONS_AUDIO_DEVICE,0); WinMenuEnable(&p->Win,1,IF_OPTIONS_ORIENTATION_FULLSCREEN,0); WinMenuEnable(&p->Win,1,IF_OPTIONS_AUDIO_QUALITY,0); if (!NodeEnumClass(NULL,CORETHEQUE_UI_ID)) WinMenuDelete(&p->Win,0,IF_FILE_CORETHEQUE); if (IsAutoRun(p,Context()->CmdLine)) DefaultSkin(p); SkinLoad(p->Skin,p->Win.Wnd,p->SkinPath); if (!p->Skin[0].Valid) CreateButtons(p); UpdateSkin(p,0); UpdateTrackBar(p,0); UpdateTitleBar(p,0); CreateVolumeTrack(p); CreateDeviceMenu(p); Resize(p); // first finish window creation and postpone loading playlist and etc... PostMessage(p->Win.Wnd,MSG_INIT,0,0); UpdateHotKey(p,1,0); break; } return 0; } static const datatable Params[] = { { IF_TITLEBAR, TYPE_BOOL, DF_SETUP|DF_HIDDEN }, { IF_TRACKBAR, TYPE_BOOL, DF_SETUP|DF_HIDDEN }, { IF_TASKBAR, TYPE_BOOL, DF_SETUP|DF_HIDDEN }, { IF_SKINNO, TYPE_INT, DF_SETUP|DF_HIDDEN }, { IF_SKINPATH, TYPE_STRING,DF_SETUP|DF_HIDDEN }, #if defined(TARGET_WINCE) { IF_ALLKEYS, TYPE_BOOL, DF_SETUP|DF_CHECKLIST }, #endif DATATABLE_END(INTERFACE_ID) }; static int Enum( intface* p, int* No, datadef* Param ) { if (NodeEnumTable(No,Param,Params)==ERR_NONE) return ERR_NONE; if (*No>=0 && *NoNo = HotKey[*No]; Param->Type = TYPE_HOTKEY; Param->Size = sizeof(int); Param->Flags = DF_SETUP; #if defined(TARGET_WINCE) if (*No==0) Param->Flags |= DF_GAP; #endif Param->Class = INTERFACE_ID; Param->Name = LangStr(INTERFACE_ID,Param->No); return ERR_NONE; } return ERR_INVALID_PARAM; } static int Get(intface* p,int No,void* Data,int Size) { int Result = ERR_INVALID_PARAM; int i; for (i=0;iHotKey[i],int); break; } switch (No) { case IF_TRACKBAR: GETVALUE(p->TrackBar,bool_t); break; case IF_TITLEBAR: GETVALUE(p->TitleBar,bool_t); break; case IF_TASKBAR: GETVALUE(p->TaskBar,bool_t); break; case IF_SKINNO: GETVALUE(p->SkinNo,int); break; case IF_SKINPATH: GETSTRING(p->SkinPath); break; case IF_ALLKEYS: GETVALUE(p->AllKeys,bool_t); break; } return Result; } static int UpdateSkin(intface* p,bool_t Others) { if (!p->Player) return ERR_NONE; if (p->SkinNo>0 && !p->Skin[p->SkinNo].Valid) p->SkinNo=0; if (Others) { if (p->Skin[p->SkinNo].Valid) SkinUpdate(&p->Skin[p->SkinNo],p->Player,p->Win.Wnd,&p->SkinArea); ShowVol(p,1); UpdateTrackBar(p,1); InvalidateRect(p->Win.Wnd,NULL,0); p->ClientRect.right = -1; Resize(p); } RefreshButton(p,PLAYER_REPEAT,NULL,0,0,0); RefreshButton(p,PLAYER_PLAY,NULL,0,0,0); RefreshButton(p,PLAYER_FFWD,NULL,0,0,0); RefreshButton(p,PLAYER_MUTE,NULL,0,0,0); RefreshButton(p,PLAYER_FULLSCREEN,NULL,0,0,0); if (p->TitleBrush) { DeleteObject(p->TitleBrush); p->TitleBrush = NULL; } if (p->Skin[p->SkinNo].Valid) { p->TitleBrush = CreateSolidBrush(p->Skin[p->SkinNo].Item[SKIN_TITLE].ColorFace); p->TitleFace = p->Skin[p->SkinNo].Item[SKIN_TITLE].ColorFace; p->TitleText = p->Skin[p->SkinNo].Item[SKIN_TITLE].ColorText; } else { p->TitleBrush = NULL; p->TitleFace = GetSysColor(COLOR_BTNFACE); p->TitleText = GetSysColor(COLOR_BTNTEXT); } return ERR_NONE; } static int UpdateAllKeys(intface* p) { if (!p->AllKeys && p->AllKeysWarning) { int i; for (i=0;iHotKey[i] && WinNoHotKey(p->HotKey[i])) { ShowMessage(LangStr(p->Win.Node.Class,NODE_NAME),LangStr(INTERFACE_ID,IF_ALLKEYS_WARNING2)); break; } } return ERR_NONE; } static void SetHotKey(intface* p,int i,int Key) { if (p->Focus && p->HotKey[i] && !p->AllKeys) WinUnRegisterHotKey(&p->Win,HotKey[i]); if (!p->AllKeys && p->AllKeysWarning && WinNoHotKey(Key)) ShowMessage(LangStr(p->Win.Node.Class,NODE_NAME),LangStr(INTERFACE_ID,IF_ALLKEYS_WARNING)); p->HotKey[i] = Key; if (p->Focus && p->HotKey[i] && !p->AllKeys && !WinEssentialKey(p->HotKey[i])) WinRegisterHotKey(&p->Win,HotKey[i],p->HotKey[i]); } static int Set(intface* p,int No,const void* Data,int Size) { int Result = ERR_INVALID_PARAM; int i,j; for (i=0;iHotKey[j] & ~HOTKEY_KEEP) == (Key & ~HOTKEY_KEEP)) SetHotKey(p,j,0); SetHotKey(p,i,Key); } Result = ERR_NONE; break; } switch (No) { case IF_TRACKBAR: SETVALUE(p->TrackBar,bool_t,UpdateTrackBar(p,1)); break; case IF_TITLEBAR: SETVALUE(p->TitleBar,bool_t,UpdateTitleBar(p,1)); break; case IF_TASKBAR: SETVALUE(p->TaskBar,bool_t,UpdateTaskBar(p)); break; case IF_SKINNO: SETVALUE(p->SkinNo,int,UpdateSkin(p,1)); break; case IF_SKINPATH: SETSTRING(p->SkinPath); Result = UpdateSkinFile(p); break; case IF_ALLKEYS: SETVALUECMP(p->AllKeys,bool_t,UpdateAllKeys(p),EqBool); break; } return Result; } static void DefaultSkin(intface* p) { tchar_t* s; GetModuleFileName(GetModuleHandle(NULL),p->SkinPath,MAXPATH); s = tcsrchr(p->SkinPath,'\\'); if (s) s[1]=0; tcscat_s(p->SkinPath,TSIZEOF(p->SkinPath),T("skin.xml")); p->SkinNo = 0; } static int Create(intface* p) { int Key; DefaultSkin(p); p->Win.WinWidth = 360; p->Win.WinHeight = 240; p->Win.Proc = Proc; p->Win.Command = (wincommand)Command; p->Win.MenuDef = MenuDef; p->Win.Node.Enum = Enum; p->Win.Node.Get = Get; p->Win.Node.Set = Set; p->Vol = -1; p->TaskBar = 1; p->TitleBar = 1; p->TrackBar = 1; p->MenuPreAmp = -1; p->MenuStreams = 0; p->MenuAStream = -1; p->MenuVStream = -1; p->MenuSubStream = -1; Key = VK_RIGHT; Set(p,IF_MOVE_FFWD,&Key,sizeof(Key)); Key = VK_LEFT; Set(p,IF_MOVE_BACK,&Key,sizeof(Key)); Key = VK_UP; Set(p,IF_OPTIONS_VOLUME_UP,&Key,sizeof(Key)); Key = VK_DOWN; Set(p,IF_OPTIONS_VOLUME_DOWN,&Key,sizeof(Key)); Key = VK_RETURN; Set(p,QueryPlatform(PLATFORM_TYPENO) == TYPE_SMARTPHONE?IF_PLAY_FULLSCREEN:IF_PLAY,&Key,sizeof(Key)); Key = 0xB0; //VK_MEDIA_NEXT_TRACK; Set(p,IF_NEXT2,&Key,sizeof(Key)); Key = 0xB1; //VK_MEDIA_PREV_TRACK; Set(p,IF_PREV_SMART2,&Key,sizeof(Key)); Key = 0xB2; //VK_MEDIA_STOP; Set(p,IF_STOP,&Key,sizeof(Key)); Key = 0xB3; //VK_MEDIA_PLAY_PAUSE; Set(p,IF_PLAYPAUSE,&Key,sizeof(Key)); #if defined(TARGET_WIN32) Key = VK_SPACE; Set(p,IF_PLAY,&Key,sizeof(Key)); #endif return ERR_NONE; } static const nodedef IntFace = { sizeof(intface)|CF_GLOBAL|CF_SETTINGS, INTERFACE_ID, WIN_CLASS, PRI_MAXIMUM+570, (nodecreate)Create, }; static const nodedef Skin = { 0, SKIN_CLASS, NODE_CLASS, PRI_MAXIMUM, }; void Interface_Init() { NodeRegisterClass(&IntFace); NodeRegisterClass(&Skin); } void Interface_Done() { NodeUnRegisterClass(INTERFACE_ID); NodeUnRegisterClass(SKIN_CLASS); } #endif