From 6a70bcc82c9b7771d318ca2b05f654bf77334663 Mon Sep 17 00:00:00 2001 From: Chris Tallon Date: Sun, 25 Mar 2007 20:10:47 +0000 Subject: [PATCH] New options screen system, new remote control handling, and all other related changes --- GNUmakefile | 2 +- audiowin.cc | 11 +- audiowin.h | 3 + box.h | 13 +- colour.cc | 1 + colour.h | 1 + command.cc | 18 +- defines.h | 4 +- dssourcefilter.cc | 591 +++++++++++++++++++++++----------------------- dssourcefilter.h | 78 +++--- dssourcepin.cc | 221 ++++++++--------- dssourcepin.h | 3 +- main.cc | 6 + message.h | 1 + mtdwin.cc | 1 + mtdwin.h | 1 + objects.mk | 1 + osdwin.cc | 1 - osdwin.h | 1 - remote.cc | 372 +++++++++++++++++++++++++++++ remote.h | 25 ++ remotemvp.cc | 2 +- remotewin.cc | 261 ++++++++++++++++++-- remotewin.h | 7 + surfacewin.cc | 1 - thread.h | 3 +- threadwin.cc | 35 ++- threadwin.h | 10 + vconnect.cc | 3 +- videowin.cc | 329 ++++++++++++++++++-------- videowin.h | 34 ++- view.cc | 2 +- view.h | 9 +- viewman.cc | 2 +- viewman.h | 21 +- vompreswin.h | 1 - voptions.cc | 36 ++- voptions.h | 1 - voptionsmenu.cc | 183 +++----------- voptionsmenu.h | 8 +- vradiorec.cc | 3 +- vrecordinglist.h | 1 - vremoteconfig.cc | 271 +++++++++++++++++++++ vremoteconfig.h | 64 +++++ vtabsviewman.cc | 436 ++++++++++++++++++++++++++++++++++ vtabsviewman.h | 54 +++++ vvideolive.h | 2 +- vvideorec.h | 2 +- vwelcome.h | 2 +- winmain.cc | 10 +- wselectlist.cc | 3 +- wselectlist.h | 3 +- 52 files changed, 2383 insertions(+), 771 deletions(-) create mode 100644 vremoteconfig.cc create mode 100644 vremoteconfig.h create mode 100644 vtabsviewman.cc create mode 100644 vtabsviewman.h diff --git a/GNUmakefile b/GNUmakefile index ddc90f5..347c5f0 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -6,7 +6,7 @@ CXX=$(CROSS)g++ LD=$(CROSS)g++ INCLUDES = -I../jpeg/jpeg-6b -CXXFLAGS_DEV = -g -O0 -Wall -Wshadow -Werror -DDEV -D_GNU_SOURCE $(INCLUDES) +CXXFLAGS_DEV = -g -O0 -Wall -Wshadow -DDEV -D_GNU_SOURCE $(INCLUDES) CXXFLAGS_REL = -O3 -Wall -Wshadow -Werror -D_GNU_SOURCE $(INCLUDES) LDFLAGS = -Wall -static diff --git a/audiowin.cc b/audiowin.cc index 8de6da6..1dcaeaa 100644 --- a/audiowin.cc +++ b/audiowin.cc @@ -111,7 +111,7 @@ int AudioWin::unPause() int AudioWin::reset() { - + if (!initted){return 0;} return ((VideoWin*)Video::getInstance())->dsreset(); } @@ -168,9 +168,9 @@ UINT AudioWin::DeliverMediaPacket(MediaPacket packet, VideoWin *vw=(VideoWin*)Video::getInstance(); if (!vw->isdsinited()) return 0; if (vw->InIframemode()) { - samplepos=0; - MILLISLEEP(10); - return 0; //Not in iframe mode! + samplepos=0; + MILLISLEEP(10); + return 0; //Not in iframe mode! } IMediaSample* ms=NULL; REFERENCE_TIME reftime1=0; @@ -209,7 +209,7 @@ UINT AudioWin::DeliverMediaPacket(MediaPacket packet, } else { if (!firstsynched) {// *samplepos=packet.length;//if we have not processed at least one - + return packet.length;//synched packet ignore it! } } @@ -301,3 +301,4 @@ int AudioWin::test() #endif + diff --git a/audiowin.h b/audiowin.h index 788548d..9942124 100644 --- a/audiowin.h +++ b/audiowin.h @@ -52,6 +52,8 @@ class AudioWin : public Audio virtual void PrepareMediaSample(const MediaPacketList&, UINT samplepos); virtual UINT DeliverMediaSample(const UCHAR* buffer, UINT *samplepos); UINT DeliverMediaPacket(MediaPacket packet, const UCHAR* buffer, UINT *samplepos); + + virtual bool supportsAc3(); private: MediaPacket mediapacket; public: @@ -68,3 +70,4 @@ private: #endif + diff --git a/box.h b/box.h index 839e352..1908b58 100644 --- a/box.h +++ b/box.h @@ -44,7 +44,7 @@ class Box void setSurfaceOffset(UINT x, UINT y); void setGap(UINT gap); - void blt(Region& r); // For use only by ViewMan + virtual void blt(Region& r); // For use only by ViewMan virtual void draw(); @@ -69,19 +69,8 @@ class Box // so viewman can read it: Region area; Surface* surface; // temp - is there a get function for this? FIXME - private: protected: - - -/* - UINT width; - UINT height; - - int screenX; - int screenY; -*/ - UINT offsetX; UINT offsetY; diff --git a/colour.cc b/colour.cc index 06c9992..711b8e8 100644 --- a/colour.cc +++ b/colour.cc @@ -28,6 +28,7 @@ Colour Colour::RED(255, 0, 0); Colour Colour::GREEN(0, 255, 0); Colour Colour::VIDEOBLUE(0, 0, 150); Colour Colour::VIEWBACKGROUND(0, 0, 100); +Colour Colour::TABVIEWBACKGROUND(0, 0, 120); Colour Colour::TITLEBARBACKGROUND(0, 0, 200); Colour Colour::SELECTHIGHLIGHT(240, 250, 80); Colour Colour::LIGHTTEXT(255, 255, 255); diff --git a/colour.h b/colour.h index 34b860f..757ad9e 100644 --- a/colour.h +++ b/colour.h @@ -56,6 +56,7 @@ class Colour static Colour BLUE; static Colour VIDEOBLUE; static Colour VIEWBACKGROUND; + static Colour TABVIEWBACKGROUND; static Colour TITLEBARBACKGROUND; static Colour SELECTHIGHLIGHT; static Colour LIGHTTEXT; diff --git a/command.cc b/command.cc index e3e2e45..a97c1db 100644 --- a/command.cc +++ b/command.cc @@ -163,7 +163,7 @@ void Command::run() #endif //logger->log("Command", Log::DEBUG, "LOCK"); - if ((button == Remote::NA_NONE) || (button == Remote::NA_UNKNOWN)) continue; + if ((button == Remote::NA_NONE) /*|| (button == Remote::NA_UNKNOWN)*/) continue; if (button != Remote::NA_SIGNAL) handleCommand(button); processMessageQueue(); @@ -694,6 +694,22 @@ void Command::doJustConnected(VConnect* vconnect) remote->setRemoteType(Remote::OLDREMOTE); } + // Set remote keys + + config = vdr->configLoad("General", "Remote keys"); + + if (config) + { + logger->log("Command", Log::INFO, "Config General/Remote keys load"); + remote->LoadKeysConfig(config); + delete[] config; + } + else + { + logger->log("Command", Log::INFO, "Config General/Remote keys not found"); + remote->InitHWCListwithDefaults(); + } + // Get TV aspect ratio config = vdr->configLoad("TV", "Aspect"); diff --git a/defines.h b/defines.h index b3bde10..6f1c78a 100644 --- a/defines.h +++ b/defines.h @@ -38,7 +38,7 @@ void MILLISLEEP(ULONG a); #define Surface_TYPE SurfaceWin #define Thread_TYPE ThreadWin - #define ThreadID_TYPE FIXME Marten + #define ThreadID_TYPE unsigned int #define SNPRINTF _snprintf #define VSNPRINTF _vsnprintf @@ -50,6 +50,8 @@ void MILLISLEEP(ULONG a); #else + int max(int, int); + #define Surface_TYPE SurfaceMVP #define Thread_TYPE ThreadP #include diff --git a/dssourcefilter.cc b/dssourcefilter.cc index 4720bf9..89b376b 100644 --- a/dssourcefilter.cc +++ b/dssourcefilter.cc @@ -24,105 +24,104 @@ class DsSFEnumPins: public IEnumPins { public: - DsSFEnumPins(DsSourcePin* audio,DsSourcePin* video,DsSourceFilter *filt,ULONG pos=0); - virtual ~DsSFEnumPins(); - virtual HRESULT STDMETHODCALLTYPE Next(ULONG numpin,IPin **pins,ULONG *fetched); - virtual HRESULT STDMETHODCALLTYPE Skip(ULONG numpin); - virtual HRESULT STDMETHODCALLTYPE Reset(); - virtual HRESULT STDMETHODCALLTYPE Clone(IEnumPins **enuma); - virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID id,void ** object); - virtual ULONG STDMETHODCALLTYPE AddRef(); + DsSFEnumPins(DsSourcePin* audio,DsSourcePin* video,DsSourceFilter *filt,ULONG pos=0); + virtual ~DsSFEnumPins(); + virtual HRESULT STDMETHODCALLTYPE Next(ULONG numpin,IPin **pins,ULONG *fetched); + virtual HRESULT STDMETHODCALLTYPE Skip(ULONG numpin); + virtual HRESULT STDMETHODCALLTYPE Reset(); + virtual HRESULT STDMETHODCALLTYPE Clone(IEnumPins **enuma); + virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID id,void ** object); + virtual ULONG STDMETHODCALLTYPE AddRef(); virtual ULONG STDMETHODCALLTYPE Release(); protected: - DsSourcePin* audiopin; - DsSourcePin* videopin; - DsSourceFilter *filter; - ULONG curpos; - volatile long refs; + DsSourcePin* audiopin; + DsSourcePin* videopin; + DsSourceFilter *filter; + ULONG curpos; + volatile long refs; }; DsSFEnumPins::DsSFEnumPins(DsSourcePin* audio,DsSourcePin* video,DsSourceFilter *filt,ULONG pos){ - audiopin=audio; - videopin=video; - curpos=pos; - filter=filt; - filt->AddRef(); - refs=0; - + audiopin=audio; + videopin=video; + curpos=pos; + filter=filt; + filt->AddRef(); + refs=0; + } DsSFEnumPins::~DsSFEnumPins(){ - filter->Release(); - + filter->Release(); + } HRESULT STDMETHODCALLTYPE DsSFEnumPins::Next(ULONG numpin,IPin **pins,ULONG *fetched) { - int i; - if (fetched==NULL) return E_POINTER; - if (pins==NULL) return E_POINTER; - *fetched=0; - - for (i=0;(iAddRef(); pins[i]=(IPin*)audiopin;break; - case 1: videopin->AddRef(); pins[i]=(IPin*)videopin;break; - }; - (*fetched)++; - curpos++; - } - if ((*fetched)!=numpin) return S_FALSE; - return S_OK; + int i; + if (fetched==NULL) return E_POINTER; + if (pins==NULL) return E_POINTER; + *fetched=0; + + for (i=0;(iAddRef(); pins[i]=(IPin*)audiopin;break; + case 1: videopin->AddRef(); pins[i]=(IPin*)videopin;break; + }; + (*fetched)++; + curpos++; + } + if ((*fetched)!=numpin) return S_FALSE; + return S_OK; } HRESULT STDMETHODCALLTYPE DsSFEnumPins::Skip(ULONG numpin){ - curpos+=numpin; - if (curpos>2) return S_FALSE; - return S_OK; + curpos+=numpin; + if (curpos>2) return S_FALSE; + return S_OK; } HRESULT STDMETHODCALLTYPE DsSFEnumPins::Reset(){ - curpos=0; - return S_OK; + curpos=0; + return S_OK; } HRESULT STDMETHODCALLTYPE DsSFEnumPins::Clone(IEnumPins **enuma){ - if (enuma==NULL) return E_POINTER; - *enuma=new DsSFEnumPins(audiopin,videopin,filter,curpos); - (*enuma)->AddRef(); - return S_OK; + if (enuma==NULL) return E_POINTER; + *enuma=new DsSFEnumPins(audiopin,videopin,filter,curpos); + (*enuma)->AddRef(); + return S_OK; } HRESULT STDMETHODCALLTYPE DsSFEnumPins::QueryInterface(REFIID id,void ** object){ - if (object==NULL) return E_POINTER; - - if (id==IID_IUnknown ||id == IID_IEnumPins) { - *object=(IUnknown*)this; - ((IUnknown*)object)->AddRef(); - return NOERROR; - } else { - *object=NULL; - return E_NOINTERFACE; - } + if (object==NULL) return E_POINTER; + if (id==IID_IUnknown ||id == IID_IEnumPins) { + *object=(IUnknown*)this; + ((IUnknown*)object)->AddRef(); + return NOERROR; + } else { + *object=NULL; + return E_NOINTERFACE; + } } ULONG STDMETHODCALLTYPE DsSFEnumPins::AddRef(){ - InterlockedIncrement(&refs); - long tempref=refs; - if (tempref>1) return tempref; - else return 1; + InterlockedIncrement(&refs); + long tempref=refs; + if (tempref>1) return tempref; + else return 1; } ULONG STDMETHODCALLTYPE DsSFEnumPins::Release(){ - long tempref=InterlockedDecrement(&refs); - - if (tempref==0) { - refs++; - delete this; - return NULL; - } else { - if (tempref>1) return tempref; - else return 1; - } + long tempref=InterlockedDecrement(&refs); + + if (tempref==0) { + refs++; + delete this; + return NULL; + } else { + if (tempref>1) return tempref; + else return 1; + } } @@ -133,288 +132,290 @@ ULONG STDMETHODCALLTYPE DsSFEnumPins::Release(){ DsSourceFilter::DsSourceFilter() { - //add audio pin - HRESULT res; - audiopin=new DsSourcePin(this,&res,L"Vomp Audio Out",true); - videopin=new DsSourcePin(this,&res,L"Vomp Video Out",false); - filtergraph=NULL; - clock=NULL; - mystate=State_Stopped; - laststart=0; - refs=0; - InitializeCriticalSection(&filterlock); + //add audio pin + HRESULT res; + audiopin=new DsSourcePin(this,&res,L"Vomp Audio Out",true); + videopin=new DsSourcePin(this,&res,L"Vomp Video Out",false); + filtergraph=NULL; + clock=NULL; + mystate=State_Stopped; + laststart=0; + refs=0; + InitializeCriticalSection(&filterlock); + } DsSourceFilter::~DsSourceFilter() { - if (audiopin) delete audiopin; - if (videopin) delete videopin; - if (clock) { - clock->Release(); - clock=NULL; - } - DeleteCriticalSection(&filterlock); - + if (audiopin) delete audiopin; + if (videopin) delete videopin; + if (clock) { + clock->Release(); + clock=NULL; + } + DeleteCriticalSection(&filterlock); + } HRESULT STDMETHODCALLTYPE DsSourceFilter::GetClassID(CLSID *clsid){ - if (clsid==NULL) return E_POINTER; - *clsid=_uuidof(this); - return S_OK; + if (clsid==NULL) return E_POINTER; + *clsid=_uuidof(this); + return S_OK; } HRESULT STDMETHODCALLTYPE DsSourceFilter::QueryInterface(REFIID id,void ** object){ - if (object==NULL) return E_POINTER; - if (id==IID_IUnknown) { - *object=(IUnknown*)this; - AddRef(); - return NOERROR; - } else if (id==IID_IBaseFilter) { - *object=(IBaseFilter*)this; - AddRef(); - return NOERROR; - } else if (id==IID_IMediaFilter) { - *object=(IMediaFilter*)this; - AddRef(); - return NOERROR; - }else { - *object=NULL; - return E_NOINTERFACE; - } + if (object==NULL) return E_POINTER; + + if (id==IID_IUnknown) { + *object=(IUnknown*)this; + AddRef(); + return NOERROR; + } else if (id==IID_IBaseFilter) { + *object=(IBaseFilter*)this; + AddRef(); + return NOERROR; + } else if (id==IID_IMediaFilter) { + *object=(IMediaFilter*)this; + AddRef(); + return NOERROR; + }else { + *object=NULL; + return E_NOINTERFACE; + } } ULONG STDMETHODCALLTYPE DsSourceFilter::AddRef(){ - InterlockedIncrement(&refs); - long tempref=refs; - if (tempref>1) return tempref; - else return 1; + InterlockedIncrement(&refs); + long tempref=refs; + if (tempref>1) return tempref; + else return 1; } ULONG STDMETHODCALLTYPE DsSourceFilter::Release(){ - long tempref=InterlockedDecrement(&refs); - - if (tempref==0) { - refs++; - delete this; - return NULL; - } else { - if (tempref>1) return tempref; - else return 1; - } + long tempref=InterlockedDecrement(&refs); + + if (tempref==0) { + refs++; + delete this; + return NULL; + } else { + if (tempref>1) return tempref; + else return 1; + } } /*IBaseFilter*/ HRESULT STDMETHODCALLTYPE DsSourceFilter::EnumPins(IEnumPins **enumar){ - if (enumar==NULL) return E_POINTER; - *enumar=new DsSFEnumPins(audiopin,videopin, this); - (*enumar)->AddRef(); - return S_OK; + if (enumar==NULL) return E_POINTER; + *enumar=new DsSFEnumPins(audiopin,videopin, this); + (*enumar)->AddRef(); + return S_OK; } HRESULT STDMETHODCALLTYPE DsSourceFilter::FindPin(LPCWSTR iden,IPin **pin){ - if (pin==NULL) return E_POINTER; - EnterCriticalSection(&filterlock); - - if (wcscmp(AUDIOPIN_NAME,iden)==NULL) { - *pin=(IPin*)audiopin; - (*pin)->AddRef(); - LeaveCriticalSection(&filterlock); - return S_OK; - } - if (wcscmp(VIDEOPIN_NAME,iden)==NULL) { - *pin=(IPin*)videopin; - (*pin)->AddRef(); - LeaveCriticalSection(&filterlock); - return S_OK; - } - - *pin=NULL; - LeaveCriticalSection(&filterlock); + if (pin==NULL) return E_POINTER; + EnterCriticalSection(&filterlock); + + if (wcscmp(AUDIOPIN_NAME,iden)==NULL) { + *pin=(IPin*)audiopin; + (*pin)->AddRef(); + LeaveCriticalSection(&filterlock); + return S_OK; + } + if (wcscmp(VIDEOPIN_NAME,iden)==NULL) { + *pin=(IPin*)videopin; + (*pin)->AddRef(); + LeaveCriticalSection(&filterlock); + return S_OK; + } + + *pin=NULL; + LeaveCriticalSection(&filterlock); return VFW_E_NOT_FOUND; } HRESULT STDMETHODCALLTYPE DsSourceFilter::QueryFilterInfo(FILTER_INFO *info){ - if (info==NULL) return E_POINTER; - wcsncpy(info->achName,L"VompWinFilter", sizeof(info->achName)/sizeof(WCHAR)); - info->pGraph=filtergraph; - if (info->pGraph!=NULL) info->pGraph->AddRef(); - return NOERROR; + if (info==NULL) return E_POINTER; + wcsncpy(info->achName,L"VompWinFilter", sizeof(info->achName)/sizeof(WCHAR)); + info->pGraph=filtergraph; + if (info->pGraph!=NULL) info->pGraph->AddRef(); + return NOERROR; } HRESULT STDMETHODCALLTYPE DsSourceFilter::JoinFilterGraph(IFilterGraph *graph,LPCWSTR name){ - //Should we lock - EnterCriticalSection(&filterlock); - filtergraph=graph; - //filtergraph->AddRef(); - //We ignore the name - LeaveCriticalSection(&filterlock); - - return S_OK; + //Should we lock + EnterCriticalSection(&filterlock); + filtergraph=graph; + //filtergraph->AddRef(); + //We ignore the name + LeaveCriticalSection(&filterlock); + + return S_OK; } HRESULT STDMETHODCALLTYPE DsSourceFilter::QueryVendorInfo(LPWSTR *vendinf) { - return E_NOTIMPL; + return E_NOTIMPL; } /*IMediaFilter*/ HRESULT STDMETHODCALLTYPE DsSourceFilter::GetState(DWORD timeout,FILTER_STATE *state){ - if (state==NULL) return E_POINTER; - EnterCriticalSection(&filterlock); - *state=mystate; - LeaveCriticalSection(&filterlock); - return S_OK; + if (state==NULL) return E_POINTER; + EnterCriticalSection(&filterlock); + *state=mystate; + LeaveCriticalSection(&filterlock); + return S_OK; } HRESULT STDMETHODCALLTYPE DsSourceFilter::SetSyncSource(IReferenceClock *uhr){ - EnterCriticalSection(&filterlock); - if (clock!=NULL) { - clock->Release(); - } - if (uhr!=NULL) { - uhr->AddRef(); - } - clock=uhr; - LeaveCriticalSection(&filterlock); - - return S_OK; + EnterCriticalSection(&filterlock); + if (clock!=NULL) { + clock->Release(); + } + if (uhr!=NULL) { + uhr->AddRef(); + } + clock=uhr; + LeaveCriticalSection(&filterlock); + + return S_OK; } HRESULT STDMETHODCALLTYPE DsSourceFilter::GetSyncSource(IReferenceClock **uhr){ - if (uhr==NULL) return E_POINTER; - EnterCriticalSection(&filterlock); - if (clock!=NULL) clock->AddRef(); - *uhr=clock; - LeaveCriticalSection(&filterlock); - - return S_OK; + if (uhr==NULL) return E_POINTER; + EnterCriticalSection(&filterlock); + if (clock!=NULL) clock->AddRef(); + *uhr=clock; + LeaveCriticalSection(&filterlock); + + return S_OK; } HRESULT STDMETHODCALLTYPE DsSourceFilter::Stop(){ - EnterCriticalSection(&filterlock); - HRESULT aphres=S_OK; - HRESULT vphres=S_OK; - - if (audiopin->IsConnected()){ - aphres=audiopin->Inactive(); - } - if (videopin->IsConnected()){ - vphres=videopin->Inactive(); - } - - mystate=State_Stopped; - LeaveCriticalSection(&filterlock); - if (aphres!=S_OK) return aphres; - if (vphres!=S_OK) return vphres; - return S_OK; + EnterCriticalSection(&filterlock); + HRESULT aphres=S_OK; + HRESULT vphres=S_OK; + + if (audiopin->IsConnected()){ + aphres=audiopin->Inactive(); + } + if (videopin->IsConnected()){ + vphres=videopin->Inactive(); + } + + mystate=State_Stopped; + LeaveCriticalSection(&filterlock); + if (aphres!=S_OK) return aphres; + if (vphres!=S_OK) return vphres; + return S_OK; } HRESULT STDMETHODCALLTYPE DsSourceFilter::Pause(){ - EnterCriticalSection(&filterlock); - HRESULT aphres; - HRESULT vphres; - - if (audiopin->IsConnected()){ - aphres=audiopin->Active(); - if (aphres!=S_OK) { - LeaveCriticalSection(&filterlock); - return aphres; - } - } - if (videopin->IsConnected()){ - vphres=videopin->Active(); - if (vphres!=S_OK) { - LeaveCriticalSection(&filterlock); - return vphres; - } - } - - mystate=State_Paused; - LeaveCriticalSection(&filterlock); - - - return S_OK; + EnterCriticalSection(&filterlock); + HRESULT aphres; + HRESULT vphres; + + if (audiopin->IsConnected()){ + aphres=audiopin->Active(); + if (aphres!=S_OK) { + LeaveCriticalSection(&filterlock); + return aphres; + } + } + if (videopin->IsConnected()){ + vphres=videopin->Active(); + if (vphres!=S_OK) { + LeaveCriticalSection(&filterlock); + return vphres; + } + } + + mystate=State_Paused; + LeaveCriticalSection(&filterlock); + + + return S_OK; } HRESULT STDMETHODCALLTYPE DsSourceFilter::Run(REFERENCE_TIME start){ - - HRESULT aphres; - HRESULT vphres; - EnterCriticalSection(&filterlock); - - if (mystate==State_Stopped) { - HRESULT phres=Pause(); - if (phres!=S_OK){ - LeaveCriticalSection(&filterlock); - return phres; - } - } - - laststart=start; - - - if (audiopin->IsConnected()){ - aphres=audiopin->Run(start); - if (aphres!=S_OK) { - LeaveCriticalSection(&filterlock); - return aphres; - } - } - - if (videopin->IsConnected()){ - vphres=videopin->Run(start); - if (vphres!=S_OK) { - LeaveCriticalSection(&filterlock); - return vphres; - } - } - - mystate=State_Running; - LeaveCriticalSection(&filterlock); - - - return S_OK; + + HRESULT aphres; + HRESULT vphres; + EnterCriticalSection(&filterlock); + + if (mystate==State_Stopped) { + HRESULT phres=Pause(); + if (phres!=S_OK){ + LeaveCriticalSection(&filterlock); + return phres; + } + } + + laststart=start; + + + if (audiopin->IsConnected()){ + aphres=audiopin->Run(start); + if (aphres!=S_OK) { + LeaveCriticalSection(&filterlock); + return aphres; + } + } + + if (videopin->IsConnected()){ + vphres=videopin->Run(start); + if (vphres!=S_OK) { + LeaveCriticalSection(&filterlock); + return vphres; + } + } + + mystate=State_Running; + LeaveCriticalSection(&filterlock); + + + return S_OK; } int DsSourceFilter::GetPinCount() { - return 2; //audio and video + return 2; //audio and video } int DsSourceFilter::getCurrentAudioMediaSample(IMediaSample** ms) { - if (!audiopin || !IsActive()) { - return 0; - } - if (audiopin->getCurrentMediaSample(ms)!=S_OK) { - return 0; - } - return 1; + if (!audiopin || !IsActive()) { + return 0; + } + if (audiopin->getCurrentMediaSample(ms)!=S_OK) { + return 0; + } + return 1; } int DsSourceFilter::getCurrentVideoMediaSample(IMediaSample** ms) { - if (!videopin || !IsActive()) { - return 0; - } - if (videopin->getCurrentMediaSample(ms)!=S_OK) { - return 0; - } - return 1; + if (!videopin || !IsActive()) { + return 0; + } + if (videopin->getCurrentMediaSample(ms)!=S_OK) { + return 0; + } + return 1; } int DsSourceFilter::DeliverAudioMediaSample(IMediaSample* ms) { - if (!audiopin || !IsActive()) { - ms->Release(); - return 0; - } - if (audiopin->deliver(ms)!=S_OK) { - ms->Release(); - return 0; - } - ms->Release(); - return 1; + if (!audiopin || !IsActive()) { + ms->Release(); + return 0; + } + if (audiopin->deliver(ms)!=S_OK) { + ms->Release(); + return 0; + } + ms->Release(); + return 1; } @@ -428,16 +429,16 @@ bool DsSourceFilter::supportsAc3() int DsSourceFilter::DeliverVideoMediaSample(IMediaSample* ms) { - if (!videopin || !IsActive()) { - ms->Release(); - return 0; - } - if (videopin->deliver(ms)!=S_OK) { - ms->Release(); - return 0; - } - ms->Release(); - return 1; + if (!videopin || !IsActive()) { + ms->Release(); + return 0; + } + if (videopin->deliver(ms)!=S_OK) { + ms->Release(); + return 0; + } + ms->Release(); + return 1; } @@ -448,7 +449,9 @@ bool DsSourceFilter::changeAType(int type,IMediaSample* ms) } audiopin->SetPinMode(type); audiopin->SetMsToMt(ms); - + return true; } + + diff --git a/dssourcefilter.h b/dssourcefilter.h index ba3f12e..2ddb60d 100644 --- a/dssourcefilter.h +++ b/dssourcefilter.h @@ -28,59 +28,61 @@ [uuid("EB87AB22-7A95-49c3-8CCE-2F6D61A87009")] class DsSourceFilter: public IBaseFilter { -friend class DsSourcePin; +friend class DsSourcePin; public: - DsSourceFilter(); - ~DsSourceFilter(); - virtual int GetPinCount(); - int getCurrentAudioMediaSample(IMediaSample** ms); - int DeliverAudioMediaSample(IMediaSample* ms); - int getCurrentVideoMediaSample(IMediaSample** ms); - int DeliverVideoMediaSample(IMediaSample* ms); - REFERENCE_TIME getStartOffset(){return laststart;}; - BOOL IsActive() {EnterCriticalSection(&filterlock); - FILTER_STATE tempstate=mystate;LeaveCriticalSection(&filterlock); - return (tempstate==State_Running) || (tempstate==State_Paused);}; + DsSourceFilter(); + ~DsSourceFilter(); + virtual int GetPinCount(); + int getCurrentAudioMediaSample(IMediaSample** ms); + int DeliverAudioMediaSample(IMediaSample* ms); + int getCurrentVideoMediaSample(IMediaSample** ms); + int DeliverVideoMediaSample(IMediaSample* ms); + REFERENCE_TIME getStartOffset(){return laststart;}; + BOOL IsActive() {EnterCriticalSection(&filterlock); + FILTER_STATE tempstate=mystate;LeaveCriticalSection(&filterlock); + return (tempstate==State_Running) || (tempstate==State_Paused);}; /* IUnknown */ - virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID id,void ** object); - virtual ULONG STDMETHODCALLTYPE AddRef(); + virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID id,void ** object); + virtual ULONG STDMETHODCALLTYPE AddRef(); virtual ULONG STDMETHODCALLTYPE Release(); /*IPersist*/ - virtual HRESULT STDMETHODCALLTYPE GetClassID(CLSID *clsid); + virtual HRESULT STDMETHODCALLTYPE GetClassID(CLSID *clsid); /*IBaseFilter*/ - virtual HRESULT STDMETHODCALLTYPE EnumPins(IEnumPins **enumar); - virtual HRESULT STDMETHODCALLTYPE FindPin(LPCWSTR iden,IPin **pin); - virtual HRESULT STDMETHODCALLTYPE QueryFilterInfo(FILTER_INFO *info); - virtual HRESULT STDMETHODCALLTYPE JoinFilterGraph(IFilterGraph *graph,LPCWSTR name); - virtual HRESULT STDMETHODCALLTYPE QueryVendorInfo(LPWSTR *vendinf); + virtual HRESULT STDMETHODCALLTYPE EnumPins(IEnumPins **enumar); + virtual HRESULT STDMETHODCALLTYPE FindPin(LPCWSTR iden,IPin **pin); + virtual HRESULT STDMETHODCALLTYPE QueryFilterInfo(FILTER_INFO *info); + virtual HRESULT STDMETHODCALLTYPE JoinFilterGraph(IFilterGraph *graph,LPCWSTR name); + virtual HRESULT STDMETHODCALLTYPE QueryVendorInfo(LPWSTR *vendinf); /*IMediaFilter*/ - virtual HRESULT STDMETHODCALLTYPE GetState(DWORD timeout,FILTER_STATE *state); - virtual HRESULT STDMETHODCALLTYPE SetSyncSource(IReferenceClock *uhr); - virtual HRESULT STDMETHODCALLTYPE GetSyncSource(IReferenceClock **uhr); - virtual HRESULT STDMETHODCALLTYPE Stop(); - virtual HRESULT STDMETHODCALLTYPE Pause(); - virtual HRESULT STDMETHODCALLTYPE Run(REFERENCE_TIME start); + virtual HRESULT STDMETHODCALLTYPE GetState(DWORD timeout,FILTER_STATE *state); + virtual HRESULT STDMETHODCALLTYPE SetSyncSource(IReferenceClock *uhr); + virtual HRESULT STDMETHODCALLTYPE GetSyncSource(IReferenceClock **uhr); + virtual HRESULT STDMETHODCALLTYPE Stop(); + virtual HRESULT STDMETHODCALLTYPE Pause(); + virtual HRESULT STDMETHODCALLTYPE Run(REFERENCE_TIME start); - DsSourcePin *GetAudioPin() {return audiopin;}; - DsSourcePin *GetVideoPin() {return videopin;}; + DsSourcePin *GetAudioPin() {return audiopin;}; + DsSourcePin *GetVideoPin() {return videopin;}; + + bool supportsAc3(); + bool changeAType(int type,IMediaSample* ms); - bool supportsAc3(); - bool changeAType(int type,IMediaSample* ms); protected: - DsSourcePin *audiopin; - DsSourcePin *videopin; - IFilterGraph* filtergraph; - IReferenceClock* clock; - FILTER_STATE mystate; - REFERENCE_TIME laststart; - CRITICAL_SECTION filterlock; + DsSourcePin *audiopin; + DsSourcePin *videopin; + IFilterGraph* filtergraph; + IReferenceClock* clock; + FILTER_STATE mystate; + REFERENCE_TIME laststart; + CRITICAL_SECTION filterlock; - volatile long refs; + volatile long refs; }; #endif + diff --git a/dssourcepin.cc b/dssourcepin.cc index 8840e28..49d932a 100644 --- a/dssourcepin.cc +++ b/dssourcepin.cc @@ -60,11 +60,11 @@ HRESULT STDMETHODCALLTYPE DsSFEnumMediaTypes::Next(ULONG numpin, AM_MEDIA_TYPE * for (i=0;(iGetMediaType(curpos+i,pins[i])!=S_OK) { - CoTaskMemFree(pins[i]); - pins[i]=NULL; - return S_FALSE; - } curpos++; + if (parent->GetMediaType(curpos+i,pins[i])!=S_OK) { + CoTaskMemFree(pins[i]); + pins[i]=NULL; + return S_FALSE; + } curpos++; if (fetched!=NULL) (*fetched)++; } return S_OK; @@ -220,36 +220,36 @@ HRESULT STDMETHODCALLTYPE DsSourcePin::Connect(IPin *pinempf,const AM_MEDIA_TYPE AM_MEDIA_TYPE * emtype; ULONG fetched=0; pinempf->AddRef(); - + while (emt->Next(1,&emtype,&fetched)==S_OK) { if (CheckMediaType(emtype)==S_OK){ - /* PIN_INFO pini; - pinempf->QueryPinInfo(&pini); - if (pini.pFilter!=NULL) { - FILTER_INFO filti; - pini.pFilter->QueryFilterInfo(&filti); - - if (filti.pGraph!=NULL) filti.pGraph->Release(); - char buffer[MAX_FILTER_NAME*2]; - wcstombs(buffer,filti.achName,MAX_FILTER_NAME*2); - MessageBox(0,buffer,"Filter",0); - pini.pFilter->Release(); - }*/ + /* PIN_INFO pini; + pinempf->QueryPinInfo(&pini); + if (pini.pFilter!=NULL) { + FILTER_INFO filti; + pini.pFilter->QueryFilterInfo(&filti); + + if (filti.pGraph!=NULL) filti.pGraph->Release(); + char buffer[MAX_FILTER_NAME*2]; + wcstombs(buffer,filti.achName,MAX_FILTER_NAME*2); + MessageBox(0,buffer,"Filter",0); + pini.pFilter->Release(); + }*/ if (pinempf->ReceiveConnection((IPin*)this,emtype)==S_OK) { connected=pinempf; CopyMType(&medtype,emtype); - if (emtype->pbFormat!=NULL) CoTaskMemFree(emtype->pbFormat); - - CoTaskMemFree(emtype); + if (emtype->pbFormat!=NULL) CoTaskMemFree(emtype->pbFormat); + + CoTaskMemFree(emtype); gotmt=true; break; } } if (emtype->pbFormat!=NULL) CoTaskMemFree(emtype->pbFormat); - CoTaskMemFree(emtype); + CoTaskMemFree(emtype); } emt->Release(); if (gotmt==false) { @@ -260,14 +260,14 @@ HRESULT STDMETHODCALLTYPE DsSourcePin::Connect(IPin *pinempf,const AM_MEDIA_TYPE connected=pinempf; CopyMType(&medtype,emtype); if (emtype->pbFormat!=NULL) CoTaskMemFree(emtype->pbFormat); - CoTaskMemFree(emtype); + CoTaskMemFree(emtype); gotmt=true; break; } } if (emtype->pbFormat!=NULL) CoTaskMemFree(emtype->pbFormat); - CoTaskMemFree(emtype); + CoTaskMemFree(emtype); } emt->Release(); if (gotmt==false) { @@ -447,7 +447,7 @@ bool DsSourcePin::supportsAc3() { { return false; //Graph is not build, please wait } - if (connected==NULL) + if (connected==NULL) { return false; //Graph is not build, please wait } @@ -472,7 +472,7 @@ bool DsSourcePin::supportsAc3() { { CoTaskMemFree(test.pbFormat); return true; - } + } CoTaskMemFree(test.pbFormat); return false; @@ -482,37 +482,37 @@ bool DsSourcePin::supportsAc3() { HRESULT DsSourcePin::GetMediaTypeMpegAudio(int iPosition, AM_MEDIA_TYPE *pmt) { HRESULT hr; - switch (iPosition) + switch (iPosition) { /* case 0: { - ZeroMemory(pmt,sizeof(*pmt)); - pmt->lSampleSize = 1; - pmt->bFixedSizeSamples = TRUE; - pmt->majortype=MEDIATYPE_Audio; - MPEG1WAVEFORMAT wfe; - ZeroMemory(&wfe,sizeof(wfe)); - wfe.wfx.cbSize=22; - wfe.wfx.nSamplesPerSec=48000; - wfe.wfx.nChannels=2; - wfe.wfx.nAvgBytesPerSec=32000; - wfe.wfx.nBlockAlign=768; - wfe.wfx.wFormatTag=WAVE_FORMAT_MPEG; - wfe.wfx.wBitsPerSample=0; - wfe.fwHeadLayer=2; - wfe.dwHeadBitrate=256000; - wfe.fwHeadMode=ACM_MPEG_STEREO; - wfe.fwHeadModeExt=1; - wfe.wHeadEmphasis=1; - wfe.fwHeadFlags=ACM_MPEG_ID_MPEG1 |ACM_MPEG_ORIGINALHOME | ACM_MPEG_PROTECTIONBIT; - pmt->subtype=MEDIASUBTYPE_MPEG2_AUDIO; - pmt->formattype=FORMAT_WaveFormatEx; - pmt->cbFormat=sizeof(wfe); - pmt->pbFormat=(BYTE*)CoTaskMemAlloc(sizeof(wfe)); - memcpy(pmt->pbFormat,&wfe,sizeof(wfe)); - pmt->lSampleSize=0; - hr=S_OK; - } break;*/ - case 0: + ZeroMemory(pmt,sizeof(*pmt)); + pmt->lSampleSize = 1; + pmt->bFixedSizeSamples = TRUE; + pmt->majortype=MEDIATYPE_Audio; + MPEG1WAVEFORMAT wfe; + ZeroMemory(&wfe,sizeof(wfe)); + wfe.wfx.cbSize=22; + wfe.wfx.nSamplesPerSec=48000; + wfe.wfx.nChannels=2; + wfe.wfx.nAvgBytesPerSec=32000; + wfe.wfx.nBlockAlign=768; + wfe.wfx.wFormatTag=WAVE_FORMAT_MPEG; + wfe.wfx.wBitsPerSample=0; + wfe.fwHeadLayer=2; + wfe.dwHeadBitrate=256000; + wfe.fwHeadMode=ACM_MPEG_STEREO; + wfe.fwHeadModeExt=1; + wfe.wHeadEmphasis=1; + wfe.fwHeadFlags=ACM_MPEG_ID_MPEG1 |ACM_MPEG_ORIGINALHOME | ACM_MPEG_PROTECTIONBIT; + pmt->subtype=MEDIASUBTYPE_MPEG2_AUDIO; + pmt->formattype=FORMAT_WaveFormatEx; + pmt->cbFormat=sizeof(wfe); + pmt->pbFormat=(BYTE*)CoTaskMemAlloc(sizeof(wfe)); + memcpy(pmt->pbFormat,&wfe,sizeof(wfe)); + pmt->lSampleSize=0; + hr=S_OK; + } break;*/ + case 0: { ZeroMemory(pmt,sizeof(*pmt)); pmt->lSampleSize = 1; @@ -528,44 +528,44 @@ HRESULT DsSourcePin::GetMediaTypeMpegAudio(int iPosition, AM_MEDIA_TYPE *pmt) wfe.wFormatTag = WAVE_FORMAT_UNKNOWN; wfe.wBitsPerSample = 0; pmt->subtype = MEDIASUBTYPE_MPEG2_AUDIO; - pmt->formattype = FORMAT_WaveFormatEx; - pmt->cbFormat = sizeof(wfe); - pmt->pbFormat = (BYTE*)CoTaskMemAlloc(sizeof(wfe)); - memcpy(pmt->pbFormat,&wfe,sizeof(wfe)); - pmt->lSampleSize=0; - hr=S_OK; + pmt->formattype = FORMAT_WaveFormatEx; + pmt->cbFormat = sizeof(wfe); + pmt->pbFormat = (BYTE*)CoTaskMemAlloc(sizeof(wfe)); + memcpy(pmt->pbFormat,&wfe,sizeof(wfe)); + pmt->lSampleSize=0; + hr=S_OK; } break; case 1: { ZeroMemory(pmt,sizeof(*pmt)); - pmt->lSampleSize = 1; - pmt->bFixedSizeSamples = TRUE; - pmt->majortype = MEDIATYPE_Audio; - MPEG1WAVEFORMAT wfe; - ZeroMemory(&wfe,sizeof(wfe)); - wfe.wfx.cbSize = 22; - wfe.wfx.nSamplesPerSec = 48000; - wfe.wfx.nChannels = 2; - wfe.wfx.nAvgBytesPerSec = 32000; - wfe.wfx.nBlockAlign = 768; - wfe.wfx.wFormatTag = WAVE_FORMAT_UNKNOWN; + pmt->lSampleSize = 1; + pmt->bFixedSizeSamples = TRUE; + pmt->majortype = MEDIATYPE_Audio; + MPEG1WAVEFORMAT wfe; + ZeroMemory(&wfe,sizeof(wfe)); + wfe.wfx.cbSize = 22; + wfe.wfx.nSamplesPerSec = 48000; + wfe.wfx.nChannels = 2; + wfe.wfx.nAvgBytesPerSec = 32000; + wfe.wfx.nBlockAlign = 768; + wfe.wfx.wFormatTag = WAVE_FORMAT_UNKNOWN; wfe.wfx.wBitsPerSample = 0; - /* wfe.fwHeadLayer=2; - wfe.dwHeadBitrate=256000; - wfe.fwHeadMode=ACM_MPEG_STEREO; - wfe.fwHeadModeExt=1; - wfe.wHeadEmphasis=1; + /* wfe.fwHeadLayer=2; + wfe.dwHeadBitrate=256000; + wfe.fwHeadMode=ACM_MPEG_STEREO; + wfe.fwHeadModeExt=1; + wfe.wHeadEmphasis=1; wfe.fwHeadFlags=ACM_MPEG_ID_MPEG1 |ACM_MPEG_ORIGINALHOME | ACM_MPEG_PROTECTIONBIT;*/ - pmt->subtype=MEDIASUBTYPE_MPEG1Payload; - pmt->formattype=FORMAT_WaveFormatEx; - pmt->cbFormat=sizeof(wfe); - pmt->pbFormat=(BYTE*)CoTaskMemAlloc(sizeof(wfe)); - memcpy(pmt->pbFormat,&wfe,sizeof(wfe)); - pmt->lSampleSize=0; - hr=S_OK; - } break; - default: { - hr=VFW_S_NO_MORE_ITEMS; - }break; + pmt->subtype=MEDIASUBTYPE_MPEG1Payload; + pmt->formattype=FORMAT_WaveFormatEx; + pmt->cbFormat=sizeof(wfe); + pmt->pbFormat=(BYTE*)CoTaskMemAlloc(sizeof(wfe)); + memcpy(pmt->pbFormat,&wfe,sizeof(wfe)); + pmt->lSampleSize=0; + hr=S_OK; + } break; + default: { + hr=VFW_S_NO_MORE_ITEMS; + }break; }; return hr ; } @@ -585,19 +585,19 @@ HRESULT DsSourcePin::GetMediaTypeAc3(int iPosition, AM_MEDIA_TYPE *pmt) ZeroMemory(&wfe,sizeof(wfe)); wfe.cbSize = 22; wfe.nSamplesPerSec = 48000; - wfe.nChannels = 2; - wfe.nAvgBytesPerSec = 32000; - wfe.nBlockAlign = 768; - wfe.wFormatTag = WAVE_FORMAT_UNKNOWN; - wfe.wBitsPerSample = 0; - pmt->subtype = MEDIASUBTYPE_DOLBY_AC3; + wfe.nChannels = 2; + wfe.nAvgBytesPerSec = 32000; + wfe.nBlockAlign = 768; + wfe.wFormatTag = WAVE_FORMAT_UNKNOWN; + wfe.wBitsPerSample = 0; + pmt->subtype = MEDIASUBTYPE_DOLBY_AC3; // pmt->subtype = MEDIASUBTYPE_DOLBY_AC3_SPDIF; - pmt->formattype = FORMAT_WaveFormatEx; - pmt->cbFormat = sizeof(wfe); - pmt->pbFormat = (BYTE*)CoTaskMemAlloc(sizeof(wfe)); - memcpy(pmt->pbFormat,&wfe,sizeof(wfe)); - pmt->lSampleSize = 0; - hr = S_OK; + pmt->formattype = FORMAT_WaveFormatEx; + pmt->cbFormat = sizeof(wfe); + pmt->pbFormat = (BYTE*)CoTaskMemAlloc(sizeof(wfe)); + memcpy(pmt->pbFormat,&wfe,sizeof(wfe)); + pmt->lSampleSize = 0; + hr = S_OK; } break; default: { hr=VFW_S_NO_MORE_ITEMS; @@ -640,7 +640,7 @@ HRESULT DsSourcePin::GetMediaType(int iPosition, AM_MEDIA_TYPE *pmt) switch (pinmode){ case MPTYPE_MPEG_AUDIO: - return GetMediaTypeMpegAudio(iPosition,pmt); + return GetMediaTypeMpegAudio(iPosition,pmt); break; case MPTYPE_VIDEO: return GetMediaTypeMpegVideo(iPosition,pmt); @@ -680,24 +680,24 @@ HRESULT DsSourcePin::CheckMediaType(const AM_MEDIA_TYPE *pmt) bool subtype=false; switch (pinmode) { case MPTYPE_MPEG_AUDIO: - subtype=(pmt->subtype==(MEDIASUBTYPE_MPEG2_AUDIO)); + subtype=(pmt->subtype==(MEDIASUBTYPE_MPEG2_AUDIO)); subtype=(pmt->subtype==MEDIASUBTYPE_MPEG1Payload) || subtype; - if (pmt->majortype==MEDIATYPE_Audio && subtype) + if (pmt->majortype==MEDIATYPE_Audio && subtype) { res = S_OK ; - } - else + } + else { res = S_FALSE ; } break; case MPTYPE_VIDEO: if (pmt->majortype==MEDIATYPE_Video && - pmt-> subtype==MEDIASUBTYPE_MPEG2_VIDEO) + pmt-> subtype==MEDIASUBTYPE_MPEG2_VIDEO) { res = S_OK ; - } - else + } + else { res = S_FALSE ; } @@ -706,11 +706,11 @@ HRESULT DsSourcePin::CheckMediaType(const AM_MEDIA_TYPE *pmt) case MPTYPE_AC3: subtype=pmt->subtype==(MEDIASUBTYPE_DOLBY_AC3); subtype=pmt->subtype==(MEDIASUBTYPE_DOLBY_AC3_SPDIF) || subtype; - if (pmt->majortype==MEDIATYPE_Audio && subtype) + if (pmt->majortype==MEDIATYPE_Audio && subtype) { res = S_OK ; } - else + else { res = S_FALSE ; } @@ -754,3 +754,4 @@ HRESULT DsSourcePin::DecideBufferSize(IMemAllocator *pa,ALLOCATOR_PROPERTIES *al return S_OK; } + diff --git a/dssourcepin.h b/dssourcepin.h index bb2a8e2..d6af62f 100644 --- a/dssourcepin.h +++ b/dssourcepin.h @@ -40,6 +40,7 @@ public: HRESULT deliver(IMediaSample * ms); void SetMsToMt(IMediaSample *ms); bool supportsAc3(); + void SetPinMode(int mode); virtual HRESULT DecideBufferSize(IMemAllocator *pa,ALLOCATOR_PROPERTIES *all_pp); @@ -77,7 +78,6 @@ protected: HRESULT GetMediaTypeAc3(int iPosition, AM_MEDIA_TYPE *pmt); HRESULT GetMediaTypeMpegVideo(int iPosition, AM_MEDIA_TYPE *pmt); - void SetPinMode(int mode); int pinmode; bool isaudiopin; DsSourceFilter *m_pFilter; @@ -94,3 +94,4 @@ protected: #endif + diff --git a/main.cc b/main.cc index 4c79009..9a329fb 100644 --- a/main.cc +++ b/main.cc @@ -475,3 +475,9 @@ void MILLISLEEP(ULONG a) Sleep(a); #endif } + +int max(int a, int b) +{ + if (a > b) return a; + else return b; +} diff --git a/message.h b/message.h index 0c7b701..9f1a4b0 100644 --- a/message.h +++ b/message.h @@ -71,6 +71,7 @@ class Message const static ULONG MOUSE_LBDOWN = 26; const static ULONG CHANGE_LANGUAGE = 27; const static ULONG LAST_VIEW_CLOSE = 28; + const static ULONG CHANGED_REMOTECONTROL = 29; }; #endif diff --git a/mtdwin.cc b/mtdwin.cc index 401289d..ea1ba48 100644 --- a/mtdwin.cc +++ b/mtdwin.cc @@ -48,3 +48,4 @@ short MtdWin::getPALorNTSC() { return Video::PAL; //Fixme! } + diff --git a/mtdwin.h b/mtdwin.h index 46ffb98..cb02dea 100644 --- a/mtdwin.h +++ b/mtdwin.h @@ -39,3 +39,4 @@ virtual short getPALorNTSC(); }; #endif + diff --git a/objects.mk b/objects.mk index a63c9d9..f86dcaa 100644 --- a/objects.mk +++ b/objects.mk @@ -11,6 +11,7 @@ OBJECTS1 = command.o log.o tcp.o dsock.o thread.o timers.o i18n.o mutex.o \ vchannellist.o vwelcome.o vvideolive.o vvideorec.o vepgsettimer.o \ vchannelselect.o vserverselect.o vconnect.o vepg.o vrecmove.o \ vradiorec.o vaudioselector.o \ + vtabsviewman.o vremoteconfig.o \ widget.o wselectlist.o wjpeg.o wsymbol.o wbutton.o \ woptionbox.o wtextbox.o wwss.o \ fonts/helvB24.o fonts/helvB18.o \ diff --git a/osdwin.cc b/osdwin.cc index 943201b..23e0b91 100644 --- a/osdwin.cc +++ b/osdwin.cc @@ -357,4 +357,3 @@ void OsdWin::Blank() { d3ddevice->Clear(0,NULL,D3DCLEAR_TARGET,D3DCOLOR_XRGB(0,0,0),1.0f,0); EndPainting(); } - diff --git a/osdwin.h b/osdwin.h index df99899..3f3844b 100644 --- a/osdwin.h +++ b/osdwin.h @@ -81,4 +81,3 @@ private: }; #endif - diff --git a/remote.cc b/remote.cc index aaa6d6f..bdaa52f 100644 --- a/remote.cc +++ b/remote.cc @@ -19,6 +19,7 @@ */ #include "remote.h" +#include "i18n.h" Remote* Remote::instance = NULL; @@ -27,6 +28,7 @@ Remote::Remote() if (instance) return; instance = this; remoteType = OLDREMOTE; + learnmode = NOLEARNMODE; } Remote::~Remote() @@ -44,3 +46,373 @@ void Remote::setRemoteType(UCHAR newType) if ((newType != OLDREMOTE) && (newType != NEWREMOTE)) return; remoteType = newType; } + +void Remote::EnterLearningMode(UCHAR command) +{ + learnmode = command; //Armed +} + +void Remote::ResetToDefault() +{ + translist.clear(); + InitHWCListwithDefaults(); +} + + +UCHAR Remote::TranslateHWCFixed(ULLONG code) +{ + switch (code) + { + case DOWN: + return DOWN; + case UP: + return UP; + case LEFT: + return LEFT; + case RIGHT: + return RIGHT; + case DF_DOWN: + return DOWN; + case DF_UP: + return UP; + case DF_LEFT: + return LEFT; + case DF_RIGHT: + return RIGHT; + case MENU: + return MENU; + case BACK: + return BACK; + case OK: + return OK; + default: + return NA_UNKNOWN; + } +} + +const char*Remote::HardcodedTranslateStr(UCHAR command) +{ + switch (command) + { + case DOWN: + return tr("Down"); + case UP: + return tr("Up"); + case LEFT: + return tr("Left"); + case RIGHT: + return tr("Right"); + case MENU: + return tr("Menu"); + case BACK: + return tr("Back"); + case OK: + return tr("Ok"); + default: + return NULL; + } +} + +UCHAR Remote::TranslateHWCList(ULLONG code) +{ + if (learnmode != NOLEARNMODE) + { + setHWCtoCommand(code, learnmode); + learnmode = NOLEARNMODE; + return NA_LEARN; + } + RemoteTranslationList::iterator it = translist.find(code); + if (it == translist.end()) + { + return NA_UNKNOWN; + } + else + { + return it->second; + } +} + +UCHAR Remote::TranslateHWC(ULLONG code) +{ + UCHAR ret = TranslateHWCFixed(code); + if (ret == NA_UNKNOWN) + { + ret = TranslateHWCList(code); + } + else + { + learnmode = NOLEARNMODE; + } + + if (ret == NA_UNKNOWN) + { + return NA_UNKNOWN; + } + return ret; +} + +void Remote::setHWCtoCommand(ULLONG hcw, UCHAR command) +{ + translist[hcw] = command; +} + +void Remote::unsetHWC(ULLONG hcw) +{ + translist.erase(hcw); +} + +void Remote::LoadKeysConfig(char *cfg) +{ + char *start = cfg; + start = strchr(cfg,'H')+1; + while ((start-1) != NULL) + { + ULONG ul1, ul2; + ULONG uc; + if (sscanf(start,"%XI%XK%X",&ul1,&ul2,&uc) == 3) + { + translist[((ULLONG) ul1) | ((ULLONG)ul2) << 32]=(UCHAR)uc; + } + start = strchr(start, 'H')+1; + } +} + +char *Remote::SaveKeysConfig() +{ + int length=21*translist.size() +1; + char *output=new char[length]; + char *current=output; + int pos=0; + RemoteTranslationList::const_iterator it; + for (it = translist.begin(); it != translist.end(); it++) + { + current+=sprintf(current,"H%08XI%08XK%02X", + (ULONG)it->first ,(ULONG) (it->first >> 32), it->second); + } + return output; +} + + +void Remote::InitHWCListwithDefaults() +{ + translist[VOLUMEUP] = VOLUMEUP; + translist[VOLUMEDOWN] = VOLUMEDOWN; + translist[CHANNELUP] = CHANNELUP; + translist[CHANNELDOWN] = CHANNELDOWN; + + // Common buttons + translist[ZERO] = ZERO; + translist[ONE] = ONE; + translist[TWO] = TWO; + translist[THREE] = THREE; + translist[FOUR] = FOUR; + translist[FIVE] = FIVE; + translist[SIX] = SIX; + translist[SEVEN] = SEVEN; + translist[EIGHT] = EIGHT; + translist[NINE] = NINE; + translist[POWER] = POWER; + translist[GO] = GO; + translist[RED] = RED; + translist[GREEN] = GREEN; + translist[YELLOW] = YELLOW; + translist[BLUE] = BLUE; + + translist[MUTE] = MUTE; + translist[RADIO] = RADIO; + translist[REVERSE] = REVERSE; + translist[FORWARD] = FORWARD; + translist[RECORD] = RECORD; + translist[STOP] = STOP; + translist[PAUSE] = PAUSE; + translist[SKIPBACK] = SKIPBACK; + translist[SKIPFORWARD] = SKIPFORWARD; + + // Old remote only + translist[FULL] = FULL; + + // New remote only + translist[TV] = TV; + translist[VIDEOS] = VIDEOS; + translist[MUSIC] = MUSIC; + translist[PICTURES] = PICTURES; + translist[GUIDE] = GUIDE; + translist[PREVCHANNEL] = PREVCHANNEL; + translist[STAR] = STAR; + translist[HASH] = HASH; +} + +const char *Remote::CommandDesc(UCHAR number) +{ + switch (number) + { + case VOLUMEUP: + return tr("Volume Up"); + + case VOLUMEDOWN: + return tr("Volume Down"); + case CHANNELUP: + return tr("Channel up"); + case CHANNELDOWN: + return tr("Channel down"); + case ZERO: + return "0"; + case ONE: + return "1"; + case TWO: + return "2"; + case THREE: + return "3"; + case FOUR: + return "4"; + case FIVE: + return "5"; + case SIX: + return "6"; + case SEVEN: + return "7"; + case EIGHT: + return "8"; + case NINE: + return "9"; + case POWER: + return tr("Power"); + case GO: + return tr("Go"); + case BACK: + return tr("Back"); + case MENU: + return tr("Menu"); + case RED: + return tr("Red"); + case GREEN: + return tr("Green"); + case YELLOW: + return tr("Yellow"); + case BLUE: + return tr("Blue"); + case MUTE: + return tr("Mute"); + case RADIO: + return tr("Radio"); + case REVERSE: + return tr("Reverse"); + case PLAY: + return tr("Play"); + case FORWARD: + return tr("Forward"); + case RECORD: + return tr("Record"); + case STOP: + return tr("Stop"); + case PAUSE: + return tr("Pause"); + case SKIPBACK: + return tr("Skip back"); + case SKIPFORWARD: + return tr("Skip forward"); + case OK: + return tr("Ok"); + case FULL: + return tr("Fullscreen"); + case TV: + return tr("TV"); + case VIDEOS: + return tr("Videos"); + case MUSIC: + return tr("Music"); + case PICTURES: + return tr("Pictures"); + case GUIDE: + return tr("Guide"); + case UP: + return tr("Up"); + case DOWN: + return tr("Down"); + case LEFT: + return tr("Left"); + case RIGHT: + return tr("Right"); + case PREVCHANNEL: + return tr("Previous Channel"); + case STAR: + return tr("Star"); + case HASH: + return tr("Hash"); + + default: + return NULL; + } +} + +char* Remote::HCWDesc(ULLONG hcw) +{ + char *dest,*temp; + temp=(char*)CommandDesc((UCHAR)hcw); + if (temp != NULL) + { + dest=new char[strlen(temp)+1]; + strcpy(dest,temp); + } + else + { + dest=new char[20]; + sprintf(dest,"C:%X",(ULONG)hcw); + } + return dest; +} + +char *Remote::CommandTranslateStr(UCHAR command) +{ + char *desc; + int length=5;//:+\t+0 + int keys=0; //max 10; + char *commanddesc=(char*)CommandDesc(command); + if (commanddesc != NULL) + { + length+=strlen(commanddesc); + } + char *preassigneddesc=(char*)HardcodedTranslateStr(command); + if (preassigneddesc != NULL) + { + length+=strlen(preassigneddesc); + } + + char *keydesc[10]; + RemoteTranslationList::const_iterator it; + for (it = translist.begin(); it != translist.end(); it++) + { + if (it->second == command) + { + keydesc[keys] = HCWDesc(it->first); + length += strlen(keydesc[keys])+2; + keys ++; + if (keys == 10) break; + } + } + + desc=new char [length]; + char *current=desc; + if (commanddesc != NULL) + { + current+=sprintf(current,"%s:\t ",commanddesc); + } + else + { + current+=sprintf(current,":\t "); + } + if (preassigneddesc != NULL) + { + current+=sprintf(current,"%s\t",preassigneddesc); + } + else + { + current+=sprintf(current,"\t"); + } + for (int i = 0;i < keys; i++) + { + current += sprintf(current,"%s, ",keydesc[i]); + delete [] keydesc[i]; + } + return desc; +} diff --git a/remote.h b/remote.h index 806dece..7d0be6e 100644 --- a/remote.h +++ b/remote.h @@ -22,10 +22,14 @@ #define REMOTE_H #include +#include #include "defines.h" #include "log.h" +using namespace std; +typedef map RemoteTranslationList; + class Remote { public: @@ -34,13 +38,28 @@ class Remote static Remote* getInstance(); void setRemoteType(UCHAR type); + void setHWCtoCommand(ULLONG hcw,UCHAR command); + void unsetHWC(ULLONG hcw); + void LoadKeysConfig(char *cfg); + char *SaveKeysConfig(); + void EnterLearningMode(UCHAR command); virtual int init(char *devName)=0; virtual int shutdown()=0; virtual UCHAR getButtonPress(int how)=0; virtual void clearBuffer()=0; + virtual void InitHWCListwithDefaults(); + virtual char* HCWDesc(ULLONG hcw); + const char *CommandDesc(UCHAR number); + char *CommandTranslateStr(UCHAR command); + virtual const char*HardcodedTranslateStr(UCHAR command); + void EnterLearnMode(UCHAR command); + void ResetToDefault(); + + const static ULONG NOLEARNMODE = 256; // Not buttons + const static UCHAR NA_LEARN = 101; const static UCHAR NA_NONE = 98; const static UCHAR NA_UNKNOWN = 99; const static UCHAR NA_SIGNAL = 100; @@ -108,8 +127,14 @@ class Remote const static UCHAR NEWREMOTE = 2; protected: + virtual UCHAR TranslateHWCFixed(ULLONG code); + UCHAR TranslateHWCList(ULLONG code); + UCHAR TranslateHWC(ULLONG code); + + ULONG learnmode; static Remote* instance; UCHAR remoteType; + RemoteTranslationList translist; }; #endif diff --git a/remotemvp.cc b/remotemvp.cc index 634ee1e..bb07859 100644 --- a/remotemvp.cc +++ b/remotemvp.cc @@ -125,7 +125,7 @@ UCHAR RemoteMVP::getButtonPress(int waitType) if (input == CHANNELDOWN) return DF_DOWN; } - return (UCHAR) input; + return (UCHAR) TranslateHWC(input); } return NA_UNKNOWN; } diff --git a/remotewin.cc b/remotewin.cc index 879142f..d03e88b 100644 --- a/remotewin.cc +++ b/remotewin.cc @@ -20,12 +20,20 @@ #include "remotewin.h" #include "vompreswin.h" +#include "i18n.h" +#define W_G_HCW(type,code) ( (((ULLONG)(type))<<32) | code) + +#define W_HCW_VK 1 /* virtual key */ +#define W_HCW_AP 2 /* App command */ +#define W_HCW_RI 3 /* remote control */ +#define W_HCW_CH 4 /* char */ RemoteWin::RemoteWin() { initted = 0; - curevent=NA_NONE; + curevent=0; + hascurevent=false; signal=false; } @@ -59,10 +67,12 @@ UCHAR RemoteWin::getButtonPress(int waitType) how = 3 - no wait */ DWORD wait; + - if (curevent!=NA_NONE) { + if (hascurevent) { UCHAR temp=curevent; - curevent=NA_NONE; + hascurevent=false; + return temp; } if (waitType==3) { @@ -76,16 +86,16 @@ UCHAR RemoteWin::getButtonPress(int waitType) } WaitForSingleObject(event,wait); ResetEvent(event); - if (curevent==NA_NONE) { + if (!hascurevent) { if (signal) { signal=false; - return NA_SIGNAL; //Since we have no signals on windows, we simulate this + return NA_SIGNAL; //Since we have no signals on windows, we simulate this } else { return NA_NONE; } } UCHAR temp2=curevent; - curevent=NA_NONE; + hascurevent=false; return temp2; } @@ -94,8 +104,199 @@ void RemoteWin::clearBuffer() { } +UCHAR RemoteWin::TranslateHWCFixed(ULLONG code) +{ + switch (code) + { + case W_G_HCW(W_HCW_VK,VK_DOWN): + return DOWN; + case W_G_HCW(W_HCW_VK,VK_UP): + return UP; + case W_G_HCW(W_HCW_VK,VK_LEFT): + return LEFT; + case W_G_HCW(W_HCW_VK,VK_RIGHT): + return RIGHT; + case W_G_HCW(W_HCW_CH,'m'): + return MENU; + case W_G_HCW(W_HCW_VK,VK_BACK): + return BACK; + case W_G_HCW(W_HCW_VK,VK_RETURN): + case W_G_HCW(W_HCW_VK,VK_SPACE): + return OK; + /* Menu IDs, no sense to make it user selectable */ + case W_G_HCW(W_HCW_AP,APPCOMMAND_BROWSER_BACKWARD): + return BACK; + case W_G_HCW(W_HCW_AP,APPCOMMAND_MEDIA_CHANNEL_DOWN): + return CHANNELDOWN;break; + case W_G_HCW(W_HCW_AP,APPCOMMAND_MEDIA_CHANNEL_UP): + return CHANNELUP;break; + case W_G_HCW(W_HCW_AP,APPCOMMAND_MEDIA_FAST_FORWARD): + return FORWARD;break; + case W_G_HCW(W_HCW_AP,APPCOMMAND_VOLUME_MUTE): + return MUTE;break; + case W_G_HCW(W_HCW_AP,APPCOMMAND_MEDIA_PAUSE): + return PAUSE;break; + case W_G_HCW(W_HCW_AP,APPCOMMAND_MEDIA_PLAY): + return PLAY;break; + case W_G_HCW(W_HCW_AP,APPCOMMAND_MEDIA_RECORD): + return RECORD;break; + case W_G_HCW(W_HCW_AP,APPCOMMAND_MEDIA_PREVIOUSTRACK): + return SKIPBACK;break; + case W_G_HCW(W_HCW_AP,APPCOMMAND_MEDIA_REWIND): + return REVERSE;break; + case W_G_HCW(W_HCW_AP,APPCOMMAND_MEDIA_NEXTTRACK): + return SKIPFORWARD;break; + case W_G_HCW(W_HCW_AP,APPCOMMAND_MEDIA_STOP): + return STOP;break; + case W_G_HCW(W_HCW_AP,APPCOMMAND_VOLUME_DOWN): + return VOLUMEDOWN;break; + case W_G_HCW(W_HCW_AP,APPCOMMAND_VOLUME_UP): + return VOLUMEUP;break; + case W_G_HCW(W_HCW_AP,VOMP_YELLOW): + return YELLOW; break; + case W_G_HCW(W_HCW_AP,VOMP_BLUE): + return BLUE;break; + case W_G_HCW(W_HCW_AP,VOMP_RED): + return RED;break; + case W_G_HCW(W_HCW_AP,VOMP_GREEN): + return GREEN;break; + case W_G_HCW(W_HCW_AP,VOMP_ENTER): + return OK;break; + case W_G_HCW(W_HCW_AP,VOMP_CANCEL): + return BACK;break; + case W_G_HCW(W_HCW_AP,VOMP_UP): + return UP;break; + case W_G_HCW(W_HCW_AP,VOMP_DOWN): + return DOWN;break; + case W_G_HCW(W_HCW_AP,VOMP_LEFT): + return LEFT;break; + case W_G_HCW(W_HCW_AP,VOMP_RIGHT): + return RIGHT;break; + case POWER: + return POWER; + default: + return NA_UNKNOWN; + }; +} + +const char*RemoteWin::HardcodedTranslateStr(UCHAR command) +{ + switch (command) + { + case DOWN: + return tr("Down"); + case UP: + return tr("Up"); + case LEFT: + return tr("Left"); + case RIGHT: + return tr("Right"); + case MENU: + return tr("M"); + case BACK: + return tr("Backspace, Back"); + case OK: + return tr("Return, Space"); + case CHANNELDOWN: + return tr("Insrt, C+Insrt, Pg down"); + case CHANNELUP: + return tr("+, C++, Pg up"); + case VOLUMEUP: + return "F10"; + case VOLUMEDOWN: + return "F9"; + case POWER: + return "Esc, A+F4"; + case MUTE: + return "F8"; + case REVERSE: + return"S+C+B"; + case FORWARD: + return "S+C+F"; + case SKIPBACK: + return "C+B"; + case SKIPFORWARD: + return "C+F"; + case PLAY: + return "S+P"; + case STOP: + return "C+S"; + case PAUSE: + return "C+P"; + default: + return NULL; + }; + +} + + +void RemoteWin::InitHWCListwithDefaults() +{ + //Processing VK_Messages + translist[W_G_HCW(W_HCW_CH,'9')] = NINE; + translist[W_G_HCW(W_HCW_CH,'8')] = EIGHT; + translist[W_G_HCW(W_HCW_CH,'7')] = SEVEN; + translist[W_G_HCW(W_HCW_CH,'6')] = SIX; + translist[W_G_HCW(W_HCW_CH,'5')] = FIVE; + translist[W_G_HCW(W_HCW_CH,'4')] = FOUR; + translist[W_G_HCW(W_HCW_CH,'3')] = THREE; + translist[W_G_HCW(W_HCW_CH,'2')] = TWO; + translist[W_G_HCW(W_HCW_CH,'1')] = ONE; + translist[W_G_HCW(W_HCW_CH,'0')] = ZERO; + translist[W_G_HCW(W_HCW_CH,'*')] = STAR; + translist[W_G_HCW(W_HCW_CH,'#')] = HASH; + translist[W_G_HCW(W_HCW_CH,'j')] = GO; //j for JUMP TO instead of go to + translist[W_G_HCW(W_HCW_CH,'r')] = RED; + translist[W_G_HCW(W_HCW_CH,'g')] = GREEN; + translist[W_G_HCW(W_HCW_CH,'y')] = YELLOW; + translist[W_G_HCW(W_HCW_CH,'b')] = BLUE; + //Processing RI Messages + translist[W_G_HCW(W_HCW_RI,0x35c)] = GREEN; + translist[W_G_HCW(W_HCW_RI,0x35b)] = RED; + translist[W_G_HCW(W_HCW_RI,0x35d)] = YELLOW; + translist[W_G_HCW(W_HCW_RI,0x35e)] = BLUE; + translist[W_G_HCW(W_HCW_RI,0x30d)] = MENU;//MCE Button, used for Menu + translist[W_G_HCW(W_HCW_RI,0x348)] = RECORD; //Record Television + translist[W_G_HCW(W_HCW_RI,0x325)] = PLAY; //Playback Televison + translist[W_G_HCW(W_HCW_RI,0x324)] = PLAY; //Playback DVD + translist[W_G_HCW(W_HCW_RI,0x209)] = OK;//Properties + translist[W_G_HCW(W_HCW_RI,0x35a)] = OK;//Teletext? + +} + +char* RemoteWin::HCWDesc(ULLONG hcw) +{ + //Determine type + ULONG type = hcw >> 32; + char *rt=NULL; + switch(type) + { + case W_HCW_VK:{ + ULONG vk=(ULONG)hcw; + ULONG scancode=MapVirtualKey(vk,0); + rt=new char[10]; + GetKeyNameText(scancode << 16,rt,10); + }break; + case W_HCW_CH:{ + ULONG ch=(ULONG)hcw; + ULONG scancode=OemKeyScan(ch); + + rt=new char[10]; + GetKeyNameText(scancode << 16,rt,10); + }break; + case W_HCW_RI:{ + ULONG ri=(ULONG)hcw; + rt=new char[10]; + sprintf(rt,"R: %X",ri); + }break; + + }; + return rt; +} + + int RemoteWin::ReceiveButtonVK(UINT button) { - UCHAR pb=NA_NONE; +/* UCHAR pb=NA_NONE; //should we use a translation table ? No APPCOMMAND iS DWORD! switch (button) { //Processing VK_Messages case VK_DOWN: @@ -160,15 +361,30 @@ int RemoteWin::ReceiveButtonVK(UINT button) { }; //All other commands are process via APPCOMMAND_MESSAGES - if (pb==NA_NONE) return 0; - curevent=pb; + if (pb==NA_NONE) return 0;*/ + UCHAR pb=NA_NONE; + pb=TranslateHWC(W_G_HCW(W_HCW_VK,button)); + if (pb==NA_UNKNOWN || pb==NA_NONE) return 0; + curevent=pb; + hascurevent=true; + //PulseEvent(event); + SetEvent(event); + return 1; +} + +int RemoteWin::ReceiveButtonCH(UINT button) { + UCHAR pb=NA_NONE; + pb=TranslateHWC(W_G_HCW(W_HCW_CH,button)); + if (pb==NA_UNKNOWN || pb==NA_NONE) return 0; + curevent=pb; + hascurevent=true; //PulseEvent(event); SetEvent(event); return 1; } int RemoteWin::ReceiveButtonAP(UINT button) { - UCHAR pb=NA_NONE; +/* UCHAR pb=NA_NONE; //should we use a translation table ? No APPCOMMAND iS DWORD! switch (button) { //Processing VK_Messages case APPCOMMAND_BROWSER_BACKWARD: @@ -219,21 +435,26 @@ int RemoteWin::ReceiveButtonAP(UINT button) { pb=LEFT;break; case VOMP_RIGHT: pb=RIGHT;break; - }; - if (pb==NA_NONE) return 0; - curevent=pb; + };*/ + + //if (pb==NA_NONE) return 0; + UCHAR pb=NA_NONE; + pb=TranslateHWC(W_G_HCW(W_HCW_AP,button)); + if (pb==NA_UNKNOWN || pb==NA_NONE) return 0; + curevent=pb; + hascurevent=true; //PulseEvent(event); SetEvent(event); return 1; } int RemoteWin::ReceiveButtonRI(UINT button) { - UCHAR pb=NA_NONE; + //UCHAR pb=NA_NONE; //Raw Input /* Note Codes above 0x29c are not listed in the specs on usb.org therefore they are used by try, they might be device dependent thus please supply codes of your remote control */ - switch (button) { //Processing VK_Messages +/* switch (button) { //Processing VK_Messages case 0x35c: //Green pb=GREEN;break; case 0x35b: //Red @@ -258,8 +479,13 @@ int RemoteWin::ReceiveButtonRI(UINT button) { }; - if (pb==NA_NONE) return 0; - curevent=pb; + if (pb==NA_NONE) return 0;*/ + + UCHAR pb=NA_NONE; + pb=TranslateHWC(W_G_HCW(W_HCW_RI,button)); + if (pb==NA_UNKNOWN || pb==NA_NONE) return 0; + curevent=pb; + hascurevent=true; //PulseEvent(event); SetEvent(event); return 1; @@ -275,6 +501,7 @@ void RemoteWin::SendPower() { curevent=POWER; + hascurevent=true; SetEvent(event); } diff --git a/remotewin.h b/remotewin.h index d203794..4b39e37 100644 --- a/remotewin.h +++ b/remotewin.h @@ -46,15 +46,22 @@ class RemoteWin : public Remote void clearBuffer(); void Signal(); int ReceiveButtonVK(UINT button);//Windows Message from WND_PROC + int ReceiveButtonCH(UINT button);//Windows Message from WND_PROC int ReceiveButtonAP(UINT button); int ReceiveButtonRI(UINT button); void SendPower(); + void InitHWCListwithDefaults(); + const char*HardcodedTranslateStr(UCHAR command); + char* HCWDesc(ULLONG hcw); + private: int initted; bool signal; UCHAR curevent; + bool hascurevent; HANDLE event; + UCHAR TranslateHWCFixed(ULLONG code); }; #endif diff --git a/surfacewin.cc b/surfacewin.cc index bec6c0e..b5f3226 100644 --- a/surfacewin.cc +++ b/surfacewin.cc @@ -267,4 +267,3 @@ void SurfaceWin::drawJpeg(char *fileName,DWORD x, DWORD y,DWORD *width, DWORD *h } - diff --git a/thread.h b/thread.h index f6dcfcf..d3fce99 100644 --- a/thread.h +++ b/thread.h @@ -37,7 +37,6 @@ class Thread virtual void threadSignal()=0; // releases a thread that has called threadWaitForSignal virtual void threadSignalNoLock()=0; // same as above but without locking guarantees. probably not a good idea. char threadIsActive(); // returns 1 if thread has been started but not stop() or cancel() 'd - virtual ThreadID_TYPE getThreadID()=0; // returns the ID of this thread // Methods to use from inside the thread virtual void threadSetKillable()=0; // allows threadCancel() to work @@ -56,6 +55,8 @@ class Thread Thread(); virtual ~Thread() {} void threadInternalStart2(); + + virtual ThreadID_TYPE getThreadID()=0; // returns the ID of this thread }; #endif diff --git a/threadwin.cc b/threadwin.cc index e0c24c4..4b3e873 100644 --- a/threadwin.cc +++ b/threadwin.cc @@ -20,6 +20,14 @@ #include "threadwin.h" +ThreadWin::~ThreadWin() +{ + CloseHandle(pthread); + CloseHandle(threadCond); + CloseHandle(threadCondMutex); +} + + // Undeclared functions, only for use in this file to start the thread DWORD WINAPI threadInternalStart(void *arg) { @@ -40,7 +48,7 @@ int ThreadWin::threadStart() } threadActive = 1; - DWORD threadId; + pthread = CreateThread(NULL, 0, threadInternalStart, (void*)this,0, &threadId); if (pthread == NULL) { @@ -130,3 +138,28 @@ void ThreadWin::threadSetKillable() //WIN32:Ignore or use a separate Event Object to simulate this } +void ThreadWin::threadSuicide() +{ +/* if(!pthread_detach(pthread_self())) + { + MILLISLEEP(1000); + if(!pthread_detach(pthread_self())) + { + MILLISLEEP(1000); + pthread_detach(pthread_self()); + } + } +*/ + + ExitThread(0); +} + +unsigned int ThreadWin::getThreadID() +{ + return threadId; +} + +unsigned int ThreadWin::thisThreadID() // returns the ID of the calling thread +{ + return GetCurrentThreadId(); +} diff --git a/threadwin.h b/threadwin.h index bc363dc..19dfc75 100644 --- a/threadwin.h +++ b/threadwin.h @@ -41,12 +41,15 @@ class ThreadWin : public Thread virtual void threadMethod()=0; virtual void threadPostStopCleanup()=0; + ~ThreadWin(); + // Methods to use from outside the thread int threadStart(); // start the thread. threadMethod() will be called in derived class void threadStop(); // stop the thread nicely. thread will be stopped when it next calls threadCheckExit() void threadCancel(); // stop thread immediately. thread will be stopped at the next cancellation point void threadSignal(); // releases a thread that has called threadWaitForSignal void threadSignalNoLock(); // same as above but without locking guarantees. probably not a good idea. + // Methods to use from inside the thread void threadSetKillable(); // allows threadCancel() to work @@ -62,6 +65,13 @@ class ThreadWin : public Thread HANDLE pthread; HANDLE threadCondMutex; HANDLE threadCond; + DWORD threadId; + + public: + void threadSuicide(); // Self termination + static unsigned int thisThreadID(); + unsigned int getThreadID(); // returns the ID of this thread }; #endif + diff --git a/vconnect.cc b/vconnect.cc index e87b555..f8ca4bd 100644 --- a/vconnect.cc +++ b/vconnect.cc @@ -22,6 +22,7 @@ VConnect::VConnect() { + viewman = ViewMan::getInstance(); vdr = VDR::getInstance(); logger = Log::getInstance(); @@ -68,8 +69,6 @@ void VConnect::threadMethod() int success; irun = 1; - ViewMan* viewman = ViewMan::getInstance(); - do { setOneLiner(tr("Locating server")); diff --git a/videowin.cc b/videowin.cc index f940a27..eef1b6b 100644 --- a/videowin.cc +++ b/videowin.cc @@ -63,6 +63,9 @@ VideoWin::VideoWin() videoposx=0; videoposy=0; iframemode=false;//We are not in Iframe mode at begining +#ifdef NEW_DS_MECHANISMENS + videofilterselected=-1; +#endif @@ -72,6 +75,15 @@ VideoWin::~VideoWin() { CleanupDS(); CloseHandle(filtermutex); +#ifdef NEW_DS_MECHANISMENS + int i; + for (i=0;ilog("VideoWin", Log::ERR , "Unable to create FilterMapper!"); + return; + } + /* Wishlist, what Mediatypes do we want */ + GUID mtypesin[]={MEDIATYPE_Video,MEDIASUBTYPE_MPEG2_VIDEO}; + IEnumMoniker *myenum; + result = filtmap->EnumMatchingFilters(&myenum,0,TRUE,MERIT_DO_NOT_USE+1, + TRUE,1,mtypesin,NULL,NULL,FALSE,TRUE,0,NULL,NULL,NULL); + if (result != S_OK) + { + filtmap->Release(); + Log::getInstance()->log("VideoWin", Log::ERR , "Unable to enum Filters!"); + return; + } + ULONG gethowmany; + IMoniker * moni; + while(myenum->Next(1,&moni,&gethowmany)==S_OK) + { + VideoFilterDesc desc; + ZeroMemory(&desc,sizeof(desc)); + // IBindCtx* bctx; + /* result = CreateBindCtx(0,&bctx); + if (result != S_OK) + { + bctx->Release(); + filtmap->Release(); + Log::getInstance()->log("VideoWin", Log::ERR , "Failed to create Bindctx!"); + return; + }*/ + LPOLESTR string; + moni->GetDisplayName(0,0,&string); + desc.displayname=new char[wcslen(string)+1]; + wcstombs(desc.displayname,string,wcslen(string)+1); + CoTaskMemFree(string); + IPropertyBag *bag; + if (moni->BindToStorage(0,0,IID_IPropertyBag,(void**)&bag) == S_OK) + { + VARIANT vari; + VariantInit(&vari); + result = bag->Read(L"FriendlyName",&vari,NULL); + if (result == S_OK) + { + desc.friendlyname=new char[wcslen(vari.bstrVal)+1]; + wcstombs(desc.friendlyname,vari.bstrVal,wcslen(vari.bstrVal)+1); + } + VariantClear(&vari); + bag->Release(); + + } + IBaseFilter *filter; + if (moni->BindToObject(0,0,IID_IBaseFilter,(void**)&filter) == S_OK) + { + IAMDecoderCaps*desccaps; + if (filter->QueryInterface(IID_IAMDecoderCaps,(void**) &desccaps)==S_OK) + { + DWORD caps; + desccaps->GetDecoderCaps(AM_GETDECODERCAP_QUERY_VMR9_SUPPORT,&caps); + if (caps == DECODER_CAP_SUPPORTED) + { + desc.vmr9 = true; + } + desccaps->Release(); + } + filter->Release(); + } + videofilterlist.push_back(desc); + + + + moni->Release(); + // bctx->Release(); + } + int i; + videofilterselected=-1; + for (i = 0;i log("VideoWin", Log::ERR , "No video filter found!"); + } + + myenum->Release(); + + + + filtmap->Release(); +} +#endif #ifdef DS_DEBUG // This stuff would not included in vomp due to lincemse restrcitions #include "dshelper.h" @@ -208,124 +328,135 @@ int VideoWin::play() return 1; } -int VideoWin::dsplay() +int VideoWin::dsInitVideoFilter() { - if (!initted) return 0; - CleanupDS(); + #ifdef DO_VIDEO + HRESULT hres; + if (videoon) { + //We alloc the vmr9 as next step + if (hres=CoCreateInstance(CLSID_VideoMixingRenderer9,0, + CLSCTX_INPROC_SERVER,IID_IBaseFilter,(void**) &dsvmrrenderer)!=S_OK) + { + Log::getInstance()->log("VideoWin", Log::WARN ,"Failed creating VMR9 renderer!"); + ReleaseMutex(filtermutex); + CleanupDS(); + } + /*VMR 9 stuff**/ + if (hres=dsgraphbuilder->AddFilter(dsvmrrenderer,L"VMR9")!=S_OK) + { + ReleaseMutex(filtermutex); + CleanupDS(); + Log::getInstance()->log("VideoWin", Log::WARN ,"Failed adding VMR9 renderer!"); + return 0; + } + IVMRFilterConfig9* vmrfilconfig; + if (dsvmrrenderer->QueryInterface(IID_IVMRFilterConfig9,(void**)&vmrfilconfig)!=S_OK) + { + ReleaseMutex(filtermutex); + CleanupDS(); + Log::getInstance()->log("VideoWin", Log::WARN ,"Failed getting VMR9 Filterconfig interface!"); + return 0; + } + vmrfilconfig->SetRenderingMode(VMR9Mode_Renderless); + vmrfilconfig->Release(); + + if (dsvmrrenderer->QueryInterface(IID_IVMRSurfaceAllocatorNotify9, + (void**)& dsvmrsurfnotify) != S_OK) + { + ReleaseMutex(filtermutex); + CleanupDS(); + Log::getInstance()->log("VideoWin", Log::WARN ,"Failed getting VMR9 Surface Allocator interface!"); + return 0; + } + allocatorvmr=new DsAllocator(); + dsvmrsurfnotify->AdviseSurfaceAllocator(NULL,allocatorvmr); + allocatorvmr->AdviseNotify(dsvmrsurfnotify); + /*VMR 9 stuff end */ + IFilterGraph2*fg2=NULL; + if (dsgraphbuilder->QueryInterface(IID_IFilterGraph2,(void**)&fg2)!= S_OK) + { + Log::getInstance()->log("VideoWin", Log::WARN , "Failed querying for FilterGraph2 Interface!"); + ReleaseMutex(filtermutex); + CleanupDS(); + return 0; + } + if (hres=fg2->RenderEx((IPin*)sourcefilter->GetVideoPin()/*video*/, + AM_RENDEREX_RENDERTOEXISTINGRENDERERS,NULL) != S_OK) + { + Log::getInstance()->log("VideoWin", Log::WARN , "Failed rendering Video!"); + fg2->Release(); + ReleaseMutex(filtermutex); + CleanupDS(); + return 0; + } + fg2->Release(); + } +#endif +} - //Build filter graph - HRESULT hres; -//So this is the real code, this prevents the feeder from calling noexisting objects! - WaitForSingleObject(filtermutex,INFINITE); - if (hres=CoCreateInstance(CLSID_FilterGraph,NULL,CLSCTX_INPROC_SERVER, - IID_IGraphBuilder,(void**)&dsgraphbuilder)!=S_OK) { - ReleaseMutex(filtermutex); - return 0; - } +int VideoWin::dsplay() +{ + if (!initted) return 0; + CleanupDS(); + + //Build filter graph + HRESULT hres; + //So this is the real code, this prevents the feeder from calling noexisting objects! + WaitForSingleObject(filtermutex,INFINITE); + if (hres=CoCreateInstance(CLSID_FilterGraph,NULL,CLSCTX_INPROC_SERVER, + IID_IGraphBuilder,(void**)&dsgraphbuilder) != S_OK) + { + ReleaseMutex(filtermutex); + return 0; + } #ifdef DS_DEBUG AddToRot(dsgraphbuilder,&graphidentifier); #endif - //This is just a try to see if building the graph works -// dsgraphbuilder->RenderFile(L"D:\\Projekte\\VTP Client\\test.mpa" ,NULL); firstsynched=false; lastaudiomode=MPTYPE_MPEG_AUDIO; //lastaudiomode=MPTYPE_AC3; sourcefilter=new DsSourceFilter(); //Creating our Source filter for pushing Data // to DirectShow - if (hres=dsgraphbuilder->AddFilter(sourcefilter,L"Vomp Win Source Filter")!=S_OK) { - Log::getInstance()->log("VideoWin", Log::WARN , "Failed adding Vomp Source Filter!"); - ReleaseMutex(filtermutex); - CleanupDS(); - return 0; + if (hres=dsgraphbuilder->AddFilter(sourcefilter,L"Vomp Win Source Filter") != S_OK) + { + Log::getInstance()->log("VideoWin", Log::WARN , "Failed adding Vomp Source Filter!"); + ReleaseMutex(filtermutex); + CleanupDS(); + return 0; } - //if (audioon) { - if (hres=dsgraphbuilder->Render((IPin*)sourcefilter->GetAudioPin()/*audio*/)!=S_OK) { - Log::getInstance()->log("VideoWin", Log::WARN , "Failed rendering audio!"); + + if (hres=dsgraphbuilder->Render((IPin*)sourcefilter->GetAudioPin()/*audio*/)!=S_OK) + { + Log::getInstance()->log("VideoWin", Log::WARN , "Failed rendering audio!"); ReleaseMutex(filtermutex); CleanupDS(); return 0; - } - //} -#ifdef DO_VIDEO - if (videoon) { - //We alloc the vmr9 as next step - if (hres=CoCreateInstance(CLSID_VideoMixingRenderer9,0, - CLSCTX_INPROC_SERVER,IID_IBaseFilter,(void**) &dsvmrrenderer)!=S_OK) { - Log::getInstance()->log("VideoWin", Log::WARN ,"Failed creating VMR9 renderer!"); - ReleaseMutex(filtermutex); - CleanupDS(); - - } - /*VMR 9 stuff**/ - if (hres=dsgraphbuilder->AddFilter(dsvmrrenderer,L"VMR9")!=S_OK) { - ReleaseMutex(filtermutex); - CleanupDS(); - Log::getInstance()->log("VideoWin", Log::WARN ,"Failed adding VMR9 renderer!"); - - return 0; - } - IVMRFilterConfig9* vmrfilconfig; - if (dsvmrrenderer->QueryInterface(IID_IVMRFilterConfig9,(void**)&vmrfilconfig)!=S_OK) { - ReleaseMutex(filtermutex); - CleanupDS(); - Log::getInstance()->log("VideoWin", Log::WARN ,"Failed getting VMR9 Filterconfig interface!"); - return 0; - } - vmrfilconfig->SetRenderingMode(VMR9Mode_Renderless); - vmrfilconfig->Release(); - - if (dsvmrrenderer->QueryInterface(IID_IVMRSurfaceAllocatorNotify9,(void**)& dsvmrsurfnotify)!=S_OK) { - ReleaseMutex(filtermutex); - CleanupDS(); - Log::getInstance()->log("VideoWin", Log::WARN ,"Failed getting VMR9 Surface Allocator interface!"); - - return 0; + } + if (dsInitVideoFilter()==0) + { + return 0; } - allocatorvmr=new DsAllocator(); - dsvmrsurfnotify->AdviseSurfaceAllocator(NULL,allocatorvmr); - allocatorvmr->AdviseNotify(dsvmrsurfnotify); - - - - /*VMR 9 stuff end */ - IFilterGraph2*fg2=NULL; - if (dsgraphbuilder->QueryInterface(IID_IFilterGraph2,(void**)&fg2)!=S_OK) { - Log::getInstance()->log("VideoWin", Log::WARN , "Failed querying for FilterGraph2 Interface!"); - ReleaseMutex(filtermutex); - CleanupDS(); - return 0; - } - if (hres=fg2->RenderEx((IPin*)sourcefilter->GetVideoPin()/*video*/, - AM_RENDEREX_RENDERTOEXISTINGRENDERERS,NULL)!=S_OK) { - Log::getInstance()->log("VideoWin", Log::WARN , "Failed rendering Video!"); - fg2->Release(); - ReleaseMutex(filtermutex); - CleanupDS(); - return 0; + if (hres=CoCreateInstance(CLSID_SystemClock,NULL,CLSCTX_INPROC_SERVER, + IID_IReferenceClock,(void**)&dsrefclock)!=S_OK) + { + return 0; } - fg2->Release(); - } -#endif - if (hres=CoCreateInstance(CLSID_SystemClock,NULL,CLSCTX_INPROC_SERVER, - IID_IReferenceClock,(void**)&dsrefclock)!=S_OK) { - return 0; - } - - dsgraphbuilder->QueryInterface(IID_IMediaFilter,(void **) &dsmediafilter); - HRESULT hresdeb=dsmediafilter->SetSyncSource(dsrefclock); - - dsgraphbuilder->QueryInterface(IID_IMediaControl,(void **) &dsmediacontrol); - dsgraphbuilder->QueryInterface(IID_IBasicAudio,(void **) &dsbasicaudio); - if (dsbasicaudio) dsbasicaudio->put_Volume(audiovolume); - dsinited=true; + dsgraphbuilder->QueryInterface(IID_IMediaFilter,(void **) &dsmediafilter); + HRESULT hresdeb = dsmediafilter->SetSyncSource(dsrefclock); + + dsgraphbuilder->QueryInterface(IID_IMediaControl,(void **) &dsmediacontrol); + dsgraphbuilder->QueryInterface(IID_IBasicAudio,(void **) &dsbasicaudio); + if (dsbasicaudio) + dsbasicaudio->put_Volume(audiovolume); + dsinited=true; //MILLISLEEP(100); - hresdeb=dsmediacontrol->Run(); - iframemode=false;//exit iframe mode - ReleaseMutex(filtermutex); - return 1; + hresdeb=dsmediacontrol->Run(); + iframemode=false;//exit iframe mode + ReleaseMutex(filtermutex); + return 1; } int VideoWin::EnterIframePlayback() diff --git a/videowin.h b/videowin.h index d8ec9ea..aa8fb77 100644 --- a/videowin.h +++ b/videowin.h @@ -27,11 +27,23 @@ #include #include #include +#include #include "defines.h" #include "video.h" //#define DS_DEBUG +//#define NEW_DS_MECHANISMENS + +#ifdef NEW_DS_MECHANISMENS +struct VideoFilterDesc { + char * displayname; + char * friendlyname; + bool vmr9; +}; +using namespace std; +typedef vector VideoFilterDescList; +#endif class DsSourceFilter; class DsAllocator; @@ -58,18 +70,18 @@ class VideoWin : public Video int setPosition(int x, int y); int sync(); int play(); - int dsplay(); - bool InIframemode() {return iframemode;}; + int dsplay(); + bool InIframemode() {return iframemode;}; int stop(); - int dsstop(); + int dsstop(); int pause(); - int dspause(); + int dspause(); int unPause(); - int dsunPause(); + int dsunPause(); int fastForward(); int unFastForward(); int reset(); - int dsreset(); + int dsreset(); int blank(); int signalOn(); int signalOff(); @@ -99,11 +111,11 @@ class VideoWin : public Video virtual void ResetTimeOffsets(); void SetAudioState(bool state){audioon=state;}; - void SetAudioVolume(long volume); + void SetAudioVolume(long volume); void turnVideoOn(){videoon=true;}; void turnVideoOff(){videoon=false;}; - + virtual void displayIFrame(const UCHAR* buffer, UINT length); unsigned int getPosx() {return videoposx;}; @@ -119,6 +131,12 @@ class VideoWin : public Video #endif private: int EnterIframePlayback(); +#ifdef NEW_DS_MECHANISMENS + void dstest(); + VideoFilterDescList videofilterlist; + int videofilterselected; +#endif + int dsInitVideoFilter(); IMediaControl* dsmediacontrol; IGraphBuilder* dsgraphbuilder; diff --git a/view.cc b/view.cc index 962069f..0354881 100644 --- a/view.cc +++ b/view.cc @@ -39,7 +39,7 @@ View::~View() { if (titleText) delete[] titleText; - delete surface; + if (surface != NULL) delete surface; numViews--; Log::getInstance()->log("View", Log::DEBUG, "Destruct, now %u", numViews); diff --git a/view.h b/view.h index 739a397..53f0755 100644 --- a/view.h +++ b/view.h @@ -29,6 +29,8 @@ #include "message.h" #include "colour.h" +class AbstractViewMan; + class View : public Box { public: @@ -46,10 +48,13 @@ class View : public Box void setBackgroundColour(Colour& colour); void setTitleBarColour(Colour& colour); + char* getTitleText() { return titleText; }; + + void setViewMan(AbstractViewMan* tviewman) { viewman=tviewman; }; + private: static char numViews; - char* titleText; UCHAR borderOn; @@ -57,6 +62,8 @@ class View : public Box Colour backgroundColour; Colour titleBarColour; UCHAR titleBarOn; + + AbstractViewMan* viewman; }; #endif diff --git a/viewman.cc b/viewman.cc index 58691d6..a4ebd12 100644 --- a/viewman.cc +++ b/viewman.cc @@ -356,7 +356,7 @@ void ViewMan::removeAll() } } -int ViewMan::handleCommand(UCHAR command) +int ViewMan::handleCommand(int command) { int retVal; int retVal2 = 0; diff --git a/viewman.h b/viewman.h index ea56d63..7a71054 100644 --- a/viewman.h +++ b/viewman.h @@ -40,11 +40,26 @@ typedef list RegionList; -class ViewMan +class AbstractViewMan +{ + public: + AbstractViewMan() {}; + virtual ~AbstractViewMan() {}; + + virtual int handleCommand(int command)=0; + + virtual int add(View* v)=0; + virtual int removeView(View* toRemove)=0; + virtual void removeAll()=0; + virtual void updateView(View* toUpdate, Region* regionToUpdate = NULL)=0; +}; + + +class ViewMan: public AbstractViewMan { public: ViewMan(); - ~ViewMan(); + virtual ~ViewMan(); static ViewMan* getInstance(); int init(); @@ -55,7 +70,7 @@ class ViewMan void removeAll(); void updateView(View* toUpdate, Region* regionToUpdate = NULL); - int handleCommand(UCHAR command); + int handleCommand(int command); void processMessage(Message* m); private: diff --git a/vompreswin.h b/vompreswin.h index 904fb00..d1897fd 100644 --- a/vompreswin.h +++ b/vompreswin.h @@ -43,4 +43,3 @@ #define VOMPRESWIN_H #endif - diff --git a/voptions.cc b/voptions.cc index cd27c36..c264846 100644 --- a/voptions.cc +++ b/voptions.cc @@ -98,8 +98,8 @@ VOptions::VOptions(void* tparent, const char* title, const OPTIONDATA* toptionDa optionsAtStart[i] = optionBoxes[i].getSelectedIndex(); } - selectedOption = 0; - optionBoxes[0].setActive(1); + selectedOption = numOptions; + //optionBoxes[0].setActive(1); int voff = 0; if ((numOptions < 8) && (numOptions >= 4)) @@ -139,10 +139,11 @@ void VOptions::draw() drawText(tr("Press back to exit, <, > or [ok] to change"), 10, area.h - 30, Colour::LIGHTTEXT); wsy.setSurface(surface); + UINT ystart=titleBarOn ? 45 : 15; for (UINT i = 0; i < numOptions; i++) { - drawText(tr(optionData[i].title), 10, 45+i*30, Colour::LIGHTTEXT); + drawText(tr(optionData[i].title), 10, ystart + i*30, Colour::LIGHTTEXT); if (i == selectedOption) cl = Colour::SELECTHIGHLIGHT; else cl = Colour::BUTTONBACKGROUND; @@ -150,11 +151,12 @@ void VOptions::draw() wsy.nextSymbol = WSymbol::LEFTARROW; wsy.nextColour = cl; - wsy.setSurfaceOffset(328, 47 + (i * 30)); + wsy.setSurfaceOffset(328, ystart + 2 + (i * 30)); wsy.draw(); wsy.nextSymbol = WSymbol::RIGHTARROW; - wsy.setSurfaceOffset(498, 47 + (i * 30)); + wsy.setSurfaceOffset(498, ystart + 2 + (i * 30)); wsy.draw(); + optionBoxes[i].setSurfaceOffset(346, ystart + (i * 30)); optionBoxes[i].draw(); } } @@ -168,12 +170,18 @@ int VOptions::handleCommand(int command) { if (selectedOption > 0) { - optionBoxes[selectedOption].setActive(0); + if (selectedOption < numOptions) optionBoxes[selectedOption].setActive(0); --selectedOption; optionBoxes[selectedOption].setActive(1); draw(); viewman->updateView(this); } + else + { + if (selectedOption < numOptions) optionBoxes[selectedOption].setActive(0); + selectedOption = numOptions; + return 0; //Control to tab view + } return 2; } case Remote::DF_DOWN: @@ -181,17 +189,25 @@ int VOptions::handleCommand(int command) { if (selectedOption < (numOptions - 1)) { - optionBoxes[selectedOption].setActive(0); + if (selectedOption < numOptions) optionBoxes[selectedOption].setActive(0); ++selectedOption; optionBoxes[selectedOption].setActive(1); draw(); viewman->updateView(this); } + else if (selectedOption == numOptions) + { + selectedOption = 0; + optionBoxes[selectedOption].setActive(1); + draw(); + viewman->updateView(this); + } return 2; } case Remote::DF_LEFT: case Remote::LEFT: { + if (selectedOption == numOptions) return 2; optionBoxes[selectedOption].left(); draw(); viewman->updateView(this); @@ -200,6 +216,7 @@ int VOptions::handleCommand(int command) case Remote::DF_RIGHT: case Remote::RIGHT: { + if (selectedOption == numOptions) return 2; optionBoxes[selectedOption].right(); draw(); viewman->updateView(this); @@ -224,6 +241,7 @@ int VOptions::handleCommand(int command) } case Remote::OK: { + if (selectedOption == numOptions) return 2; optionBoxes[selectedOption].cycle(); draw(); viewman->updateView(this); @@ -294,11 +312,11 @@ void VOptions::processMessage(Message* m) { if (optionBoxes[i].mouseMove(x,y)) { - optionBoxes[selectedOption].setActive(0); + if (selectedOption != numOptions) optionBoxes[selectedOption].setActive(0); optionBoxes[i].setActive(1); selectedOption=i; draw(); - ViewMan::getInstance()->updateView(this); + viewman->updateView(this); break; } } diff --git a/voptions.h b/voptions.h index 9aec6b7..ea6684e 100644 --- a/voptions.h +++ b/voptions.h @@ -65,7 +65,6 @@ class VOptions : public View WOptionBox* optionBoxes; VDR* vdr; int* optionsAtStart; - ViewMan* viewman; void* parent; }; diff --git a/voptionsmenu.cc b/voptionsmenu.cc index 7bc1c72..ee7ef78 100644 --- a/voptionsmenu.cc +++ b/voptionsmenu.cc @@ -24,170 +24,55 @@ VOptionsMenu::VOptionsMenu() { viewman = ViewMan::getInstance(); - create(460, 200); - if (Video::getInstance()->getFormat() == Video::PAL) - { - setScreenPos(140, 170); - } - else - { - setScreenPos(130, 140); - } - setBackgroundColour(Colour::VIEWBACKGROUND); setTitleBarOn(1); setTitleBarColour(Colour::TITLEBARBACKGROUND); setTitleText(tr("Options")); - int fontHeight = surface->getFontHeight(); - - // Build gui - WButton* wb; - - wb = new WButton(); - wb->setText(tr("General")); - wb->setSurface(surface); - wb->setSurfaceOffset(160, 60); - wb->setDimensions(140, fontHeight); - wb->setTag(1); - buttons.push_back(wb); - - wb = new WButton(); - wb->setText(tr("Timers")); - wb->setSurface(surface); - wb->setSurfaceOffset(160, 100); - wb->setDimensions(140, fontHeight); - wb->setTag(2); - buttons.push_back(wb); - - wb = new WButton(); - wb->setText(tr("Advanced")); - wb->setSurface(surface); - wb->setSurfaceOffset(160, 140); - wb->setDimensions(140, fontHeight); - wb->setTag(3); - buttons.push_back(wb); - - - selectedButton = buttons.begin(); - (*selectedButton)->setActive(1); +// int fontHeight = surface->getFontHeight(); + + doGeneral(); + doRemoteConfig(); + doTimers(); + doAdvanced(); + + create(); + draw(); } VOptionsMenu::~VOptionsMenu() { - while (!buttons.empty()) - { - delete buttons.back(); - buttons.pop_back(); - } } void VOptionsMenu::draw() { - View::draw(); - - vector::iterator i; - for(i = buttons.begin(); i != buttons.end(); i++) - { - (*i)->draw(); - } + VTabsViewMan::draw(); } int VOptionsMenu::handleCommand(int command) { - switch(command) - { - case Remote::DF_UP: - case Remote::UP: - { - if (selectedButton == buttons.begin()) return 2; - (*selectedButton)->setActive(0); - selectedButton--; - (*selectedButton)->setActive(1); - draw(); // fixme - just draw buttons - viewman->updateView(this); - return 2; - } - case Remote::DF_DOWN: - case Remote::DOWN: - { - if (selectedButton == (buttons.end() - 1)) return 2; - (*selectedButton)->setActive(0); - selectedButton++; - (*selectedButton)->setActive(1); - draw(); // fixme - just draw buttons - viewman->updateView(this); - return 2; - } - case Remote::BACK: - { - return 4; - } - case Remote::OK: - { - switch((*selectedButton)->getTag()) - { - case 1: doGeneral(); break; - case 2: doTimers(); break; - case 3: doAdvanced(); break; - } - return 2; - } - } - - return 1; + return VTabsViewMan::handleCommand(command); } void VOptionsMenu::processMessage(Message* m) { - if (m->message == Message::MOUSE_MOVE) - { - int x=(m->parameter>>16)-getScreenX(); - int y=(m->parameter&0xFFFF)-getScreenY(); - vector::iterator i; - for (i=buttons.begin(); i!=buttons.end();i++) - { - if ((*i)->mouseMove(x,y)) - { - (*selectedButton)->setActive(0); - selectedButton=i; - draw(); - ViewMan::getInstance()->updateView(this); - break; - } - } - } - else if (m->message == Message::MOUSE_LBDOWN) - { - int x=(m->parameter>>16)-getScreenX(); - int y=(m->parameter&0xFFFF)-getScreenY(); - vector::iterator i; - bool butpress=false; - for (i=buttons.begin(); i!=buttons.end();i++) - { - if ((*i)->mouseLBDOWN(x,y)) - { - ViewMan::getInstance()->handleCommand(Remote::OK); //simulate OK press - butpress=true; - break; - } - } - if (!butpress) - { - //check if press is outside this view! then simulate cancel - if (x<0 || y <0 || x>getWidth() || y>getHeight()) - { - ViewMan::getInstance()->handleCommand(Remote::BACK); //simulate cancel press - } - } - } - else if (m->message == Message::CHANGED_OPTIONS) + if (m->message == Message::CHANGED_OPTIONS) { doApplyChanges((map*)m->parameter); //viewman->removeView(this); if (!VDR::getInstance()->isConnected()) Command::getInstance()->connectionLost(); } + else if (m->message == Message::CHANGED_REMOTECONTROL) + { + char* remote = Remote::getInstance()->SaveKeysConfig(); //FIXME + VDR::getInstance()->configSave("General","Remote keys",remote); + delete[] remote; + } + else + { + VTabsViewMan::processMessage(m); + } } void VOptionsMenu::doApplyChanges(map* changedOptions) @@ -315,12 +200,18 @@ void VOptionsMenu::doGeneral() // As all the above data is const static, it can be sent to the new View, this stack frame can // quit and the pointers will all still be valid. I think. (Hope). - VOptions* v = new VOptions(this, tr("General Options"), optionData, numOptions); + VOptions* v = new VOptions(this, tr("General"), optionData, numOptions); v->draw(); - viewman->add(v); - viewman->updateView(v); + add(v); + //viewman->updateView(v); } +void VOptionsMenu::doRemoteConfig() +{ + VRemoteConfig* v = new VRemoteConfig(this); + v->draw(); + add(v); +} void VOptionsMenu::doTimers() { @@ -337,10 +228,10 @@ void VOptionsMenu::doTimers() // As all the above data is const static, it can be sent to the new View, this stack frame can // quit and the pointers will all still be valid. I think. (Hope). - VOptions* v = new VOptions(this, tr("Timer Options"), optionData, numOptions); + VOptions* v = new VOptions(this, tr("Timers"), optionData, numOptions); v->draw(); - viewman->add(v); - viewman->updateView(v); + add(v); + //viewman->updateView(v); } void VOptionsMenu::doAdvanced() @@ -360,8 +251,8 @@ void VOptionsMenu::doAdvanced() // As all the above data is const static, it can be sent to the new View, this stack frame can // quit and the pointers will all still be valid. I think. (Hope). - VOptions* v = new VOptions(this, tr("Advanced Options"), optionData, numOptions); + VOptions* v = new VOptions(this, tr("Advanced"), optionData, numOptions); v->draw(); - viewman->add(v); - viewman->updateView(v); + add(v); + //viewman->updateView(v); } diff --git a/voptionsmenu.h b/voptionsmenu.h index 7c29315..9f07582 100644 --- a/voptionsmenu.h +++ b/voptionsmenu.h @@ -32,8 +32,10 @@ #include "wbutton.h" #include "i18n.h" #include "voptions.h" +#include "vremoteconfig.h" +#include "vtabsviewman.h" -class VOptionsMenu : public View +class VOptionsMenu : public VTabsViewMan { public: VOptionsMenu(); @@ -47,11 +49,9 @@ class VOptionsMenu : public View void doGeneral(); void doTimers(); void doAdvanced(); + void doRemoteConfig(); void doApplyChanges(map* changedOptions); - VDR* vdr; - ViewMan* viewman; - vector buttons; vector::iterator selectedButton; }; diff --git a/vradiorec.cc b/vradiorec.cc index abd68a3..f630f93 100644 --- a/vradiorec.cc +++ b/vradiorec.cc @@ -22,6 +22,7 @@ VRadioRec::VRadioRec(Recording* rec) { + viewman = ViewMan::getInstance(); vdr = VDR::getInstance(); video = Video::getInstance(); timers = Timers::getInstance(); @@ -121,8 +122,6 @@ void VRadioRec::go() return; } - ViewMan* viewman = ViewMan::getInstance(); - Message* m = new Message(); m->message = Message::CLOSE_ME; m->from = this; diff --git a/vrecordinglist.h b/vrecordinglist.h index eaf6bd8..ae0c480 100644 --- a/vrecordinglist.h +++ b/vrecordinglist.h @@ -57,7 +57,6 @@ class VRecordingList : public View void drawData(bool doIndexPop = false); private: - ViewMan* viewman; bool loading; RecMan* recman; diff --git a/vremoteconfig.cc b/vremoteconfig.cc new file mode 100644 index 0000000..cb720e2 --- /dev/null +++ b/vremoteconfig.cc @@ -0,0 +1,271 @@ +/* + Copyright 2004-2007 Chris Tallon, Marten Richter + + This file is part of VOMP. + + VOMP 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. + + VOMP 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 VOMP; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "vremoteconfig.h" + +VRemoteConfig::VRemoteConfig(void* tparent) +{ + parent = tparent; + viewman = ViewMan::getInstance(); + remote = Remote::getInstance(); + learnmode = false; + + + create(530, 320); + if (Video::getInstance()->getFormat() == Video::PAL) + { + setScreenPos(80, 70); + } + else + { + setScreenPos(70, 35); + } + + setBackgroundColour(Colour::VIEWBACKGROUND); + setTitleBarOn(1); + setTitleBarColour(Colour::TITLEBARBACKGROUND); + setTitleText(tr("Remote control")); + + + + initSelectList(true); + sl.setShowSelOption(false); + + + +} + +VRemoteConfig::~VRemoteConfig() +{ + +} + +void VRemoteConfig::initSelectList(bool startup) +{ + ULONG selection=0; + ULONG top=0; + if (!startup) + { + selection=sl.getCurrentOption(); + top=sl.getTopOption(); + + } + sl.setSurface(surface); + sl.setSurfaceOffset(10, 40); + sl.setDimensions(area.w - 20, area.h - 30 - 15 -30 ); + sl.clear(); + sl.addColumn(0); + sl.addColumn(150); + sl.addColumn(300); + ULONG i; + for (i = 0; i < 256;i++) + { + const char * name = remote->CommandDesc((UCHAR)i); + if (name != NULL) + { + char *line = remote->CommandTranslateStr((UCHAR)i); + char * desc=new char [strlen(line)+1]; + strcpy(desc,line); + sl.addOption(desc,i,0); + } + } + if (!startup) + { + sl.hintSetCurrent(selection); + sl.hintSetTop(top); + } +} + + +void VRemoteConfig::draw() +{ + View::draw(); + + drawText(tr("Command"), 15, 15, Colour::LIGHTTEXT); + drawText(tr("Hardwired"), 165, 15, Colour::LIGHTTEXT); + drawText(tr("Userassignable"), 315, 15, Colour::LIGHTTEXT); + sl.draw(); + if (learnmode) + { + drawText(tr("Learning! Press any hardwired key to exit!"), 15, area.h - 30, Colour::SELECTHIGHLIGHT); + } + else + { + drawText(tr("Press [ok] for learning or MENU to reset to defaults! "), 15, area.h - 30, Colour::LIGHTTEXT); + } + + + + +} + + +void VRemoteConfig::processMessage(Message* m) +{ + Log::getInstance()->log("VRecordingList", Log::DEBUG, "Got message value %lu", m->message); + + if (m->message == Message::MOUSE_MOVE) + { + if (sl.mouseMove((m->parameter>>16)-getScreenX(),(m->parameter&0xFFFF)-getScreenY())) + { + sl.setShowSelOption(true); + sl.draw(); + viewman->updateView(this); + } + } + else if (m->message == Message::MOUSE_LBDOWN) + { + if (sl.mouseLBDOWN((m->parameter>>16)-getScreenX(),(m->parameter&0xFFFF)-getScreenY())) + { + ViewMan::getInstance()->handleCommand(Remote::OK); //simulate OK press + } + else + { + //check if press is outside this view! then simulate cancel + int x=(m->parameter>>16)-getScreenX(); + int y=(m->parameter&0xFFFF)-getScreenY(); + if (x<0 || y <0 || x>getWidth() || y>getHeight()) + { + ViewMan::getInstance()->handleCommand(Remote::BACK); //simulate cancel press + } + } + } + +} + + +void VRemoteConfig::doSave() +{ + Message* m = new Message(); + m->message = Message::CHANGED_REMOTECONTROL; + m->to = parent; + m->parameter = 0; + Command::getInstance()->postMessageNoLock(m); + +} + + +int VRemoteConfig::handleCommand(int command) +{ + if (learnmode) + { + learnmode = false; + if (command == Remote::NA_LEARN) + { + initSelectList(false); + } + draw(); + viewman->updateView(this); + return 2; + } + switch(command) + { + case Remote::DF_UP: + case Remote::UP: + { + if (sl.getCurrentOption() != 0) + { + sl.up(); + sl.setShowSelOption(true); + draw(); + viewman->updateView(this); + return 2; + } + else + { + sl.setShowSelOption(false); + return 0; //Control to tab control + } + } + case Remote::DF_DOWN: + case Remote::DOWN: + { + Log::getInstance()->log("P", Log::DEBUG, "1"); + sl.down(); + sl.setShowSelOption(true); + Log::getInstance()->log("P", Log::DEBUG, "1.5"); + draw(); + Log::getInstance()->log("P", Log::DEBUG, "2"); + + + Log::getInstance()->log("P", Log::DEBUG, "3"); + viewman->updateView(this); + Log::getInstance()->log("P", Log::DEBUG, "4"); + return 2; + } + case Remote::SKIPBACK: + { + sl.pageUp(); + sl.draw(); + + + viewman->updateView(this); + return 2; + } + case Remote::SKIPFORWARD: + { + sl.pageDown(); + sl.draw(); + + + viewman->updateView(this); + return 2; + } + case Remote::OK: + { + learnmode = true; + draw(); + remote->EnterLearningMode(sl.getCurrentOptionData()); + viewman->updateView(this); + return 2; + } + case Remote::BACK: + { + doSave(); + + // Instead of returning 4 here which would delete this view + // before the doSave message is processed, let the message queue + // do the doSave then this close message. That will make the options menu + // disappear before this view + + Message* m = new Message(); + m->message = Message::CLOSE_ME; + m->from = this; + m->to = viewman; + Command::getInstance()->postMessageNoLock(m); + return 2; + + } + case Remote::MENU: + { + remote->ResetToDefault(); + initSelectList(false); + draw(); + viewman->updateView(this); + return 2; + } + + + } + // stop command getting to any more views + return 1; +} + + diff --git a/vremoteconfig.h b/vremoteconfig.h new file mode 100644 index 0000000..193b767 --- /dev/null +++ b/vremoteconfig.h @@ -0,0 +1,64 @@ +/* + Copyright 2004-2005 Chris Tallon + + This file is part of VOMP. + + VOMP 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. + + VOMP 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 VOMP; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef VREMOTECONFIG_H +#define VREMOTECONFIG_H + +#include +#include +#include +#include +#include + +#include "view.h" +#include "wselectlist.h" +#include "remote.h" +#include "wsymbol.h" +#include "viewman.h" +#include "vdr.h" +#include "colour.h" +#include "video.h" +#include "i18n.h" +#include "command.h" + +class VRemoteConfig : public View +{ + public: + VRemoteConfig (void* tparent); + ~VRemoteConfig (); + + int handleCommand(int command); + void processMessage(Message* m); + void draw(); + + + private: + WSelectList sl; + Remote *remote; + bool learnmode; + void initSelectList(bool startup); + void doSave(); + void* parent; + + +}; + +#endif + diff --git a/vtabsviewman.cc b/vtabsviewman.cc new file mode 100644 index 0000000..d9ad912 --- /dev/null +++ b/vtabsviewman.cc @@ -0,0 +1,436 @@ +/* + Copyright 2004-2007 Chris Tallon, Marten Richter + + This file is part of VOMP. + + VOMP 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. + + VOMP 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 VOMP; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +#include "vtabsviewman.h" +#include "video.h" +#include "wsymbol.h" +#include "remote.h" +#include "command.h" +#include "viewman.h" + +VTabsViewMan::VTabsViewMan() +{ + numViews = 0; + selectedView = 0; + backgroundColour = Colour::VIEWBACKGROUND; + tabHasControl = true; +} + +VTabsViewMan::~VTabsViewMan() +{ + removeAll(); +} + +int VTabsViewMan::add(View* v) +{ + if (numViews == 16) return 0; + + v->setTitleBarOn(0); //No Title Bar + v->setViewMan(this); //For this view, we are the viewman + v->setBackgroundColour(Colour::TABVIEWBACKGROUND); + + views[numViews++] = v; + + if (surface!=NULL) create(); //Recreating surface + + return 1; +} + +int VTabsViewMan::removeView(View* toDelete) +{ + if (numViews == 0) return 0; + + int i; + + if (toDelete == NULL) + { + toDelete = views[numViews-1]; + i = numViews - 1; + } + else + { + // to be deleted view is more likely to be at the top + for (i = numViews-1; i >= 0; i--) + { + if (views[i] == toDelete) break; + } + if (i == -1) + { + // not a View we have! + return 0; + } + } +// deleteView(i); + + // Shift the views on top down one + --numViews; + for(int j = i; j < numViews; j++) views[j] = views[j+1]; + + // Delete the view + delete toDelete; + + if (surface!=NULL) create(); //Recreating surface, if we are initted + if (selectedView >= numViews) selectedView = numViews-1; + + return 1; +} + +void VTabsViewMan::removeAll() +{ + for (; numViews > 0; --numViews) + { + delete views[numViews-1]; + } +} + +void VTabsViewMan::updateView(View* toUpdate, Region* regionToUpdate) +{ + draw(); + ViewMan::getInstance()->updateView(this,regionToUpdate); +} + +void VTabsViewMan::create() +{ + if (surface!=NULL) + { + delete surface;//destroy old surface + surface=NULL; + } + Region newarea; + int i; + if (numViews == 0) + { + newarea.h=200; + newarea.w=200; + } + else + { + for (i = 0; i < numViews; i++) + { + newarea.h=max(views[i]->getHeight(),newarea.h); + newarea.w=max(views[i]->getWidth(),newarea.w); + } + } + newarea.h += 30; //Title Bar + newarea.h += 30; //Tab bar + newarea.h += 2; //Border + newarea.w += 2; + + //centering + + newarea.y = Video::getInstance()->getScreenHeight()/2-newarea.h/2; + newarea.x = Video::getInstance()->getScreenWidth()/2-newarea.w/2; + setScreenPos(newarea.x,newarea.y); + + //Now iterate through the views and set the position + + for (i = 0; i < numViews; i++) + { + views[i]->setScreenPos(newarea.x+1,newarea.y+1+30+30); + } + View::create(newarea.w,newarea.h); + +} + + +void VTabsViewMan::draw() +{ + if (surface==NULL) return; + View::draw(); + //Now Drawing the tabs bar + int xpos=1; + WSymbol wsy; + wsy.setSurface(surface); + + if (selectedView>=2) + { + wsy.nextSymbol = WSymbol::LEFTARROW; + wsy.nextColour = Colour::BUTTONBACKGROUND; + wsy.setSurfaceOffset(xpos, 40); + wsy.draw(); + xpos+=20; + } + int i; + UINT textypos=30+30-2-surface->getFontHeight(); + for (i = max(selectedView-1,0); i < numViews && xpos+150+20 < (int)area.w; i++) + { + if (i == selectedView) + { + rectangle(xpos+1,30+1,150,30,Colour::TABVIEWBACKGROUND); + } + else + { + rectangle(xpos+1,30+1,150,28,Colour::TABVIEWBACKGROUND); + } + if (i == selectedView && tabHasControl) + drawText(views[i]->getTitleText(),xpos+5,textypos,Colour::SELECTHIGHLIGHT); + else + drawText(views[i]->getTitleText(),xpos+5,textypos,Colour::LIGHTTEXT); + + xpos+=151; + } + if (i < numViews) + { + wsy.nextSymbol = WSymbol::RIGHTARROW; + wsy.nextColour = Colour::BUTTONBACKGROUND; + wsy.setSurfaceOffset(xpos+5, 40); + wsy.draw(); + xpos+=20; + } + + + if (selectedView < numViews) views[selectedView]->draw(); +} + +void VTabsViewMan::blt(Region& r) +{ + Box::blt(r); + + if (selectedView < numViews) { + Region helper=r; + helper.x = max(helper.x,views[selectedView]->area.x); + helper.w -= helper.x-r.x; + helper.y = max(helper.y,views[selectedView]->area.y); + helper.h -= helper.y-r.y; + helper.w = min(helper.w,views[selectedView]->area.w); + helper.h = min(helper.h,views[selectedView]->area.h); + views[selectedView]->blt(helper); + } +} + + +int VTabsViewMan::handleCommand(int command) +{ + int retVal; + int i; + if (command == Remote::BACK) + { + for (i=0;ihandleCommand(Remote::BACK); + } + // Instead of returning 4 here which would delete this view + // before the doSave messages are processed, let the message queue + // do the doSave then this close message. That will make the options menu + // disappear before this view + + Message* m = new Message(); + m->message = Message::CLOSE_ME; + m->from = this; + m->to = ViewMan::getInstance(); + Command::getInstance()->postMessageNoLock(m); + return 2; + } + else if (tabHasControl) //our control bar is selected, we are the master of the universe + { + switch (command) + { + case Remote::DF_DOWN: + case Remote::DOWN: + { + tabHasControl = false; //loose control + if (selectedView < numViews) + { + views[selectedView]->handleCommand(command); + draw(); + viewman->updateView(this); + return 2; + } + else + return 2; + }break; + case Remote::DF_LEFT: + case Remote::LEFT: + { + selectedView=max(0,selectedView-1); + draw(); + viewman->updateView(this); + return 2; + }break; + case Remote::DF_RIGHT: + case Remote::RIGHT: + { + selectedView=min(numViews-1,selectedView+1); + draw(); + viewman->updateView(this); + return 2; + }break; + } + return 1; + } + else if (command != Remote::NA_NONE) + { + // handle command return values + // 0 - drop through to next view //this means me + // 1 - dont drop to next view, but not handled + // 2 - handled - stop command here + // 4 - handled - delete this view //delete me too + + + if (selectedView < numViews) + { + retVal = views[selectedView]->handleCommand(command); + if (retVal == 1) + { + // not handled but don't give to any more views + return 1; + } + if (retVal == 2) + { + // command handled + return 2; + } + else if (retVal == 4) + { + // Log::getInstance()->log("ViewMan", Log::DEBUG, "Return 4: i=%i, views[i]=%p", i, views[i]); + + return 1; + } else if (retVal == 0) { + tabHasControl = true; + draw(); // I have control + viewman->updateView(this); + return 2; + } + + } + } + else + { + // fake the return code + return 2; + } + + return 0; + +} + +void VTabsViewMan::processMessage(Message* m) +{ + /* Handle mouse events*/ + // They come in with m->to = ViewMan and just need to be delivered to selectedView? + if ((numViews > 0) && ((m->message == Message::MOUSE_MOVE) || (m->message == Message::MOUSE_LBDOWN))) + { + //TODO, add Tab bar interaction + int x=(m->parameter>>16)-getScreenX(); + int y=(m->parameter&0xFFFF)-getScreenY(); + if (x<0 || y <0 || x>getWidth() || y>getHeight()) + { + if (m->message == Message::MOUSE_LBDOWN) + { + Message *newm=new Message(); + newm->from=NULL; + newm->to=Command::getInstance(); + newm->message=Message::UDP_BUTTON; + newm->parameter=Remote::BACK; + Command::getInstance()->postMessage(newm); + } + } else { + if ( y <= 60) + { //my area + if (y >= 30 && m->message == Message::MOUSE_LBDOWN) + { + int xpos=1; + if (selectedView>=2) + { + if (xpos < x && x <=xpos+20) + { + tabHasControl=true; + Message *newm=new Message(); + newm->from=NULL; + newm->to=Command::getInstance(); + newm->message=Message::UDP_BUTTON; + newm->parameter=Remote::LEFT; + Command::getInstance()->postMessage(newm); + return; + } + xpos+=20; + } + int i; + for (i = max(selectedView-1,0);i < numViews && xpos+150+20 < (int)area.w; i++) + { + if (xpos < x && x <=xpos+150) + { + tabHasControl=true; + selectedView = i; + draw(); + ViewMan::getInstance()->updateView(this); + return; + } + xpos+=151; + } + if (i < numViews) + { + if (xpos < x && x <=xpos+20) + { + tabHasControl=true; + Message *newm=new Message(); + newm->from=NULL; + newm->to=Command::getInstance(); + newm->message=Message::UDP_BUTTON; + newm->parameter=Remote::RIGHT; + Command::getInstance()->postMessage(newm); + return; + } + } + } + } + else //tabs area + { + tabHasControl=false; + views[selectedView]->processMessage(m); + } + } + return; + } + + if (m->to != this) + { + for (int i = numViews-1; i >= 0; i--) + { + if (views[i] == m->to) + { + Log::getInstance()->log("VTabsViewMan", Log::DEBUG, "sending message from view %p to view %p %lu", m->from, m->to, m->message); + views[i]->processMessage(m); + return; + } + } + return; + } + + + + Log::getInstance()->log("VTabsViewMan", Log::DEBUG, "it's for meeee!"); + + switch(m->message) + { + case Message::CLOSE_ME: + { + removeView((View*)m->from); + break; + } + case Message::ADD_VIEW: // currently not used by anything but it might come in useful again + { + View* toAdd = (View*)m->parameter; + add(toAdd); + toAdd->draw(); + ViewMan::getInstance()->updateView(this); + break; + } + } +} diff --git a/vtabsviewman.h b/vtabsviewman.h new file mode 100644 index 0000000..198e31a --- /dev/null +++ b/vtabsviewman.h @@ -0,0 +1,54 @@ +/* + Copyright 2004-2007 Chris Tallon,Marten Richter + + This file is part of VOMP. + + VOMP 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. + + VOMP 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 VOMP; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef VTABSVIEWMAN_H +#define VTABSVIEWMAN_H + +#include "view.h" +#include "viewman.h" + + +class VTabsViewMan: public View,AbstractViewMan +{ +public: + VTabsViewMan(); + ~VTabsViewMan(); + + int add(View* v); + int removeView(View* toRemove); + void removeAll(); + void create(); + + void draw(); + int handleCommand(int command); + void processMessage(Message* m); // The master lock will be locked + void updateView(View* toUpdate, Region* regionToUpdate = NULL); + + void blt(Region& r); + +protected: + View* views[20]; + int numViews; + int selectedView; + bool tabHasControl; + +}; +#endif + diff --git a/vvideolive.h b/vvideolive.h index 768fa5f..6a8354f 100644 --- a/vvideolive.h +++ b/vvideolive.h @@ -73,7 +73,7 @@ class VVideoLive : public View private: static VVideoLive* instance; - ViewMan* viewman; + // ViewMan* viewman; VDR* vdr; Video* video; void* player; // HA HA FIXME diff --git a/vvideorec.h b/vvideorec.h index 3efb7c3..0901436 100644 --- a/vvideorec.h +++ b/vvideorec.h @@ -55,7 +55,7 @@ class VVideoRec : public View, public TimerReceiver void processMessage(Message* m); private: - ViewMan* viewman; + // ViewMan* viewman; VDR* vdr; Video* video; Timers* timers; diff --git a/vwelcome.h b/vwelcome.h index 258c047..3f8be28 100644 --- a/vwelcome.h +++ b/vwelcome.h @@ -56,7 +56,7 @@ class VWelcome : public View, public TimerReceiver WSelectList sl; WJpeg jpeg; - ViewMan* viewman; + // ViewMan* viewman; void doChannelsList(); void doRadioList(); diff --git a/winmain.cc b/winmain.cc index 504f48b..31ce101 100644 --- a/winmain.cc +++ b/winmain.cc @@ -575,6 +575,14 @@ LONG FAR PASCAL WindowProc(HWND wind, UINT msg, WPARAM wparam, LPARAM lparam) return DefWindowProc(wind, msg, wparam, lparam); } + break; + case WM_CHAR: + if (((RemoteWin*)remote)->ReceiveButtonCH(wparam)) { + return 0L; //We process that Key + } else { + return DefWindowProc(wind, msg, wparam, lparam); + } + break; case WM_APPCOMMAND: if (((RemoteWin*)remote)->ReceiveButtonAP(GET_APPCOMMAND_LPARAM(lparam))){ @@ -870,4 +878,4 @@ ULLONG htonll(ULLONG a) return (((ULLONG)htonl((ULONG)((a<<32)>> 32))<<32) |(ULONG)htonl(((ULONG) (a >> 32)))); } -#endif +#endif \ No newline at end of file diff --git a/wselectlist.cc b/wselectlist.cc index 796042f..6fdf0f7 100644 --- a/wselectlist.cc +++ b/wselectlist.cc @@ -28,6 +28,7 @@ WSelectList::WSelectList() numColumns = 0; noLoop = 0; gap = 1; + showseloption = true; } WSelectList::~WSelectList() @@ -105,7 +106,7 @@ void WSelectList::draw() if (i == options.size()) return; if ((ypos + ySeperation) > area.h) break; - if (i == selectedOption) + if (i == selectedOption && showseloption) { rectangle(0, ypos, area.w, fontHeight, Colour::SELECTHIGHLIGHT); drawOptionLine(options[i].text, 5, ypos, Colour::DARKTEXT); diff --git a/wselectlist.h b/wselectlist.h index a39a52a..2a486c5 100644 --- a/wselectlist.h +++ b/wselectlist.h @@ -47,6 +47,7 @@ class WSelectList : public Widget void addColumn(int x); void setNoLoop(); + void setShowSelOption(bool set) { showseloption = set; }; int addOption(char* text, ULONG data, int selected); void draw(); @@ -78,7 +79,7 @@ class WSelectList : public Widget int columns[10]; int numColumns; int noLoop; - + bool showseloption; }; #endif -- 2.39.2