Initial commit.

git-svn-id: https://gambatte.svn.sourceforge.net/svnroot/gambatte@3 9dfb2916-2d38-0410-aef4-c5fe6c9ffc24
This commit is contained in:
sinamas 2007-08-22 01:27:07 +00:00
parent 8700ab170f
commit f30f14130d
62 changed files with 6406 additions and 0 deletions

View File

@ -0,0 +1,5 @@
SUBDIRS += src
TEMPLATE = subdirs
CONFIG += warn_on \
qt \
thread

View File

@ -0,0 +1,25 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "addaudioengines.h"
#include "audioengines/aoengine.h"
void addAudioEngines(std::vector<AudioEngine*> &audioEngines, const unsigned long /*winId*/) {
audioEngines.push_back(new AoEngine);
}

View File

@ -0,0 +1,28 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef ADD_AUDIO_ENGINES_H
#define ADD_AUDIO_ENGINES_H
class AudioEngine;
#include <vector>
void addAudioEngines(std::vector<AudioEngine*> &audioEngines, unsigned long winId);
#endif

View File

@ -0,0 +1,27 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "addaudioengines.h"
#include "audioengines/alsaengine.h"
#include "audioengines/ossengine.h"
void addAudioEngines(std::vector<AudioEngine*> &audioEngines, const unsigned long /*winId*/) {
audioEngines.push_back(new OssEngine);
audioEngines.push_back(new AlsaEngine);
}

View File

@ -0,0 +1,25 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "addaudioengines.h"
#include "audioengines/ossengine.h"
void addAudioEngines(std::vector<AudioEngine*> &audioEngines, const unsigned long /*winId*/) {
audioEngines.push_back(new OssEngine);
}

View File

@ -0,0 +1,25 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "addaudioengines.h"
#include "audioengines/directsoundengine.h"
void addAudioEngines(std::vector<AudioEngine*> &audioEngines, const unsigned long winId) {
audioEngines.push_back(new DirectSoundEngine(winId));
}

View File

@ -0,0 +1,21 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "addblitterwidgets.h"
void addBlitterWidgets(std::vector<BlitterWidget*> &/*blitters*/, VideoBufferReseter &/*resetVideoBuffer*/) {}

View File

@ -0,0 +1,29 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef ADD_BLITTER_WIDGETS_H
#define ADD_BLITTER_WIDGETS_H
class BlitterWidget;
class VideoBufferReseter;
#include <vector>
void addBlitterWidgets(std::vector<BlitterWidget*> &blitters, VideoBufferReseter &resetVideoBuffer);
#endif

View File

@ -0,0 +1,27 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "addblitterwidgets.h"
#include "blitterwidgets/x11blitter.h"
#include "blitterwidgets/xvblitter.h"
void addBlitterWidgets(std::vector<BlitterWidget*> &blitters, VideoBufferReseter &resetVideoBuffer) {
blitters.push_back(new X11Blitter(resetVideoBuffer));
blitters.push_back(new XvBlitter);
}

View File

@ -0,0 +1,25 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "addblitterwidgets.h"
#include "blitterwidgets/directdrawblitter.h"
void addBlitterWidgets(std::vector<BlitterWidget*> &blitters, VideoBufferReseter &resetVideoBuffer) {
blitters.push_back(new DirectDrawBlitter(resetVideoBuffer));
}

View File

@ -0,0 +1,37 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef AUDIOENGINE_H
#define AUDIOENGINE_H
class AudioEngine {
public:
struct BufferState {
unsigned fromUnderrun;
unsigned fromOverflow;
};
virtual ~AudioEngine() {}
virtual int init() = 0;
virtual void uninit() {}
virtual int write(void *buffer, unsigned samples) = 0;
virtual const BufferState bufferState() const { static const BufferState s = { 0xFFFFFFFF, 0xFFFFFFFF }; return s; }
virtual void pause() {}
};
#endif

View File

@ -0,0 +1,142 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "alsaengine.h"
#include <algorithm>
AlsaEngine::AlsaEngine() : pcm_handle(NULL) {}
AlsaEngine::~AlsaEngine() {
uninit();
}
int AlsaEngine::init() {
unsigned rate = 48000;
if (snd_pcm_open(&pcm_handle, "default", SND_PCM_STREAM_PLAYBACK, 0) < 0) {
fprintf(stderr, "Error opening PCM device %s\n", "default");
pcm_handle = NULL;
goto fail;
}
{
snd_pcm_hw_params_t *hwparams;
snd_pcm_hw_params_alloca(&hwparams);
if (snd_pcm_hw_params_any(pcm_handle, hwparams) < 0) {
fprintf(stderr, "Can not configure this PCM device.\n");
goto fail;
}
if (snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED) < 0) {
fprintf(stderr, "Error setting access.\n");
goto fail;
}
{
#ifdef WORDS_BIGENDIAN
const snd_pcm_format_t format = SND_PCM_FORMAT_S16_BE;
#else
const snd_pcm_format_t format = SND_PCM_FORMAT_S16_LE;
#endif
if (snd_pcm_hw_params_set_format(pcm_handle, hwparams, format) < 0) {
fprintf(stderr, "Error setting format.\n");
goto fail;
}
}
if (snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &rate, 0) < 0) {
fprintf(stderr, "Error setting rate.\n");
goto fail;
}
if (snd_pcm_hw_params_set_channels(pcm_handle, hwparams, 2) < 0) {
fprintf(stderr, "Error setting channels.\n");
goto fail;
}
/*if (snd_pcm_hw_params_set_periods(pcm_handle, hwparams, 2, 0) < 0) {
fprintf(stderr, "Error setting periods.\n");
goto fail;
}*/
{
snd_pcm_uframes_t periodSize = ((rate * 4389) / 262144) + 1 << 1;
periodSize |= periodSize >> 1;
periodSize |= periodSize >> 2;
periodSize |= periodSize >> 4;
periodSize |= periodSize >> 8;
periodSize |= periodSize >> 16;
++periodSize;
snd_pcm_uframes_t bSize = periodSize * 2;
if (snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, &periodSize, 0) < 0) {
fprintf(stderr, "Error setting period size %lu.\n", static_cast<unsigned long>(periodSize));
goto fail;
}
if (snd_pcm_hw_params_set_buffer_size_near(pcm_handle, hwparams, &bSize) < 0) {
fprintf(stderr, "Error setting buffer size %u.\n", bufSize);
goto fail;
}
bufSize = bSize;
}
if (snd_pcm_hw_params(pcm_handle, hwparams) < 0) {
fprintf(stderr, "Error setting HW params.\n");
goto fail;
}
}
return rate;
fail:
uninit();
return -1;
}
void AlsaEngine::uninit() {
if (pcm_handle)
snd_pcm_close(pcm_handle);
pcm_handle = NULL;
}
int AlsaEngine::write(void *const buffer, const unsigned samples) {
while (snd_pcm_writei(pcm_handle, buffer, samples) < 0) {
snd_pcm_prepare(pcm_handle);
// fprintf(stderr, "<<<<<<<<<<<<<<< Buffer Underrun >>>>>>>>>>>>>>>\n");
}
return 0;
}
const AudioEngine::BufferState AlsaEngine::bufferState() const {
const snd_pcm_sframes_t avail = snd_pcm_avail_update(pcm_handle);
BufferState s = { bufSize - avail, avail };
if (avail < 0)
s.fromOverflow = s.fromUnderrun = bufSize;
return s;
}

View File

@ -0,0 +1,38 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef ALSAENGINE_H
#define ALSAENGINE_H
#include "../audioengine.h"
#include <alsa/asoundlib.h>
class AlsaEngine : public AudioEngine {
snd_pcm_t *pcm_handle;
unsigned bufSize;
public:
AlsaEngine();
~AlsaEngine();
int init();
void uninit();
int write(void *buffer, unsigned samples);
const BufferState bufferState() const;
};
#endif

View File

@ -0,0 +1,65 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "aoengine.h"
AoEngine::AoEngine() : aoDevice(NULL) {}
AoEngine::~AoEngine() {
uninit();
}
int AoEngine::init() {
ao_initialize();
aoDevice = NULL;
ao_sample_format sampleFormat = { 16, 48000, 2, AO_FMT_NATIVE };
int aoDriverId = ao_default_driver_id();
if (aoDriverId != -1) {
if ((aoDevice = ao_open_live(aoDriverId, &sampleFormat, NULL)) == NULL) {
sampleFormat.rate = 44100;
aoDevice = ao_open_live(aoDriverId, &sampleFormat, NULL);
}
}
if (aoDevice == NULL) {
ao_shutdown();
return -1;
}
return sampleFormat.rate;
}
void AoEngine::uninit() {
if (aoDevice) {
ao_close(aoDevice);
aoDevice = NULL;
ao_shutdown();
}
}
int AoEngine::write(void *const buffer, const unsigned samples) {
if (ao_play(aoDevice, reinterpret_cast<char*>(buffer), samples * 4) == 0)
return -1;
return 0;
}

View File

@ -0,0 +1,37 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef AOENGINE_H
#define AOENGINE_H
#include "../audioengine.h"
#include <ao/ao.h>
class AoEngine : public AudioEngine {
ao_device *aoDevice;
public:
AoEngine();
~AoEngine();
int init();
void uninit();
int write(void *buffer, unsigned samples);
};
#endif

View File

@ -0,0 +1,193 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "directsoundengine.h"
#include <iostream>
DirectSoundEngine::DirectSoundEngine(HWND hwnd_in) : lpDS(NULL), lpDSB(NULL), hwnd(hwnd_in) {}
DirectSoundEngine::~DirectSoundEngine() {
uninit();
}
int DirectSoundEngine::init() {
unsigned rate = 48000;
if (DirectSoundCreate(NULL, &lpDS, NULL) != DS_OK) {
lpDS = NULL;
goto fail;
}
if (lpDS->SetCooperativeLevel(hwnd, DSSCL_PRIORITY) != DS_OK)
goto fail;
{
DSBUFFERDESC dsbd;
memset(&dsbd, 0, sizeof(dsbd));
dsbd.dwSize = sizeof(dsbd);
{
int bufferSize = (((rate * 4389) / 262144) + 1) * 8 * 4;
bufferSize |= bufferSize >> 1;
bufferSize |= bufferSize >> 2;
bufferSize |= bufferSize >> 4;
bufferSize |= bufferSize >> 8;
bufferSize |= bufferSize >> 16;
++bufferSize;
if (bufferSize < DSBSIZE_MIN)
bufferSize = DSBSIZE_MIN;
if (bufferSize > DSBSIZE_MAX)
bufferSize = DSBSIZE_MAX;
dsbd.dwBufferBytes = bufSize = bufferSize;
}
WAVEFORMATEX wfe;
memset(&wfe, 0, sizeof(wfe));
wfe.wFormatTag = WAVE_FORMAT_PCM;
wfe.nChannels = 2;
wfe.nSamplesPerSec = rate;
wfe.wBitsPerSample = 16;
wfe.nBlockAlign = wfe.nChannels * wfe.wBitsPerSample >> 3;
wfe.nAvgBytesPerSec = rate * wfe.nBlockAlign;
dsbd.lpwfxFormat = &wfe;
{
GUID guidNULL;
memset(&guidNULL,0,sizeof(GUID));
dsbd.guid3DAlgorithm = guidNULL;
}
if (lpDS->CreateSoundBuffer(&dsbd, &lpDSB, NULL) != DS_OK) {
rate = 44100;
wfe.nSamplesPerSec = rate;
wfe.nAvgBytesPerSec = rate * wfe.nBlockAlign;
if (lpDS->CreateSoundBuffer(&dsbd, &lpDSB, NULL) != DS_OK) {
lpDSB = NULL;
goto fail;
}
}
}
return rate;
fail:
uninit();
return -1;
}
void DirectSoundEngine::uninit() {
if (lpDSB) {
lpDSB->Stop();
lpDSB->Release();
}
lpDSB = NULL;
if (lpDS)
lpDS->Release();
lpDS = NULL;
}
int DirectSoundEngine::write(void *const buffer, const unsigned frames) {
DWORD status;
lpDSB->GetStatus(&status);
if (status & DSBSTATUS_BUFFERLOST) {
lpDSB->Restore();
status &= ~DSBSTATUS_PLAYING;
}
if (!(status & DSBSTATUS_PLAYING)) {
std:: cout << "notplaying" << std::endl;
offset = bufSize >> 1;
lpDSB->SetCurrentPosition(0);
} else for (DWORD pc, wc;;) {
if (lpDSB->GetCurrentPosition(&pc, &wc) != DS_OK)
return -1;
//std::cout << "wc-pc: " << ((wc < pc ? bufSize : 0) + wc - pc) << std::endl;
if (offset > pc && offset < wc) {
std::cout << "underrun" << std::endl;
offset = wc;
break;
}
if ((pc < offset ? bufSize : 0) + pc - offset >= frames * 4)
break;
Sleep(1);
}
{
LPVOID ptr1;
LPVOID ptr2;
DWORD bytes1;
DWORD bytes2;
if (lpDSB->Lock(offset, frames * 4, &ptr1, &bytes1, &ptr2, &bytes2, 0) != DS_OK)
return 0;
memcpy(ptr1, buffer, bytes1);
if (ptr2) {
memcpy(ptr2, static_cast<char*>(buffer) + bytes1, bytes2);
}
lpDSB->Unlock(ptr1, bytes1, ptr2, bytes2);
}
if ((offset += frames * 4) >= bufSize)
offset -= bufSize;
if (!(status & DSBSTATUS_PLAYING)) {
lpDSB->Play(0, 0, DSBPLAY_LOOPING);
}
return 0;
}
const AudioEngine::BufferState DirectSoundEngine::bufferState() const {
BufferState s;
DWORD pc, wc;
if (lpDSB->GetCurrentPosition(&pc, &wc) != DS_OK) {
s.fromOverflow = s.fromUnderrun = bufSize >> 2;
} else if (offset > pc && offset < wc) {
s.fromUnderrun = 0;
s.fromOverflow = bufSize >> 2;
} else {
s.fromUnderrun = (offset < wc ? bufSize : 0) + offset - wc >> 2;
s.fromOverflow = (pc < offset ? bufSize : 0) + pc - offset >> 2;
}
return s;
}
void DirectSoundEngine::pause() {
if (lpDSB) {
lpDSB->Stop();
}
}

View File

@ -0,0 +1,43 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef DIRECTSOUNDENGINE_H
#define DIRECTSOUNDENGINE_H
#include "../audioengine.h"
#include <dsound.h>
class DirectSoundEngine : public AudioEngine {
LPDIRECTSOUND lpDS;
LPDIRECTSOUNDBUFFER lpDSB;
unsigned bufSize;
DWORD offset;
HWND hwnd;
public:
DirectSoundEngine(HWND hwnd);
~DirectSoundEngine();
int init();
void uninit();
int write(void *buffer, unsigned frames);
const BufferState bufferState() const;
void pause();
};
#endif

View File

@ -0,0 +1,130 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "ossengine.h"
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/soundcard.h>
#include <algorithm>
#include <cmath>
OssEngine::OssEngine() : audio_fd(-1) {}
OssEngine::~OssEngine() {
uninit();
}
int OssEngine::init() {
int speed = 48000;
if ((audio_fd = open("/dev/dsp", O_WRONLY, 0)) == -1) {
perror("/dev/dsp");
goto fail;
}
{
int format = AFMT_S16_NE;
if (ioctl(audio_fd, SNDCTL_DSP_SETFMT, &format) == -1) {
perror("SNDCTL_DSP_SETFMT");
goto fail;
}
if (format != AFMT_S16_NE) {
printf("oss-sound: unsupported format\n");
goto fail;
}
}
{
int channels = 2;
if (ioctl(audio_fd, SNDCTL_DSP_CHANNELS, &channels) == -1) {
perror("SNDCTL_DSP_CHANNELS");
goto fail;
}
if (channels != 2) {
printf("oss-sound: unsupported number of channels\n");
goto fail;
}
}
if (ioctl(audio_fd, SNDCTL_DSP_SPEED, &speed) == -1) {
perror("SNDCTL_DSP_SPEED");
goto fail;
}
{
const int bytes = (((speed * 4389) / 262144) + 1) * 4;
int arg = 0x00040000 | std::min(static_cast<int>(log2(static_cast<float>(bytes))) + 1, 0xFFFF);
if (ioctl(audio_fd, SNDCTL_DSP_SETFRAGMENT, &arg) == -1) {
perror("SNDCTL_DSP_SETFRAGMENT");
// goto fail;
}
}
{
audio_buf_info info;
if (ioctl(audio_fd, SNDCTL_DSP_GETOSPACE, &info) == -1) {
perror("SNDCTL_DSP_GETOSPACE");
goto fail;
}
bufSize = (info.fragstotal * info.fragsize) >> 2;
}
return speed;
fail:
uninit();
return -1;
}
void OssEngine::uninit() {
if (audio_fd != -1)
close(audio_fd);
audio_fd = -1;
}
int OssEngine::write(void *const buffer, const unsigned samples) {
if (::write(audio_fd, buffer, samples * 4) != static_cast<int>(samples * 4))
return -1;
return 0;
}
const AudioEngine::BufferState OssEngine::bufferState() const {
BufferState s;
audio_buf_info info;
if (ioctl(audio_fd, SNDCTL_DSP_GETOSPACE, &info) == -1 || info.bytes < 0) {
s.fromOverflow = s.fromUnderrun = bufSize;
} else {
s.fromUnderrun = bufSize - (info.bytes >> 2);
s.fromOverflow = info.bytes >> 2;
}
return s;
}

View File

@ -0,0 +1,37 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef OSSENGINE_H
#define OSSENGINE_H
#include "../audioengine.h"
class OssEngine : public AudioEngine {
int audio_fd;
unsigned bufSize;
public:
OssEngine();
~OssEngine();
int init();
void uninit();
int write(void *buffer, unsigned samples);
const BufferState bufferState() const;
};
#endif

View File

@ -0,0 +1,90 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "blittercontainer.h"
#include "blitterwidget.h"
#include "fullrestoggler.h"
#include <QResizeEvent>
BlitterContainer::BlitterContainer(const FullResToggler &resToggler_in, QWidget *parent) :
QWidget(parent),
resToggler(resToggler_in),
blitter(NULL)
{
QPalette pal = palette();
pal.setColor(QPalette::Window, QColor(0, 0, 0));
setPalette(pal);
// setBackgroundRole(QPalette::Window);
setAutoFillBackground(true);
}
BlitterContainer::~BlitterContainer()
{}
void BlitterContainer::doLayout(const int w, const int h) {
if (!blitter)
return;
if (blitter->keepsAspectRatio() && !blitter->selfScaling) {
if (blitter->scalesByInteger()) {
const int scale = std::min(w / minimumWidth(), h / minimumHeight());
const int new_w = minimumWidth() * scale;
const int new_h = minimumHeight() * scale;
blitter->setGeometry(w - new_w >> 1, h - new_h >> 1, new_w, new_h);
} else {
if (w * 9 > h * 10) {
const int new_w = (h * 20 + 9) / 18;
blitter->setGeometry(w - new_w >> 1, 0, new_w, h);
} else {
const int new_h = (w * 9 + 5) / 10;
blitter->setGeometry(0, h - new_h >> 1, w, new_h);
}
}
} else {
blitter->setGeometry(0, 0, w, h);
}
if (!resToggler.resVector().empty()) {
const ResInfo &res = resToggler.resVector()[resToggler.currentResIndex()];
blitter->setExclusive(res.w == static_cast<unsigned>(w) && res.h == static_cast<unsigned>(h));
}
}
void BlitterContainer::setBlitter(BlitterWidget *const blitter_in) {
if (blitter)
blitter->setParent(0);
blitter = blitter_in;
if (blitter) {
blitter->setParent(this);
updateLayout();
}
}
void BlitterContainer::resizeEvent(QResizeEvent *const event) {
doLayout(event->size().width(), event->size().height());
}
void BlitterContainer::hideEvent(QHideEvent *const event) {
if (blitter)
blitter->setExclusive(false);
QWidget::hideEvent(event);
}

View File

@ -0,0 +1,44 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef BLITTERCONTAINER_H
#define BLITTERCONTAINER_H
#include <QWidget>
class BlitterWidget;
class FullResToggler;
class BlitterContainer : public QWidget {
const FullResToggler &resToggler;
BlitterWidget *blitter;
void doLayout(int w, int h);
protected:
void resizeEvent(QResizeEvent *event);
void hideEvent(QHideEvent *event);
public:
BlitterContainer(const FullResToggler &fullResToggler, QWidget *parent = 0);
~BlitterContainer();
void setBlitter(BlitterWidget *blitter);
void updateLayout() { doLayout(width(), height()); }
};
#endif

View File

@ -0,0 +1,85 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "blitterwidget.h"
#include <sys/time.h>
// #include <time.h>
const BlitterWidget::Rational BlitterWidget::frameTime() const {
Rational r = { 16743, 1000000 };
return r;
}
int BlitterWidget::sync(const bool turbo) {
if (turbo)
return 0;
timeval t;
gettimeofday(&t, NULL);
static timeval time = t;
static long late = 0;
static unsigned noSleep = 60;
if (time.tv_sec > t.tv_sec || (time.tv_sec == t.tv_sec && time.tv_usec > t.tv_usec)) {
timeval tmp;
tmp.tv_sec = 0;
tmp.tv_usec = time.tv_usec - t.tv_usec;
if (time.tv_sec != t.tv_sec)
tmp.tv_usec += 1000000;
if (tmp.tv_usec > late) {
tmp.tv_usec -= late;
if (tmp.tv_usec >= 1000000) {
tmp.tv_usec -= 1000000;
++tmp.tv_sec;
}
timespec tspec = { tmp.tv_sec, tmp.tv_usec * 1000 };
nanosleep(&tspec, NULL);
gettimeofday(&t, NULL);
late -= (time.tv_sec - t.tv_sec) * 1000000 + time.tv_usec - t.tv_usec >> 1;
// printf("late: %d\n", late);
if (late < 0)
late = 0;
noSleep = 60;
} else if (noSleep-- == 0) {
noSleep = 60;
late = 0;
}
while (time.tv_sec > t.tv_sec || (time.tv_sec == t.tv_sec && time.tv_usec > t.tv_usec)) {
gettimeofday(&t, NULL);
}
} else
time = t; //quickfix:catches up to current time (The GUI tends to pause the run loop, so this function doesn't get called)
time.tv_usec += 16743;
if (time.tv_usec >= 1000000) {
time.tv_usec -= 1000000;
++time.tv_sec;
}
return 0;
}

View File

@ -0,0 +1,69 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef BLITTERWIDGET_H
#define BLITTERWIDGET_H
#include <QWidget>
#include <videoblitter.h>
#include <QString>
class QHBoxLayout;
class BlitterWidget : public QWidget, public VideoBlitter {
Q_OBJECT
public:
struct Rational {
unsigned numerator;
unsigned denominator;
};
const QString nameString;
const bool integerOnlyScaler;
const bool selfScaling;
BlitterWidget(const QString &name, bool integerOnlyScaler_in = false, bool selfScaling_in = false, QWidget *parent = 0) :
QWidget(parent),
nameString(name),
integerOnlyScaler(integerOnlyScaler_in),
selfScaling(selfScaling_in)
{}
virtual void init() {}
virtual void uninit() {}
virtual bool isUnusable() { return false; }
virtual void keepAspectRatio(const bool enable) = 0;
virtual bool keepsAspectRatio() = 0;
virtual void scaleByInteger(const bool enable) = 0;
virtual bool scalesByInteger() = 0;
virtual const Rational frameTime() const;
virtual int sync(bool turbo);
virtual QWidget* settingsWidget() { return NULL; }
virtual void setExclusive(bool) {}
// public slots:
virtual void acceptSettings() {}
virtual void rejectSettings() {}
public slots:
virtual void rateChange(int /*newHz*/) {}
// virtual void modeChange() {}
};
#endif

View File

@ -0,0 +1,71 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "blitterwidget.h"
#include <windows.h>
class Freq {
LONGLONG value;
public:
Freq() {
LARGE_INTEGER li;
QueryPerformanceFrequency(&li);
value = li.QuadPart;
}
LONGLONG get() const { return value; }
};
const BlitterWidget::Rational BlitterWidget::frameTime() const {
Rational r = { 16743, 1000000 };
return r;
}
int BlitterWidget::sync(const bool turbo) {
if (turbo)
return 0;
static Freq freq;
static const LONGLONG inc = (freq.get() * 16743) / 1000000;
LARGE_INTEGER t;
QueryPerformanceCounter(&t);
static LONGLONG time = t.QuadPart;
if (time > t.QuadPart) {
{
const DWORD tmp = ((time - t.QuadPart) * 1000) / freq.get();
if (tmp > 1) {
Sleep(tmp - 1);
}
}
do {
QueryPerformanceCounter(&t);
} while (time > t.QuadPart);
} else
time = t.QuadPart; //quickfix:catches up to current time (The GUI tends to pause the run loop, so this function doesn't get called)
time += inc;
return 0;
}

View File

@ -0,0 +1,511 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "directdrawblitter.h"
#include "../videobufferreseter.h"
#include <QCheckBox>
#include <QSettings>
#include <QVBoxLayout>
#include <iostream>
DirectDrawBlitter::DirectDrawBlitter(VideoBufferReseter &resetVideoBuffer_in, QWidget *parent) :
BlitterWidget("DirectDraw", parent),
resetVideoBuffer(resetVideoBuffer_in),
confWidget(new QWidget),
vblankBox(new QCheckBox(QString("Sync to vertical blank in 60 Hz modes"))),
flippingBox(new QCheckBox(QString("Page flipping"))),
videoSurfaceBox(new QCheckBox(QString("Use video memory surface"))),
lpDD(NULL),
lpDDSPrimary(NULL),
lpDDSSystem(NULL),
lpDDSVideo(NULL),
lpClipper(NULL),
keepRatio(true),
integerScaling(false),
exclusive(false)
{
pixb.pixels = NULL;
setAttribute(Qt::WA_OpaquePaintEvent, true);
setAttribute(Qt::WA_PaintOnScreen, true);
QSettings settings;
settings.beginGroup("directdrawblitter");
vblank = settings.value("vblank", false).toBool();
flipping = settings.value("flipping", false).toBool();
videoSurface = settings.value("videoSurface", true).toBool();
settings.endGroup();
confWidget->setLayout(new QVBoxLayout);
confWidget->layout()->setMargin(0);
confWidget->layout()->addWidget(vblankBox);
confWidget->layout()->addWidget(flippingBox);
confWidget->layout()->addWidget(videoSurfaceBox);
vblankBox->setChecked(vblank);
flippingBox->setChecked(flipping);
videoSurfaceBox->setChecked(videoSurface);
}
DirectDrawBlitter::~DirectDrawBlitter() {
uninit();
QSettings settings;
settings.beginGroup("directdrawblitter");
settings.setValue("vblank", vblank);
settings.setValue("flipping", flipping);
settings.setValue("videoSurface", videoSurface);
settings.endGroup();
delete confWidget;
}
void DirectDrawBlitter::videoSurfaceBlit() {
lpDDSSystem->PageLock(0);
lpDDSVideo->PageLock(0);
HRESULT ddrval;
ddrval = lpDDSVideo->BltFast(0, 0, lpDDSSystem, NULL, DDBLTFAST_WAIT);
if (ddrval == DDERR_SURFACELOST) {
if (!restoreSurfaces())
ddrval = lpDDSVideo->BltFast(0, 0, lpDDSSystem, NULL, DDBLTFAST_WAIT);
}
if (ddrval != DD_OK) {
std::cout << "lpDDSVideo->BltFast(0, 0, lpDDSSystem, NULL, DDBLTFAST_WAIT) failed" << std::endl;
if (lpDDSPrimary) {
lpDDSPrimary->Release();
lpDDSPrimary = NULL;
}
}
lpDDSVideo->PageUnlock(0);
lpDDSSystem->PageUnlock(0);
}
void DirectDrawBlitter::systemSurfaceBlit() {
LPDIRECTDRAWSURFACE7 lpDDSTmp = lpDDSSystem;
lpDDSSystem = lpDDSVideo;
lpDDSVideo = lpDDSTmp;
}
void DirectDrawBlitter::blit() {
if (!lpDDSPrimary)
return;
lpDDSSystem->Unlock(NULL);
if (videoSurface)
videoSurfaceBlit();
else
systemSurfaceBlit();
DDSURFACEDESC2 ddsd;
ddsd.dwSize = sizeof(ddsd);
if (lpDDSSystem->Lock(NULL, &ddsd, DDLOCK_NOSYSLOCK, NULL) != DD_OK)
std::cout << "lpDDSSystem->Lock(NULL, &ddsd, DDLOCK_NOSYSLOCK, NULL) failed" << std::endl;
pixb.pixels = ddsd.lpSurface;
pixb.pitch = pixb.format == PixelBuffer::RGB16 ? ddsd.lPitch >> 1 : (ddsd.lPitch >> 2);
resetVideoBuffer();
}
const PixelBuffer DirectDrawBlitter::inBuffer() {
return pixb;
}
bool DirectDrawBlitter::initPrimarySurface() {
{
DDSURFACEDESC2 ddsd;
memset(&ddsd, 0, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_CAPS;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
if (exclusive && flipping) {
ddsd.dwFlags |= DDSD_BACKBUFFERCOUNT;
ddsd.dwBackBufferCount = 1;
ddsd.ddsCaps.dwCaps |= DDSCAPS_COMPLEX | DDSCAPS_FLIP;
}
HRESULT ddrval = lpDD->CreateSurface(&ddsd, &lpDDSPrimary, NULL);
lpDDSBack = lpDDSPrimary;
if (exclusive && flipping && ddrval == DD_OK) {
ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER;
ddrval = lpDDSPrimary->GetAttachedSurface(&ddsd.ddsCaps, &lpDDSBack);
}
if (ddrval != DD_OK) {
std::cout << "CreateSurface failed" << std::endl;
lpDDSPrimary = NULL;
return true;
}
}
if (lpDDSPrimary->SetClipper(lpClipper) != DD_OK) {
std::cout << "SetClipper failed" << std::endl;
return true;
}
return false;
}
bool DirectDrawBlitter::initVideoSurface() {
DDSURFACEDESC2 ddsd;
memset(&ddsd, 0, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
lpDDSSystem->GetSurfaceDesc(&ddsd);
ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
if (!videoSurface)
ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
if (lpDD->CreateSurface(&ddsd, &lpDDSVideo, NULL) != DD_OK) {
lpDDSVideo = NULL;
return true;
}
return false;
}
void DirectDrawBlitter::init() {
if (DirectDrawCreateEx(NULL, reinterpret_cast<void**>(&lpDD), IID_IDirectDraw7, NULL) != DD_OK) {
std::cout << "DirectDrawCreateEx failed" << std::endl;
goto fail;
}
if (lpDD->SetCooperativeLevel(GetParent(GetParent(winId())), (exclusive && flipping) ? DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN : DDSCL_NORMAL) != DD_OK) {
std::cout << "SetCooperativeLevel failed" << std::endl;
goto fail;
}
if (lpDD->CreateClipper(0, &lpClipper, NULL) != DD_OK) {
std::cout << "CreateClipper failed" << std::endl;
goto fail;
}
if (lpClipper->SetHWnd(0, winId()) != DD_OK) {
std::cout << "SetHWnd failed" << std::endl;
goto fail;
}
if (initPrimarySurface())
goto fail;
DDPIXELFORMAT ddpf;
ddpf.dwSize = sizeof(ddpf);
if (lpDDSPrimary->GetPixelFormat(&ddpf) == DD_OK && (ddpf.dwFlags & DDPF_RGB) && ddpf.dwRGBBitCount == 16) {
pixb.format = PixelBuffer::RGB16;
} else {
pixb.format = PixelBuffer::RGB32;
}
return;
fail:
uninit();
}
bool DirectDrawBlitter::restoreSurfaces() {
lpDDSPrimary->Restore();
lpDDSVideo->Restore();
if (lpDDSPrimary->IsLost() != DDERR_SURFACELOST && lpDDSVideo->IsLost() != DDERR_SURFACELOST)
return false;
lpDDSPrimary->Release();
if (initPrimarySurface()) {
return true;
}
if (videoSurface) {
lpDDSVideo->Release();
if (initVideoSurface())
return true;
}
return false;
}
static void setDdPf(DDPIXELFORMAT *const ddpf, const PixelBuffer::Format format) {
memset(ddpf, 0, sizeof(DDPIXELFORMAT));
ddpf->dwSize = sizeof(DDPIXELFORMAT);
if (format == PixelBuffer::RGB16) {
ddpf->dwFlags = DDPF_RGB;
ddpf->dwRGBBitCount = 16;
ddpf->dwRGBAlphaBitMask = 0x0000;
ddpf->dwRBitMask = 0xF800;
ddpf->dwGBitMask = 0x07E0;
ddpf->dwBBitMask = 0x001F;
} else {
ddpf->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
ddpf->dwRGBBitCount = 32;
ddpf->dwRGBAlphaBitMask = 0xFF000000;
ddpf->dwRBitMask = 0x00FF0000;
ddpf->dwGBitMask = 0x0000FF00;
ddpf->dwBBitMask = 0x000000FF;
}
}
void DirectDrawBlitter::setBufferDimensions(const unsigned int w, const unsigned int h) {
if (lpDDSPrimary == NULL)
return;
if (lpDDSSystem) {
lpDDSSystem->Release();
lpDDSSystem = NULL;
}
if (lpDDSVideo) {
lpDDSVideo->Release();
lpDDSVideo = NULL;
}
DDPIXELFORMAT ddpf;
setDdPf(&ddpf, pixb.format);
DDSURFACEDESC2 ddsd;
memset(&ddsd, 0, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
ddsd.dwWidth = w;
ddsd.dwHeight = h;
ddsd.ddpfPixelFormat = ddpf;
if (lpDD->CreateSurface(&ddsd, &lpDDSSystem, NULL) != DD_OK) {
std::cout << "lpDD->CreateSurface(&ddsd, &lpDDSSystem, NULL) failed" << std::endl;
goto fail;
}
if (videoSurface)
ddsd.ddsCaps.dwCaps &= ~DDSCAPS_SYSTEMMEMORY;
if (lpDD->CreateSurface(&ddsd, &lpDDSVideo, NULL) != DD_OK) {
std::cout << "lpDD->CreateSurface(&ddsd, &lpDDSVideo, NULL) failed" << std::endl;
goto fail;
}
if (lpDDSSystem->Lock(NULL, &ddsd, DDLOCK_NOSYSLOCK, NULL) != DD_OK) {
std::cout << "lpDDSSystem->Lock(NULL, &ddsd, DDLOCK_NOSYSLOCK, NULL) failed" << std::endl;
goto fail;
}
pixb.pixels = ddsd.lpSurface;
pixb.pitch = pixb.format == PixelBuffer::RGB16 ? ddsd.lPitch >> 1 : (ddsd.lPitch >> 2);
return;
fail:
uninit();
}
void DirectDrawBlitter::uninit() {
if (lpClipper) {
lpClipper->Release();
lpClipper = NULL;
}
if (lpDDSPrimary) {
lpDDSPrimary->Release();
lpDDSPrimary = NULL;
}
if (lpDDSSystem) {
lpDDSSystem->Release();
lpDDSSystem = NULL;
}
if (lpDDSVideo) {
lpDDSVideo->Release();
lpDDSVideo = NULL;
}
if (lpDD) {
lpDD->Release();
lpDD = NULL;
}
pixb.pixels = NULL;
}
const BlitterWidget::Rational DirectDrawBlitter::frameTime() const {
if (vblank && hz60) {
Rational r = { 1, 60 };
return r;
}
return BlitterWidget::frameTime();
}
int DirectDrawBlitter::sync(const bool turbo) {
if (lpDDSPrimary == NULL)
return -1;
lpDDSVideo->PageLock(0);
RECT rcRectDest;
GetWindowRect(winId(), &rcRectDest);
if (!turbo) {
if (vblank && hz60) {
if (!(exclusive && flipping))
lpDD->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN, 0);
} else
BlitterWidget::sync(turbo);
}
const bool dontwait = exclusive && flipping && !(vblank && hz60 && !turbo);
HRESULT ddrval = lpDDSBack->Blt(&rcRectDest, lpDDSVideo, NULL, dontwait ? DDBLT_DONOTWAIT : DDBLT_WAIT, NULL);
if (ddrval == DDERR_SURFACELOST) {
if (!restoreSurfaces())
ddrval = lpDDSBack->Blt(&rcRectDest, lpDDSVideo, NULL, dontwait ? DDBLT_DONOTWAIT : DDBLT_WAIT, NULL);
}
lpDDSVideo->PageUnlock(0);
if (ddrval == DD_OK && exclusive && flipping) {
ddrval = lpDDSPrimary->Flip(NULL, dontwait ? DDFLIP_DONOTWAIT : DDFLIP_WAIT);
}
if (ddrval != DD_OK && ddrval != DDERR_WASSTILLDRAWING) {
//std::cout << "lpDDSPrimary->Blt(&rcRectDest, lpDDSVideo, NULL, DDBLT_WAIT, NULL) failed" << std::endl;
return -1;
}
return 0;
}
void DirectDrawBlitter::keepAspectRatio(const bool enable) {
keepRatio = enable;
}
bool DirectDrawBlitter::keepsAspectRatio() {
return keepRatio;
}
void DirectDrawBlitter::scaleByInteger(const bool enable) {
integerScaling = enable;
}
bool DirectDrawBlitter::scalesByInteger() {
return integerScaling;
}
void DirectDrawBlitter::acceptSettings() {
vblank = vblankBox->isChecked();
if (flipping != flippingBox->isChecked()) {
flipping = flippingBox->isChecked();
if (exclusive)
reinit();
}
if (videoSurface != videoSurfaceBox->isChecked()) {
videoSurface = videoSurfaceBox->isChecked();
if (lpDDSVideo) {
lpDDSVideo->Release();
if (initVideoSurface()) {
lpDDSPrimary->Release();
lpDDSPrimary = NULL;
}
}
}
}
void DirectDrawBlitter::rejectSettings() {
vblankBox->setChecked(vblank);
flippingBox->setChecked(flipping);
videoSurfaceBox->setChecked(videoSurface);
}
void DirectDrawBlitter::rateChange(int hz) {
hz60 = hz == 60;
}
void DirectDrawBlitter::paintEvent(QPaintEvent */*event*/) {
sync(true);
}
/*void DirectDrawBlitter::detectExclusive() {
if (!lpDD || !parentWidget())
return;
DDSURFACEDESC2 ddsd;
memset(&ddsd, 0, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
lpDD->GetDisplayMode(&ddsd);
setExclusive(parentWidget()->width() == ddsd.dwWidth && parentWidget()->height() == ddsd.dwHeight);
}
void DirectDrawBlitter::resizeEvent(QResizeEvent *event) {
BlitterWidget::resizeEvent(event);
detectExclusive();
}
void DirectDrawBlitter::moveEvent(QMoveEvent *event) {
BlitterWidget::moveEvent(event);
detectExclusive();
}
void DirectDrawBlitter::hideEvent(QHideEvent *event) {
BlitterWidget::hideEvent(event);
setExclusive(false);
}*/
void DirectDrawBlitter::setExclusive(const bool exclusive) {
if (this->exclusive == exclusive)
return;
this->exclusive = exclusive;
std::cout << "exclusive: " << exclusive << std::endl;
if (flipping)
reinit();
}
void DirectDrawBlitter::reinit() {
if (lpDDSSystem) {
DDSURFACEDESC2 ddsd;
memset(&ddsd, 0, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
lpDDSSystem->GetSurfaceDesc(&ddsd);
uninit();
init();
setBufferDimensions(ddsd.dwWidth, ddsd.dwHeight);
resetVideoBuffer();
}
}

View File

@ -0,0 +1,89 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef DIRECTDRAWBLITTER_H_
#define DIRECTDRAWBLITTER_H_
#include "../blitterwidget.h"
#include <ddraw.h>
class QCheckBox;
class VideoBufferReseter;
class DirectDrawBlitter : public BlitterWidget {
VideoBufferReseter &resetVideoBuffer;
QWidget *const confWidget;
QCheckBox *const vblankBox;
QCheckBox *const flippingBox;
QCheckBox *const videoSurfaceBox;
LPDIRECTDRAW7 lpDD;
LPDIRECTDRAWSURFACE7 lpDDSPrimary;
LPDIRECTDRAWSURFACE7 lpDDSBack;
LPDIRECTDRAWSURFACE7 lpDDSSystem;
LPDIRECTDRAWSURFACE7 lpDDSVideo;
LPDIRECTDRAWCLIPPER lpClipper;
PixelBuffer pixb;
bool keepRatio;
bool integerScaling;
bool vblank;
bool hz60;
bool videoSurface;
bool exclusive;
bool flipping;
bool initPrimarySurface();
bool initVideoSurface();
bool restoreSurfaces();
void systemSurfaceBlit();
void videoSurfaceBlit();
//void detectExclusive();
void reinit();
protected:
void paintEvent(QPaintEvent *event);
/*void resizeEvent(QResizeEvent *event);
void moveEvent(QMoveEvent *event);
void hideEvent(QHideEvent *event);*/
public:
DirectDrawBlitter(VideoBufferReseter &resetVideoBuffer_in, QWidget *parent = 0);
~DirectDrawBlitter();
void blit();
const PixelBuffer inBuffer();
void init();
void keepAspectRatio(bool enable);
bool keepsAspectRatio();
void scaleByInteger(bool enable);
bool scalesByInteger();
void setBufferDimensions(unsigned int w, unsigned int h);
const Rational frameTime() const;
int sync(bool turbo);
void uninit();
void setExclusive(bool exclusive);
QWidget* settingsWidget() { return confWidget; }
void acceptSettings();
void rejectSettings();
public slots:
// void modeChange();
void rateChange(int hz);
};
#endif /*DIRECTDRAWBLITTER_H_*/

View File

@ -0,0 +1,447 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "qglblitter.h"
#include <QSizePolicy>
#include <QVBoxLayout>
#include <QCheckBox>
#include <QResizeEvent>
#include <QSettings>
#include <QGLWidget>
#ifdef PLATFORM_WIN32
#include <GL/glext.h>
#endif
#ifdef PLATFORM_UNIX
#include "../x11getprocaddress.h"
#endif
class QGLSubWidget : public QGLWidget {
unsigned textureRes;
unsigned inWidth;
unsigned inHeight;
unsigned swapInterval;
bool initialized;
bool keepRatio;
bool integerScaling;
bool bf;
protected:
void initializeGL();
void paintGL();
void resizeGL(int w, int h);
public:
QGLSubWidget(unsigned swapInterval, bool bf, QWidget *parent = 0);
~QGLSubWidget();
void blit();
void blitFront();
unsigned getInWidth() const {
return inWidth;
}
unsigned getInHeight() const {
return inHeight;
}
unsigned getSwapInterval() const {
return swapInterval;
}
bool keepsRatio() {
return keepRatio;
}
bool scalesByInteger() {
return integerScaling;
}
void setBilinearFiltering(bool on);
void setBufferDimensions(unsigned w, unsigned h);
void setIntegerScaling(const bool on) {
integerScaling = on;
if (initialized) {
makeCurrent();
resizeGL(width(), height());
}
}
void setKeepRatio(const bool on) {
keepRatio = on;
if (initialized) {
makeCurrent();
resizeGL(width(), height());
}
}
void updateTexture(uint32_t *buffer);
void uninit();
};
static const QGLFormat getQGLFormat(const unsigned swapInterval) {
QGLFormat f;
#ifndef PLATFORM_UNIX
f.setSwapInterval(swapInterval);
#endif
return f;
}
QGLSubWidget::QGLSubWidget(const unsigned swapInterval_in, const bool bf_in, QWidget *parent) :
QGLWidget(getQGLFormat(swapInterval_in), parent),
inWidth(160),
inHeight(144),
swapInterval(swapInterval_in),
initialized(false),
keepRatio(true),
integerScaling(false),
bf(bf_in)
{
setAutoBufferSwap(false);
// setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
// QSettings settings;
// settings.beginGroup("qglsubwidget");
// bf = settings.value("bf", true).toBool();
// settings.endGroup();
}
QGLSubWidget::~QGLSubWidget() {
uninit();
// QSettings settings;
// settings.beginGroup("qglsubwidget");
// settings.setValue("bf", bf);
// settings.endGroup();
}
void QGLSubWidget::blit() {
glCallList(1);
glFlush();
}
void QGLSubWidget::initializeGL() {
// void *libHandle = dlopen("libgl.so", RTLD_LAZY);
// glXGetVideoSyncSGI_ptr = (glXGetVideoSyncSGI_Func) dlsym(libHandle, "glXGetVideoSyncSGI");
// glXWaitVideoSyncSGI_ptr = (glXWaitVideoSyncSGI_Func) dlsym(libHandle, "glXWaitVideoSyncSGI");
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, bf ? GL_LINEAR : GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, bf ? GL_LINEAR : GL_NEAREST);
glShadeModel(GL_FLAT);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glEnable(GL_TEXTURE_2D);
glDisable(GL_DITHER);
glClearColor(0.0, 0.0, 0.0, 0.0);
glNewList(1, GL_COMPILE);
glBegin(GL_QUADS);
glTexCoord2f(0.0, -0.2); glVertex2f(0.0, -0.2);
glTexCoord2f(0.0, 1.0); glVertex2f(0.0, 1.0);
glTexCoord2f(1.2, 1.0); glVertex2f(1.2, 1.0);
glTexCoord2f(1.2, -0.2); glVertex2f(1.2, -0.2);
glEnd();
glEndList();
#ifdef PLATFORM_UNIX
if (swapInterval) {
static void (*const glXSwapIntervalSGI)(int) = reinterpret_cast<void (*)(int)>(x11GetProcAddress("glXSwapIntervalSGI"));
if (glXSwapIntervalSGI) {
glXSwapIntervalSGI(swapInterval);
} else
swapInterval = 0;
}
#endif
initialized = true;
}
void QGLSubWidget::blitFront() {
GLint drawBuffer;
glGetIntegerv(GL_DRAW_BUFFER, &drawBuffer);
glDrawBuffer(GL_FRONT);
blit();
glDrawBuffer(drawBuffer);
}
void QGLSubWidget::paintGL() {
if (swapInterval)
blitFront();
else {
blit();
swapBuffers();
}
}
void QGLSubWidget::resizeGL(const int w, const int h) {
if (keepRatio) {
{
GLint drawBuffer;
glGetIntegerv(GL_DRAW_BUFFER, &drawBuffer);
glDrawBuffer(GL_FRONT_AND_BACK);
glClear(GL_COLOR_BUFFER_BIT);
glDrawBuffer(drawBuffer);
}
if (integerScaling) {
const unsigned int scale_factor = std::min(w / inWidth, h / inHeight);
const int new_w = inWidth * scale_factor;
const int new_h = inHeight * scale_factor;
glViewport(w - new_w >> 1, h - new_h >> 1, new_w, new_h);
} else {
if (w * 9 > h * 10) {
const int new_w = (h * 20 + 9) / 18;
glViewport(w - new_w >> 1, 0, new_w, h);
} else {
const int new_h = (w * 9 + 5) / 10;
glViewport(0, h - new_h >> 1, w, new_h);
}
}
} else {
glViewport(0, 0, w, h);
}
}
void QGLSubWidget::setBilinearFiltering(const bool on) {
const bool oldbf = bf;
bf = on;
if (bf != oldbf && initialized) {
makeCurrent();
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, bf ? GL_LINEAR : GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, bf ? GL_LINEAR : GL_NEAREST);
}
}
void QGLSubWidget::setBufferDimensions(const unsigned int width, const unsigned int height) {
inWidth = width;
inHeight = height;
textureRes = std::max(width, height);
//Next power of 2
--textureRes;
textureRes |= textureRes >> 1;
textureRes |= textureRes >> 2;
textureRes |= textureRes >> 4;
textureRes |= textureRes >> 8;
textureRes |= textureRes >> 16;
++textureRes;
if (!initialized)
glInit();
else
makeCurrent();
glLoadIdentity();
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, textureRes, textureRes, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 0);
double dres = textureRes;
glOrtho(0, width / dres, 1, 1.0 - height / dres, -1, 1);
}
void QGLSubWidget::uninit() {
initialized = false;
}
void QGLSubWidget::updateTexture(uint32_t *const buffer) {
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, textureRes - inHeight, inWidth, inHeight, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, buffer);
}
QGLBlitter::QGLBlitter(QWidget *parent) :
BlitterWidget(QString("OpenGL"), false, true, parent),
confWidget(new QWidget),
vsyncBox(new QCheckBox(QString("Sync to vertical blank in 60, 119 and 120 Hz modes"))),
bfBox(new QCheckBox(QString("Bilinear filtering"))),
buffer(NULL),
hz(0)
{
// setLayout(new QVBoxLayout);
// layout()->setMargin(0);
// layout()->setSpacing(0);
// layout()->addWidget(subWidget);
QSettings settings;
settings.beginGroup("qglblitter");
vsync = settings.value("vsync", false).toBool();
bf = settings.value("bf", true).toBool();
settings.endGroup();
confWidget->setLayout(new QVBoxLayout);
confWidget->layout()->setMargin(0);
confWidget->layout()->addWidget(vsyncBox);
confWidget->layout()->addWidget(bfBox);
vsyncBox->setChecked(vsync);
bfBox->setChecked(bf);
subWidget = new QGLSubWidget(0, bf, this);
}
QGLBlitter::~QGLBlitter() {
uninit();
// delete subWidget;
delete confWidget;
QSettings settings;
settings.beginGroup("qglblitter");
settings.setValue("vsync", vsync);
settings.setValue("bf", bf);
settings.endGroup();
}
void QGLBlitter::resizeEvent(QResizeEvent *const event) {
subWidget->setGeometry(0, 0, event->size().width(), event->size().height());
}
void QGLBlitter::uninit() {
subWidget->uninit();
delete[] buffer;
buffer = NULL;
}
bool QGLBlitter::isUnusable() {
return !subWidget->isValid();
}
void QGLBlitter::keepAspectRatio(const bool enable) {
subWidget->setKeepRatio(enable);
}
bool QGLBlitter::keepsAspectRatio() {
return subWidget->keepsRatio();
}
void QGLBlitter::scaleByInteger(const bool enable) {
subWidget->setIntegerScaling(enable);
}
bool QGLBlitter::scalesByInteger() {
return subWidget->scalesByInteger();
}
void QGLBlitter::setBufferDimensions(const unsigned int width, const unsigned int height) {
delete []buffer;
buffer = new uint32_t[width * height];
subWidget->setBufferDimensions(width, height);
}
const PixelBuffer QGLBlitter::inBuffer() {
PixelBuffer pixb;
pixb.format = PixelBuffer::RGB32;
pixb.pixels = buffer;
pixb.pitch = subWidget->getInWidth();
return pixb;
}
void QGLBlitter::blit() {
if (buffer) {
subWidget->makeCurrent();
subWidget->updateTexture(buffer);
}
}
const BlitterWidget::Rational QGLBlitter::frameTime() const {
if (subWidget->getSwapInterval()) {
Rational r = { subWidget->getSwapInterval(), hz };
return r;
}
return BlitterWidget::frameTime();
}
int QGLBlitter::sync(const bool turbo) {
subWidget->makeCurrent();
if (subWidget->getSwapInterval() && turbo)
subWidget->blitFront();
else {
subWidget->blit();
subWidget->swapBuffers();
}
if (subWidget->getSwapInterval())
return 0;
return BlitterWidget::sync(turbo);
}
void QGLBlitter::resetSubWidget() {
unsigned swapInterval = 0;
if (vsync) {
if (hz == 60)
swapInterval = 1;
else if (hz == 119 || hz == 120)
swapInterval = 2;
}
if (swapInterval == subWidget->getSwapInterval())
return;
const bool keepRatio = subWidget->keepsRatio();
const bool integerScaling = subWidget->scalesByInteger();
const unsigned w = subWidget->getInWidth();
const unsigned h = subWidget->getInHeight();
// subWidget->hide();
delete subWidget;
subWidget = new QGLSubWidget(swapInterval, bf, this);
subWidget->setKeepRatio(keepRatio);
subWidget->setIntegerScaling(integerScaling);
subWidget->setGeometry(0, 0, width(), height());
subWidget->show();
if (buffer)
subWidget->setBufferDimensions(w, h);
}
void QGLBlitter::acceptSettings() {
bf = bfBox->isChecked();
subWidget->setBilinearFiltering(bf);
vsync = vsyncBox->isChecked();
resetSubWidget();
}
void QGLBlitter::rejectSettings() {
vsyncBox->setChecked(vsync);
bfBox->setChecked(bf);
}
void QGLBlitter::rateChange(const int hz) {
this->hz = hz;
resetSubWidget();
}

View File

@ -0,0 +1,68 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef QGLBLITTER_H
#define QGLBLITTER_H
#include "../blitterwidget.h"
class QGLSubWidget;
class QCheckBox;
class QGLBlitter : public BlitterWidget {
QGLSubWidget *subWidget;
QWidget *const confWidget;
QCheckBox *const vsyncBox;
QCheckBox *const bfBox;
uint32_t *buffer;
unsigned hz;
bool vsync;
bool bf;
void resetSubWidget();
protected:
void resizeEvent(QResizeEvent *event);
public:
QGLBlitter(QWidget *parent = 0);
~QGLBlitter();
// void init();
void uninit();
bool isUnusable();
void keepAspectRatio(bool enable);
bool keepsAspectRatio();
void scaleByInteger(bool enable);
bool scalesByInteger();
void setBufferDimensions(unsigned int width, unsigned int height);
const PixelBuffer inBuffer();
void blit();
const Rational frameTime() const;
int sync(bool turbo);
QWidget* settingsWidget() { return confWidget; }
// // public slots:
void acceptSettings();
void rejectSettings();
public slots:
void rateChange(int hz);
};
#endif

View File

@ -0,0 +1,117 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "qpainterblitter.h"
#include "../scalebuffer.h"
#include "../videobufferreseter.h"
#include <QPainter>
#include <QImage>
#include <QPaintEvent>
QPainterBlitter::QPainterBlitter(VideoBufferReseter &resetVideoBuffer_in, QWidget *parent) :
BlitterWidget("QPainter", true, parent),
resetVideoBuffer(resetVideoBuffer_in),
image(NULL),
buffer(NULL),
inWidth(160),
inHeight(144),
scale(0)
{
setAttribute(Qt::WA_OpaquePaintEvent, true);
}
QPainterBlitter::~QPainterBlitter() {
uninit();
}
void QPainterBlitter::blit() {
repaint();
}
const PixelBuffer QPainterBlitter::inBuffer() {
PixelBuffer pixb;
pixb.format = PixelBuffer::RGB32;
pixb.pixels = image->bits();
pixb.pitch = image->bytesPerLine() >> 2;
if (buffer) {
pixb.pixels = buffer;
pixb.pitch = inWidth;
}
return pixb;
}
void QPainterBlitter::paintEvent(QPaintEvent *const event) {
if (buffer) {
scaleBuffer(buffer, reinterpret_cast<uint32_t*>(image->bits()), inWidth, inHeight, scale);
}
QPainter painter(this);
painter.setClipRegion(event->region());
painter.drawImage(rect(), *image);
}
void QPainterBlitter::resizeEvent(QResizeEvent */*event*/) {
const unsigned newScale = std::min(width() / inWidth, height() / inHeight);
if (newScale != scale) {
scale = newScale;
if (image) {
setBufferDimensions(inWidth, inHeight);
resetVideoBuffer();
}
}
}
void QPainterBlitter::setBufferDimensions(const unsigned int w, const unsigned int h) {
inWidth = w;
inHeight = h;
scale = std::min(width() / w, height() / h);
uninit();
if (scale > 1)
buffer = new uint32_t[w * h];
image = new QImage(w * scale, h * scale, QImage::Format_RGB32);
}
void QPainterBlitter::uninit() {
delete image;
image = NULL;
delete[] buffer;
buffer = NULL;
}
void QPainterBlitter::keepAspectRatio(const bool /*enable*/) {}
bool QPainterBlitter::keepsAspectRatio() {
return true;
}
void QPainterBlitter::scaleByInteger(const bool /*enable*/) {}
bool QPainterBlitter::scalesByInteger() {
return true;
}

View File

@ -0,0 +1,52 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef QPAINTERBLITTER_H
#define QPAINTERBLITTER_H
#include "../blitterwidget.h"
class QPainter;
class QImage;
class VideoBufferReseter;
class QPainterBlitter : public BlitterWidget {
VideoBufferReseter &resetVideoBuffer;
QImage *image;
uint32_t *buffer;
unsigned int inWidth, inHeight;
unsigned int scale;
protected:
void paintEvent(QPaintEvent *event);
void resizeEvent(QResizeEvent *event);
public:
QPainterBlitter(VideoBufferReseter &resetVideoBuffer_in, QWidget *parent = 0);
~QPainterBlitter();
void blit();
const PixelBuffer inBuffer();
void keepAspectRatio(bool enable);
bool keepsAspectRatio();
void scaleByInteger(bool enable);
bool scalesByInteger();
void setBufferDimensions(unsigned int w, unsigned int h);
void uninit();
};
#endif

View File

@ -0,0 +1,301 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include <QPaintEvent>
#include "x11blitter.h"
#include "../scalebuffer.h"
#include "../videobufferreseter.h"
#include <QX11Info>
#include <X11/Xlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <X11/extensions/XShm.h>
#include <sys/types.h>
#include <videoblitter.h>
#include <iostream>
class X11SubBlitter {
public:
virtual void blit(Drawable drawable, unsigned x, unsigned y, unsigned w, unsigned h) = 0;
virtual bool failed() = 0;
virtual const PixelBuffer inBuffer() = 0;
virtual ~X11SubBlitter() {};
};
class X11ShmBlitter : public X11SubBlitter {
XShmSegmentInfo shminfo;
XImage *ximage;
public:
X11ShmBlitter(unsigned int width, unsigned int height);
void blit(Drawable drawable, unsigned x, unsigned y, unsigned w, unsigned h);
bool failed();
const PixelBuffer inBuffer();
~X11ShmBlitter();
};
X11ShmBlitter::X11ShmBlitter(const unsigned int width, const unsigned int height) {
shminfo.shmaddr = NULL;
std::cout << "creating shm ximage...\n";
ximage = XShmCreateImage(QX11Info::display(), reinterpret_cast<Visual*>(QX11Info::appVisual()), QX11Info::appDepth(), ZPixmap, NULL, &shminfo, width, height);
if (ximage == NULL) {
std::cout << "failed to create shm ximage\n";
} else {
shminfo.shmid = shmget(IPC_PRIVATE, ximage->bytes_per_line * ximage->height, IPC_CREAT | 0777);
shminfo.shmaddr = ximage->data = static_cast<char*>(shmat(shminfo.shmid, 0, 0));
shminfo.readOnly = True;
XShmAttach(QX11Info::display(), &shminfo);
XSync(QX11Info::display(), 0);
}
}
X11ShmBlitter::~X11ShmBlitter() {
if (shminfo.shmaddr != NULL) {
XShmDetach(QX11Info::display(), &shminfo);
XSync(QX11Info::display(), 0);
shmdt(shminfo.shmaddr);
shmctl(shminfo.shmid, IPC_RMID, 0);
}
if (ximage != NULL)
XFree(ximage);
}
void X11ShmBlitter::blit(const Drawable drawable, const unsigned x, const unsigned y, const unsigned w, const unsigned h) {
if (ximage && shminfo.shmaddr) {
XShmPutImage(QX11Info::display(), drawable, DefaultGC(QX11Info::display(), QX11Info::appScreen()), ximage, x, y, x, y, w, h, False);
}
}
bool X11ShmBlitter::failed() {
return ximage == NULL || shminfo.shmaddr == NULL;
}
const PixelBuffer X11ShmBlitter::inBuffer() {
PixelBuffer pixb;
pixb.format = QX11Info::appDepth() == 16 ? PixelBuffer::RGB16 : PixelBuffer::RGB32;
pixb.pixels = ximage ? ximage->data : NULL;
pixb.pitch = ximage ? ximage->width : 0;
return pixb;
}
class X11PlainBlitter : public X11SubBlitter {
XImage *ximage;
public:
X11PlainBlitter (unsigned int width, unsigned int height);
void blit(Drawable drawable, unsigned x, unsigned y, unsigned w, unsigned h);
bool failed();
const PixelBuffer inBuffer();
~X11PlainBlitter ();
};
X11PlainBlitter::X11PlainBlitter(const unsigned int width, const unsigned int height) {
std::cout << "creating ximage...\n";
ximage = XCreateImage(QX11Info::display(), reinterpret_cast<Visual*>(QX11Info::appVisual()), QX11Info::appDepth(), ZPixmap, 0, NULL, width, height, QX11Info::appDepth(), 0);
if (ximage == NULL) {
std::cout << "failed to create ximage\n";
} else {
ximage->data = new char[ximage->bytes_per_line * ximage->height];
}
}
X11PlainBlitter::~X11PlainBlitter () {
if (ximage) {
delete[] ximage->data;
XFree(ximage);
}
}
void X11PlainBlitter::blit(const Drawable drawable, const unsigned x, const unsigned y, const unsigned w, const unsigned h) {
if (ximage) {
XPutImage(QX11Info::display(), drawable, DefaultGC(QX11Info::display(), QX11Info::appScreen()), ximage, x, y, x, y, w, h);
}
}
bool X11PlainBlitter::failed() {
return ximage == NULL;
}
const PixelBuffer X11PlainBlitter::inBuffer() {
PixelBuffer pixb;
pixb.format = QX11Info::appDepth() == 16 ? PixelBuffer::RGB16 : PixelBuffer::RGB32;
pixb.pixels = ximage ? ximage->data : NULL;
pixb.pitch = ximage ? ximage->width : 0;
return pixb;
}
X11Blitter::X11Blitter(VideoBufferReseter &resetVideoBuffer_in, QWidget *parent) :
BlitterWidget(QString("X11"), true, parent),
resetVideoBuffer(resetVideoBuffer_in),
subBlitter(NULL),
buffer(NULL),
inWidth(160),
inHeight(144),
scale(0)
{
/*QPalette pal = palette();
pal.setColor(QPalette::Window, QColor(0,0,0));
setPalette(pal);
setBackgroundRole(QPalette::Window);
setAutoFillBackground(true);*/
setAttribute(Qt::WA_OpaquePaintEvent, true);
setAttribute(Qt::WA_PaintOnScreen, true);
}
bool X11Blitter::isUnusable() {
return !(QX11Info::appDepth() == 16 || QX11Info::appDepth() == 24 || QX11Info::appDepth() == 32);
}
void X11Blitter::init() {
XSync(QX11Info::display(), 0);
shm = XShmQueryExtension(QX11Info::display());
// shm = false;
std::cout << "shm: " << shm << std::endl;
}
void X11Blitter::uninit() {
delete subBlitter;
subBlitter = NULL;
delete[] buffer;
buffer = NULL;
}
X11Blitter::~X11Blitter() {
uninit();
}
int X11Blitter::sync(const bool turbo) {
if (subBlitter->failed())
return -1;
return BlitterWidget::sync(turbo);
}
void X11Blitter::keepAspectRatio(const bool /*enable*/) {
// keepRatio = enable;
}
bool X11Blitter::keepsAspectRatio() {
return true;
}
void X11Blitter::scaleByInteger(const bool /*enable*/) {
// integerScaling = enable;
}
bool X11Blitter::scalesByInteger() {
return true;
}
/*
void X11Blitter::paintEvent(QPaintEvent *event) {
if(event)
event->accept();
if(xvimage) {
XvShmPutImage(QX11Info::display(), xvport, winId(), DefaultGC(QX11Info::display(), QX11Info::appScreen()), xvimage, 0, 0, inWidth*2, inHeight, 0, 0, width(), height(), False);
XSync(QX11Info::display(),0);
}
}
*/
void X11Blitter::paintEvent(QPaintEvent *event) {
if (subBlitter) {
event->accept();
const QRect &rect = event->rect();
subBlitter->blit(winId(), rect.x(), rect.y(), rect.width(), rect.height());
}
}
void X11Blitter::setBufferDimensions(const unsigned int w, const unsigned int h) {
inWidth = w;
inHeight = h;
scale = std::min(width() / w, height() / h);
uninit();
if (scale > 1)
buffer = new char[w * h * (QX11Info::appDepth() == 16 ? 2 : 4)];
if (shm) {
subBlitter = new X11ShmBlitter(w * scale, h * scale);
if (subBlitter->failed()) {
shm = false;
delete subBlitter;
}
}
if (!shm)
subBlitter = new X11PlainBlitter (w * scale, h * scale);
}
const PixelBuffer X11Blitter::inBuffer() {
if (buffer) {
PixelBuffer pixb;
pixb.format = QX11Info::appDepth() == 16 ? PixelBuffer::RGB16 : PixelBuffer::RGB32;
pixb.pixels = buffer;
pixb.pitch = inWidth;
return pixb;
}
return subBlitter->inBuffer();
}
void X11Blitter::blit() {
if (buffer) {
const PixelBuffer &pb = subBlitter->inBuffer();
if (QX11Info::appDepth() == 16) {
scaleBuffer(reinterpret_cast<uint16_t*>(buffer), reinterpret_cast<uint16_t*>(pb.pixels), inWidth, inHeight, scale);
} else {
scaleBuffer(reinterpret_cast<uint32_t*>(buffer), reinterpret_cast<uint32_t*>(pb.pixels), inWidth, inHeight, scale);
}
}
subBlitter->blit(winId(), 0, 0, width(), height());
XSync(QX11Info::display(), 0);
}
void X11Blitter::resizeEvent(QResizeEvent */*event*/) {
const unsigned newScale = std::min(width() / inWidth, height() / inHeight);
if (newScale != scale) {
scale = newScale;
if (subBlitter) {
setBufferDimensions(inWidth, inHeight);
resetVideoBuffer();
}
}
}

View File

@ -0,0 +1,62 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef X11BLITTER_H
#define X11BLITTER_H
#include "../blitterwidget.h"
#include <sys/types.h>
class X11SubBlitter;
class VideoBufferReseter;
class X11Blitter : public BlitterWidget {
VideoBufferReseter &resetVideoBuffer;
X11SubBlitter *subBlitter;
char *buffer;
unsigned int inWidth, inHeight;
unsigned int scale;
// bool init;
// bool keepRatio;
// bool integerScaling;
bool shm;
// bool failed;
protected:
void paintEvent(QPaintEvent *event);
void resizeEvent(QResizeEvent *event);
public:
X11Blitter(VideoBufferReseter &resetVideoBuffer_in, QWidget *parent = 0);
~X11Blitter();
void init();
void uninit();
// void init(const unsigned int srcW, const unsigned int srcH);
bool isUnusable();
void keepAspectRatio(const bool enable);
bool keepsAspectRatio();
void scaleByInteger(const bool enable);
bool scalesByInteger();
int sync(bool turbo);
void setBufferDimensions(const unsigned int width, const unsigned int height);
const PixelBuffer inBuffer();
void blit();
};
#endif

View File

@ -0,0 +1,469 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include <QHBoxLayout>
#include <QLabel>
#include <QSettings>
#include <QPaintEvent>
#include "xvblitter.h"
#include <iostream>
#include <QX11Info>
#include <X11/Xlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <X11/extensions/XShm.h>
#include <X11/extensions/Xvlib.h>
class XvSubBlitter {
public:
virtual void blit(Drawable drawable, XvPortID xvport, unsigned width, unsigned height) = 0;
virtual bool failed() = 0;
virtual const PixelBuffer inBuffer() = 0;
virtual ~XvSubBlitter() {};
};
class XvShmBlitter : public XvSubBlitter {
XShmSegmentInfo shminfo;
XvImage *xvimage;
public:
XvShmBlitter(XvPortID xvport, unsigned int width, unsigned int height);
void blit(Drawable drawable, XvPortID xvport, unsigned width, unsigned height);
bool failed();
const PixelBuffer inBuffer();
~XvShmBlitter();
};
XvShmBlitter::XvShmBlitter(const XvPortID xvport, const unsigned int width, const unsigned int height) {
std::cout << "creating xvimage...\n";
xvimage = XvShmCreateImage(QX11Info::display(), xvport, 0x59565955, NULL, width * 2, height, &shminfo);
if (xvimage == NULL) {
std::cout << "failed to create xvimage\n";
} else {
shminfo.shmid = shmget(IPC_PRIVATE, xvimage->data_size, IPC_CREAT | 0777);
shminfo.shmaddr = xvimage->data = static_cast<char*>(shmat(shminfo.shmid, 0, 0));
shminfo.readOnly = True;
XShmAttach(QX11Info::display(), &shminfo);
XSync(QX11Info::display(), 0);
}
}
XvShmBlitter::~XvShmBlitter() {
if (shminfo.shmaddr != NULL) {
XShmDetach(QX11Info::display(), &shminfo);
XSync(QX11Info::display(), 0);
shmdt(shminfo.shmaddr);
shmctl(shminfo.shmid, IPC_RMID, 0);
}
if (xvimage != NULL)
XFree(xvimage);
}
void XvShmBlitter::blit(const Drawable drawable, const XvPortID xvport, const unsigned width, const unsigned height) {
if (xvimage && shminfo.shmaddr) {
if (XvShmPutImage(QX11Info::display(), xvport, drawable, DefaultGC(QX11Info::display(), QX11Info::appScreen()), xvimage, 0, 0, xvimage->width, xvimage->height, 0, 0, width, height, False) != Success) {
std::cout << "failed to put xvimage\n";
// failed = true;
}
}
}
bool XvShmBlitter::failed() {
return xvimage == NULL || shminfo.shmaddr == NULL;
}
const PixelBuffer XvShmBlitter::inBuffer() {
PixelBuffer pixb;
pixb.format = PixelBuffer::UYVY;
pixb.pixels = xvimage ? xvimage->data + xvimage->offsets[0] : NULL;
pixb.pitch = xvimage ? xvimage->pitches[0] >> 2 : 0;
return pixb;
}
class XvPlainBlitter : public XvSubBlitter {
XvImage *xvimage;
public:
XvPlainBlitter(XvPortID xvport, unsigned int width, unsigned int height);
void blit(Drawable drawable, XvPortID xvport, unsigned width, unsigned height);
bool failed();
const PixelBuffer inBuffer();
~XvPlainBlitter();
};
XvPlainBlitter::XvPlainBlitter(const XvPortID xvport, const unsigned int width, const unsigned int height) {
std::cout << "creating xvimage...\n";
xvimage = XvCreateImage(QX11Info::display(), xvport, 0x59565955, NULL, width * 2, height);
if (xvimage == NULL) {
std::cout << "failed to create xvimage\n";
} else {
xvimage->data = new char[xvimage->data_size];
}
}
XvPlainBlitter::~XvPlainBlitter() {
if (xvimage) {
if (xvimage->data)
delete[] xvimage->data;
XFree(xvimage);
}
}
void XvPlainBlitter::blit(const Drawable drawable, const XvPortID xvport, const unsigned width, const unsigned height) {
if (xvimage) {
if (XvPutImage(QX11Info::display(), xvport, drawable, DefaultGC(QX11Info::display(), QX11Info::appScreen()), xvimage, 0, 0, xvimage->width, xvimage->height, 0, 0, width, height) != Success) {
std::cout << "failed to put xvimage\n";
// failed = true;
}
}
}
bool XvPlainBlitter::failed() {
return xvimage == NULL;
}
const PixelBuffer XvPlainBlitter::inBuffer() {
PixelBuffer pixb;
pixb.format = PixelBuffer::UYVY;
pixb.pixels = xvimage ? xvimage->data + xvimage->offsets[0] : NULL;
pixb.pitch = xvimage ? xvimage->pitches[0] >> 2 : 0;
return pixb;
}
static void addPorts(QComboBox *portSelector) {
unsigned int num_adaptors;
XvAdaptorInfo *adaptor_info;
if (XvQueryAdaptors(QX11Info::display(), QX11Info::appRootWindow(), &num_adaptors, &adaptor_info) == Success) {
for (unsigned int i = 0; i < num_adaptors; ++i) {
if (!(adaptor_info[i].type & XvImageMask))
continue;
int numImages;
XvImageFormatValues *const formats = XvListImageFormats(QX11Info::display(), adaptor_info[i].base_id, &numImages);
for (int j = 0; j < numImages; ++j) {
if (formats[j].id == 0x59565955) {
portSelector->addItem(adaptor_info[i].name, static_cast<qulonglong>(adaptor_info[i].base_id));
break;
}
}
XFree(formats);
}
XvFreeAdaptorInfo(adaptor_info);
} else {
std::cout << "failed to query xv adaptors\n";
}
}
XvBlitter::XvBlitter(QWidget *parent) :
BlitterWidget(QString("Xv"), parent),
subBlitter(NULL),
// xvbuffer(NULL),
// yuv_table(NULL),
// xvimage(NULL),
inWidth(160),
inHeight(144),
old_w(0),
old_h(0),
keepRatio(true),
integerScaling(false),
portGrabbed(false),
failed(true),
initialized(false)
{
/*QPalette pal = palette();
pal.setColor(QPalette::Window, QColor(2110));
setPalette(pal);
setBackgroundRole(QPalette::Window);
setAutoFillBackground(true);*/
setAttribute(Qt::WA_OpaquePaintEvent, true);
setAttribute(Qt::WA_PaintOnScreen, true);
{
XGCValues gcValues;
gcValues.foreground = gcValues.background = 2110;
gc = XCreateGC(QX11Info::display(), QX11Info::appRootWindow(), GCForeground | GCBackground, &gcValues);
}
confWidget = new QWidget();
QHBoxLayout *layout = new QHBoxLayout;
layout->setMargin(0);
layout->addWidget(new QLabel(QString(tr("Xv Port:"))));
portSelector = new QComboBox;
addPorts(portSelector);
layout->addWidget(portSelector);
confWidget->setLayout(layout);
QSettings settings;
settings.beginGroup("xvblitter");
if ((portIndex = settings.value("portIndex", 0).toUInt()) >= static_cast<unsigned>(portSelector->count()))
portIndex = 0;
settings.endGroup();
rejectSettings();
}
bool XvBlitter::isUnusable() {
return portSelector->count() == 0;
}
/*static bool getBestPort(const unsigned int num_adaptors, const XvAdaptorInfo *const adaptor_info, XvPortID *const port_out) {
for (unsigned int i = 0; i < num_adaptors; ++i) {
if (!(adaptor_info[i].type & XvImageMask))
continue;
int numImages;
XvImageFormatValues *const formats = XvListImageFormats(QX11Info::display(), adaptor_info[i].base_id, &numImages);
for (int j = 0; j < numImages; ++j) {
if (formats[j].id == 0x59565955 &&
XvGrabPort(QX11Info::display(), adaptor_info[i].base_id, CurrentTime) == Success) {
*port_out = adaptor_info[i].base_id;
XFree(formats);
return false;
}
}
XFree(formats);
}
return true;
}*/
void XvBlitter::init() {
/*if (yuv_table == NULL) {
yuv_table = new u_int32_t[0x10000];
u_int32_t r, g, b, y, u, v;
for (u_int32_t i = 0;i < 0x10000;++i) {
r = (i & 0xF800) >> 8;
g = (i & 0x07E0) >> 3;
b = (i & 0x001F) << 3;
y = (r * 299 * 219 + g * 587 * 219 + b * 114 * 219 + (255 * 1000) / 2) / (255 * 1000) + 16;
u = (b * 886 * 112 - r * 299 * 112 - g * 587 * 112 + (886 * 255) / 2 + 128 * 886 * 255) / (886 * 255);
v = (r * 701 * 112 - b * 114 * 112 - g * 587 * 112 + (701 * 255) / 2 + 128 * 701 * 255) / (701 * 255);
yuv_table[i] = (y << 24) | (v << 16) | (y << 8) | u;
}
}*/
XSync(QX11Info::display(), 0);
shm = XShmQueryExtension(QX11Info::display());
std::cout << "shm: " << shm << std::endl;
initPort();
initialized = true;
}
void XvBlitter::uninit() {
// delete []xvbuffer;
// xvbuffer = NULL;
// delete []yuv_table;
// yuv_table = NULL;
if (subBlitter) {
delete subBlitter;
subBlitter = NULL;
}
if (portGrabbed) {
XvUngrabPort(QX11Info::display(), xvport, CurrentTime);
portGrabbed = false;
}
failed = true;
initialized = false;
}
XvBlitter::~XvBlitter() {
uninit();
XFreeGC(QX11Info::display(), gc);
delete confWidget;
QSettings settings;
settings.beginGroup("xvblitter");
settings.setValue("portIndex", portIndex);
settings.endGroup();
}
int XvBlitter::sync(const bool turbo) {
if (failed || subBlitter->failed())
return -1;
return BlitterWidget::sync(turbo);
}
void XvBlitter::keepAspectRatio(const bool enable) {
keepRatio = enable;
}
bool XvBlitter::keepsAspectRatio() {
return keepRatio;
}
void XvBlitter::scaleByInteger(const bool enable) {
integerScaling = enable;
}
bool XvBlitter::scalesByInteger() {
return integerScaling;
}
void XvBlitter::paintEvent(QPaintEvent *event) {
event->accept();
const QRect &rect = event->rect();
XFillRectangle(QX11Info::display(), winId(), gc, rect.x(), rect.y(), rect.width(), rect.height());
if (!failed)
subBlitter->blit(winId(), xvport, width(), height());
}
void XvBlitter::setBufferDimensions(const unsigned int width, const unsigned int height) {
inWidth = width;
inHeight = height;
if (subBlitter) {
delete subBlitter;
subBlitter = NULL;
}
if (shm) {
subBlitter = new XvShmBlitter(xvport, width, height);
if (subBlitter->failed()) {
shm = false;
delete subBlitter;
}
}
if (!shm)
subBlitter = new XvPlainBlitter(xvport, width, height);
// delete []xvbuffer;
// xvbuffer = new u_int16_t[width*height];
old_w = old_h = 0;
}
const PixelBuffer XvBlitter::inBuffer() {
/*PixelBuffer pixb;
pixb.format = PixelBuffer::RGB16;
pixb.pixels = xvbuffer;
pixb.pitch = inWidth;
return pixb;*/
return subBlitter->inBuffer();
}
void XvBlitter::blit() {
if (!failed) {
/*{
u_int32_t *yuv_pixel = (u_int32_t*)(subBlitter->inBuffer().pixels);
const u_int16_t *s = xvbuffer;
unsigned n = inWidth * inHeight;
while (n--) {
*yuv_pixel++ = yuv_table[*s++];
}
}*/
subBlitter->blit(winId(), xvport, width(), height());
XSync(QX11Info::display(), 0);
}
}
/*void XvBlitter::resizeEvent(QResizeEvent *event) {
// std::cout << "resizeEvent\n";
if (keepRatio) {
// static int old_w=0;
// static int old_h=0;
if (width() != old_w || height() != old_h) {
if (integerScaling) {
unsigned int scale = std::min((width() / inWidth), (height() / inHeight));
old_w = inWidth * scale;
old_h = inHeight * scale;
setGeometry(x() + (width() - old_w) / 2, y() + (height() - old_h) / 2, old_w, old_h);
} else {
if ((static_cast<double>(width()) / static_cast<double>(height())) > (10.0 / 9.0)) {
old_w = height() * 10.0 / 9.0 + 0.5;
old_h = height();
if (old_w < width())
setGeometry(x() + (width() - old_w) / 2, y(), old_w, old_h);
} else {
old_w = width();
old_h = old_w * 0.9 + 0.5;
if (old_h < height())
setGeometry(x(), y() + (height() - old_h) / 2, old_w, old_h);
}
}
}
}
}*/
void XvBlitter::initPort() {
xvport = portSelector->itemData(portIndex).toULongLong();
failed = !(portGrabbed = (XvGrabPort(QX11Info::display(), xvport, CurrentTime) == Success));
if (!failed) {
Atom atom = XInternAtom(QX11Info::display(), "XV_AUTOPAINT_COLORKEY", True);
if (atom != None)
XvSetPortAttribute(QX11Info::display(), xvport, atom, 0);
atom = XInternAtom(QX11Info::display(), "XV_COLORKEY", True);
if (atom != None)
XvSetPortAttribute(QX11Info::display(), xvport, atom, 2110);
}
}
void XvBlitter::acceptSettings() {
portIndex = portSelector->currentIndex();
if (initialized) {
if (portGrabbed) {
XvUngrabPort(QX11Info::display(), xvport, CurrentTime);
portGrabbed = false;
}
initPort();
setBufferDimensions(inWidth, inHeight);
}
}
void XvBlitter::rejectSettings() {
portSelector->setCurrentIndex(portIndex);
}

View File

@ -0,0 +1,82 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef XVBLITTER_H
#define XVBLITTER_H
#include <QComboBox>
#include "../blitterwidget.h"
#include <X11/Xlib.h>
#include <X11/extensions/XShm.h>
#include <X11/extensions/Xvlib.h>
#include <sys/types.h>
class XvSubBlitter;
class XvBlitter : public BlitterWidget {
// XShmSegmentInfo shminfo;
XvSubBlitter *subBlitter;
XvPortID xvport;
// u_int16_t *xvbuffer;
// u_int32_t *yuv_table;
// XvImage *xvimage;
QWidget *confWidget;
QComboBox *portSelector;
unsigned int inWidth, inHeight;
int old_w, old_h;
unsigned portIndex;
GC gc;
// bool init;
bool keepRatio;
bool integerScaling;
bool shm;
bool portGrabbed;
bool failed;
bool initialized;
void initPort();
protected:
void paintEvent(QPaintEvent *event);
// void resizeEvent(QResizeEvent *event);
public:
XvBlitter(QWidget *parent = 0);
~XvBlitter();
void init();
void uninit();
// void init(const unsigned int srcW, const unsigned int srcH);
bool isUnusable();
void keepAspectRatio(const bool enable);
bool keepsAspectRatio();
void scaleByInteger(const bool enable);
bool scalesByInteger();
int sync(bool turbo);
void setBufferDimensions(const unsigned int width, const unsigned int height);
const PixelBuffer inBuffer();
void blit();
QWidget* settingsWidget() { return confWidget; }
void acceptSettings();
void rejectSettings();
};
#endif

View File

@ -0,0 +1,45 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef FULLRESTOGGLER_H
#define FULLRESTOGGLER_H
#include <QObject>
#include <vector>
#include "resinfo.h"
class FullResToggler : public QObject {
Q_OBJECT
public:
virtual ~FullResToggler() {};
virtual unsigned currentResIndex() const = 0;
virtual unsigned currentRateIndex() const = 0;
virtual bool isFullRes() const = 0;
virtual void setMode(unsigned newID, unsigned rate) = 0;
virtual void setFullRes(bool enable) = 0;
virtual void emitRate() = 0;
virtual const std::vector<ResInfo>& resVector() const = 0;
signals:
void rateChange(int newHz);
// void modeChange();
};
#endif

View File

@ -0,0 +1,124 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "gditoggler.h"
#include <windows.h>
GdiToggler::GdiToggler() :
isFull(false)
{
DEVMODE devmode;
devmode.dmSize = sizeof(DEVMODE);
devmode.dmDriverExtra = 0;
EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &devmode);
const unsigned originalWidth = devmode.dmPelsWidth;
const unsigned originalHeight = devmode.dmPelsHeight;
const short originalRate = devmode.dmDisplayFrequency;
const unsigned bpp = devmode.dmBitsPerPel;
int n = 0;
while (EnumDisplaySettings(NULL, n++, &devmode)) {
if (devmode.dmBitsPerPel != bpp)
continue;
ResInfo info;
info.w = devmode.dmPelsWidth;
info.h = devmode.dmPelsHeight;
if (infoVector.empty() || infoVector.back().w != info.w || infoVector.back().h != info.h) {
infoVector.push_back(info);
}
infoVector.back().rates.push_back(devmode.dmDisplayFrequency);
}
{
unsigned i = 0;
while (infoVector[i].w != originalWidth || infoVector[i].h != originalHeight)
++i;
fullResIndex = originalResIndex = i;
}
{
unsigned i = 0;
while (infoVector[fullResIndex].rates[i] != originalRate)
++i;
fullRateIndex = originalRateIndex = i;
}
}
GdiToggler::~GdiToggler() {
setFullRes(false);
}
bool GdiToggler::isFullRes() const {
return isFull;
}
void GdiToggler::setMode(const unsigned resIndex, const unsigned rateIndex) {
fullResIndex = resIndex;
fullRateIndex = rateIndex;
if (isFullRes())
setFullRes(true);
}
void GdiToggler::setFullRes(const bool enable) {
DEVMODE devmode;
devmode.dmSize = sizeof(DEVMODE);
devmode.dmDriverExtra = 0;
EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &devmode);
const unsigned currentWidth = devmode.dmPelsWidth;
const unsigned currentHeight = devmode.dmPelsHeight;
const unsigned currentRate = devmode.dmDisplayFrequency;
{
const ResInfo &info = infoVector[enable ? fullResIndex : originalResIndex];
devmode.dmPelsWidth = info.w;
devmode.dmPelsHeight = info.h;
devmode.dmDisplayFrequency = info.rates[enable ? fullRateIndex : originalRateIndex];
}
if (devmode.dmPelsWidth != currentWidth || devmode.dmPelsHeight != currentHeight || devmode.dmDisplayFrequency != currentRate) {
devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY;
ChangeDisplaySettings(&devmode, CDS_FULLSCREEN);
//emit modeChange();
if (devmode.dmDisplayFrequency != currentRate)
emit rateChange(devmode.dmDisplayFrequency);
}
isFull = enable;
}
void GdiToggler::emitRate() {
DEVMODE devmode;
devmode.dmSize = sizeof(DEVMODE);
devmode.dmDriverExtra = 0;
EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &devmode);
emit rateChange(devmode.dmDisplayFrequency);
}

View File

@ -0,0 +1,56 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef GDITOGGLER_H_
#define GDITOGGLER_H_
#include "../fullrestoggler.h"
#include <QObject>
#include <vector>
#include "../resinfo.h"
class GdiToggler : public FullResToggler {
Q_OBJECT
std::vector<ResInfo> infoVector;
unsigned originalResIndex;
unsigned originalRateIndex;
unsigned fullResIndex;
unsigned fullRateIndex;
bool isFull;
public:
GdiToggler();
~GdiToggler();
unsigned currentResIndex() const { return fullResIndex; }
unsigned currentRateIndex() const { return fullRateIndex; }
bool isFullRes() const;
void setMode(unsigned resIndex, unsigned rateIndex);
void setFullRes(bool enable);
void emitRate();
const std::vector<ResInfo>& resVector() const { return infoVector; }
signals:
void rateChange(int newHz);
// void modeChange();
};
#endif /*GDITOGGLER_H_*/

View File

@ -0,0 +1,40 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef NULLTOGGLER_H
#define NULLTOGGLER_H
#include "../fullrestoggler.h"
class NullToggler : public FullResToggler {
const std::vector<ResInfo> nullVector;
bool fullRes;
public:
NullToggler() : fullRes(false) {}
unsigned currentResIndex() const { return 0; }
unsigned currentRateIndex() const { return 0; }
bool isFullRes() const { return fullRes; }
void setMode(unsigned /*newID*/, unsigned /*rate*/) {}
void setFullRes(const bool enable) { fullRes = enable; }
void emitRate() {}
const std::vector<ResInfo>& resVector() const { return nullVector; }
};
#endif

View File

@ -0,0 +1,120 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "xrandrtoggler.h"
#include <QX11Info>
bool XRandRToggler::isUsable() {
int unused;
return XQueryExtension(QX11Info::display(), "RANDR", &unused, &unused, &unused);
}
XRandRToggler::XRandRToggler() :
isFull(false)
{
XRRScreenConfiguration *config = XRRGetScreenInfo(QX11Info::display(), QX11Info::appRootWindow());
/*Rotation */rotation = 0;
fullResIndex = originalResIndex = XRRConfigCurrentConfiguration(config, &rotation);
const short rate = XRRConfigCurrentRate(config);
int nSizes;
XRRScreenSize *randrSizes = XRRConfigSizes(config, &nSizes);
for (int i = 0; i < nSizes; ++i) {
ResInfo info;
info.w = randrSizes[i].width;
info.h = randrSizes[i].height;
int nHz;
short *rates = XRRConfigRates(config, i, &nHz);
for (int j = 0; j < nHz; ++j)
info.rates.push_back(rates[j]);
infoVector.push_back(info);
}
{
unsigned i = 0;
while (infoVector[fullResIndex].rates[i] != rate)
++i;
fullRateIndex = originalRateIndex = i;
}
XRRFreeScreenConfigInfo(config);
}
XRandRToggler::~XRandRToggler() {
setFullRes(false);
// XRRFreeScreenConfigInfo(config);
}
bool XRandRToggler::isFullRes() const {
return isFull;
}
void XRandRToggler::setMode(const unsigned resIndex, const unsigned rateIndex) {
fullResIndex = resIndex;
fullRateIndex = rateIndex;
if (isFullRes())
setFullRes(true);
}
void XRandRToggler::setFullRes(const bool enable) {
XRRScreenConfiguration *config = XRRGetScreenInfo(QX11Info::display(), QX11Info::appRootWindow());
// Rotation rotation=0;
SizeID currentID = XRRConfigCurrentConfiguration(config, &rotation);
int currentRate = XRRConfigCurrentRate(config);
// std::cout << "current rate: " << currentRate << "\n";
SizeID newID;
int newRate;
if (enable) {
newID = fullResIndex;
newRate = infoVector[fullResIndex].rates[fullRateIndex];
} else {
newID = originalResIndex;
newRate = infoVector[originalResIndex].rates[originalRateIndex];
}
// std::cout << "new rate: " << newRate << "\n";
if (newID != currentID || newRate != currentRate) {
XRRSetScreenConfigAndRate(QX11Info::display(), config, QX11Info::appRootWindow(), newID, rotation, newRate, CurrentTime);
//emit modeChange();
if (newRate != currentRate)
emit rateChange(newRate);
}
XRRFreeScreenConfigInfo(config);
isFull = enable;
}
void XRandRToggler::emitRate() {
XRRScreenConfiguration *config = XRRGetScreenInfo(QX11Info::display(), QX11Info::appRootWindow());
emit rateChange(XRRConfigCurrentRate(config));
XRRFreeScreenConfigInfo(config);
}

View File

@ -0,0 +1,61 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef XRANDRTOGGLER_H
#define XRANDRTOGGLER_H
#include "../fullrestoggler.h"
#include <QObject>
#include <vector>
#include <X11/Xlib.h>
#include <X11/extensions/Xrandr.h>
#include "../resinfo.h"
class XRandRToggler : public FullResToggler {
Q_OBJECT
std::vector<ResInfo> infoVector;
// XRRScreenConfiguration *config;
unsigned originalResIndex;
unsigned fullResIndex;
Rotation rotation;
unsigned originalRateIndex;
unsigned fullRateIndex;
bool isFull;
public:
static bool isUsable();
XRandRToggler();
~XRandRToggler();
unsigned currentResIndex() const { return fullResIndex; }
unsigned currentRateIndex() const { return fullRateIndex; }
bool isFullRes() const;
void setMode(unsigned resIndex, unsigned rateIndex);
void setFullRes(bool enable);
void emitRate();
const std::vector<ResInfo>& resVector() const { return infoVector; }
signals:
void rateChange(int newHz);
// void modeChange();
};
#endif

View File

@ -0,0 +1,625 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include <iostream>
#include <QtGui>
#include <QVBoxLayout>
#include "gambatte_qt.h"
#include "blitterwidgets/qpainterblitter.h"
#include "blitterwidgets/qglblitter.h"
#include "videodialog.h"
#include "inputdialog.h"
#include "blittercontainer.h"
#include "addaudioengines.h"
#include "addblitterwidgets.h"
#include "getfullrestoggler.h"
#include "audioengine.h"
#include "fullrestoggler.h"
#ifdef PLATFORM_WIN32
#include <windows.h>
#endif
#include "resizesignalingmenubar.h"
GambatteQt::GambatteQt() : resetVideoBuffer(gambatte) {
blitter = NULL;
ae = NULL;
timerId = 0;
running = false;
turbo = false;
//samplesPrFrame = ((sampleFormat.rate * 4389) / 262144) + 1;
samplesPrFrame = 0;
sndBuffer = NULL;
setAttribute(Qt::WA_DeleteOnClose);
setFocusPolicy(Qt::StrongFocus);
{
ResizeSignalingMenuBar *m = new ResizeSignalingMenuBar;
connect(m, SIGNAL(resized()), this, SLOT(resetWindowSize()));
setMenuBar(m);
}
{
QSettings settings;
settings.beginGroup("mainwindow");
resize(settings.value("size", QSize(160, 144)).toSize());
settings.endGroup();
}
addAudioEngines(audioEngines, winId());
inputDialog = new InputDialog(this);
fullResToggler = getFullResToggler();
addBlitterWidgets(blitters, resetVideoBuffer);
blitters.push_back(new QGLBlitter);
blitters.push_back(new QPainterBlitter(resetVideoBuffer));
for (std::vector<BlitterWidget*>::iterator it = blitters.begin(); it != blitters.end();) {
if ((*it)->isUnusable()) {
delete *it;
it = blitters.erase(it);
} else
++it;
}
videoDialog = new VideoDialog(blitters, gambatte.filterInfo(), *fullResToggler, this);
connect(videoDialog, SIGNAL(accepted()), this, SLOT(videoSettingsChange()));
/*QPalette pal = palette();
pal.setColor(QPalette::AlternateBase, QColor(0, 0, 0));
setPalette(pal);
setBackgroundRole(QPalette::AlternateBase);
setAutoFillBackground(true);*/
blitterContainer = new BlitterContainer(*fullResToggler);
blitterContainer->setMinimumSize(160, 144);
setCentralWidget(blitterContainer);
createActions();
createMenus();
setWindowTitle("gambatte");
gambatte.setInputStateGetter(&inputGetter);
{
QSettings iniSettings(QSettings::IniFormat, QSettings::UserScope, "gambatte", "gambatte_qt");
QString savepath = iniSettings.fileName();
savepath.truncate(iniSettings.fileName().lastIndexOf("/") + 1);
savepath += "saves";
QDir::root().mkpath(savepath);
gambatte.set_savedir(savepath.toAscii().data());
}
videoSettingsChange();
setFocus();
}
GambatteQt::~GambatteQt() {
delete fullResToggler;
for (uint i = 0; i < blitters.size(); ++i)
delete blitters[i];
for (uint i = 0; i < audioEngines.size(); ++i)
delete audioEngines[i];
delete []sndBuffer;
}
void GambatteQt::open() {
pause();
QString fileName = QFileDialog::getOpenFileName(this, "Open", recentFileActs[0]->data().toString(), "Game Boy ROM Images (*.gb *.gbc *.sgb)");
if (!fileName.isEmpty())
loadFile(fileName);
unpause();
}
void GambatteQt::openRecentFile() {
QAction *action = qobject_cast<QAction *>(sender());
if (action)
loadFile(action->data().toString());
}
void GambatteQt::about() {
pause();
QMessageBox::about(
this,
tr("About gambatte"),
tr("gambatte is a Game Boy / Game Boy Color emulator.")
);
unpause();
}
void GambatteQt::resetWindowSize() {
if (isFullScreen())
return;
const QSize s(videoDialog->winRes());
if (s == QSize(-1, -1)) {
setMinimumSize(0, 0);
setMaximumSize(0xFFFFFF, 0xFFFFFF);
} else {
setFixedSize(s.width(), s.height() + (menuBar()->isVisible() ? menuBar()->height() : 0));
}
}
void GambatteQt::toggleFullScreen() {
if (fullResToggler->isFullRes()) {
fullResToggler->setFullRes(false);
showNormal();
resetWindowSize();
} else {
fullResToggler->setFullRes(true);
showFullScreen();
}
}
void GambatteQt::toggleMenuHidden() {
menuBar()->setVisible(!menuBar()->isVisible());
if (menuBar()->isVisible())
centralWidget()->unsetCursor();
else
centralWidget()->setCursor(Qt::BlankCursor);
resetWindowSize();
}
void GambatteQt::videoSettingsChange() {
{
const int engineIndex = videoDialog->engine();
if (blitter != blitters[engineIndex]) {
bool updatesEnabled = true;
bool visible = false;
if (blitter) {
updatesEnabled = blitter->updatesEnabled();
visible = blitter->isVisible();
disconnect(fullResToggler, SIGNAL(rateChange(int)), blitter, SLOT(rateChange(int)));
if (running)
blitter->uninit();
blitter->setVisible(false);
}
blitter = blitters[engineIndex];
blitter->setVisible(false);
blitter->setUpdatesEnabled(updatesEnabled);
//connect(fullResToggler, SIGNAL(modeChange()), blitter, SLOT(modeChange()));
connect(fullResToggler, SIGNAL(rateChange(int)), blitter, SLOT(rateChange(int)));
fullResToggler->emitRate();
blitterContainer->setBlitter(blitter);
blitter->setVisible(visible);
if (running) {
// XSync(QX11Info::display(), 0);
blitter->init();
gambatte.setVideoBlitter(blitter);
}
}
}
gambatte.setVideoFilter(videoDialog->filterIndex());
centralWidget()->setMinimumSize(gambatte.videoWidth(), gambatte.videoHeight());
resetWindowSize();
if (fullResToggler->currentResIndex() != videoDialog->fullMode() ||
fullResToggler->currentRateIndex() != videoDialog->fullRate()) {
fullResToggler->setMode(videoDialog->fullMode(), videoDialog->fullRate());
#ifdef PLATFORM_WIN32
if (fullResToggler->isFullRes()) {
showNormal();
showFullScreen();
}
#endif
}
setSamplesPrFrame();
blitter->keepAspectRatio(videoDialog->keepsRatio());
blitter->scaleByInteger(videoDialog->scalesByInteger());
blitterContainer->updateLayout();
}
void GambatteQt::createActions() {
exitAct = new QAction(tr("E&xit"), this);
exitAct->setShortcut(tr("Ctrl+Q"));
exitAct->setStatusTip(tr("Exit the application"));
connect(exitAct, SIGNAL(triggered()), qApp, SLOT(closeAllWindows()));
hideMenuAct = new QAction(this);
hideMenuAct->setVisible(false);
hideMenuAct->setShortcut(tr("Esc"));
connect(hideMenuAct, SIGNAL(triggered()), this, SLOT(toggleMenuHidden()));
fsAct = new QAction(tr("&Full screen"), this);
fsAct->setShortcut(tr("Ctrl+F"));
fsAct->setCheckable(true);
connect(fsAct, SIGNAL(triggered()), this, SLOT(toggleFullScreen()));
}
void GambatteQt::createMenus() {
QAction *openAct = new QAction(tr("&Open..."), this);
openAct->setShortcut(tr("Ctrl+O"));
openAct->setStatusTip(tr("Open an existing file"));
connect(openAct, SIGNAL(triggered()), this, SLOT(open()));
for (int i = 0; i < MaxRecentFiles; ++i) {
recentFileActs[i] = new QAction(this);
recentFileActs[i]->setVisible(false);
connect(recentFileActs[i], SIGNAL(triggered()), this, SLOT(openRecentFile()));
}
QAction *aboutAct = new QAction(tr("&About"), this);
aboutAct->setStatusTip(tr("Show the application's About box"));
connect(aboutAct, SIGNAL(triggered()), this, SLOT(about()));
QMenu *fileMenu = menuBar()->addMenu(tr("&File"));
fileMenu->addAction(openAct);
separatorAct = fileMenu->addSeparator();
for (int i = 0; i < MaxRecentFiles; ++i)
fileMenu->addAction(recentFileActs[i]);
fileMenu->addSeparator();
fileMenu->addAction(exitAct);
updateRecentFileActions();
QMenu *videom = menuBar()->addMenu(tr("&Settings"));
{
QAction *inputDialogAct = new QAction(tr("&Input..."), this);
connect(inputDialogAct, SIGNAL(triggered()), this, SLOT(execInputDialog()));
videom->addAction(inputDialogAct);
}
{
QAction *videoDialogAct = new QAction(tr("&Video..."), this);
connect(videoDialogAct, SIGNAL(triggered()), this, SLOT(execVideoDialog()));
videom->addAction(videoDialogAct);
}
videom->addAction(fsAct);
videom->addAction(hideMenuAct);
menuBar()->addSeparator();
QMenu *helpMenu = menuBar()->addMenu(tr("&Help"));
helpMenu->addAction(aboutAct);
}
void GambatteQt::loadFile(const QString &fileName) {
if (gambatte.load((fileName.toAscii()).data())) {
stop();
QMessageBox::critical(
this,
tr("Error"),
tr("Failed to load file ") + fileName + "."
);
return;
}
setCurrentFile(fileName);
run();
}
void GambatteQt::execDialog(QDialog *const dialog) {
pause();
dialog->exec();
unpause();
}
void GambatteQt::execVideoDialog() {
execDialog(videoDialog);
}
void GambatteQt::execInputDialog() {
execDialog(inputDialog);
}
void GambatteQt::setSamplesPrFrame() {
const BlitterWidget::Rational r = blitter->frameTime();
const unsigned old = samplesPrFrame;
samplesPrFrame = ((sampleRate * r.numerator) / r.denominator) + 1;
if (old != samplesPrFrame) {
delete []sndBuffer;
sndBuffer = new int16_t[(samplesPrFrame + 4) * 2];
samplesCalc.setBaseSamples(samplesPrFrame);
}
}
AudioEngine* GambatteQt::initAudio() {
AudioEngine *ae;
int rate = -1;
while (!audioEngines.empty()) {
ae = audioEngines.back();
rate = ae->init();
if (rate >= 0)
break;
delete ae;
audioEngines.pop_back();
}
if (rate < 0) {
ae = NULL;
rate = 0;
}
sampleRate = rate;
setSamplesPrFrame();
return ae;
}
void GambatteQt::timerEvent(QTimerEvent */*event*/) {
gambatte.runFor(70224);
if (!turbo)
gambatte.fill_buffer(reinterpret_cast<uint16_t*>(sndBuffer), samplesCalc.getSamples());
if (blitter->sync(turbo)) {
QMessageBox::critical(this, tr("Error"), tr("Video engine failure."));
blitter->uninit();
blitter->init();
gambatte.setVideoBlitter(blitter);
if (ae)
ae->pause();
videoDialog->exec();
return;
}
if (!turbo) {
if (ae) {
unsigned lastSamples = samplesCalc.getSamples();
const AudioEngine::BufferState bufState = ae->bufferState();
if (bufState.fromUnderrun != 0xFFFFFFFF)
samplesCalc.update(bufState.fromUnderrun, bufState.fromOverflow);
if (ae->write(sndBuffer, lastSamples) < 0) {
delete ae;
audioEngines.pop_back();
ae = initAudio();
}
}
}
}
void GambatteQt::run() {
if (running)
return;
running = true;
memset(&inputGetter.is, 0, sizeof(inputGetter.is));
ae = initAudio();
#ifdef PLATFORM_WIN32
timeBeginPeriod(1);
#endif
blitter->setVisible(true);
blitter->init();
gambatte.setVideoBlitter(blitter);
timerId = startTimer(0);
}
void GambatteQt::stop() {
if (!running)
return;
running = false;
killTimer(timerId);
blitter->uninit();
blitter->setVisible(false);
ae->uninit();
ae = NULL;
#ifdef PLATFORM_WIN32
timeEndPeriod(1);
#endif
}
void GambatteQt::pause() {
if (!running || !timerId)
return;
if (ae)
ae->pause();
killTimer(timerId);
timerId = 0;
}
void GambatteQt::unpause() {
if (!running || timerId)
return;
timerId = startTimer(0);
}
void GambatteQt::setCurrentFile(const QString &fileName) {
QString curFile = fileName;
if (curFile.isEmpty())
setWindowTitle(tr("gambatte"));
else
setWindowTitle(tr("%1 - %2").arg(strippedName(curFile)) .arg(tr("gambatte")));
QSettings settings;
QStringList files = settings.value("recentFileList").toStringList();
files.removeAll(fileName);
files.prepend(fileName);
while (files.size() > MaxRecentFiles)
files.removeLast();
settings.setValue("recentFileList", files);
foreach(QWidget *widget, QApplication::topLevelWidgets()) {
GambatteQt *mainWin = qobject_cast<GambatteQt *>(widget);
if (mainWin)
mainWin->updateRecentFileActions();
}
}
void GambatteQt::updateRecentFileActions() {
QSettings settings;
QStringList files = settings.value("recentFileList").toStringList();
int numRecentFiles = qMin(files.size(), (int)MaxRecentFiles);
for (int i = 0; i < numRecentFiles; ++i) {
QString text = tr("&%1 %2").arg(i + 1).arg(strippedName(files[i]));
recentFileActs[i]->setText(text);
recentFileActs[i]->setData(files[i]);
recentFileActs[i]->setVisible(true);
}
for (int j = numRecentFiles; j < MaxRecentFiles; ++j)
recentFileActs[j]->setVisible(false);
separatorAct->setVisible(numRecentFiles > 0);
}
QString GambatteQt::strippedName(const QString &fullFileName) {
return QFileInfo(fullFileName).fileName();
}
void GambatteQt::keyPressEvent(QKeyEvent *e) {
// memset(&is, 0, sizeof(is));
e->accept();
if (e->key() == inputDialog->getStartKey())
inputGetter.is.startButton = 1;
else if (e->key() == inputDialog->getSelectKey())
inputGetter.is.selectButton = 1;
else if (e->key() == inputDialog->getBKey())
inputGetter.is.bButton = 1;
else if (e->key() == inputDialog->getAKey())
inputGetter.is.aButton = 1;
else if (e->key() == inputDialog->getDownKey()) {
inputGetter.is.dpadDown = 1;
inputGetter.is.dpadUp = 0;
} else if (e->key() == inputDialog->getUpKey()) {
inputGetter.is.dpadUp = 1;
inputGetter.is.dpadDown = 0;
} else if (e->key() == inputDialog->getLeftKey()) {
inputGetter.is.dpadLeft = 1;
inputGetter.is.dpadRight = 0;
} else if (e->key() == inputDialog->getRightKey()) {
inputGetter.is.dpadRight = 1;
inputGetter.is.dpadLeft = 0;
}
switch (e->key()) {
case Qt::Key_Tab: turbo = true; break;
case Qt::Key_Escape:
hideMenuAct->trigger();
break;
case Qt::Key_F:
if (e->modifiers()&Qt::ControlModifier) {
fsAct->trigger();
}
break;
case Qt::Key_Q:
if (e->modifiers()&Qt::ControlModifier) {
exitAct->trigger();
}
break;
default: e->ignore(); break;
}
}
void GambatteQt::keyReleaseEvent(QKeyEvent *e) {
// memset(&is, 0, sizeof(is));
if (e->key() == inputDialog->getStartKey())
inputGetter.is.startButton = 0;
else if (e->key() == inputDialog->getSelectKey())
inputGetter.is.selectButton = 0;
else if (e->key() == inputDialog->getBKey())
inputGetter.is.bButton = 0;
else if (e->key() == inputDialog->getAKey())
inputGetter.is.aButton = 0;
else if (e->key() == inputDialog->getDownKey())
inputGetter.is.dpadDown = 0;
else if (e->key() == inputDialog->getUpKey())
inputGetter.is.dpadUp = 0;
else if (e->key() == inputDialog->getLeftKey())
inputGetter.is.dpadLeft = 0;
else if (e->key() == inputDialog->getRightKey())
inputGetter.is.dpadRight = 0;
switch (e->key()) {
case Qt::Key_Tab: turbo = false; break;
default: e->ignore(); return;
}
// e->accept();
}
void GambatteQt::closeEvent(QCloseEvent *e) {
stop();
if (!isFullScreen()) {
QSettings settings;
settings.beginGroup("mainwindow");
settings.setValue("size", size());
settings.endGroup();
}
QMainWindow::closeEvent(e);
}
/*void GambatteQt::showEvent(QShowEvent *event) {
QMainWindow::showEvent(event);
resetWindowSize();
}*/

View File

@ -0,0 +1,132 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef GAMBATTE_QT_H
#define GAMBATTE_QT_H
#include <QList>
#include <QMainWindow>
#include <QSize>
#include <vector>
#include <gambatte.h>
#include "videobufferreseter.h"
#include "samplescalculator.h"
class QAction;
class QMenu;
// class QTextEdit;
class AudioEngine;
class BlitterWidget;
class VideoDialog;
class InputDialog;
class FullResToggler;
class BlitterContainer;
class InputGetter : public InputStateGetter {
public:
InputState is;
const InputState& operator()() { return is; }
};
class GambatteQt : public QMainWindow {
Q_OBJECT
public:
GambatteQt();
~GambatteQt();
protected:
void timerEvent(QTimerEvent *event);
void keyPressEvent(QKeyEvent *e);
void keyReleaseEvent(QKeyEvent *e);
void closeEvent(QCloseEvent *e);
// void showEvent(QShowEvent *event);
private slots:
void open();
void openRecentFile();
void about();
void resetWindowSize();
void toggleFullScreen();
void toggleMenuHidden();
// void gl();
// void xv();
void videoSettingsChange();
void execVideoDialog();
void execInputDialog();
private:
void createActions();
void createMenus();
void loadFile(const QString &fileName);
AudioEngine* initAudio();
void run();
void stop();
void pause();
void unpause();
void setSamplesPrFrame();
// void calculateSamples(unsigned bufPos, unsigned bufSize);
void setCurrentFile(const QString &fileName);
void updateRecentFileActions();
QString strippedName(const QString &fullFileName);
// void toggleFullScreen();
// void pauseAudio();
void execDialog(QDialog *dialog);
Gambatte gambatte;
// QString curFile;
// QSize fixedSize;
std::vector<AudioEngine*> audioEngines;
std::vector<BlitterWidget*> blitters;
InputGetter inputGetter;
VideoBufferReseter resetVideoBuffer;
int16_t *sndBuffer;
BlitterContainer *blitterContainer;
QAction *exitAct;
QAction *separatorAct;
QAction *fsAct;
QAction *hideMenuAct;
InputDialog *inputDialog;
VideoDialog* videoDialog;
BlitterWidget *blitter;
FullResToggler *fullResToggler;
enum { MaxRecentFiles = 8 };
QAction *recentFileActs[MaxRecentFiles];
AudioEngine *ae;
unsigned sampleRate;
unsigned samplesPrFrame;
int timerId;
SamplesCalculator samplesCalc;
bool running;
bool turbo;
//bool esc;
};
#endif

View File

@ -0,0 +1,25 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "getfullrestoggler.h"
#include "fullrestogglers/nulltoggler.h"
FullResToggler* getFullResToggler() {
return new NullToggler;
}

View File

@ -0,0 +1,26 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef GET_FULL_RES_TOGGLER_H
#define GET_FULL_RES_TOGGLER_H
class FullResToggler;
FullResToggler* getFullResToggler();
#endif

View File

@ -0,0 +1,29 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "getfullrestoggler.h"
#include "fullrestogglers/nulltoggler.h"
#include "fullrestogglers/xrandrtoggler.h"
FullResToggler* getFullResToggler() {
if (XRandRToggler::isUsable())
return new XRandRToggler;
return new NullToggler;
}

View File

@ -0,0 +1,25 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "getfullrestoggler.h"
#include "fullrestogglers/gditoggler.h"
FullResToggler* getFullResToggler() {
return new GdiToggler;
}

View File

@ -0,0 +1,503 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "inputdialog.h"
#include <QLineEdit>
#include <QKeyEvent>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QLabel>
#include <QPushButton>
#include <QSettings>
static QString keyToString(int key) {
switch (key) {
case Qt::Key_Escape: return QString("Escape");
case Qt::Key_Tab: return QString("Tab");
case Qt::Key_Backtab: return QString("Backtab");
case Qt::Key_Backspace: return QString("Backspace");
case Qt::Key_Return: return QString("Return");
case Qt::Key_Enter: return QString("Enter");
case Qt::Key_Insert: return QString("Insert");
case Qt::Key_Delete: return QString("Delete");
case Qt::Key_Pause: return QString("Pause");
case Qt::Key_Print: return QString("Print");
case Qt::Key_SysReq: return QString("SysReq");
case Qt::Key_Clear: return QString("Clear");
case Qt::Key_Home: return QString("Home");
case Qt::Key_End: return QString("End");
case Qt::Key_Left: return QString("Left");
case Qt::Key_Up: return QString("Up");
case Qt::Key_Right: return QString("Right");
case Qt::Key_Down: return QString("Down");
case Qt::Key_PageUp: return QString("PageUp");
case Qt::Key_PageDown: return QString("PageDown");
case Qt::Key_Shift: return QString("Shift");
case Qt::Key_Control: return QString("Control");
case Qt::Key_Meta: return QString("Meta");
case Qt::Key_Alt: return QString("Alt");
case Qt::Key_AltGr: return QString("AltGr");
case Qt::Key_CapsLock: return QString("CapsLock");
case Qt::Key_NumLock: return QString("NumLock");
case Qt::Key_ScrollLock: return QString("ScrollLock");
case Qt::Key_F1: return QString("F1");
case Qt::Key_F2: return QString("F2");
case Qt::Key_F3: return QString("F3");
case Qt::Key_F4: return QString("F4");
case Qt::Key_F5: return QString("F5");
case Qt::Key_F6: return QString("F6");
case Qt::Key_F7: return QString("F7");
case Qt::Key_F8: return QString("F8");
case Qt::Key_F9: return QString("F9");
case Qt::Key_F10: return QString("F10");
case Qt::Key_F11: return QString("F11");
case Qt::Key_F12: return QString("F12");
case Qt::Key_F13: return QString("F13");
case Qt::Key_F14: return QString("F14");
case Qt::Key_F15: return QString("F15");
case Qt::Key_F16: return QString("F16");
case Qt::Key_F17: return QString("F17");
case Qt::Key_F18: return QString("F18");
case Qt::Key_F19: return QString("F19");
case Qt::Key_F20: return QString("F20");
case Qt::Key_F21: return QString("F21");
case Qt::Key_F22: return QString("F22");
case Qt::Key_F23: return QString("F23");
case Qt::Key_F24: return QString("F24");
case Qt::Key_F25: return QString("F25");
case Qt::Key_F26: return QString("F26");
case Qt::Key_F27: return QString("F27");
case Qt::Key_F28: return QString("F28");
case Qt::Key_F29: return QString("F29");
case Qt::Key_F30: return QString("F30");
case Qt::Key_F31: return QString("F31");
case Qt::Key_F32: return QString("F32");
case Qt::Key_F33: return QString("F33");
case Qt::Key_F34: return QString("F34");
case Qt::Key_F35: return QString("F35");
case Qt::Key_Super_L: return QString("Super_L");
case Qt::Key_Super_R: return QString("Super_R");
case Qt::Key_Menu: return QString("Menu");
case Qt::Key_Hyper_L: return QString("Hyper_L");
case Qt::Key_Hyper_R: return QString("Hyper_R");
case Qt::Key_Help: return QString("Help");
case Qt::Key_Direction_L: return QString("Direction_L");
case Qt::Key_Direction_R: return QString("Direction_R");
case Qt::Key_Space: return QString("Space");
case Qt::Key_Exclam: return QString("Exclam");
case Qt::Key_QuoteDbl: return QString("QuoteDbl");
case Qt::Key_NumberSign: return QString("NumberSign");
case Qt::Key_Dollar: return QString("Dollar");
case Qt::Key_Percent: return QString("Percent");
case Qt::Key_Ampersand: return QString("Ampersand");
case Qt::Key_Apostrophe: return QString("Apostrophe");
case Qt::Key_ParenLeft: return QString("ParenLeft");
case Qt::Key_ParenRight: return QString("ParenRight");
case Qt::Key_Asterisk: return QString("Asterisk");
case Qt::Key_Plus: return QString("Plus");
case Qt::Key_Comma: return QString("Comma");
case Qt::Key_Minus: return QString("Minus");
case Qt::Key_Period: return QString("Period");
case Qt::Key_Slash: return QString("Slash");
case Qt::Key_0: return QString("0");
case Qt::Key_1: return QString("1");
case Qt::Key_2: return QString("2");
case Qt::Key_3: return QString("3");
case Qt::Key_4: return QString("4");
case Qt::Key_5: return QString("5");
case Qt::Key_6: return QString("6");
case Qt::Key_7: return QString("7");
case Qt::Key_8: return QString("8");
case Qt::Key_9: return QString("9");
case Qt::Key_Colon: return QString("Colon");
case Qt::Key_Semicolon: return QString("Semicolon");
case Qt::Key_Less: return QString("Less");
case Qt::Key_Equal: return QString("Equal");
case Qt::Key_Greater: return QString("Greater");
case Qt::Key_Question: return QString("Question");
case Qt::Key_At: return QString("At");
case Qt::Key_A: return QString("A");
case Qt::Key_B: return QString("B");
case Qt::Key_C: return QString("C");
case Qt::Key_D: return QString("D");
case Qt::Key_E: return QString("E");
case Qt::Key_F: return QString("F");
case Qt::Key_G: return QString("G");
case Qt::Key_H: return QString("H");
case Qt::Key_I: return QString("I");
case Qt::Key_J: return QString("J");
case Qt::Key_K: return QString("K");
case Qt::Key_L: return QString("L");
case Qt::Key_M: return QString("M");
case Qt::Key_N: return QString("N");
case Qt::Key_O: return QString("O");
case Qt::Key_P: return QString("P");
case Qt::Key_Q: return QString("Q");
case Qt::Key_R: return QString("R");
case Qt::Key_S: return QString("S");
case Qt::Key_T: return QString("T");
case Qt::Key_U: return QString("U");
case Qt::Key_V: return QString("V");
case Qt::Key_W: return QString("W");
case Qt::Key_X: return QString("X");
case Qt::Key_Y: return QString("Y");
case Qt::Key_Z: return QString("Z");
case Qt::Key_BracketLeft: return QString("BracketLeft");
case Qt::Key_Backslash: return QString("Backslash");
case Qt::Key_BracketRight: return QString("BracketRight");
case Qt::Key_AsciiCircum: return QString("AsciiCircum");
case Qt::Key_Underscore: return QString("Underscore");
case Qt::Key_QuoteLeft: return QString("QuoteLeft");
case Qt::Key_BraceLeft: return QString("BraceLeft");
case Qt::Key_Bar: return QString("Bar");
case Qt::Key_BraceRight: return QString("BraceRight");
case Qt::Key_AsciiTilde: return QString("AsciiTilde");
case Qt::Key_nobreakspace: return QString("nobreakspace");
case Qt::Key_exclamdown: return QString("exclamdown");
case Qt::Key_cent: return QString("cent");
case Qt::Key_sterling: return QString("sterling");
case Qt::Key_currency: return QString("currency");
case Qt::Key_yen: return QString("yen");
case Qt::Key_brokenbar: return QString("brokenbar");
case Qt::Key_section: return QString("section");
case Qt::Key_diaeresis: return QString("diaeresis");
case Qt::Key_copyright: return QString("copyright");
case Qt::Key_ordfeminine: return QString("ordfeminine");
case Qt::Key_guillemotleft: return QString("guillemotleft");
case Qt::Key_notsign: return QString("notsign");
case Qt::Key_hyphen: return QString("hyphen");
case Qt::Key_registered: return QString("registered");
case Qt::Key_macron: return QString("macron");
case Qt::Key_degree: return QString("degree");
case Qt::Key_plusminus: return QString("plusminus");
case Qt::Key_twosuperior: return QString("twosuperior");
case Qt::Key_threesuperior: return QString("threesuperior");
case Qt::Key_acute: return QString("acute");
case Qt::Key_mu: return QString("mu");
case Qt::Key_paragraph: return QString("paragraph");
case Qt::Key_periodcentered: return QString("periodcentered");
case Qt::Key_cedilla: return QString("cedilla");
case Qt::Key_onesuperior: return QString("onesuperior");
case Qt::Key_masculine: return QString("masculine");
case Qt::Key_guillemotright: return QString("guillemotright");
case Qt::Key_onequarter: return QString("onequarter");
case Qt::Key_onehalf: return QString("onehalf");
case Qt::Key_threequarters: return QString("threequarters");
case Qt::Key_questiondown: return QString("questiondown");
case Qt::Key_Agrave: return QString("Agrave");
case Qt::Key_Aacute: return QString("Aacute");
case Qt::Key_Acircumflex: return QString("Acircumflex");
case Qt::Key_Atilde: return QString("Atilde");
case Qt::Key_Adiaeresis: return QString("Adiaeresis");
case Qt::Key_Aring: return QString("Aring");
case Qt::Key_AE: return QString("AE");
case Qt::Key_Ccedilla: return QString("Ccedilla");
case Qt::Key_Egrave: return QString("Egrave");
case Qt::Key_Eacute: return QString("Eacute");
case Qt::Key_Ecircumflex: return QString("Ecircumflex");
case Qt::Key_Ediaeresis: return QString("Ediaeresis");
case Qt::Key_Igrave: return QString("Igrave");
case Qt::Key_Iacute: return QString("Iacute");
case Qt::Key_Icircumflex: return QString("Icircumflex");
case Qt::Key_Idiaeresis: return QString("Idiaeresis");
case Qt::Key_ETH: return QString("ETH");
case Qt::Key_Ntilde: return QString("Ntilde");
case Qt::Key_Ograve: return QString("Ograve");
case Qt::Key_Oacute: return QString("Oacute");
case Qt::Key_Ocircumflex: return QString("Ocircumflex");
case Qt::Key_Otilde: return QString("Otilde");
case Qt::Key_Odiaeresis: return QString("Odiaeresis");
case Qt::Key_multiply: return QString("multiply");
case Qt::Key_Ooblique: return QString("Ooblique");
case Qt::Key_Ugrave: return QString("Ugrave");
case Qt::Key_Uacute: return QString("Uacute");
case Qt::Key_Ucircumflex: return QString("Ucircumflex");
case Qt::Key_Udiaeresis: return QString("Udiaeresis");
case Qt::Key_Yacute: return QString("Yacute");
case Qt::Key_THORN: return QString("THORN");
case Qt::Key_ssharp: return QString("ssharp");
case Qt::Key_division: return QString("division");
case Qt::Key_ydiaeresis: return QString("ydiaeresis");
case Qt::Key_Multi_key: return QString("Multi_key");
case Qt::Key_Codeinput: return QString("Codeinput");
case Qt::Key_SingleCandidate: return QString("SingleCandidate");
case Qt::Key_MultipleCandidate: return QString("MultipleCandidate");
case Qt::Key_PreviousCandidate: return QString("PreviousCandidate");
case Qt::Key_Mode_switch: return QString("Mode_switch");
case Qt::Key_Kanji: return QString("Kanji");
case Qt::Key_Muhenkan: return QString("Muhenkan");
case Qt::Key_Henkan: return QString("Henkan");
case Qt::Key_Romaji: return QString("Romaji");
case Qt::Key_Hiragana: return QString("Hiragana");
case Qt::Key_Katakana: return QString("Katakana");
case Qt::Key_Hiragana_Katakana: return QString("Hiragana_Katakana");
case Qt::Key_Zenkaku: return QString("Zenkaku");
case Qt::Key_Hankaku: return QString("Hankaku");
case Qt::Key_Zenkaku_Hankaku: return QString("Zenkaku_Hankaku");
case Qt::Key_Touroku: return QString("Touroku");
case Qt::Key_Massyo: return QString("Massyo");
case Qt::Key_Kana_Lock: return QString("Kana_Lock");
case Qt::Key_Kana_Shift: return QString("Kana_Shift");
case Qt::Key_Eisu_Shift: return QString("Eisu_Shift");
case Qt::Key_Eisu_toggle: return QString("Eisu_toggle");
case Qt::Key_Hangul: return QString("Hangul");
case Qt::Key_Hangul_Start: return QString("Hangul_Start");
case Qt::Key_Hangul_End: return QString("Hangul_End");
case Qt::Key_Hangul_Hanja: return QString("Hangul_Hanja");
case Qt::Key_Hangul_Jamo: return QString("Hangul_Jamo");
case Qt::Key_Hangul_Romaja: return QString("Hangul_Romaja");
case Qt::Key_Hangul_Jeonja: return QString("Hangul_Jeonja");
case Qt::Key_Hangul_Banja: return QString("Hangul_Banja");
case Qt::Key_Hangul_PreHanja: return QString("Hangul_PreHanja");
case Qt::Key_Hangul_PostHanja: return QString("Hangul_PostHanja");
case Qt::Key_Hangul_Special: return QString("Hangul_Special");
case Qt::Key_Dead_Grave: return QString("Dead_Grave");
case Qt::Key_Dead_Acute: return QString("Dead_Acute");
case Qt::Key_Dead_Circumflex: return QString("Dead_Circumflex");
case Qt::Key_Dead_Tilde: return QString("Dead_Tilde");
case Qt::Key_Dead_Macron: return QString("Dead_Macron");
case Qt::Key_Dead_Breve: return QString("Dead_Breve");
case Qt::Key_Dead_Abovedot: return QString("Dead_Abovedot");
case Qt::Key_Dead_Diaeresis: return QString("Dead_Diaeresis");
case Qt::Key_Dead_Abovering: return QString("Dead_Abovering");
case Qt::Key_Dead_Doubleacute: return QString("Dead_Doubleacute");
case Qt::Key_Dead_Caron: return QString("Dead_Caron");
case Qt::Key_Dead_Cedilla: return QString("Dead_Cedilla");
case Qt::Key_Dead_Ogonek: return QString("Dead_Ogonek");
case Qt::Key_Dead_Iota: return QString("Dead_Iota");
case Qt::Key_Dead_Voiced_Sound: return QString("Dead_Voiced_Sound");
case Qt::Key_Dead_Semivoiced_Sound: return QString("Dead_Semivoiced_Sound");
case Qt::Key_Dead_Belowdot: return QString("Dead_Belowdot");
case Qt::Key_Dead_Hook: return QString("Dead_Hook");
case Qt::Key_Dead_Horn: return QString("Dead_Horn");
case Qt::Key_Back: return QString("Back");
case Qt::Key_Forward: return QString("Forward");
case Qt::Key_Stop: return QString("Stop");
case Qt::Key_Refresh: return QString("Refresh");
case Qt::Key_VolumeDown: return QString("VolumeDown");
case Qt::Key_VolumeMute: return QString("VolumeMute");
case Qt::Key_VolumeUp: return QString("VolumeUp");
case Qt::Key_BassBoost: return QString("BassBoost");
case Qt::Key_BassUp: return QString("BassUp");
case Qt::Key_BassDown: return QString("BassDown");
case Qt::Key_TrebleUp: return QString("TrebleUp");
case Qt::Key_TrebleDown: return QString("TrebleDown");
case Qt::Key_MediaPlay: return QString("MediaPlay");
case Qt::Key_MediaStop: return QString("MediaStop");
case Qt::Key_MediaPrevious: return QString("MediaPrevious");
case Qt::Key_MediaNext: return QString("MediaNext");
case Qt::Key_MediaRecord: return QString("MediaRecord");
case Qt::Key_HomePage: return QString("HomePage");
case Qt::Key_Favorites: return QString("Favorites");
case Qt::Key_Search: return QString("Search");
case Qt::Key_Standby: return QString("Standby");
case Qt::Key_OpenUrl: return QString("OpenUrl");
case Qt::Key_LaunchMail: return QString("LaunchMail");
case Qt::Key_LaunchMedia: return QString("LaunchMedia");
case Qt::Key_Launch0: return QString("Launch0");
case Qt::Key_Launch1: return QString("Launch1");
case Qt::Key_Launch2: return QString("Launch2");
case Qt::Key_Launch3: return QString("Launch3");
case Qt::Key_Launch4: return QString("Launch4");
case Qt::Key_Launch5: return QString("Launch5");
case Qt::Key_Launch6: return QString("Launch6");
case Qt::Key_Launch7: return QString("Launch7");
case Qt::Key_Launch8: return QString("Launch8");
case Qt::Key_Launch9: return QString("Launch9");
case Qt::Key_LaunchA: return QString("LaunchA");
case Qt::Key_LaunchB: return QString("LaunchB");
case Qt::Key_LaunchC: return QString("LaunchC");
case Qt::Key_LaunchD: return QString("LaunchD");
case Qt::Key_LaunchE: return QString("LaunchE");
case Qt::Key_LaunchF: return QString("LaunchF");
case Qt::Key_MediaLast: return QString("MediaLast");
case Qt::Key_unknown: return QString("unknown");
case Qt::Key_Call: return QString("Call");
case Qt::Key_Context1: return QString("Context1");
case Qt::Key_Context2: return QString("Context2");
case Qt::Key_Context3: return QString("Context3");
case Qt::Key_Context4: return QString("Context4");
case Qt::Key_Flip: return QString("Flip");
case Qt::Key_Hangup: return QString("Hangup");
case Qt::Key_No: return QString("No");
case Qt::Key_Select: return QString("Select");
case Qt::Key_Yes: return QString("Yes");
case Qt::Key_Execute: return QString("Execute");
case Qt::Key_Printer: return QString("Printer");
case Qt::Key_Play: return QString("Play");
case Qt::Key_Sleep: return QString("Sleep");
case Qt::Key_Zoom: return QString("Zoom");
case Qt::Key_Cancel: return QString("Cancel");
default: return QString("");
}
}
class InputBox : public QLineEdit {
int key;
protected:
void keyPressEvent(QKeyEvent *e) {
setKey(e->key());;
}
public:
InputBox(int key = 0) {
setKey(key);;
setReadOnly(true);
}
int getKey() const {
return key;
}
void setKey(int key) {
this->key = key;
setText(keyToString(key));
}
};
InputDialog::InputDialog(QWidget *parent)
: QDialog(parent)
{
setWindowTitle(tr("Input settings"));
upBox = new InputBox;
downBox = new InputBox;
leftBox = new InputBox;
rightBox = new InputBox;
aBox = new InputBox;
bBox = new InputBox;
startBox = new InputBox;
selectBox = new InputBox;
QVBoxLayout *mainLayout = new QVBoxLayout;
QHBoxLayout *topLayout = new QHBoxLayout;
QVBoxLayout *vLayout;
QHBoxLayout *hLayout;
hLayout = new QHBoxLayout;
vLayout = new QVBoxLayout;
vLayout->addWidget(new QLabel(tr("Up:")));
vLayout->addWidget(new QLabel(tr("Down:")));
vLayout->addWidget(new QLabel(tr("Left:")));
vLayout->addWidget(new QLabel(tr("Right:")));
hLayout->addLayout(vLayout);
vLayout = new QVBoxLayout;
vLayout->addWidget(upBox);
vLayout->addWidget(downBox);
vLayout->addWidget(leftBox);
vLayout->addWidget(rightBox);
hLayout->addLayout(vLayout);
topLayout->addLayout(hLayout);
hLayout = new QHBoxLayout;
vLayout = new QVBoxLayout;
vLayout->addWidget(new QLabel(tr("A:")));
vLayout->addWidget(new QLabel(tr("B:")));
vLayout->addWidget(new QLabel(tr("Start:")));
vLayout->addWidget(new QLabel(tr("Select:")));
hLayout->addLayout(vLayout);
vLayout = new QVBoxLayout;
vLayout->addWidget(aBox);
vLayout->addWidget(bBox);
vLayout->addWidget(startBox);
vLayout->addWidget(selectBox);
hLayout->addLayout(vLayout);
topLayout->addLayout(hLayout);
mainLayout->addLayout(topLayout);
QPushButton *okButton = new QPushButton(tr("OK"));
QPushButton *cancelButton = new QPushButton(tr("Cancel"));
hLayout = new QHBoxLayout;
hLayout->addWidget(okButton);
hLayout->addWidget(cancelButton);
mainLayout->addLayout(hLayout);
mainLayout->setAlignment(hLayout, Qt::AlignBottom | Qt::AlignRight);
okButton->setDefault(true);
setLayout(mainLayout);
connect(okButton, SIGNAL(clicked()), this, SLOT(accept()));
connect(cancelButton, SIGNAL(clicked()), this, SLOT(reject()));
QSettings settings;
settings.beginGroup("input");
upKey = settings.value("upKey", Qt::Key_Up).toInt();
downKey = settings.value("downKey", Qt::Key_Down).toInt();
leftKey = settings.value("leftKey", Qt::Key_Left).toInt();
rightKey = settings.value("rightKey", Qt::Key_Right).toInt();
aKey = settings.value("aKey", Qt::Key_D).toInt();
bKey = settings.value("bKey", Qt::Key_C).toInt();
startKey = settings.value("startKey", Qt::Key_Return).toInt();
selectKey = settings.value("selectKey", Qt::Key_Shift).toInt();
settings.endGroup();
restore();
}
InputDialog::~InputDialog() {
QSettings settings;
settings.beginGroup("input");
settings.setValue("upKey", upKey);
settings.setValue("downKey", downKey);
settings.setValue("leftKey", leftKey);
settings.setValue("rightKey", rightKey);
settings.setValue("aKey", aKey);
settings.setValue("bKey", bKey);
settings.setValue("startKey", startKey);
settings.setValue("selectKey", selectKey);
settings.endGroup();
}
void InputDialog::store() {
upKey = upBox->getKey();
downKey = downBox->getKey();
leftKey = leftBox->getKey();
rightKey = rightBox->getKey();
aKey = aBox->getKey();
bKey = bBox->getKey();
startKey = startBox->getKey();
selectKey = selectBox->getKey();
}
void InputDialog::restore() {
upBox->setKey(upKey);
downBox->setKey(downKey);
leftBox->setKey(leftKey);
rightBox->setKey(rightKey);
aBox->setKey(aKey);
bBox->setKey(bKey);
startBox->setKey(startKey);
selectBox->setKey(selectKey);
}
void InputDialog::accept() {
store();
QDialog::accept();
}
void InputDialog::reject() {
restore();
QDialog::reject();
}

View File

@ -0,0 +1,68 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef INPUTDIALOG_H
#define INPUTDIALOG_H
#include <QDialog>
class InputBox;
class InputDialog : public QDialog {
Q_OBJECT
InputBox *upBox;
InputBox *downBox;
InputBox *leftBox;
InputBox *rightBox;
InputBox *aBox;
InputBox *bBox;
InputBox *startBox;
InputBox *selectBox;
int upKey;
int downKey;
int leftKey;
int rightKey;
int aKey;
int bKey;
int startKey;
int selectKey;
void store();
void restore();
public:
InputDialog(QWidget *parent = 0);
~InputDialog();
int getUpKey() const { return upKey; }
int getDownKey() const { return downKey; }
int getLeftKey() const { return leftKey; }
int getRightKey() const { return rightKey; }
int getAKey() const { return aKey; }
int getBKey() const { return bKey; }
int getStartKey() const { return startKey; }
int getSelectKey() const { return selectKey; }
public slots:
void accept();
void reject();
};
#endif

32
gambatte_qt/src/main.cpp Normal file
View File

@ -0,0 +1,32 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include <QApplication>
#include "gambatte_qt.h"
int main(int argc, char *argv[]) {
// Q_INIT_RESOURCE(application);
QApplication app(argc, argv);
QCoreApplication::setOrganizationName("gambatte");
QCoreApplication::setApplicationName("gambatte_qt");
GambatteQt * mw = new GambatteQt();
mw->show();
return app.exec();
}

30
gambatte_qt/src/resinfo.h Normal file
View File

@ -0,0 +1,30 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef RESINFO_H
#define RESINFO_H
#include <vector>
struct ResInfo {
unsigned w;
unsigned h;
std::vector<short> rates;
};
#endif

View File

@ -0,0 +1,29 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "resizesignalingmenubar.h"
ResizeSignalingMenuBar::ResizeSignalingMenuBar(QWidget *parent)
: QMenuBar(parent)
{
}
void ResizeSignalingMenuBar::resizeEvent(QResizeEvent *event) {
QMenuBar::resizeEvent(event);
emit resized();
}

View File

@ -0,0 +1,37 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef RESIZESIGNALINGMENUBAR_H
#define RESIZESIGNALINGMENUBAR_H
#include <QMenuBar>
class ResizeSignalingMenuBar : public QMenuBar {
Q_OBJECT
protected:
void resizeEvent(QResizeEvent *event);
public:
ResizeSignalingMenuBar(QWidget *parent = 0);
signals:
void resized();
};
#endif

View File

@ -0,0 +1,66 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "samplescalculator.h"
SamplesCalculator::SamplesCalculator(const unsigned baseSamples, const unsigned maxDiff)
: maxDiff(maxDiff)
{
setBaseSamples(baseSamples);
}
void SamplesCalculator::setBaseSamples(const unsigned baseSamples) {
this->baseSamples = baseSamples;
samples = baseSamples;
lastFromUnderrun = baseSamples >> 2;
lastOverflowTime = lastUnderrunTime = updates = samplesOverflowed = 0;
}
#include <cstdio>
void SamplesCalculator::update(const unsigned fromUnderrun, const unsigned fromOverflow) {
++updates;
if (fromUnderrun < samples * 2) {
if (fromUnderrun <= lastFromUnderrun && samples < baseSamples + maxDiff && updates - lastUnderrunTime >= 60) {
++samples;
lastFromUnderrun = fromUnderrun;
lastUnderrunTime = updates;
printf("samples: %u\n", samples);
lastOverflowTime = samplesOverflowed = 0;
}
} else {
const unsigned of = samples - fromOverflow;
if (!(of & 0x80000000)) {
if (!lastOverflowTime)
lastOverflowTime = updates;
else {
samplesOverflowed += of;
if (samples > baseSamples - maxDiff && samplesOverflowed >= (updates - lastOverflowTime) * 2 + samples && updates - lastOverflowTime >= 300) {
--samples;
lastFromUnderrun = 0xFFFFFFFF;
printf("samples: %u\n", samples);
samplesOverflowed = 0;
lastOverflowTime = updates;
}
}
}
}
}

View File

@ -0,0 +1,44 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef SAMPLESCALCULATOR_H
#define SAMPLESCALCULATOR_H
class SamplesCalculator {
unsigned samples;
unsigned baseSamples;
unsigned updates;
unsigned lastFromUnderrun;
unsigned lastUnderrunTime;
unsigned lastOverflowTime;
unsigned samplesOverflowed;
const unsigned maxDiff;
public:
SamplesCalculator(unsigned baseSamples = 804, unsigned maxDiff = 4);
void setBaseSamples(unsigned samples);
void update(unsigned fromUnderrun, unsigned fromOverflow);
unsigned getSamples() const {
return samples;
}
};
#endif

View File

@ -0,0 +1,66 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef SCALEBUFFER_H_
#define SCALEBUFFER_H_
#include <cstring>
#define SCALE_BUFFER \
const unsigned dstW = srcW * scale; \
\
for (unsigned h = srcH; h--;) { \
for (unsigned w = srcW; w--;) { \
for (unsigned n = scale; n--;) \
*d++ = *s; \
\
++s; \
} \
\
std::memcpy(d, d - dstW, dstW * (scale - 1) * sizeof(T)); \
d += dstW * (scale - 1); \
}
template<typename T, const unsigned scale>
static void do_scaleBuffer(const T *s, T *d, const unsigned srcW, const unsigned srcH) {
SCALE_BUFFER
}
template<typename T>
static void do_scaleBuffer(const T *s, T *d, const unsigned srcW, const unsigned srcH, const unsigned scale) {
SCALE_BUFFER
}
#undef SCALE_BUFFER
template<typename T>
void scaleBuffer(const T *s, T *d, const unsigned srcW, const unsigned srcH, const unsigned scale) {
switch (scale) {
case 2: do_scaleBuffer<T, 2>(s, d, srcW, srcH); break;
case 3: do_scaleBuffer<T, 3>(s, d, srcW, srcH); break;
case 4: do_scaleBuffer<T, 4>(s, d, srcW, srcH); break;
case 5: do_scaleBuffer<T, 5>(s, d, srcW, srcH); break;
case 6: do_scaleBuffer<T, 6>(s, d, srcW, srcH); break;
case 7: do_scaleBuffer<T, 7>(s, d, srcW, srcH); break;
case 8: do_scaleBuffer<T, 8>(s, d, srcW, srcH); break;
default: do_scaleBuffer(s, d, srcW, srcH, scale); break;
}
}
#endif /*SCALEBUFFER_H_*/

91
gambatte_qt/src/src.pro Normal file
View File

@ -0,0 +1,91 @@
SOURCES += gambatte_qt.cpp \
main.cpp \
videodialog.cpp \
videobufferreseter.cpp \
blittercontainer.cpp \
inputdialog.cpp \
resizesignalingmenubar.cpp \
samplescalculator.cpp \
blitterwidgets/qglblitter.cpp \
blitterwidgets/qpainterblitter.cpp
HEADERS += gambatte_qt.h \
blitterwidget.h \
fullrestoggler.h \
videodialog.h \
videobufferreseter.h \
blittercontainer.h \
resinfo.h \
inputdialog.h \
resizesignalingmenubar.h \
audioengine.h \
samplescalculator.h \
addaudioengines.h \
addblitterwidgets.h \
getfullrestoggler.h \
blitterwidgets/qglblitter.h \
blitterwidgets/qpainterblitter.h \
fullrestogglers/nulltoggler.h
TEMPLATE = app
CONFIG += warn_on \
thread \
qt \
release
QT += opengl
TARGET = ../bin/gambatte_qt
INCLUDEPATH += ../../libgambatte/include
LIBS += -L../../libgambatte -lgambatte
unix {
DEFINES += PLATFORM_UNIX
SOURCES += blitterwidget.cpp \
x11getprocaddress.cpp \
addblitterwidgets_unix.cpp \
getfullrestoggler_unix.cpp \
audioengines/ossengine.cpp \
blitterwidgets/xvblitter.cpp \
blitterwidgets/x11blitter.cpp \
fullrestogglers/xrandrtoggler.cpp
HEADERS += x11getprocaddress.h \
audioengines/ossengine.h \
blitterwidgets/xvblitter.h \
blitterwidgets/x11blitter.h \
fullrestogglers/xrandrtoggler.h
LIBS += -L/usr/X11R6/lib -lXv -lXrandr
linux-g++ {
SOURCES += addaudioengines_linux.cpp audioengines/alsaengine.cpp
HEADERS += audioengines/alsaengine.h
LIBS += -lasound
} else {
SOURCES += addaudioengines_unix.cpp
}
}
win32 {
DEFINES += PLATFORM_WIN32
SOURCES += getfullrestoggler_win32.cpp \
blitterwidget_win32.cpp \
addaudioengines_win32.cpp \
addblitterwidgets_win32.cpp \
audioengines/directsoundengine.cpp \
blitterwidgets/directdrawblitter.cpp \
fullrestogglers/gditoggler.cpp
HEADERS += audioengines/directsoundengine.h \
blitterwidgets/directdrawblitter.h \
fullrestogglers/gditoggler.h
LIBS += -lwinmm -lddraw -ldxguid -ldsound
}
!win32 : !unix {
SOURCES += addaudioengines.cpp addblitterwidgets.cpp getfullrestoggler.cpp audioengines/aoengine.cpp
HEADERS += audioengines/aoengine.h
LIBS += -lao
}

View File

@ -0,0 +1,29 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "videobufferreseter.h"
#include <gambatte.h>
VideoBufferReseter::VideoBufferReseter(Gambatte &gambatte_in) :
gambatte(gambatte_in)
{}
void VideoBufferReseter::operator()() {
gambatte.videoBufferChange();
}

View File

@ -0,0 +1,32 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef VIDEOBUFFERRESETER_H
#define VIDEOBUFFERRESETER_H
class Gambatte;
class VideoBufferReseter {
Gambatte &gambatte;
public:
VideoBufferReseter(Gambatte &gambatte_in);
void operator()();
};
#endif

View File

@ -0,0 +1,399 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "videodialog.h"
#include <filterinfo.h>
#include "blitterwidget.h"
#include <QPushButton>
#include <QComboBox>
#include <QCheckBox>
#include <QString>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QLabel>
#include <QSettings>
#include <iostream>
#include "fullrestoggler.h"
VideoDialog::VideoDialog(const std::vector<BlitterWidget*> &blitters, std::vector<const FilterInfo*> filterInfo, const FullResToggler& resHandler, QWidget *parent) : QDialog(parent), engines(blitters), resVector(resHandler.resVector()) {
ResInfo currentRes;
if (resVector.empty()) {
currentRes.w = 1600;
currentRes.h = 1200;
} else
currentRes = resVector.at(resHandler.currentResIndex());
std::cout << currentRes.w << "x" << currentRes.h << std::endl;
QVBoxLayout *mainLayout = new QVBoxLayout;
setLayout(mainLayout);
QLabel *winResLabel = new QLabel(QString(tr("Windowed resolution:")));
winResSelector = new QComboBox;
winResSelectorBackup = new QComboBox;
{
unsigned hres = 160;
unsigned vres = 144;
while (hres <= currentRes.w && vres <= currentRes.h) {
winResSelector->addItem(QString::number(hres) + QString("x") + QString::number(vres), QVariant(QSize(hres, vres)));
winResSelectorBackup->addItem(QString::number(hres) + QString("x") + QString::number(vres), QVariant(QSize(hres, vres)));
hres += 160;
vres += 144;
}
}
winResSelector->addItem(QString(tr("Variable")), QVariant(QSize(-1, -1)));
// winResSelectorBackup->addItem(QString(tr("Variable")), QVariant(QSize(-1, -1)));
QLabel *fullResLabel = new QLabel(QString(tr("Full screen resolution:")));
fullResSelector = new QComboBox;
// fullResSelectorBackup = new QComboBox;
hzSelector = new QComboBox;
fillFullResSelector(QSize(160, 144));
// fullResSelector->setCurrentIndex(fullIndex);
for (unsigned int i = 0; i < currentRes.rates.size(); ++i)
hzSelector->addItem(QString::number(currentRes.rates[i]) + QString(" Hz"), i);
QPushButton *okButton = new QPushButton(tr("OK"));
QPushButton *cancelButton = new QPushButton(tr("Cancel"));
topLayout = new QVBoxLayout;
QHBoxLayout *hLayout = new QHBoxLayout;
hLayout->addWidget(new QLabel(tr("Video engine:")));
engineSelector = new QComboBox;
for (unsigned int i = 0; i < engines.size(); ++i) {
engineSelector->addItem(engines[i]->nameString);
}
hLayout->addWidget(engineSelector);
topLayout->addLayout(hLayout);
engineWidget = engines[0]->settingsWidget();
if (engineWidget)
topLayout->addWidget(engineWidget);
hLayout = new QHBoxLayout;
hLayout->addWidget(winResLabel);
hLayout->addWidget(winResSelector);
topLayout->addLayout(hLayout);
hLayout = new QHBoxLayout;
hLayout->addWidget(fullResLabel);
QHBoxLayout *hhLayout = new QHBoxLayout;
hhLayout->addWidget(fullResSelector);
hhLayout->addWidget(hzSelector);
hLayout->addLayout(hhLayout);
topLayout->addLayout(hLayout);
keepRatioBox = new QCheckBox(QString("Keep aspect ratio"));
topLayout->addWidget(keepRatioBox);
integerScalingBox = new QCheckBox(QString("Only scale by integer factors"));
topLayout->addWidget(integerScalingBox);
hLayout = new QHBoxLayout;
hLayout->addWidget(new QLabel(tr("Video filter:")));
filterSelector = new QComboBox;
{
unsigned maxW = 0;
unsigned maxH = 0;
for (unsigned i = 0, max = 0; i < resVector.size(); ++i) {
const unsigned cur = std::min(resVector[i].w * 9, resVector[i].h * 10);
if (cur > max) {
max = cur;
maxW = resVector[i].w;
maxH = resVector[i].h;
}
}
if (!maxW) {
maxW = 1600;
maxH = 1200;
}
for (unsigned int i = 0; i < filterInfo.size(); ++i) {
if (filterInfo[i]->outWidth <= maxW && filterInfo[i]->outHeight <= maxH)
filterSelector->addItem(filterInfo[i]->handle.c_str(), QSize(filterInfo[i]->outWidth, filterInfo[i]->outHeight));
}
}
hLayout->addWidget(filterSelector);
topLayout->addLayout(hLayout);
mainLayout->addLayout(topLayout);
mainLayout->setAlignment(topLayout, Qt::AlignTop);
hLayout = new QHBoxLayout;
hLayout->addWidget(okButton);
hLayout->addWidget(cancelButton);
mainLayout->addLayout(hLayout);
mainLayout->setAlignment(hLayout, Qt::AlignBottom | Qt::AlignRight);
okButton->setDefault(true);
connect(engineSelector, SIGNAL(currentIndexChanged(int)), this, SLOT(engineChange(int)));
connect(fullResSelector, SIGNAL(currentIndexChanged(int)), this, SLOT(fullresChange(int)));
connect(keepRatioBox, SIGNAL(toggled(bool)), this, SLOT(keepRatioChange(bool)));
connect(integerScalingBox, SIGNAL(toggled(bool)), this, SLOT(integerScalingChange(bool)));
connect(filterSelector, SIGNAL(currentIndexChanged(int)), this, SLOT(filterChange(int)));
connect(okButton, SIGNAL(clicked()), this, SLOT(accept()));
// connect(this, SIGNAL(accepted()), this, SLOT(store()));
connect(cancelButton, SIGNAL(clicked()), this, SLOT(reject()));
// connect(this, SIGNAL(rejected()), this, SLOT(restore()));
QSettings settings;
settings.beginGroup("video");
if (static_cast<unsigned>(fullIndex = settings.value("fullIndex", resHandler.currentResIndex()).toInt()) >= static_cast<unsigned>(fullResSelector->count()))
fullIndex = resHandler.currentResIndex();
if (static_cast<unsigned>(filterIndexStore = settings.value("filterIndexStore", 0).toInt()) >= static_cast<unsigned>(filterSelector->count()))
filterIndexStore = 0;
if (static_cast<unsigned>(engineIndex = settings.value("engineIndex", 0).toInt()) >= static_cast<unsigned>(engineSelector->count()))
engineIndex = 0;
restore();
store();
if (static_cast<unsigned>(winIndex = settings.value("winIndex", winResSelector->count() - 1).toInt()) >= static_cast<unsigned>(winResSelector->count()))
winIndex = winResSelector->count() - 1;
if (static_cast<unsigned>(hzIndex = settings.value("hzIndex", resHandler.currentRateIndex()).toInt()) >= static_cast<unsigned>(hzSelector->count()))
hzIndex = resHandler.currentRateIndex();
keepRatio = settings.value("keepRatio", true).toBool();
integerScaling = settings.value("integerScaling", false).toBool();
restore();
engineChange(engineIndex);
store();
settings.endGroup();
setWindowTitle(tr("Video settings"));
}
VideoDialog::~VideoDialog() {
delete winResSelectorBackup;
// delete fullResSelectorBackup;
QSettings settings;
settings.beginGroup("video");
settings.setValue("fullIndex", fullIndex);
settings.setValue("winIndex", winIndex);
settings.setValue("hzIndex", hzIndex);
settings.setValue("keepRatio", keepRatio);
settings.setValue("integerScaling", integerScaling);
settings.setValue("filterIndexStore", filterIndexStore);
settings.setValue("engineIndex", engineIndex);
settings.endGroup();
}
void VideoDialog::fillFullResSelector(const QSize &minimumRes) {
while (fullResSelector->count())
fullResSelector->removeItem(0);
for (std::size_t i = 0; i < resVector.size(); ++i) {
const int hres = resVector[i].w;
const int vres = resVector[i].h;
if (hres >= minimumRes.width() && vres >= minimumRes.height())
fullResSelector->addItem(QString::number(hres) + QString("x") + QString::number(vres), i);
}
}
void VideoDialog::store() {
engineIndex = engineSelector->currentIndex();
for (unsigned int i = 0; i < engines.size(); ++i)
engines[i]->acceptSettings();
hzIndex = hzSelector->currentIndex();
winIndex = winResSelector->currentIndex();
fullIndex = fullResSelector->currentIndex();
keepRatio = keepRatioBox->checkState() != Qt::Unchecked;
integerScaling = integerScalingBox->checkState() != Qt::Unchecked;
filterIndexStore = filterSelector->currentIndex();
}
void VideoDialog::restore() {
keepRatioBox->setChecked(keepRatio);
integerScalingBox->setChecked(integerScaling);
filterSelector->setCurrentIndex(filterIndexStore);
winResSelector->setCurrentIndex(winIndex);
fullResSelector->setCurrentIndex(fullIndex);
hzSelector->setCurrentIndex(hzIndex);
for (unsigned int i = 0;i < engines.size();++i)
engines[i]->rejectSettings();
engineSelector->setCurrentIndex(engineIndex);
}
void VideoDialog::engineChange(int index) {
if (engineWidget) {
topLayout->removeWidget(engineWidget);
engineWidget->setParent(NULL);
}
engineWidget = engines[index]->settingsWidget();
if (engineWidget)
topLayout->insertWidget(1, engineWidget);
if (engines[index]->integerOnlyScaler) {
keepRatioBox->setChecked(true);
integerScalingBox->setChecked(true);
keepRatioBox->setEnabled(false);
integerScalingBox->setEnabled(false);
} else {
keepRatioBox->setEnabled(true);
if (keepRatioBox->checkState() != Qt::Unchecked)
integerScalingBox->setEnabled(true);
}
}
void VideoDialog::fullresChange(int index) {
while (hzSelector->count())
hzSelector->removeItem(0);
if (index >= 0) {
const std::vector<short> &v = resVector[index].rates;
for (unsigned int i = 0; i < v.size(); ++i)
hzSelector->addItem(QString::number(v[i]) + QString(" Hz"), i);
}
}
void VideoDialog::filterChange(int index) {
const QSize filterSize = filterSelector->itemData(index).toSize();
{
QString oldtext = winResSelector->itemText(winResSelector->currentIndex());
while (winResSelector->count())
winResSelector->removeItem(0);
if (integerScalingBox->checkState() != Qt::Unchecked) {
QSize fSize = filterSize;
for (int i = 0;i < winResSelectorBackup->count();++i) {
QSize s = winResSelectorBackup->itemData(i).toSize();
if (s == fSize) {
winResSelector->addItem(winResSelectorBackup->itemText(i), s);
fSize += filterSize;
}
}
} else {
for (int i = 0;i < winResSelectorBackup->count();++i) {
QSize s = winResSelectorBackup->itemData(i).toSize();
if (s.width() >= filterSize.width() && s.height() >= filterSize.height())
winResSelector->addItem(winResSelectorBackup->itemText(i), s);
}
}
winResSelector->addItem(QString(tr("Variable")), QVariant(QSize(-1, -1)));
int newIndex = winResSelector->findText(oldtext);
if (newIndex >= 0)
winResSelector->setCurrentIndex(newIndex);
}
{
QString oldtext = fullResSelector->itemText(fullResSelector->currentIndex());
int oldHzIndex = hzSelector->currentIndex();
fillFullResSelector(filterSize);
int newIndex = fullResSelector->findText(oldtext);
if (newIndex >= 0) {
fullResSelector->setCurrentIndex(newIndex);
hzSelector->setCurrentIndex(oldHzIndex);
}
}
}
void VideoDialog::keepRatioChange(bool checked) {
if (integerScalingBox->checkState() != Qt::Unchecked)
integerScalingBox->setChecked(checked);
integerScalingBox->setEnabled(checked);
}
void VideoDialog::integerScalingChange(bool /*checked*/) {
filterChange(filterSelector->currentIndex());
}
const int VideoDialog::engine() const {
return engineSelector->currentIndex();
}
const QSize VideoDialog::winRes() const {
return winResSelector->itemData(winResSelector->currentIndex()).toSize();
}
const unsigned VideoDialog::fullMode() const {
//return fullResSelector->currentIndex();
// return fullResSelectorBackup->findText(fullResSelector->itemText(fullResSelector->currentIndex()));
return fullResSelector->itemData(fullResSelector->currentIndex()).toUInt();
}
const unsigned VideoDialog::fullRate() const {
return hzSelector->itemData(hzSelector->currentIndex()).toUInt();
}
bool VideoDialog::keepsRatio() const {
return keepRatio;
}
bool VideoDialog::scalesByInteger() const {
return integerScaling;
}
const unsigned int VideoDialog::filterIndex() const {
return filterSelector->currentIndex();
}
void VideoDialog::accept() {
store();
QDialog::accept();
}
void VideoDialog::reject() {
restore();
QDialog::reject();
}

View File

@ -0,0 +1,86 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef VIDEODIALOG_H
#define VIDEODIALOG_H
#include <QDialog>
#include <vector>
class QVBoxLayout;
class QHBoxLayout;
class QComboBox;
class QCheckBox;
class FilterInfo;
class BlitterWidget;
class FullResToggler;
#include "resinfo.h"
class VideoDialog : public QDialog {
Q_OBJECT
const std::vector<BlitterWidget*> &engines;
const std::vector<ResInfo>& resVector;
QVBoxLayout *topLayout;
QWidget *engineWidget;
QComboBox *engineSelector;
QComboBox *winResSelector;
QComboBox *winResSelectorBackup;
QComboBox *fullResSelector;
// QComboBox *fullResSelectorBackup;
QComboBox *hzSelector;
QCheckBox *keepRatioBox;
QCheckBox *integerScalingBox;
QComboBox *filterSelector;
int engineIndex;
int winIndex;
int fullIndex;
int hzIndex;
int filterIndexStore;
bool keepRatio;
bool integerScaling;
void fillFullResSelector(const QSize &minimum);
void store();
void restore();
private slots:
void engineChange(int index);
void fullresChange(int index);
void filterChange(int index);
void keepRatioChange(bool checked);
void integerScalingChange(bool checked);
public:
VideoDialog(const std::vector<BlitterWidget*> &engines, std::vector<const FilterInfo*> filterInfo, const FullResToggler &resHandler, QWidget *parent = 0);
~VideoDialog();
const int engine() const;
const QSize winRes() const;
const unsigned fullMode() const;
const unsigned fullRate() const;
bool keepsRatio() const;
bool scalesByInteger() const;
const unsigned int filterIndex() const;
public slots:
void accept();
void reject();
};
#endif

View File

@ -0,0 +1,45 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* Based on source code from The OpenGL Extension Wrangler Library. *
* Copyright (C) 2002-2007, Milan Ikits <milan ikits[]ieee org> *
* Copyright (C) 2002-2007, Marcelo E. Magallon <mmagallo[]debian org> *
* Copyright (C) 2002, Lev Povalahev *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "x11getprocaddress.h"
#include <dlfcn.h>
#include <GL/gl.h>
void* x11GetProcAddress(const char* name) {
static void* h = NULL;
static void* gpa;
if (h == NULL) {
if ((h = dlopen(NULL, RTLD_LAZY | RTLD_LOCAL)) == NULL)
return NULL;
if ((gpa = dlsym(h, "glXGetProcAddress")) == NULL)
gpa = dlsym(h, "glXGetProcAddressARB");
}
if (gpa != NULL)
return (reinterpret_cast<void*(*)(const GLubyte*)>(gpa))((const GLubyte*)name);
else
return dlsym(h, name);
}

View File

@ -0,0 +1,25 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef X11GETPROCADDRESS_H
#define X11GETPROCADDRESS_H
void* x11GetProcAddress(const char* name);
#endif