trailing whitespace
This commit is contained in:
parent
379ef56791
commit
1a4b00bfb6
@ -21,36 +21,36 @@
|
||||
usec_t AdaptiveSleep::sleepUntil(usec_t base, usec_t inc) {
|
||||
usec_t now = getusecs();
|
||||
usec_t diff = now - base;
|
||||
|
||||
|
||||
if (diff >= inc)
|
||||
return diff - inc;
|
||||
|
||||
|
||||
diff = inc - diff;
|
||||
|
||||
|
||||
if (diff > oversleep + oversleepVar) {
|
||||
diff -= oversleep + oversleepVar;
|
||||
usecsleep(diff);
|
||||
const usec_t ideal = now + diff;
|
||||
now = getusecs();
|
||||
|
||||
|
||||
{
|
||||
usec_t curOversleep = now - ideal;
|
||||
|
||||
|
||||
if (negate(curOversleep) < curOversleep)
|
||||
curOversleep = 0;
|
||||
|
||||
|
||||
oversleepVar = (oversleepVar * 15 + (curOversleep < oversleep ? oversleep - curOversleep : curOversleep - oversleep) + 8) >> 4;
|
||||
oversleep = (oversleep * 15 + curOversleep + 8) >> 4;
|
||||
}
|
||||
|
||||
|
||||
noSleep = 60;
|
||||
} else if (--noSleep == 0) {
|
||||
noSleep = 60;
|
||||
oversleep = oversleepVar = 0;
|
||||
}
|
||||
|
||||
|
||||
while (now - base < inc)
|
||||
now = getusecs();
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ class AdaptiveSleep {
|
||||
usec_t oversleep;
|
||||
usec_t oversleepVar;
|
||||
unsigned noSleep;
|
||||
|
||||
|
||||
public:
|
||||
AdaptiveSleep() : oversleep(0), oversleepVar(0), noSleep(60) {}
|
||||
usec_t sleepUntil(usec_t base, usec_t inc);
|
||||
|
@ -27,7 +27,7 @@ template<typename T>
|
||||
class Array : Uncopyable {
|
||||
T *a;
|
||||
std::size_t sz;
|
||||
|
||||
|
||||
public:
|
||||
explicit Array(std::size_t size = 0) : a(size ? new T[size] : 0), sz(size) {}
|
||||
~Array() { delete[] defined_ptr(a); }
|
||||
@ -40,7 +40,7 @@ public:
|
||||
template<typename T>
|
||||
class ScopedArray : Uncopyable {
|
||||
T *a_;
|
||||
|
||||
|
||||
public:
|
||||
explicit ScopedArray(T *a = 0) : a_(a) {}
|
||||
~ScopedArray() { delete[] defined_ptr(a_); }
|
||||
|
@ -25,18 +25,18 @@
|
||||
class Resampler {
|
||||
long inRate_;
|
||||
long outRate_;
|
||||
|
||||
|
||||
protected:
|
||||
void setRate(const long inRate, const long outRate) { inRate_ = inRate; outRate_ = outRate; }
|
||||
Resampler() : inRate_(0), outRate_(0) {}
|
||||
|
||||
|
||||
public:
|
||||
/** Returns the sampling rate of the input that this resampler expects. */
|
||||
long inRate() const { return inRate_; }
|
||||
|
||||
|
||||
/** Returns the approximate sampling rate of the output. */
|
||||
long outRate() const { return outRate_; }
|
||||
|
||||
|
||||
/** Can be used to adjust the input and output sampling rates slightly with minimal disturbance in the output.
|
||||
* Should only be used for slight changes or the quality could detoriate.
|
||||
* It can for instance be useful to tweak the output rate slightly to synchronize production speed to playback
|
||||
@ -47,7 +47,7 @@ public:
|
||||
* @param outRate Desired new output sampling rate.
|
||||
*/
|
||||
virtual void adjustRate(long inRate, long outRate) = 0;
|
||||
|
||||
|
||||
/** Returns the exact ratio that this resampler is configured to use,
|
||||
* such that the actual output sampling rate is (input rate) * mul / div.
|
||||
* outRate() / inRate() is not necessarily equal to mul / div.
|
||||
@ -55,12 +55,12 @@ public:
|
||||
* much whether the output sampling rate is 100% exact. Playback hardware is also slightly off.
|
||||
*/
|
||||
virtual void exactRatio(unsigned long &mul, unsigned long &div) const = 0;
|
||||
|
||||
|
||||
/** Returns an upper bound on how many samples are produced for 'inlen' input samples.
|
||||
* Can be used to calculate buffer sizes.
|
||||
*/
|
||||
virtual std::size_t maxOut(std::size_t inlen) const = 0;
|
||||
|
||||
|
||||
/** Resamples the samples in 'in' and puts the resulting samples in 'out'.
|
||||
*
|
||||
* @param inlen The number of samples in 'in' to be resampled/consumed.
|
||||
|
@ -29,7 +29,7 @@
|
||||
struct ResamplerInfo {
|
||||
/** Short character string description of the resampler. */
|
||||
const char *desc;
|
||||
|
||||
|
||||
/** Points to a function that can be used to create an instance of the resampler.
|
||||
* @param inRate The input sampling rate.
|
||||
* @param outRate The desired output sampling rate.
|
||||
@ -37,13 +37,13 @@ struct ResamplerInfo {
|
||||
* @return Pointer to the created instance (on the heap). Caller must free this with the delete operator.
|
||||
*/
|
||||
Resampler* (*create)(long inRate, long outRate, std::size_t periodSz);
|
||||
|
||||
|
||||
/** Returns the number of ResamplerInfos that can be gotten with get(). */
|
||||
static std::size_t num() { return num_; }
|
||||
|
||||
|
||||
/** Returns ResamplerInfo number n. Where n is less than num(). */
|
||||
static const ResamplerInfo& get(std::size_t n) { return resamplers[n]; }
|
||||
|
||||
|
||||
private:
|
||||
static const ResamplerInfo resamplers[];
|
||||
static const std::size_t num_;
|
||||
|
@ -48,27 +48,27 @@ public:
|
||||
const float widthTimesTaps = 4.5f;
|
||||
return std::max(static_cast<unsigned>(std::ceil(widthTimesTaps / rollOffWidth)), 4u);
|
||||
}
|
||||
|
||||
|
||||
static float toFc(const float rollOffStart, const int taps) {
|
||||
const float startToFcDeltaTimesTaps = 1.69f;
|
||||
return startToFcDeltaTimesTaps / taps + rollOffStart;
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
const unsigned taps;
|
||||
const float fc;
|
||||
|
||||
|
||||
RollOff(float rollOffStart, float rollOffWidth) : taps(toTaps(rollOffWidth)), fc(toFc(rollOffStart, taps)) {}
|
||||
};
|
||||
|
||||
BlackmanSinc(unsigned div, unsigned phaseLen, double fc)
|
||||
: kernel(phaseLen * phases), convoluter_(kernel, phaseLen, div)
|
||||
{ makeSincKernel(kernel, phases, phaseLen, fc, blackmanWin, 1.0); }
|
||||
|
||||
|
||||
BlackmanSinc(unsigned div, RollOff ro, double gain)
|
||||
: kernel(ro.taps * phases), convoluter_(kernel, ro.taps, div)
|
||||
{ makeSincKernel(kernel, phases, ro.taps, ro.fc, blackmanWin, gain);}
|
||||
|
||||
|
||||
std::size_t resample(short *out, const short *in, std::size_t inlen) { return convoluter_.filter(out, in, inlen); }
|
||||
void adjustDiv(unsigned div) { convoluters_.adjustDiv(div); }
|
||||
unsigned mul() const { return MUL; }
|
||||
|
@ -63,17 +63,17 @@ void ChainResampler::downinitAddSincResamplers(double ratio, float const outRate
|
||||
// For high outRate: Start roll-off at 36000 Hz continue until outRate Hz, then wrap around back down to 40000 Hz.
|
||||
const float outPeriod = 1.0f / outRate;
|
||||
const float finalRollOffLen = std::max((outRate - 36000.0f + outRate - 40000.0f) * outPeriod, 0.2f);
|
||||
|
||||
|
||||
{
|
||||
const float midRollOffStart = std::min(36000.0f * outPeriod, 1.0f);
|
||||
const float midRollOffEnd = std::min(40000.0f * outPeriod, 1.0f); // after wrap at folding freq.
|
||||
const float midRollOffStartPlusEnd = midRollOffStart + midRollOffEnd;
|
||||
const float ideal2ChainMidRatio = get2ChainMidRatio(ratio, finalRollOffLen, midRollOffStartPlusEnd);
|
||||
|
||||
|
||||
int div_2c = int(ratio * smallSincMul / ideal2ChainMidRatio + 0.5f);
|
||||
double ratio_2c = ratio * smallSincMul / div_2c;
|
||||
float cost_2c = get2ChainCost(ratio, finalRollOffLen, ratio_2c, midRollOffStartPlusEnd);
|
||||
|
||||
|
||||
if (cost_2c < get1ChainCost(ratio, finalRollOffLen)) {
|
||||
const float ideal3ChainRatio1 = get3ChainRatio1(ratio_2c, finalRollOffLen,
|
||||
ratio, midRollOffStartPlusEnd);
|
||||
@ -83,7 +83,7 @@ void ChainResampler::downinitAddSincResamplers(double ratio, float const outRate
|
||||
midRollOffStartPlusEnd);
|
||||
const int div2_3c = int(ratio1_3c * smallSincMul / ideal3ChainRatio2 + 0.5f);
|
||||
const double ratio2_3c = ratio1_3c * smallSincMul / div2_3c;
|
||||
|
||||
|
||||
if (get3ChainCost(ratio, finalRollOffLen, ratio1_3c,
|
||||
ratio2_3c, midRollOffStartPlusEnd) < cost_2c) {
|
||||
list.push_back(createSmallSinc(div1_3c,
|
||||
@ -95,7 +95,7 @@ void ChainResampler::downinitAddSincResamplers(double ratio, float const outRate
|
||||
ratio_2c = ratio2_3c;
|
||||
gain = 1.0;
|
||||
}
|
||||
|
||||
|
||||
list.push_back(createSmallSinc(div_2c,
|
||||
0.5f * midRollOffStart / ratio,
|
||||
(ratio_2c - 0.5f * midRollOffStartPlusEnd) / ratio,
|
||||
@ -104,7 +104,7 @@ void ChainResampler::downinitAddSincResamplers(double ratio, float const outRate
|
||||
gain = 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
list.push_back(bigSinc =
|
||||
createBigSinc(int(bigSincMul * ratio + 0.5),
|
||||
0.5f * (1.0f + std::max((outRate - 40000.0f) * outPeriod, 0.0f) - finalRollOffLen) / ratio,
|
||||
@ -115,24 +115,24 @@ std::size_t ChainResampler::reallocateBuffer() {
|
||||
std::size_t bufSz[2] = { 0, 0 };
|
||||
std::size_t inSz = periodSize;
|
||||
int i = -1;
|
||||
|
||||
|
||||
for (list_t::iterator it = list.begin(); it != list.end(); ++it) {
|
||||
inSz = (inSz * (*it)->mul() - 1) / (*it)->div() + 1;
|
||||
|
||||
|
||||
++i;
|
||||
|
||||
|
||||
if (inSz > bufSz[i&1])
|
||||
bufSz[i&1] = inSz;
|
||||
}
|
||||
|
||||
|
||||
if (inSz >= bufSz[i&1])
|
||||
bufSz[i&1] = 0;
|
||||
|
||||
|
||||
if (buffer.size() < (bufSz[0] + bufSz[1]) * channels)
|
||||
buffer.reset((bufSz[0] + bufSz[1]) * channels);
|
||||
|
||||
|
||||
buffer2 = bufSz[1] ? buffer + bufSz[0] * channels : 0;
|
||||
|
||||
|
||||
return (maxOut_ = inSz);
|
||||
}
|
||||
|
||||
@ -148,7 +148,7 @@ void ChainResampler::adjustRate(const long inRate, const long outRate) {
|
||||
void ChainResampler::exactRatio(unsigned long &mul, unsigned long &div) const {
|
||||
mul = 1;
|
||||
div = 1;
|
||||
|
||||
|
||||
for (list_t::const_iterator it = list.begin(); it != list.end(); ++it) {
|
||||
mul *= (*it)->mul();
|
||||
div *= (*it)->div();
|
||||
@ -157,13 +157,13 @@ void ChainResampler::exactRatio(unsigned long &mul, unsigned long &div) const {
|
||||
|
||||
std::size_t ChainResampler::resample(short *const out, const short *const in, std::size_t inlen) {
|
||||
assert(inlen <= periodSize);
|
||||
|
||||
|
||||
short *const buf = buffer != buffer2 ? buffer : out;
|
||||
short *const buf2 = buffer2 ? buffer2 : out;
|
||||
|
||||
|
||||
const short *inbuf = in;
|
||||
short *outbuf = 0;
|
||||
|
||||
|
||||
for (list_t::iterator it = list.begin(); it != list.end(); ++it) {
|
||||
outbuf = ++list_t::iterator(it) == list.end()
|
||||
? out
|
||||
@ -171,7 +171,7 @@ std::size_t ChainResampler::resample(short *const out, const short *const in, st
|
||||
inlen = (*it)->resample(outbuf, inbuf, inlen);
|
||||
inbuf = outbuf;
|
||||
}
|
||||
|
||||
|
||||
return inlen;
|
||||
}
|
||||
|
||||
|
@ -32,14 +32,14 @@
|
||||
class ChainResampler : public Resampler {
|
||||
typedef std::list<SubResampler*> list_t;
|
||||
typedef SubResampler * (*CreateSinc)(unsigned div, float rollOffStart, float rollOffWidth, double gain);
|
||||
|
||||
|
||||
list_t list;
|
||||
SubResampler *bigSinc;
|
||||
Array<short> buffer;
|
||||
short *buffer2;
|
||||
std::size_t periodSize;
|
||||
std::size_t maxOut_;
|
||||
|
||||
|
||||
static float get1ChainCost(float ratio, float finalRollOffLen) { return ratio / finalRollOffLen; }
|
||||
|
||||
static float get2ChainMidRatio(float ratio, float finalRollOffLen, float midRollOffStartPlusEnd);
|
||||
@ -51,32 +51,32 @@ class ChainResampler : public Resampler {
|
||||
|
||||
static float get3ChainRatio1(float ratio1, float finalRollOffLen, float ratio, float midRollOffStartPlusEnd);
|
||||
static float get3ChainCost(float ratio, float finalRollOffLen, float ratio1, float ratio2, float midRollOffStartPlusEnd);
|
||||
|
||||
|
||||
void downinitAddSincResamplers(double ratio, float outRate,
|
||||
CreateSinc createBigSinc, CreateSinc createSmallSinc,
|
||||
unsigned bigSincMul, unsigned smallSincMul, double gain);
|
||||
|
||||
|
||||
template<class Sinc>
|
||||
static SubResampler * createSinc(unsigned div, float rollOffStart, float rollOffWidth, double gain) {
|
||||
return new Sinc(div, typename Sinc::RollOff(rollOffStart, rollOffWidth), gain);
|
||||
}
|
||||
|
||||
|
||||
template<template<unsigned,unsigned> class Sinc>
|
||||
std::size_t downinit(long inRate, long outRate, std::size_t periodSize);
|
||||
|
||||
|
||||
template<template<unsigned,unsigned> class Sinc>
|
||||
std::size_t upinit(long inRate, long outRate, std::size_t periodSize);
|
||||
|
||||
|
||||
std::size_t reallocateBuffer();
|
||||
|
||||
|
||||
public:
|
||||
enum { channels = 2 };
|
||||
ChainResampler();
|
||||
~ChainResampler() { uninit(); }
|
||||
|
||||
|
||||
void adjustRate(long inRate, long outRate);
|
||||
void exactRatio(unsigned long &mul, unsigned long &div) const;
|
||||
|
||||
|
||||
template<template<unsigned,unsigned> class Sinc>
|
||||
std::size_t init(long inRate, long outRate, std::size_t periodSize);
|
||||
std::size_t maxOut(std::size_t /*inlen*/) const { return maxOut_; }
|
||||
@ -87,7 +87,7 @@ public:
|
||||
template<template<unsigned,unsigned> class Sinc>
|
||||
std::size_t ChainResampler::init(const long inRate, const long outRate, const std::size_t periodSize) {
|
||||
setRate(inRate, outRate);
|
||||
|
||||
|
||||
if (outRate > inRate)
|
||||
return upinit<Sinc>(inRate, outRate, periodSize);
|
||||
else
|
||||
@ -98,23 +98,23 @@ template<template<unsigned,unsigned> class Sinc>
|
||||
std::size_t ChainResampler::downinit(const long inRate, const long outRate, const std::size_t periodSize) {
|
||||
typedef Sinc<channels,2048> BigSinc;
|
||||
typedef Sinc<channels, 32> SmallSinc;
|
||||
|
||||
|
||||
uninit();
|
||||
this->periodSize = periodSize;
|
||||
|
||||
|
||||
double ratio = static_cast<double>(inRate) / outRate;
|
||||
double gain = 1.0;
|
||||
|
||||
|
||||
while (ratio >= BigSinc::cicLimit() * 2) {
|
||||
const int div = std::min<int>(static_cast<int>(ratio / BigSinc::cicLimit()), BigSinc::Cic::MAX_DIV);
|
||||
list.push_back(new typename BigSinc::Cic(div));
|
||||
ratio /= div;
|
||||
gain *= 1.0 / BigSinc::Cic::gain(div);
|
||||
}
|
||||
|
||||
|
||||
downinitAddSincResamplers(ratio, outRate, createSinc<BigSinc>,
|
||||
createSinc<SmallSinc>, BigSinc::MUL, SmallSinc::MUL, gain);
|
||||
|
||||
|
||||
return reallocateBuffer();
|
||||
}
|
||||
|
||||
@ -125,47 +125,47 @@ std::size_t ChainResampler::upinit(const long inRate, const long outRate, const
|
||||
|
||||
uninit();
|
||||
this->periodSize = periodSize;
|
||||
|
||||
|
||||
double ratio = static_cast<double>(outRate) / inRate;
|
||||
|
||||
|
||||
// Spectral images above 20 kHz assumed inaudible
|
||||
{
|
||||
const int div = outRate / std::max(inRate, 40000l);
|
||||
|
||||
|
||||
if (div >= 2) {
|
||||
list.push_front(new Upsampler<channels>(div));
|
||||
ratio /= div;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const float rollOff = std::max((inRate - 36000.0f) / inRate, 0.2f);
|
||||
|
||||
|
||||
/*{
|
||||
int div_2c = get2ChainMidRatio(ratio, rollOff) * SmallSinc::MUL / ratio + 0.5f;
|
||||
double ratio_2c = ratio * div_2c / SmallSinc::MUL;
|
||||
float cost_2c = get2ChainCost(ratio, rollOff, ratio_2c);
|
||||
|
||||
|
||||
if (cost_2c < get1ChainCost(ratio, rollOff)) {
|
||||
const int div1_3c = get3ChainRatio1(ratio_2c, rollOff, ratio) * SmallSinc::MUL / ratio + 0.5f;
|
||||
const double ratio1_3c = ratio * div1_3c / SmallSinc::MUL;
|
||||
const int div2_3c = get3ChainRatio2(ratio1_3c, rollOff) * SmallSinc::MUL / ratio1_3c + 0.5f;
|
||||
const double ratio2_3c = ratio1_3c * div2_3c / SmallSinc::MUL;
|
||||
|
||||
|
||||
if (get3ChainCost(ratio, rollOff, ratio1_3c, ratio2_3c) < cost_2c) {
|
||||
list.push_front(new SmallSinc(div1_3c, typename SmallSinc::RollOff(0.5f / ratio1_3c, (ratio1_3c - 1) / ratio1_3c), 1.0));
|
||||
ratio = ratio1_3c;
|
||||
div_2c = div2_3c;
|
||||
ratio_2c = ratio2_3c;
|
||||
}
|
||||
|
||||
|
||||
list.push_front(new SmallSinc(div_2c, typename SmallSinc::RollOff(0.5f / ratio_2c, (ratio_2c - 1) / ratio_2c), 1.0));
|
||||
ratio = ratio_2c;
|
||||
}
|
||||
}*/
|
||||
|
||||
|
||||
list.push_front(bigSinc = new BigSinc(static_cast<int>(BigSinc::MUL / ratio + 0.5),
|
||||
typename BigSinc::RollOff(0.5f * (1 - rollOff), 0.5f * rollOff), 1.0));
|
||||
|
||||
|
||||
return reallocateBuffer();
|
||||
}
|
||||
|
||||
|
@ -22,7 +22,7 @@
|
||||
#include "subresampler.h"
|
||||
#include "rshift16_round.h"
|
||||
|
||||
template<unsigned channels>
|
||||
template<unsigned channels>
|
||||
class Cic2Core {
|
||||
// enum { BUFLEN = 64 };
|
||||
// unsigned long buf[BUFLEN];
|
||||
@ -33,10 +33,10 @@ class Cic2Core {
|
||||
unsigned div_;
|
||||
unsigned nextdivn;
|
||||
// unsigned bufpos;
|
||||
|
||||
|
||||
// trouble if div is too large, may be better to only support power of 2 div
|
||||
static long mulForDiv(unsigned div) { return 0x10000 / (div * div); }
|
||||
|
||||
|
||||
public:
|
||||
explicit Cic2Core(const unsigned div = 2) { reset(div); }
|
||||
unsigned div() const { return div_; }
|
||||
@ -45,7 +45,7 @@ public:
|
||||
static double gain(unsigned div) { return rshift16_round(-32768l * (div * div) * mulForDiv(div)) / -32768.0; }
|
||||
};
|
||||
|
||||
template<unsigned channels>
|
||||
template<unsigned channels>
|
||||
void Cic2Core<channels>::reset(const unsigned div) {
|
||||
sum2 = sum1 = 0;
|
||||
/*prev2 = */prev1 = 0;
|
||||
@ -60,15 +60,15 @@ std::size_t Cic2Core<channels>::filter(short *out, const short *const in, std::s
|
||||
const std::size_t produced = (inlen + div_ - nextdivn) / div_;
|
||||
const long mul = mulForDiv(div_);
|
||||
const short *s = in;
|
||||
|
||||
|
||||
/*unsigned long sm1 = sum1;
|
||||
unsigned long sm2 = sum2;
|
||||
|
||||
|
||||
while (inlen >> 2) {
|
||||
unsigned n = (inlen < BUFLEN ? inlen >> 2 : BUFLEN >> 2);
|
||||
const unsigned end = n * 4;
|
||||
unsigned i = 0;
|
||||
|
||||
|
||||
do {
|
||||
unsigned long s1 = sm1 += static_cast<long>(*s);
|
||||
s += channels;
|
||||
@ -83,74 +83,74 @@ std::size_t Cic2Core<channels>::filter(short *out, const short *const in, std::s
|
||||
buf[i++] = sm2 += s1;
|
||||
buf[i++] = sm2 += sm1;
|
||||
} while (--n);
|
||||
|
||||
|
||||
while (bufpos < end) {
|
||||
const unsigned long out2 = buf[bufpos] - prev2;
|
||||
prev2 = buf[bufpos];
|
||||
bufpos += div_;
|
||||
|
||||
|
||||
*out = rshift16_round(static_cast<long>(out2 - prev1) * mul);
|
||||
prev1 = out2;
|
||||
out += channels;
|
||||
}
|
||||
|
||||
|
||||
bufpos -= end;
|
||||
inlen -= end;
|
||||
}
|
||||
|
||||
|
||||
if (inlen) {
|
||||
unsigned n = inlen;
|
||||
unsigned i = 0;
|
||||
|
||||
|
||||
do {
|
||||
sm1 += static_cast<long>(*s);
|
||||
s += channels;
|
||||
buf[i++] = sm2 += sm1;
|
||||
} while (--n);
|
||||
|
||||
|
||||
while (bufpos < inlen) {
|
||||
const unsigned long out2 = buf[bufpos] - prev2;
|
||||
prev2 = buf[bufpos];
|
||||
bufpos += div_;
|
||||
|
||||
|
||||
*out = rshift16_round(static_cast<long>(out2 - prev1) * mul);
|
||||
prev1 = out2;
|
||||
out += channels;
|
||||
}
|
||||
|
||||
|
||||
bufpos -= inlen;
|
||||
}
|
||||
|
||||
|
||||
sum1 = sm1;
|
||||
sum2 = sm2;*/
|
||||
|
||||
|
||||
unsigned long sm1 = sum1;
|
||||
unsigned long sm2 = sum2;
|
||||
|
||||
|
||||
if (inlen >= nextdivn) {
|
||||
{
|
||||
unsigned divn = nextdivn;
|
||||
|
||||
|
||||
do {
|
||||
sm1 += static_cast<long>(*s);
|
||||
s += channels;
|
||||
sm2 += sm1;
|
||||
} while (--divn);
|
||||
|
||||
|
||||
const unsigned long out2 = sm2;
|
||||
sm2 = 0;
|
||||
|
||||
|
||||
*out = rshift16_round(static_cast<long>(out2 - prev1) * mul);
|
||||
prev1 = out2;
|
||||
out += channels;
|
||||
}
|
||||
|
||||
|
||||
if (div_ & 1) {
|
||||
std::size_t n = produced;
|
||||
|
||||
|
||||
while (--n) {
|
||||
unsigned divn = div_ >> 1;
|
||||
|
||||
|
||||
do {
|
||||
sm1 += static_cast<long>(*s);
|
||||
s += channels;
|
||||
@ -159,11 +159,11 @@ std::size_t Cic2Core<channels>::filter(short *out, const short *const in, std::s
|
||||
s += channels;
|
||||
sm2 += sm1;
|
||||
} while (--divn);
|
||||
|
||||
|
||||
sm1 += static_cast<long>(*s);
|
||||
s += channels;
|
||||
sm2 += sm1;
|
||||
|
||||
|
||||
*out = rshift16_round(static_cast<long>(sm2 - prev1) * mul);
|
||||
out += channels;
|
||||
prev1 = sm2;
|
||||
@ -171,10 +171,10 @@ std::size_t Cic2Core<channels>::filter(short *out, const short *const in, std::s
|
||||
}
|
||||
} else {
|
||||
std::size_t n = produced;
|
||||
|
||||
|
||||
while (--n) {
|
||||
unsigned divn = div_ >> 1;
|
||||
|
||||
|
||||
do {
|
||||
sm1 += static_cast<long>(*s);
|
||||
s += channels;
|
||||
@ -183,38 +183,38 @@ std::size_t Cic2Core<channels>::filter(short *out, const short *const in, std::s
|
||||
s += channels;
|
||||
sm2 += sm1;
|
||||
} while (--divn);
|
||||
|
||||
|
||||
*out = rshift16_round(static_cast<long>(sm2 - prev1) * mul);
|
||||
out += channels;
|
||||
prev1 = sm2;
|
||||
sm2 = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
nextdivn = div_;
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
unsigned divn = (in + inlen * channels - s) / channels;
|
||||
nextdivn -= divn;
|
||||
|
||||
|
||||
while (divn--) {
|
||||
sm1 += static_cast<long>(*s);
|
||||
s += channels;
|
||||
sm2 += sm1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sum1 = sm1;
|
||||
sum2 = sm2;
|
||||
|
||||
|
||||
return produced;
|
||||
}
|
||||
|
||||
template<unsigned channels>
|
||||
class Cic2 : public SubResampler {
|
||||
Cic2Core<channels> cics[channels];
|
||||
|
||||
|
||||
public:
|
||||
enum { MAX_DIV = 64 };
|
||||
explicit Cic2(unsigned div);
|
||||
@ -233,11 +233,11 @@ Cic2<channels>::Cic2(const unsigned div) {
|
||||
template<unsigned channels>
|
||||
std::size_t Cic2<channels>::resample(short *const out, const short *const in, const std::size_t inlen) {
|
||||
std::size_t samplesOut;
|
||||
|
||||
|
||||
for (unsigned i = 0; i < channels; ++i) {
|
||||
samplesOut = cics[i].filter(out + i, in + i, inlen);
|
||||
}
|
||||
|
||||
|
||||
return samplesOut;
|
||||
}
|
||||
|
||||
|
@ -22,7 +22,7 @@
|
||||
#include "subresampler.h"
|
||||
#include "rshift16_round.h"
|
||||
|
||||
template<unsigned channels>
|
||||
template<unsigned channels>
|
||||
class Cic3Core {
|
||||
// enum { BUFLEN = 64 };
|
||||
// unsigned long buf[BUFLEN];
|
||||
@ -34,10 +34,10 @@ class Cic3Core {
|
||||
unsigned div_;
|
||||
unsigned nextdivn;
|
||||
// unsigned bufpos;
|
||||
|
||||
|
||||
// trouble if div is too large, may be better to only support power of 2 div
|
||||
static long mulForDiv(unsigned div) { return 0x10000 / (div * div * div); }
|
||||
|
||||
|
||||
public:
|
||||
explicit Cic3Core(const unsigned div = 1) { reset(div); }
|
||||
unsigned div() const { return div_; }
|
||||
@ -46,7 +46,7 @@ public:
|
||||
static double gain(unsigned div) { return rshift16_round(-32768l * (div * div * div) * mulForDiv(div)) / -32768.0; }
|
||||
};
|
||||
|
||||
template<unsigned channels>
|
||||
template<unsigned channels>
|
||||
void Cic3Core<channels>::reset(const unsigned div) {
|
||||
sum3 = sum2 = sum1 = 0;
|
||||
prev2 = prev1 = 0;
|
||||
@ -60,16 +60,16 @@ std::size_t Cic3Core<channels>::filter(short *out, const short *const in, std::s
|
||||
// const std::size_t produced = (inlen + div_ - (bufpos + 1)) / div_;
|
||||
const std::size_t produced = (inlen + div_ - nextdivn) / div_;
|
||||
const short *s = in;
|
||||
|
||||
|
||||
/*unsigned long sm1 = sum1;
|
||||
unsigned long sm2 = sum2;
|
||||
unsigned long sm3 = sum3;
|
||||
|
||||
|
||||
while (inlen >> 1) {
|
||||
unsigned n = (inlen < BUFLEN ? inlen >> 1 : BUFLEN >> 1);
|
||||
const unsigned end = n * 2;
|
||||
unsigned i = 0;
|
||||
|
||||
|
||||
do {
|
||||
unsigned long s1 = sm1 += static_cast<long>(*s);
|
||||
s += channels;
|
||||
@ -80,65 +80,65 @@ std::size_t Cic3Core<channels>::filter(short *out, const short *const in, std::s
|
||||
buf[i++] = sm3 += s2;
|
||||
buf[i++] = sm3 += sm2;
|
||||
} while (--n);
|
||||
|
||||
|
||||
while (bufpos < end) {
|
||||
const unsigned long out3 = buf[bufpos] - prev3;
|
||||
prev3 = buf[bufpos];
|
||||
bufpos += div_;
|
||||
|
||||
|
||||
const unsigned long out2 = out3 - prev2;
|
||||
prev2 = out3;
|
||||
|
||||
|
||||
*out = rshift16_round(static_cast<long>(out2 - prev1) * mul);
|
||||
prev1 = out2;
|
||||
out += channels;
|
||||
}
|
||||
|
||||
|
||||
bufpos -= end;
|
||||
inlen -= end;
|
||||
}
|
||||
|
||||
|
||||
if (inlen) {
|
||||
unsigned n = inlen;
|
||||
unsigned i = 0;
|
||||
|
||||
|
||||
do {
|
||||
sm1 += static_cast<long>(*s);
|
||||
s += channels;
|
||||
sm2 += sm1;
|
||||
buf[i++] = sm3 += sm2;
|
||||
} while (--n);
|
||||
|
||||
|
||||
while (bufpos < inlen) {
|
||||
const unsigned long out3 = buf[bufpos] - prev3;
|
||||
prev3 = buf[bufpos];
|
||||
bufpos += div_;
|
||||
|
||||
|
||||
const unsigned long out2 = out3 - prev2;
|
||||
prev2 = out3;
|
||||
|
||||
|
||||
*out = rshift16_round(static_cast<long>(out2 - prev1) * mul);
|
||||
prev1 = out2;
|
||||
out += channels;
|
||||
}
|
||||
|
||||
|
||||
bufpos -= inlen;
|
||||
}
|
||||
|
||||
|
||||
sum1 = sm1;
|
||||
sum2 = sm2;
|
||||
sum3 = sm3;*/
|
||||
|
||||
|
||||
|
||||
|
||||
unsigned long sm1 = sum1;
|
||||
unsigned long sm2 = sum2;
|
||||
unsigned long sm3 = sum3;
|
||||
|
||||
|
||||
if (inlen >= nextdivn) {
|
||||
const long mul = mulForDiv(div_);
|
||||
unsigned divn = nextdivn;
|
||||
std::size_t n = produced;
|
||||
|
||||
|
||||
do {
|
||||
do {
|
||||
sm1 += static_cast<long>(*s);
|
||||
@ -146,7 +146,7 @@ std::size_t Cic3Core<channels>::filter(short *out, const short *const in, std::s
|
||||
sm3 += sm2;
|
||||
s += channels;
|
||||
} while (--divn);
|
||||
|
||||
|
||||
const unsigned long out2 = sm3 - prev2;
|
||||
prev2 = sm3;
|
||||
*out = rshift16_round(static_cast<long>(out2 - prev1) * mul);
|
||||
@ -155,14 +155,14 @@ std::size_t Cic3Core<channels>::filter(short *out, const short *const in, std::s
|
||||
divn = div_;
|
||||
sm3 = 0;
|
||||
} while (--n);
|
||||
|
||||
|
||||
nextdivn = div_;
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
unsigned divn = (in + inlen * channels - s) / channels;
|
||||
nextdivn -= divn;
|
||||
|
||||
|
||||
while (divn--) {
|
||||
sm1 += static_cast<long>(*s);
|
||||
sm2 += sm1;
|
||||
@ -170,15 +170,15 @@ std::size_t Cic3Core<channels>::filter(short *out, const short *const in, std::s
|
||||
s += channels;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sum1 = sm1;
|
||||
sum2 = sm2;
|
||||
sum3 = sm3;
|
||||
|
||||
|
||||
return produced;
|
||||
}
|
||||
|
||||
/*template<unsigned channels>
|
||||
/*template<unsigned channels>
|
||||
class Cic3EvenOddCore {
|
||||
unsigned long sum1;
|
||||
unsigned long sum2;
|
||||
@ -188,25 +188,25 @@ class Cic3EvenOddCore {
|
||||
unsigned long prev3;
|
||||
unsigned div_;
|
||||
unsigned nextdivn;
|
||||
|
||||
|
||||
static int getMul(unsigned div) {
|
||||
return 0x10000 / (div * div * div); // trouble if div is too large, may be better to only support power of 2 div
|
||||
}
|
||||
|
||||
|
||||
void filterEven(short *out, const short *s, std::size_t n);
|
||||
void filterOdd(short *out, const short *s, std::size_t n);
|
||||
|
||||
|
||||
public:
|
||||
Cic3EvenOddCore(const unsigned div = 2) {
|
||||
reset(div);
|
||||
}
|
||||
|
||||
|
||||
unsigned div() const { return div_; }
|
||||
std::size_t filter(short *out, const short *in, std::size_t inlen);
|
||||
void reset(unsigned div);
|
||||
};
|
||||
|
||||
template<unsigned channels>
|
||||
template<unsigned channels>
|
||||
void Cic3EvenOddCore<channels>::reset(const unsigned div) {
|
||||
sum3 = sum2 = sum1 = 0;
|
||||
prev3 = prev2 = prev1 = 0;
|
||||
@ -220,11 +220,11 @@ void Cic3EvenOddCore<channels>::filterEven(short *out, const short *s, std::size
|
||||
unsigned long sm1 = sum1;
|
||||
unsigned long sm2 = sum2;
|
||||
unsigned long sm3 = sum3;
|
||||
|
||||
|
||||
while (n--) {
|
||||
{
|
||||
unsigned sn = div_ >> 1;
|
||||
|
||||
|
||||
do {
|
||||
unsigned long s1 = sm1 += static_cast<long>(*s);
|
||||
s += channels;
|
||||
@ -236,7 +236,7 @@ void Cic3EvenOddCore<channels>::filterEven(short *out, const short *s, std::size
|
||||
sm3 += sm2;
|
||||
} while (--sn);
|
||||
}
|
||||
|
||||
|
||||
const unsigned long out3 = sm3 - prev3;
|
||||
prev3 = sm3;
|
||||
const unsigned long out2 = out3 - prev2;
|
||||
@ -245,7 +245,7 @@ void Cic3EvenOddCore<channels>::filterEven(short *out, const short *s, std::size
|
||||
prev1 = out2;
|
||||
out += channels;
|
||||
}
|
||||
|
||||
|
||||
sum1 = sm1;
|
||||
sum2 = sm2;
|
||||
sum3 = sm3;
|
||||
@ -257,11 +257,11 @@ void Cic3EvenOddCore<channels>::filterOdd(short *out, const short *s, std::size_
|
||||
unsigned long sm1 = sum1;
|
||||
unsigned long sm2 = sum2;
|
||||
unsigned long sm3 = sum3;
|
||||
|
||||
|
||||
while (n--) {
|
||||
{
|
||||
unsigned sn = div_ >> 1;
|
||||
|
||||
|
||||
do {
|
||||
unsigned long s1 = sm1 += static_cast<long>(*s);
|
||||
s += channels;
|
||||
@ -273,12 +273,12 @@ void Cic3EvenOddCore<channels>::filterOdd(short *out, const short *s, std::size_
|
||||
sm3 += sm2;
|
||||
} while (--sn);
|
||||
}
|
||||
|
||||
|
||||
sm1 += static_cast<long>(*s);
|
||||
s += channels;
|
||||
sm2 += sm1;
|
||||
sm3 += sm2;
|
||||
|
||||
|
||||
const unsigned long out3 = sm3 - prev3;
|
||||
prev3 = sm3;
|
||||
const unsigned long out2 = out3 - prev2;
|
||||
@ -287,7 +287,7 @@ void Cic3EvenOddCore<channels>::filterOdd(short *out, const short *s, std::size_
|
||||
prev1 = out2;
|
||||
out += channels;
|
||||
}
|
||||
|
||||
|
||||
sum1 = sm1;
|
||||
sum2 = sm2;
|
||||
sum3 = sm3;
|
||||
@ -297,12 +297,12 @@ template<unsigned channels>
|
||||
std::size_t Cic3EvenOddCore<channels>::filter(short *out, const short *const in, std::size_t inlen) {
|
||||
short *const outStart = out;
|
||||
const short *s = in;
|
||||
|
||||
|
||||
if (inlen >= nextdivn) {
|
||||
{
|
||||
{
|
||||
unsigned divn = nextdivn;
|
||||
|
||||
|
||||
do {
|
||||
sum1 += static_cast<long>(*s);
|
||||
s += channels;
|
||||
@ -310,7 +310,7 @@ std::size_t Cic3EvenOddCore<channels>::filter(short *out, const short *const in,
|
||||
sum3 += sum2;
|
||||
} while (--divn);
|
||||
}
|
||||
|
||||
|
||||
const unsigned long out3 = sum3 - prev3;
|
||||
prev3 = sum3;
|
||||
const unsigned long out2 = out3 - prev2;
|
||||
@ -319,23 +319,23 @@ std::size_t Cic3EvenOddCore<channels>::filter(short *out, const short *const in,
|
||||
prev1 = out2;
|
||||
out += channels;
|
||||
}
|
||||
|
||||
|
||||
std::size_t n = (inlen - nextdivn) / div_;
|
||||
|
||||
|
||||
if (div_ & 1)
|
||||
filterOdd(out, s, n);
|
||||
else
|
||||
filterEven(out, s, n);
|
||||
|
||||
|
||||
s += n * div_ * channels;
|
||||
out += n * channels;
|
||||
nextdivn = div_;
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
unsigned divn = inlen - (s - in) / channels;
|
||||
nextdivn -= divn;
|
||||
|
||||
|
||||
while (divn--) {
|
||||
sum1 += static_cast<long>(*s);
|
||||
s += channels;
|
||||
@ -343,14 +343,14 @@ std::size_t Cic3EvenOddCore<channels>::filter(short *out, const short *const in,
|
||||
sum3 += sum2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return (out - outStart) / channels;
|
||||
}*/
|
||||
|
||||
template<unsigned channels>
|
||||
class Cic3 : public SubResampler {
|
||||
Cic3Core<channels> cics[channels];
|
||||
|
||||
|
||||
public:
|
||||
enum { MAX_DIV = 23 };
|
||||
explicit Cic3(unsigned div);
|
||||
@ -369,11 +369,11 @@ Cic3<channels>::Cic3(const unsigned div) {
|
||||
template<unsigned channels>
|
||||
std::size_t Cic3<channels>::resample(short *const out, const short *const in, const std::size_t inlen) {
|
||||
std::size_t samplesOut;
|
||||
|
||||
|
||||
for (unsigned i = 0; i < channels; ++i) {
|
||||
samplesOut = cics[i].filter(out + i, in + i, inlen);
|
||||
}
|
||||
|
||||
|
||||
return samplesOut;
|
||||
}
|
||||
|
||||
|
@ -22,7 +22,7 @@
|
||||
#include "subresampler.h"
|
||||
#include "rshift16_round.h"
|
||||
|
||||
template<unsigned channels>
|
||||
template<unsigned channels>
|
||||
class Cic4Core {
|
||||
enum { BUFLEN = 64 };
|
||||
unsigned long buf[BUFLEN];
|
||||
@ -37,10 +37,10 @@ class Cic4Core {
|
||||
unsigned div_;
|
||||
// unsigned nextdivn;
|
||||
unsigned bufpos;
|
||||
|
||||
|
||||
// trouble if div is too large, may be better to only support power of 2 div
|
||||
static long mulForDiv(unsigned div) { return 0x10000 / (div * div * div * div); }
|
||||
|
||||
|
||||
public:
|
||||
explicit Cic4Core(const unsigned div = 1) { reset(div); }
|
||||
unsigned div() const { return div_; }
|
||||
@ -49,7 +49,7 @@ public:
|
||||
static double gain(unsigned div) { return rshift16_round(-32768l * (div * div * div * div) * mulForDiv(div)) / -32768.0; }
|
||||
};
|
||||
|
||||
template<unsigned channels>
|
||||
template<unsigned channels>
|
||||
void Cic4Core<channels>::reset(const unsigned div) {
|
||||
sum4 = sum3 = sum2 = sum1 = 0;
|
||||
prev4 = prev3 = prev2 = prev1 = 0;
|
||||
@ -64,7 +64,7 @@ std::size_t Cic4Core<channels>::filter(short *out, const short *const in, std::s
|
||||
// const std::size_t produced = (inlen + div_ - nextdivn) / div_;
|
||||
const long mul = mulForDiv(div_);
|
||||
const short *s = in;
|
||||
|
||||
|
||||
unsigned long sm1 = sum1;
|
||||
unsigned long sm2 = sum2;
|
||||
unsigned long sm3 = sum3;
|
||||
@ -73,12 +73,12 @@ std::size_t Cic4Core<channels>::filter(short *out, const short *const in, std::s
|
||||
unsigned long prv2 = prev2;
|
||||
unsigned long prv3 = prev3;
|
||||
unsigned long prv4 = prev4;
|
||||
|
||||
|
||||
while (inlen >> 2) {
|
||||
const unsigned end = inlen < BUFLEN ? inlen & ~3 : BUFLEN & ~3;
|
||||
unsigned long *b = buf;
|
||||
unsigned n = end;
|
||||
|
||||
|
||||
do {
|
||||
unsigned long s1 = sm1 += static_cast<long>(s[0 * channels]);
|
||||
sm1 += static_cast<long>(s[1 * channels]);
|
||||
@ -99,30 +99,30 @@ std::size_t Cic4Core<channels>::filter(short *out, const short *const in, std::s
|
||||
s += 4 * channels;
|
||||
b += 4;
|
||||
} while (n -= 4);
|
||||
|
||||
|
||||
while (bufpos < end) {
|
||||
const unsigned long out4 = buf[bufpos] - prv4;
|
||||
prv4 = buf[bufpos];
|
||||
bufpos += div_;
|
||||
|
||||
|
||||
const unsigned long out3 = out4 - prv3;
|
||||
prv3 = out4;
|
||||
const unsigned long out2 = out3 - prv2;
|
||||
prv2 = out3;
|
||||
|
||||
|
||||
*out = rshift16_round(static_cast<long>(out2 - prv1) * mul);
|
||||
prv1 = out2;
|
||||
out += channels;
|
||||
}
|
||||
|
||||
|
||||
bufpos -= end;
|
||||
inlen -= end;
|
||||
}
|
||||
|
||||
|
||||
if (inlen) {
|
||||
unsigned n = inlen;
|
||||
unsigned i = 0;
|
||||
|
||||
|
||||
do {
|
||||
sm1 += static_cast<long>(*s);
|
||||
s += channels;
|
||||
@ -130,25 +130,25 @@ std::size_t Cic4Core<channels>::filter(short *out, const short *const in, std::s
|
||||
sm3 += sm2;
|
||||
buf[i++] = sm4 += sm3;
|
||||
} while (--n);
|
||||
|
||||
|
||||
while (bufpos < inlen) {
|
||||
const unsigned long out4 = buf[bufpos] - prv4;
|
||||
prv4 = buf[bufpos];
|
||||
bufpos += div_;
|
||||
|
||||
|
||||
const unsigned long out3 = out4 - prv3;
|
||||
prv3 = out4;
|
||||
const unsigned long out2 = out3 - prv2;
|
||||
prv2 = out3;
|
||||
|
||||
|
||||
*out = rshift16_round(static_cast<long>(out2 - prv1) * mul);
|
||||
prv1 = out2;
|
||||
out += channels;
|
||||
}
|
||||
|
||||
|
||||
bufpos -= inlen;
|
||||
}
|
||||
|
||||
|
||||
sum1 = sm1;
|
||||
sum2 = sm2;
|
||||
sum3 = sm3;
|
||||
@ -157,16 +157,16 @@ std::size_t Cic4Core<channels>::filter(short *out, const short *const in, std::s
|
||||
prev2 = prv2;
|
||||
prev3 = prv3;
|
||||
prev4 = prv4;
|
||||
|
||||
|
||||
/*unsigned long sm1 = sum1;
|
||||
unsigned long sm2 = sum2;
|
||||
unsigned long sm3 = sum3;
|
||||
unsigned long sm4 = sum4;
|
||||
|
||||
|
||||
if (produced) {
|
||||
unsigned divn = nextdivn;
|
||||
std::size_t n = produced;
|
||||
|
||||
|
||||
do {
|
||||
do {
|
||||
sm1 += static_cast<long>(*s);
|
||||
@ -175,7 +175,7 @@ std::size_t Cic4Core<channels>::filter(short *out, const short *const in, std::s
|
||||
sm3 += sm2;
|
||||
sm4 += sm3;
|
||||
} while (--divn);
|
||||
|
||||
|
||||
const unsigned long out4 = sm4 - prev4;
|
||||
prev4 = sm4;
|
||||
const unsigned long out3 = out4 - prev3;
|
||||
@ -185,17 +185,17 @@ std::size_t Cic4Core<channels>::filter(short *out, const short *const in, std::s
|
||||
*out = rshift16_round(static_cast<long>(out2 - prev1) * mul);
|
||||
prev1 = out2;
|
||||
out += channels;
|
||||
|
||||
|
||||
divn = div_;
|
||||
} while (--n);
|
||||
|
||||
|
||||
nextdivn = div_;
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
unsigned divn = (in + inlen * channels - s) / channels;
|
||||
nextdivn -= divn;
|
||||
|
||||
|
||||
while (divn--) {
|
||||
sm1 += static_cast<long>(*s);
|
||||
s += channels;
|
||||
@ -204,19 +204,19 @@ std::size_t Cic4Core<channels>::filter(short *out, const short *const in, std::s
|
||||
sm4 += sm3;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sum1 = sm1;
|
||||
sum2 = sm2;
|
||||
sum3 = sm3;
|
||||
sum4 = sm4;*/
|
||||
|
||||
|
||||
return produced;
|
||||
}
|
||||
|
||||
template<unsigned channels>
|
||||
class Cic4 : public SubResampler {
|
||||
Cic4Core<channels> cics[channels];
|
||||
|
||||
|
||||
public:
|
||||
enum { MAX_DIV = 13 };
|
||||
explicit Cic4(unsigned div);
|
||||
@ -235,11 +235,11 @@ Cic4<channels>::Cic4(const unsigned div) {
|
||||
template<unsigned channels>
|
||||
std::size_t Cic4<channels>::resample(short *const out, const short *const in, const std::size_t inlen) {
|
||||
std::size_t samplesOut;
|
||||
|
||||
|
||||
for (unsigned i = 0; i < channels; ++i) {
|
||||
samplesOut = cics[i].filter(out + i, in + i, inlen);
|
||||
}
|
||||
|
||||
|
||||
return samplesOut;
|
||||
}
|
||||
|
||||
|
@ -30,7 +30,7 @@ class PolyPhaseConvoluter {
|
||||
Array<short> const prevbuf;
|
||||
unsigned div_;
|
||||
unsigned x_;
|
||||
|
||||
|
||||
public:
|
||||
PolyPhaseConvoluter(const short *kernel, unsigned phaseLen, unsigned div);
|
||||
std::size_t filter(short *out, const short *in, std::size_t inlen);
|
||||
@ -50,10 +50,10 @@ template<int channels, unsigned phases>
|
||||
std::size_t PolyPhaseConvoluter<channels, phases>::filter(short *out, const short *const in, std::size_t inlen) {
|
||||
if (!kernel || !inlen)
|
||||
return 0;
|
||||
|
||||
|
||||
// The gist of what happens here is given by the commented pseudo-code below.
|
||||
// Note that the order of the kernel elements has been changed for efficiency in the real implementation.
|
||||
|
||||
|
||||
/*for (std::size_t x = 0; x < inlen + M; ++x) {
|
||||
const int end = x < inlen ? M + 1 : inlen + M - x;
|
||||
int j = x < M ? M - x : 0;
|
||||
@ -63,9 +63,9 @@ std::size_t PolyPhaseConvoluter<channels, phases>::filter(short *out, const shor
|
||||
buffer[x] += kernel[j] * start[(x - M + j) / phases];
|
||||
}
|
||||
}*/
|
||||
|
||||
|
||||
// Slightly more optimized version.
|
||||
|
||||
|
||||
/*for (std::size_t x = 0; x < inlen + M; ++x) {
|
||||
const int end = x < inlen ? M + 1 : inlen + M - x;
|
||||
int j = x < M ? M - x : 0;
|
||||
@ -78,12 +78,12 @@ std::size_t PolyPhaseConvoluter<channels, phases>::filter(short *out, const shor
|
||||
buffer[x] += *k++ * *s++;
|
||||
} while (--n);
|
||||
}*/
|
||||
|
||||
|
||||
const std::size_t phaseLen = prevbuf.size() / channels;
|
||||
const std::size_t M = phaseLen * phases - 1;
|
||||
inlen *= phases;
|
||||
std::size_t x = x_;
|
||||
|
||||
|
||||
for (; x < (M < inlen ? M : inlen); x += div_) {
|
||||
for (int c = 0; c < channels; ++c) {
|
||||
const short *k = kernel + ((x + 1) % phases) * phaseLen; // adjust phase so we don't start on a virtual 0 sample
|
||||
@ -93,18 +93,18 @@ std::size_t PolyPhaseConvoluter<channels, phases>::filter(short *out, const shor
|
||||
|
||||
for (; n; n -= channels)
|
||||
acc += *k++ * *(s-n);
|
||||
|
||||
|
||||
n = (x / phases + 1) * channels;
|
||||
s = in + n + c;
|
||||
|
||||
|
||||
do {
|
||||
acc += *k++ * *(s-n);
|
||||
} while (n -= channels);
|
||||
|
||||
|
||||
*out++ = rshift16_round(acc);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// We could easily get rid of the division and modulus here by updating the
|
||||
// k and s pointers incrementally. However, we currently only use powers of 2
|
||||
// and we would end up referencing more variables which often compiles to bad
|
||||
@ -115,41 +115,41 @@ std::size_t PolyPhaseConvoluter<channels, phases>::filter(short *out, const shor
|
||||
const short *const s = in + (x / phases + 1) * channels + c;
|
||||
long accl = 0, accr = 0;
|
||||
int i = -static_cast<int>(phaseLen * channels);
|
||||
|
||||
|
||||
do {
|
||||
accl += *k * s[i ];
|
||||
accr += *k * s[i+1];
|
||||
++k;
|
||||
} while (i += channels);
|
||||
|
||||
|
||||
out[0] = rshift16_round(accl);
|
||||
out[1] = rshift16_round(accr);
|
||||
out += 2;
|
||||
}
|
||||
|
||||
|
||||
if (channels & 1) {
|
||||
const short *k = kernel + ((x + 1) % phases) * phaseLen; // adjust phase so we don't start on a virtual 0 sample
|
||||
const short *const s = in + (x / phases + 1) * channels + channels-1;
|
||||
long acc = 0;
|
||||
int i = -static_cast<int>(phaseLen * channels);
|
||||
|
||||
|
||||
do {
|
||||
acc += *k++ * s[i];
|
||||
} while (i += channels);
|
||||
|
||||
|
||||
*out++ = rshift16_round(acc);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const std::size_t produced = (x - x_) / div_;
|
||||
x_ = x - inlen;
|
||||
inlen /= phases;
|
||||
|
||||
|
||||
{
|
||||
short *p = prevbuf;
|
||||
const short *s = in + (inlen - phaseLen) * channels;
|
||||
unsigned n = phaseLen;
|
||||
|
||||
|
||||
if (inlen < phaseLen) {
|
||||
const unsigned i = phaseLen - inlen;
|
||||
std::memmove(p, p + inlen * channels, i * channels * sizeof *p);
|
||||
@ -157,10 +157,10 @@ std::size_t PolyPhaseConvoluter<channels, phases>::filter(short *out, const shor
|
||||
n -= i;
|
||||
s = in;
|
||||
}
|
||||
|
||||
|
||||
std::memcpy(p, s, n * channels * sizeof *p);
|
||||
}
|
||||
|
||||
|
||||
return produced;
|
||||
}
|
||||
|
||||
|
@ -48,27 +48,27 @@ public:
|
||||
const float widthTimesTaps = 3.0f;
|
||||
return std::max(static_cast<unsigned>(std::ceil(widthTimesTaps / rollOffWidth)), 4u);
|
||||
}
|
||||
|
||||
|
||||
static float toFc(const float rollOffStart, const int taps) {
|
||||
const float startToFcDeltaTimesTaps = 1.27f;
|
||||
return startToFcDeltaTimesTaps / taps + rollOffStart;
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
const unsigned taps;
|
||||
const float fc;
|
||||
|
||||
|
||||
RollOff(float rollOffStart, float rollOffWidth) : taps(toTaps(rollOffWidth)), fc(toFc(rollOffStart, taps)) {}
|
||||
};
|
||||
|
||||
HammingSinc(unsigned div, unsigned phaseLen, double fc)
|
||||
: kernel(phaseLen * phases), convoluter_(kernel, phaseLen, div)
|
||||
{ makeSincKernel(kernel, phases, phaseLen, fc, hammingWin, 1.0); }
|
||||
|
||||
|
||||
HammingSinc(unsigned div, RollOff ro, double gain)
|
||||
: kernel(ro.taps * phases), convoluter_(kernel, ro.taps, div)
|
||||
{ makeSincKernel(kernel, phases, ro.taps, ro.fc, hammingWin, gain);}
|
||||
|
||||
|
||||
std::size_t resample(short *out, const short *in, std::size_t inlen) { return convoluter_.filter(out, in, inlen); }
|
||||
void adjustDiv(unsigned div) { convoluter_.adjustDiv(div); }
|
||||
unsigned mul() const { return MUL; }
|
||||
|
@ -23,14 +23,14 @@ double i0(double x) {
|
||||
double xpm_dmfac = 1.0;
|
||||
double m = 1.0;
|
||||
unsigned n = 16;
|
||||
|
||||
|
||||
x = 0.25 * x * x;
|
||||
|
||||
|
||||
do {
|
||||
xpm_dmfac *= x / (m*m);
|
||||
sum += xpm_dmfac;
|
||||
m += 1.0;
|
||||
} while (--n);
|
||||
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
@ -27,6 +27,6 @@ double kaiser50SincWin(const long n, const long M) {
|
||||
double x = static_cast<double>(n * 2) / M - 1.0;
|
||||
x = x * x;
|
||||
x = beta * std::sqrt(1.0 - x);
|
||||
|
||||
|
||||
return i0(x) * i0beta_rec;
|
||||
}
|
||||
|
@ -45,27 +45,27 @@ public:
|
||||
const float widthTimesTaps = 2.715f;
|
||||
return std::max(static_cast<unsigned>(std::ceil(widthTimesTaps / rollOffWidth)), 4u);
|
||||
}
|
||||
|
||||
|
||||
static float toFc(const float rollOffStart, const int taps) {
|
||||
const float startToFcDeltaTimesTaps = 1.2f;
|
||||
return startToFcDeltaTimesTaps / taps + rollOffStart;
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
const unsigned taps;
|
||||
const float fc;
|
||||
|
||||
|
||||
RollOff(float rollOffStart, float rollOffWidth) : taps(toTaps(rollOffWidth)), fc(toFc(rollOffStart, taps)) {}
|
||||
};
|
||||
|
||||
Kaiser50Sinc(unsigned div, unsigned phaseLen, double fc)
|
||||
: kernel(phaseLen * phases), convoluter_(kernel, phaseLen, div)
|
||||
{ makeSincKernel(kernel, phases, phaseLen, fc, kaiser50SincWin, 1.0); }
|
||||
|
||||
|
||||
Kaiser50Sinc(unsigned div, RollOff ro, double gain)
|
||||
: kernel(ro.taps * phases), convoluter_(kernel, ro.taps, div)
|
||||
{ makeSincKernel(kernel, phases, ro.taps, ro.fc, kaiser50SincWin, gain);}
|
||||
|
||||
|
||||
std::size_t resample(short *out, const short *in, std::size_t inlen) { return convoluter_.filter(out, in, inlen); }
|
||||
void adjustDiv(unsigned div) { convoluter_.adjustDiv(div); }
|
||||
unsigned mul() const { return MUL; }
|
||||
|
@ -23,10 +23,10 @@
|
||||
double kaiser70SincWin(const long n, const long M) {
|
||||
const double beta = 6.9;
|
||||
static const double i0beta_rec = 1.0 / i0(beta);
|
||||
|
||||
|
||||
double x = static_cast<double>(n * 2) / M - 1.0;
|
||||
x = x * x;
|
||||
x = beta * std::sqrt(1.0 - x);
|
||||
|
||||
|
||||
return i0(x) * i0beta_rec;
|
||||
}
|
||||
|
@ -45,23 +45,23 @@ public:
|
||||
const float widthTimesTaps = 3.75f;
|
||||
return std::max(static_cast<unsigned>(std::ceil(widthTimesTaps / rollOffWidth)), 4u);
|
||||
}
|
||||
|
||||
|
||||
static float toFc(const float rollOffStart, const int taps) {
|
||||
const float startToFcDeltaTimesTaps = 1.5f;
|
||||
return startToFcDeltaTimesTaps / taps + rollOffStart;
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
const unsigned taps;
|
||||
const float fc;
|
||||
|
||||
|
||||
RollOff(float rollOffStart, float rollOffWidth) : taps(toTaps(rollOffWidth)), fc(toFc(rollOffStart, taps)) {}
|
||||
};
|
||||
|
||||
Kaiser70Sinc(unsigned div, unsigned phaseLen, double fc)
|
||||
: kernel(phaseLen * phases), convoluter_(kernel, phaseLen, div)
|
||||
{ makeSincKernel(kernel, phases, phaseLen, fc, kaiser70SincWin, 1.0); }
|
||||
|
||||
|
||||
Kaiser70Sinc(unsigned div, RollOff ro, double gain)
|
||||
: kernel(ro.taps * phases), convoluter_(kernel, ro.taps, div)
|
||||
{ makeSincKernel(kernel, phases, ro.taps, ro.fc, kaiser70SincWin, gain);}
|
||||
|
@ -30,7 +30,7 @@ class LinintCore {
|
||||
std::size_t pos_;
|
||||
unsigned fracPos_;
|
||||
int prevSample_;
|
||||
|
||||
|
||||
public:
|
||||
explicit LinintCore(long inRate = 1, long outRate = 1) { init(inRate, outRate); }
|
||||
|
||||
@ -98,7 +98,7 @@ std::size_t LinintCore<channels>::resample(short *const out, const short *const
|
||||
template<int channels>
|
||||
class Linint : public Resampler {
|
||||
LinintCore<channels> cores[channels];
|
||||
|
||||
|
||||
public:
|
||||
Linint(long inRate, long outRate);
|
||||
void adjustRate(long inRate, long outRate);
|
||||
@ -110,7 +110,7 @@ public:
|
||||
template<int channels>
|
||||
Linint<channels>::Linint(const long inRate, const long outRate) {
|
||||
setRate(inRate, outRate);
|
||||
|
||||
|
||||
for (int i = 0; i < channels; ++i)
|
||||
cores[i].init(inRate, outRate);
|
||||
}
|
||||
@ -118,7 +118,7 @@ Linint<channels>::Linint(const long inRate, const long outRate) {
|
||||
template<int channels>
|
||||
void Linint<channels>::adjustRate(const long inRate, const long outRate) {
|
||||
setRate(inRate, outRate);
|
||||
|
||||
|
||||
for (int i = 0; i < channels; ++i)
|
||||
cores[i].adjustRate(inRate, outRate);
|
||||
}
|
||||
@ -126,10 +126,10 @@ void Linint<channels>::adjustRate(const long inRate, const long outRate) {
|
||||
template<int channels>
|
||||
std::size_t Linint<channels>::resample(short *const out, const short *const in, const std::size_t inlen) {
|
||||
std::size_t outlen = 0;
|
||||
|
||||
|
||||
for (int i = 0; i < channels; ++i)
|
||||
outlen = cores[i].resample(out + i, in + i, inlen);
|
||||
|
||||
|
||||
return outlen;
|
||||
}
|
||||
|
||||
|
@ -23,119 +23,119 @@ void makeSincKernel(short *const kernel, const unsigned phases,
|
||||
const unsigned phaseLen, double fc, double (*win)(long m, long M), double const maxAllowedGain) {
|
||||
static const double PI = 3.14159265358979323846;
|
||||
fc /= phases;
|
||||
|
||||
|
||||
/*{
|
||||
const Array<double> dkernel(phaseLen * phases);
|
||||
const long M = static_cast<long>(phaseLen) * phases - 1;
|
||||
|
||||
|
||||
for (long i = 0; i < M + 1; ++i) {
|
||||
const double sinc = i * 2 == M ?
|
||||
PI * fc :
|
||||
std::sin(PI * fc * (i * 2 - M)) / (i * 2 - M);
|
||||
|
||||
|
||||
dkernel[((phases - (i % phases)) % phases) * phaseLen + i / phases] = win(i, M) * sinc;
|
||||
}
|
||||
|
||||
|
||||
double maxabsgain = 0;
|
||||
|
||||
|
||||
for (unsigned ph = 0; ph < phases; ++ph) {
|
||||
double gain = 0;
|
||||
double absgain = 0;
|
||||
|
||||
|
||||
for (unsigned i = 0; i < phaseLen; ++i) {
|
||||
gain += dkernel[ph * phaseLen + i];
|
||||
absgain += std::abs(dkernel[ph * phaseLen + i]);
|
||||
}
|
||||
|
||||
|
||||
gain = 1.0 / gain;
|
||||
|
||||
|
||||
// Per phase normalization to avoid DC fluctuations.
|
||||
for (unsigned i = 0; i < phaseLen; ++i)
|
||||
dkernel[ph * phaseLen + i] *= gain;
|
||||
|
||||
|
||||
absgain *= gain;
|
||||
|
||||
|
||||
if (absgain > maxabsgain)
|
||||
maxabsgain = absgain;
|
||||
}
|
||||
|
||||
|
||||
const double gain = (0x10000 - 0.5 * phaseLen) * maxAllowedGain / maxabsgain;
|
||||
|
||||
|
||||
for (long i = 0; i < M + 1; ++i)
|
||||
kernel[i] = std::floor(dkernel[i] * gain + 0.5);
|
||||
}*/
|
||||
|
||||
|
||||
// The following is equivalent to the more readable version above
|
||||
|
||||
|
||||
const long M = static_cast<long>(phaseLen) * phases - 1;
|
||||
const Array<double> dkernel(M / 2 + 1);
|
||||
|
||||
|
||||
{
|
||||
double *dk = dkernel;
|
||||
|
||||
|
||||
for (unsigned ph = 0; ph < phases; ++ph) {
|
||||
for (long i = ph; i < M / 2 + 1; i += phases) {
|
||||
const double sinc = i * 2 == M ?
|
||||
PI * fc :
|
||||
std::sin(PI * fc * (i * 2 - M)) / (i * 2 - M);
|
||||
|
||||
|
||||
*dk++ = win(i, M) * sinc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
double maxabsgain = 0.0;
|
||||
|
||||
|
||||
{
|
||||
double *dkp1 = dkernel;
|
||||
double *dkp2 = dkernel + M / 2;
|
||||
|
||||
|
||||
for (unsigned ph = 0; ph < (phases + 1) / 2; ++ph) {
|
||||
double gain = 0.0;
|
||||
double absgain = 0.0;
|
||||
|
||||
|
||||
{
|
||||
const double *kp1 = dkp1;
|
||||
const double *kp2 = dkp2;
|
||||
long i = ph;
|
||||
|
||||
|
||||
for (; i < M / 2 + 1; i += phases) {
|
||||
gain += *kp1;
|
||||
absgain += std::abs(*kp1++);
|
||||
}
|
||||
|
||||
|
||||
for (; i < M + 1; i += phases) {
|
||||
gain += *kp2;
|
||||
absgain += std::abs(*kp2--);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
gain = 1.0 / gain;
|
||||
|
||||
|
||||
long i = ph;
|
||||
|
||||
|
||||
for (; i < M / 2 + 1; i += phases)
|
||||
*dkp1++ *= gain;
|
||||
|
||||
|
||||
if (dkp1 < dkp2) {
|
||||
for (; i < M + 1; i += phases)
|
||||
*dkp2-- *= gain;
|
||||
}
|
||||
|
||||
|
||||
absgain *= gain;
|
||||
|
||||
|
||||
if (absgain > maxabsgain)
|
||||
maxabsgain = absgain;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const double gain = (0x10000 - 0.5 * phaseLen) * maxAllowedGain / maxabsgain;
|
||||
const double *dk = dkernel;
|
||||
|
||||
|
||||
for (unsigned ph = 0; ph < phases; ++ph) {
|
||||
short *k = kernel + ((phases - ph) % phases) * phaseLen;
|
||||
short *km = kernel + phaseLen - 1 + ((ph + 1) % phases) * phaseLen;
|
||||
|
||||
|
||||
for (long i = ph; i < M / 2 + 1; i += phases)
|
||||
*km-- = *k++ = static_cast<short>(std::floor(*dk++ * gain + 0.5));
|
||||
}
|
||||
|
@ -45,27 +45,27 @@ public:
|
||||
const float widthTimesTaps = 0.9f;
|
||||
return std::max(static_cast<unsigned>(std::ceil(widthTimesTaps / rollOffWidth)), 4u);
|
||||
}
|
||||
|
||||
|
||||
static float toFc(const float rollOffStart, const int taps) {
|
||||
const float startToFcDeltaTimesTaps = 0.43f;
|
||||
return startToFcDeltaTimesTaps / taps + rollOffStart;
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
const unsigned taps;
|
||||
const float fc;
|
||||
|
||||
|
||||
RollOff(float rollOffStart, float rollOffWidth) : taps(toTaps(rollOffWidth)), fc(toFc(rollOffStart, taps)) {}
|
||||
};
|
||||
|
||||
RectSinc(unsigned div, unsigned phaseLen, double fc)
|
||||
: kernel(phaseLen * phases), convoluter_(kernel, phaseLen, div)
|
||||
{ makeSincKernel(kernel, phases, phaseLen, fc, rectWin, 1.0); }
|
||||
|
||||
|
||||
RectSinc(unsigned div, RollOff ro, double gain)
|
||||
: kernel(ro.taps * phases), convoluter_(kernel, ro.taps, div)
|
||||
{ makeSincKernel(kernel, phases, ro.taps, ro.fc, rectWin, gain);}
|
||||
|
||||
|
||||
std::size_t resample(short *out, const short *in, std::size_t inlen) { return convoluter_.filter(out, in, inlen); }
|
||||
void adjustDiv(unsigned div) { convoluter_.adjustDiv(div); }
|
||||
unsigned mul() const { return MUL; }
|
||||
|
@ -21,7 +21,7 @@
|
||||
unsigned long u48div(unsigned long num1, unsigned num2, const unsigned long den) {
|
||||
unsigned long res = 0;
|
||||
unsigned s = 16;
|
||||
|
||||
|
||||
do {
|
||||
if (num1 < 0x10000) {
|
||||
num1 <<= s;
|
||||
@ -33,22 +33,22 @@ unsigned long u48div(unsigned long num1, unsigned num2, const unsigned long den)
|
||||
num1 <<= maxs;
|
||||
num1 |= (num2 >> (s -= maxs)) & ((1 << maxs) - 1);
|
||||
}
|
||||
|
||||
|
||||
if (num1 < 0x10000000) {
|
||||
const unsigned maxs = s < 4 ? s : 4;
|
||||
num1 <<= maxs;
|
||||
num1 |= (num2 >> (s -= maxs)) & ((1 << maxs) - 1);
|
||||
}
|
||||
|
||||
|
||||
while (num1 < den && s) {
|
||||
num1 <<= 1; // if this overflows we're screwed
|
||||
num1 |= num2 >> --s & 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
res += (num1 / den) << s;
|
||||
num1 = (num1 % den);
|
||||
} while (s);
|
||||
|
||||
|
||||
return res;
|
||||
}
|
||||
|
@ -25,7 +25,7 @@
|
||||
template<unsigned channels>
|
||||
class Upsampler : public SubResampler {
|
||||
unsigned mul_;
|
||||
|
||||
|
||||
public:
|
||||
Upsampler(const unsigned mul) : mul_(mul) {}
|
||||
std::size_t resample(short *out, const short *in, std::size_t inlen);
|
||||
@ -37,14 +37,14 @@ template<unsigned channels>
|
||||
std::size_t Upsampler<channels>::resample(short *out, const short *in, std::size_t inlen) {
|
||||
if (inlen) {
|
||||
std::memset(out, 0, inlen * mul_ * channels * sizeof *out);
|
||||
|
||||
|
||||
do {
|
||||
std::memcpy(out, in, channels * sizeof *out);
|
||||
in += channels;
|
||||
out += mul_ * channels;
|
||||
} while (--inlen);
|
||||
}
|
||||
|
||||
|
||||
return inlen * mul_;
|
||||
}
|
||||
|
||||
|
@ -30,32 +30,32 @@ class RingBuffer {
|
||||
std::size_t sz;
|
||||
std::size_t rpos;
|
||||
std::size_t wpos;
|
||||
|
||||
|
||||
public:
|
||||
explicit RingBuffer(const std::size_t sz_in = 0) : sz(0), rpos(0), wpos(0) { reset(sz_in); }
|
||||
|
||||
|
||||
std::size_t avail() const {
|
||||
return (wpos < rpos ? 0 : sz) + rpos - wpos - 1;
|
||||
}
|
||||
|
||||
|
||||
void clear() {
|
||||
wpos = rpos = 0;
|
||||
}
|
||||
|
||||
|
||||
void fill(T value);
|
||||
|
||||
|
||||
void read(T *out, std::size_t num);
|
||||
|
||||
|
||||
void reset(std::size_t sz_in);
|
||||
|
||||
|
||||
std::size_t size() const {
|
||||
return sz - 1;
|
||||
}
|
||||
|
||||
|
||||
std::size_t used() const {
|
||||
return (wpos < rpos ? sz : 0) + wpos - rpos;
|
||||
}
|
||||
|
||||
|
||||
void write(const T *in, std::size_t num);
|
||||
};
|
||||
|
||||
@ -70,16 +70,16 @@ template<typename T>
|
||||
void RingBuffer<T>::read(T *out, std::size_t num) {
|
||||
if (rpos + num > sz) {
|
||||
const std::size_t n = sz - rpos;
|
||||
|
||||
|
||||
std::memcpy(out, buf + rpos, n * sizeof *out);
|
||||
|
||||
|
||||
rpos = 0;
|
||||
num -= n;
|
||||
out += n;
|
||||
}
|
||||
|
||||
|
||||
std::memcpy(out, buf + rpos, num * sizeof *out);
|
||||
|
||||
|
||||
if ((rpos += num) == sz)
|
||||
rpos = 0;
|
||||
}
|
||||
@ -95,16 +95,16 @@ template<typename T>
|
||||
void RingBuffer<T>::write(const T *in, std::size_t num) {
|
||||
if (wpos + num > sz) {
|
||||
const std::size_t n = sz - wpos;
|
||||
|
||||
|
||||
std::memcpy(buf + wpos, in, n * sizeof *buf);
|
||||
|
||||
|
||||
wpos = 0;
|
||||
num -= n;
|
||||
in += n;
|
||||
}
|
||||
|
||||
|
||||
std::memcpy(buf + wpos, in, num * sizeof *buf);
|
||||
|
||||
|
||||
if ((wpos += num) == sz)
|
||||
wpos = 0;
|
||||
}
|
||||
|
@ -28,12 +28,12 @@ class Rgb32ToUyvy {
|
||||
gambatte::uint_least32_t rgb32;
|
||||
gambatte::uint_least32_t uyvy;
|
||||
};
|
||||
|
||||
|
||||
enum { cache_size = 0x100 };
|
||||
enum { cache_mask = cache_size - 1 };
|
||||
|
||||
|
||||
CacheUnit cache[cache_size];
|
||||
|
||||
|
||||
public:
|
||||
Rgb32ToUyvy();
|
||||
void operator()(const gambatte::uint_least32_t *s, gambatte::uint_least32_t *d,
|
||||
@ -54,7 +54,7 @@ void Rgb32ToUyvy::operator()(const gambatte::uint_least32_t *s,
|
||||
{
|
||||
while (h--) {
|
||||
unsigned n = w >> 1;
|
||||
|
||||
|
||||
do {
|
||||
if ((cache[*s & cache_mask].rgb32 - *s) | (cache[*(s+1) & cache_mask].rgb32 - *(s+1))) {
|
||||
cache[*s & cache_mask].rgb32 = *s;
|
||||
@ -76,7 +76,7 @@ void Rgb32ToUyvy::operator()(const gambatte::uint_least32_t *s,
|
||||
cache[*(s+1) & cache_mask].uyvy = (y & 0xFF000000) | (v >> 8 & 0x00FF0000) | (y >> 16 & 0x0000FF00) | u >> 24;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
*d = cache[*s & cache_mask].uyvy;
|
||||
*(d+1) = cache[*(s+1) & cache_mask].uyvy;
|
||||
s += 2;
|
||||
@ -118,10 +118,10 @@ public:
|
||||
height_(height)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
virtual void* inBuf() const { return inbuf_; }
|
||||
virtual int inPitch() const { return width_; }
|
||||
|
||||
|
||||
virtual void draw(void *dst, int dstpitch) {
|
||||
rgb32ToUyvy(inbuf_, static_cast<gambatte::uint_least32_t*>(dst), width_, height_, inPitch(), dstpitch);
|
||||
}
|
||||
@ -139,10 +139,10 @@ public:
|
||||
height_(height)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
virtual void* inBuf() const { return inbuf_; }
|
||||
virtual int inPitch() const { return width_; }
|
||||
|
||||
|
||||
virtual void draw(void *dst, int dstpitch) {
|
||||
rgb32ToRgb16(inbuf_, static_cast<gambatte::uint_least16_t*>(dst), width_, height_, inPitch(), dstpitch);
|
||||
}
|
||||
|
@ -26,12 +26,12 @@ class VideoLink;
|
||||
struct VfilterInfo {
|
||||
enum { IN_WIDTH = 160 };
|
||||
enum { IN_HEIGHT = 144 };
|
||||
|
||||
|
||||
const char *handle;
|
||||
unsigned outWidth;
|
||||
unsigned outHeight;
|
||||
VideoLink* (*create)();
|
||||
|
||||
|
||||
static const VfilterInfo& get(std::size_t n);
|
||||
static std::size_t numVfilters();
|
||||
};
|
||||
|
@ -30,129 +30,129 @@ struct Colorsum {
|
||||
|
||||
static void merge_columns(gambatte::uint_least32_t *dest, const Colorsum *sums) {
|
||||
unsigned w = WIDTH;
|
||||
|
||||
|
||||
while (w--) {
|
||||
{
|
||||
gambatte::uint_least32_t rsum = sums[1].r;
|
||||
gambatte::uint_least32_t gsum = sums[1].g;
|
||||
gambatte::uint_least32_t bsum = sums[1].b;
|
||||
|
||||
|
||||
if (rsum & 0x80000000) rsum = 0;
|
||||
if (gsum & 0x80000000) gsum = 0;
|
||||
if (bsum & 0x80000000) bsum = 0;
|
||||
|
||||
|
||||
rsum <<= 12;
|
||||
rsum += 0x008000;
|
||||
gsum >>= 4;
|
||||
gsum += 0x0080;
|
||||
bsum += 0x0008;
|
||||
bsum >>= 4;
|
||||
|
||||
|
||||
if (rsum > 0xFF0000) rsum = 0xFF0000;
|
||||
if (gsum > 0x00FF00) gsum = 0x00FF00;
|
||||
if (bsum > 0x0000FF) bsum = 0x0000FF;
|
||||
|
||||
|
||||
*dest++ = (rsum & 0xFF0000) | (gsum & 0x00FF00) | bsum;
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
gambatte::uint_least32_t rsum = sums[1].r * 9;
|
||||
gambatte::uint_least32_t gsum = sums[1].g * 9;
|
||||
gambatte::uint_least32_t bsum = sums[1].b * 9;
|
||||
|
||||
|
||||
rsum -= sums[0].r;
|
||||
gsum -= sums[0].g;
|
||||
bsum -= sums[0].b;
|
||||
|
||||
|
||||
rsum += sums[2].r * 9;
|
||||
gsum += sums[2].g * 9;
|
||||
bsum += sums[2].b * 9;
|
||||
|
||||
|
||||
rsum -= sums[3].r;
|
||||
gsum -= sums[3].g;
|
||||
bsum -= sums[3].b;
|
||||
|
||||
|
||||
if (rsum & 0x80000000) rsum = 0;
|
||||
if (gsum & 0x80000000) gsum = 0;
|
||||
if (bsum & 0x80000000) bsum = 0;
|
||||
|
||||
|
||||
rsum <<= 8;
|
||||
rsum += 0x008000;
|
||||
gsum >>= 8;
|
||||
gsum += 0x000080;
|
||||
bsum += 0x000080;
|
||||
bsum >>= 8;
|
||||
|
||||
|
||||
if (rsum > 0xFF0000) rsum = 0xFF0000;
|
||||
if (gsum > 0x00FF00) gsum = 0x00FF00;
|
||||
if (bsum > 0x0000FF) bsum = 0x0000FF;
|
||||
|
||||
|
||||
*dest++ = (rsum & 0xFF0000) | (gsum & 0x00FF00) | bsum;
|
||||
}
|
||||
|
||||
|
||||
++sums;
|
||||
}
|
||||
}
|
||||
|
||||
static void filter(gambatte::uint_least32_t *dline, const int pitch, const gambatte::uint_least32_t *sline) {
|
||||
Colorsum sums[PITCH];
|
||||
|
||||
|
||||
for (unsigned h = HEIGHT; h--;) {
|
||||
{
|
||||
const gambatte::uint_least32_t *s = sline;
|
||||
Colorsum *sum = sums;
|
||||
unsigned n = PITCH;
|
||||
|
||||
|
||||
while (n--) {
|
||||
unsigned long pixel = *s;
|
||||
sum->r = pixel >> 12 & 0x000FF0 ;
|
||||
pixel <<= 4;
|
||||
sum->g = pixel & 0x0FF000;
|
||||
sum->b = pixel & 0x000FF0;
|
||||
|
||||
|
||||
++s;
|
||||
++sum;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
merge_columns(dline, sums);
|
||||
dline += pitch;
|
||||
|
||||
|
||||
{
|
||||
const gambatte::uint_least32_t *s = sline;
|
||||
Colorsum *sum = sums;
|
||||
unsigned n = PITCH;
|
||||
|
||||
|
||||
while (n--) {
|
||||
unsigned long pixel = *s;
|
||||
unsigned long rsum = (pixel >> 16) * 9;
|
||||
unsigned long gsum = (pixel & 0x00FF00) * 9;
|
||||
unsigned long bsum = (pixel & 0x0000FF) * 9;
|
||||
|
||||
|
||||
pixel = s[-1*PITCH];
|
||||
rsum -= pixel >> 16;
|
||||
gsum -= pixel & 0x00FF00;
|
||||
bsum -= pixel & 0x0000FF;
|
||||
|
||||
|
||||
pixel = s[1*PITCH];
|
||||
rsum += (pixel >> 16) * 9;
|
||||
gsum += (pixel & 0x00FF00) * 9;
|
||||
bsum += (pixel & 0x0000FF) * 9;
|
||||
|
||||
|
||||
pixel = s[2*PITCH];
|
||||
rsum -= pixel >> 16;
|
||||
gsum -= pixel & 0x00FF00;
|
||||
bsum -= pixel & 0x0000FF;
|
||||
|
||||
|
||||
sum->r = rsum;
|
||||
sum->g = gsum;
|
||||
sum->b = bsum;
|
||||
|
||||
|
||||
++s;
|
||||
++sum;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
merge_columns(dline, sums);
|
||||
dline += pitch;
|
||||
sline += PITCH;
|
||||
|
@ -29,7 +29,7 @@ class Catrom2x : public VideoLink {
|
||||
public:
|
||||
enum { OUT_WIDTH = VfilterInfo::IN_WIDTH * 2 };
|
||||
enum { OUT_HEIGHT = VfilterInfo::IN_HEIGHT * 2 };
|
||||
|
||||
|
||||
Catrom2x();
|
||||
virtual void* inBuf() const;
|
||||
virtual int inPitch() const;
|
||||
|
@ -30,7 +30,7 @@ struct Colorsum {
|
||||
|
||||
static void merge_columns(gambatte::uint_least32_t *dest, const Colorsum *sums) {
|
||||
unsigned w = WIDTH;
|
||||
|
||||
|
||||
while (w--) {
|
||||
{
|
||||
gambatte::uint_least32_t rsum = sums[1].r;
|
||||
@ -229,7 +229,7 @@ static void filter(gambatte::uint_least32_t *dline, const int pitch, const gamba
|
||||
const gambatte::uint_least32_t *s = sline;
|
||||
Colorsum *sum = sums;
|
||||
unsigned n = PITCH;
|
||||
|
||||
|
||||
while (n--) {
|
||||
const unsigned long pixel = *s;
|
||||
sum->r = (pixel >> 16) * 27;
|
||||
@ -240,7 +240,7 @@ static void filter(gambatte::uint_least32_t *dline, const int pitch, const gamba
|
||||
++sum;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
merge_columns(dline, sums);
|
||||
dline += pitch;
|
||||
|
||||
@ -248,7 +248,7 @@ static void filter(gambatte::uint_least32_t *dline, const int pitch, const gamba
|
||||
const gambatte::uint_least32_t *s = sline;
|
||||
Colorsum *sum = sums;
|
||||
unsigned n = PITCH;
|
||||
|
||||
|
||||
while (n--) {
|
||||
unsigned long pixel = *s;
|
||||
unsigned long rsum = (pixel >> 16) * 21;
|
||||
@ -279,7 +279,7 @@ static void filter(gambatte::uint_least32_t *dline, const int pitch, const gamba
|
||||
++sum;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
merge_columns(dline, sums);
|
||||
dline += pitch;
|
||||
|
||||
@ -287,7 +287,7 @@ static void filter(gambatte::uint_least32_t *dline, const int pitch, const gamba
|
||||
const gambatte::uint_least32_t *s = sline;
|
||||
Colorsum *sum = sums;
|
||||
unsigned n = PITCH;
|
||||
|
||||
|
||||
while (n--) {
|
||||
unsigned long pixel = *s;
|
||||
unsigned long rsum = (pixel >> 16) * 9;
|
||||
@ -318,7 +318,7 @@ static void filter(gambatte::uint_least32_t *dline, const int pitch, const gamba
|
||||
++sum;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
merge_columns(dline, sums);
|
||||
dline += pitch;
|
||||
sline += PITCH;
|
||||
|
@ -29,7 +29,7 @@ class Catrom3x : public VideoLink {
|
||||
public:
|
||||
enum { OUT_WIDTH = VfilterInfo::IN_WIDTH * 3 };
|
||||
enum { OUT_HEIGHT = VfilterInfo::IN_HEIGHT * 3 };
|
||||
|
||||
|
||||
Catrom3x();
|
||||
virtual void* inBuf() const;
|
||||
virtual int inPitch() const;
|
||||
|
@ -27,17 +27,17 @@ static inline int getResult1(const unsigned long a, const unsigned long b, const
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
int r = 0;
|
||||
|
||||
|
||||
if (a == c) ++x;
|
||||
else if (b == c) ++y;
|
||||
|
||||
|
||||
if (a == d) ++x;
|
||||
else if (b == d) ++y;
|
||||
|
||||
|
||||
if (x <= 1) ++r;
|
||||
|
||||
|
||||
if (y <= 1) --r;
|
||||
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
@ -45,17 +45,17 @@ static inline int getResult2(const unsigned long a, const unsigned long b, const
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
int r = 0;
|
||||
|
||||
|
||||
if (a == c) ++x;
|
||||
else if (b == c) ++y;
|
||||
|
||||
|
||||
if (a == d) ++x;
|
||||
else if (b == d) ++y;
|
||||
|
||||
|
||||
if (x <= 1) --r;
|
||||
|
||||
|
||||
if (y <= 1) ++r;
|
||||
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
@ -65,7 +65,7 @@ static inline unsigned long interpolate(const unsigned long a, const unsigned lo
|
||||
|
||||
static inline unsigned long qInterpolate(const unsigned long a, const unsigned long b, const unsigned long c, const unsigned long d) {
|
||||
const unsigned long lowBits = ((a & 0x030303) + (b & 0x030303) + (c & 0x030303) + (d & 0x030303)) & 0x030303;
|
||||
|
||||
|
||||
return (a + b + c + d - lowBits) >> 2;
|
||||
}
|
||||
|
||||
@ -73,20 +73,20 @@ template<unsigned srcPitch, unsigned width, unsigned height>
|
||||
static void filter(gambatte::uint_least32_t *dstPtr, const int dstPitch, const gambatte::uint_least32_t *srcPtr)
|
||||
{
|
||||
unsigned h = height;
|
||||
|
||||
|
||||
while (h--) {
|
||||
const gambatte::uint_least32_t *bP = srcPtr;
|
||||
gambatte::uint_least32_t *dP = dstPtr;
|
||||
|
||||
|
||||
for (unsigned finish = width; finish--;) {
|
||||
register unsigned long colorA, colorB;
|
||||
unsigned long colorC, colorD,
|
||||
colorE, colorF, colorG, colorH,
|
||||
colorI, colorJ, colorK, colorL,
|
||||
|
||||
|
||||
colorM, colorN, colorO, colorP;
|
||||
unsigned long product, product1, product2;
|
||||
|
||||
|
||||
//---------------------------------------
|
||||
// Map of the pixels: I|E F|J
|
||||
// G|A B|K
|
||||
@ -96,22 +96,22 @@ static void filter(gambatte::uint_least32_t *dstPtr, const int dstPitch, const g
|
||||
colorE = *(bP - srcPitch);
|
||||
colorF = *(bP - srcPitch + 1);
|
||||
colorJ = *(bP - srcPitch + 2);
|
||||
|
||||
|
||||
colorG = *(bP - 1);
|
||||
colorA = *(bP);
|
||||
colorB = *(bP + 1);
|
||||
colorK = *(bP + 2);
|
||||
|
||||
|
||||
colorH = *(bP + srcPitch - 1);
|
||||
colorC = *(bP + srcPitch);
|
||||
colorD = *(bP + srcPitch + 1);
|
||||
colorL = *(bP + srcPitch + 2);
|
||||
|
||||
|
||||
colorM = *(bP + srcPitch * 2 - 1);
|
||||
colorN = *(bP + srcPitch * 2);
|
||||
colorO = *(bP + srcPitch * 2 + 1);
|
||||
colorP = *(bP + srcPitch * 2 + 2);
|
||||
|
||||
|
||||
if (colorA == colorD && colorB != colorC) {
|
||||
if ((colorA == colorE && colorB == colorL) ||
|
||||
(colorA == colorC && colorA == colorF
|
||||
@ -120,7 +120,7 @@ static void filter(gambatte::uint_least32_t *dstPtr, const int dstPitch, const g
|
||||
} else {
|
||||
product = interpolate(colorA, colorB);
|
||||
}
|
||||
|
||||
|
||||
if ((colorA == colorG && colorC == colorO) ||
|
||||
(colorA == colorB && colorA == colorH
|
||||
&& colorG != colorC && colorC == colorM)) {
|
||||
@ -137,7 +137,7 @@ static void filter(gambatte::uint_least32_t *dstPtr, const int dstPitch, const g
|
||||
} else {
|
||||
product = interpolate(colorA, colorB);
|
||||
}
|
||||
|
||||
|
||||
if ((colorC == colorH && colorA == colorF) ||
|
||||
(colorC == colorG && colorC == colorD
|
||||
&& colorA != colorH && colorA == colorI)) {
|
||||
@ -153,15 +153,15 @@ static void filter(gambatte::uint_least32_t *dstPtr, const int dstPitch, const g
|
||||
product2 = colorA;
|
||||
} else {
|
||||
register int r = 0;
|
||||
|
||||
|
||||
product1 = interpolate(colorA, colorC);
|
||||
product = interpolate(colorA, colorB);
|
||||
|
||||
|
||||
r += getResult1(colorA, colorB, colorG, colorE);
|
||||
r += getResult2(colorB, colorA, colorK, colorF);
|
||||
r += getResult2(colorB, colorA, colorH, colorN);
|
||||
r += getResult1(colorA, colorB, colorL, colorO);
|
||||
|
||||
|
||||
if (r > 0)
|
||||
product2 = colorA;
|
||||
else if (r < 0)
|
||||
@ -172,7 +172,7 @@ static void filter(gambatte::uint_least32_t *dstPtr, const int dstPitch, const g
|
||||
}
|
||||
} else {
|
||||
product2 = qInterpolate(colorA, colorB, colorC, colorD);
|
||||
|
||||
|
||||
if (colorA == colorC && colorA == colorF
|
||||
&& colorB != colorE && colorB == colorJ) {
|
||||
product = colorA;
|
||||
@ -182,7 +182,7 @@ static void filter(gambatte::uint_least32_t *dstPtr, const int dstPitch, const g
|
||||
} else {
|
||||
product = interpolate(colorA, colorB);
|
||||
}
|
||||
|
||||
|
||||
if (colorA == colorB && colorA == colorH
|
||||
&& colorG != colorC && colorC == colorM) {
|
||||
product1 = colorA;
|
||||
@ -197,11 +197,11 @@ static void filter(gambatte::uint_least32_t *dstPtr, const int dstPitch, const g
|
||||
*(dP + 1) = product;
|
||||
*(dP + dstPitch) = product1;
|
||||
*(dP + dstPitch + 1) = product2;
|
||||
|
||||
|
||||
++bP;
|
||||
dP += 2;
|
||||
}
|
||||
|
||||
|
||||
srcPtr += srcPitch;
|
||||
dstPtr += dstPitch * 2;
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ class Kreed2xSaI : public VideoLink {
|
||||
public:
|
||||
enum { OUT_WIDTH = VfilterInfo::IN_WIDTH * 2 };
|
||||
enum { OUT_HEIGHT = VfilterInfo::IN_HEIGHT * 2 };
|
||||
|
||||
|
||||
Kreed2xSaI();
|
||||
virtual void* inBuf() const;
|
||||
virtual int inPitch() const;
|
||||
|
@ -29,7 +29,7 @@ class MaxStHq2x : public VideoLink {
|
||||
public:
|
||||
enum { OUT_WIDTH = VfilterInfo::IN_WIDTH * 2 };
|
||||
enum { OUT_HEIGHT = VfilterInfo::IN_HEIGHT * 2 };
|
||||
|
||||
|
||||
MaxStHq2x();
|
||||
virtual void* inBuf() const;
|
||||
virtual int inPitch() const;
|
||||
|
@ -29,7 +29,7 @@ class MaxStHq3x : public VideoLink {
|
||||
public:
|
||||
enum { OUT_WIDTH = VfilterInfo::IN_WIDTH * 3 };
|
||||
enum { OUT_HEIGHT = VfilterInfo::IN_HEIGHT * 3 };
|
||||
|
||||
|
||||
MaxStHq3x();
|
||||
virtual void* inBuf() const;
|
||||
virtual int inPitch() const;
|
||||
|
@ -44,20 +44,20 @@ struct CheatItemLess {
|
||||
|
||||
class CheatListModel : public QAbstractListModel {
|
||||
std::vector<CheatListItem> items_;
|
||||
|
||||
|
||||
public:
|
||||
explicit CheatListModel(QObject *parent = 0) : QAbstractListModel(parent) {}
|
||||
explicit CheatListModel(const std::vector<CheatListItem> &items, QObject *parent = 0)
|
||||
: QAbstractListModel(parent), items_(items)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
virtual int rowCount(const QModelIndex&) const { return items_.size(); }
|
||||
|
||||
|
||||
virtual Qt::ItemFlags flags(const QModelIndex &index) const {
|
||||
return QAbstractListModel::flags(index) | Qt::ItemIsUserCheckable;
|
||||
}
|
||||
|
||||
|
||||
virtual QVariant data(const QModelIndex &index, const int role) const {
|
||||
if (static_cast<std::size_t>(index.row()) < items_.size()) {
|
||||
switch (role) {
|
||||
@ -65,19 +65,19 @@ public:
|
||||
case Qt::CheckStateRole: return items_[index.row()].checked ? Qt::Checked : Qt::Unchecked;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
|
||||
virtual bool setData(const QModelIndex &index, const QVariant &value, const int role) {
|
||||
if (static_cast<std::size_t>(index.row()) < items_.size() && role == Qt::CheckStateRole) {
|
||||
items_[index.row()].checked = value.toBool();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
const std::vector<CheatListItem> & items() const { return items_; }
|
||||
};
|
||||
|
||||
@ -95,19 +95,19 @@ GetCheatInput::GetCheatInput(const QString &desc, const QString &code, QWidget *
|
||||
l->addWidget(descEdit_);
|
||||
l->addWidget(new QLabel(tr("GG/GS Code:")));
|
||||
l->addWidget(codeEdit_);
|
||||
|
||||
|
||||
const QString cheatre("((01[0-9a-fA-F]{6,6})|([0-9a-fA-F]{3,3}-[0-9a-fA-F]{3,3}(-[0-9a-fA-F]{3,3})?))");
|
||||
codeEdit_->setValidator(new QRegExpValidator(QRegExp(cheatre + "(;" + cheatre + ")*"), codeEdit_));
|
||||
codeEdit_->setToolTip(tr("Game Genie: hhh-hhh-hhh;...\nGame Shark: 01hhhhhh;..."));
|
||||
codeEdit_->setWhatsThis(codeEdit_->toolTip());
|
||||
|
||||
|
||||
QHBoxLayout *const hl = new QHBoxLayout;
|
||||
l->addLayout(hl);
|
||||
l->setAlignment(hl, Qt::AlignBottom | Qt::AlignRight);
|
||||
hl->addWidget(okButton_);
|
||||
QPushButton *const cancelButton = new QPushButton(tr("Cancel"));
|
||||
hl->addWidget(cancelButton);
|
||||
|
||||
|
||||
okButton_->setEnabled(codeEdit_->hasAcceptableInput());
|
||||
connect(codeEdit_, SIGNAL(textChanged(const QString&)), this, SLOT(codeTextEdited(const QString&)));
|
||||
connect(okButton_, SIGNAL(clicked()), this, SLOT(accept()));
|
||||
@ -134,35 +134,35 @@ CheatDialog::CheatDialog(const QString &savefile, QWidget *const parent)
|
||||
savefile_(savefile)
|
||||
{
|
||||
setWindowTitle("Cheats");
|
||||
|
||||
|
||||
QVBoxLayout *const mainLayout = new QVBoxLayout;
|
||||
setLayout(mainLayout);
|
||||
QVBoxLayout *const viewLayout = new QVBoxLayout;
|
||||
mainLayout->addLayout(viewLayout);
|
||||
viewLayout->addWidget(view_);
|
||||
resetViewModel(items_);
|
||||
|
||||
|
||||
{
|
||||
QPushButton *const addButton = new QPushButton("Add...");
|
||||
viewLayout->addWidget(addButton);
|
||||
connect(addButton, SIGNAL(clicked()), this, SLOT(addCheat()));
|
||||
}
|
||||
|
||||
|
||||
viewLayout->addWidget(editButton_);
|
||||
connect(editButton_, SIGNAL(clicked()), this, SLOT(editCheat()));
|
||||
|
||||
|
||||
viewLayout->addWidget(rmButton_);
|
||||
connect(rmButton_, SIGNAL(clicked()), this, SLOT(removeCheat()));
|
||||
|
||||
|
||||
{
|
||||
QPushButton *const okButton = new QPushButton(tr("OK"));
|
||||
QPushButton *const cancelButton = new QPushButton(tr("Cancel"));
|
||||
|
||||
|
||||
okButton->setDefault(true);
|
||||
|
||||
|
||||
connect(okButton, SIGNAL(clicked()), this, SLOT(accept()));
|
||||
connect(cancelButton, SIGNAL(clicked()), this, SLOT(reject()));
|
||||
|
||||
|
||||
QBoxLayout *const hLayout = new QHBoxLayout;
|
||||
hLayout->addWidget(okButton);
|
||||
hLayout->addWidget(cancelButton);
|
||||
@ -177,21 +177,21 @@ CheatDialog::~CheatDialog() {
|
||||
|
||||
void CheatDialog::loadFromSettingsFile() {
|
||||
items_.clear();
|
||||
|
||||
|
||||
if (!gamename_.isEmpty()) {
|
||||
QSettings settings(savefile_, QSettings::IniFormat);
|
||||
settings.beginGroup(gamename_);
|
||||
|
||||
|
||||
foreach (const QString &key, settings.childKeys()) {
|
||||
const QStringList &l = settings.value(key).toStringList();
|
||||
|
||||
|
||||
if (1 < l.size())
|
||||
items_.push_back(CheatListItem(l[0], l[1], 2 < l.size() && l[2] == "on"));
|
||||
}
|
||||
|
||||
|
||||
std::sort(items_.begin(), items_.end(), CheatItemLess());
|
||||
}
|
||||
|
||||
|
||||
resetViewModel(items_);
|
||||
}
|
||||
|
||||
@ -200,15 +200,15 @@ void CheatDialog::saveToSettingsFile() {
|
||||
QSettings settings(savefile_, QSettings::IniFormat);
|
||||
settings.beginGroup(gamename_);
|
||||
settings.remove("");
|
||||
|
||||
|
||||
for (std::size_t i = 0; i < items_.size(); ++i) {
|
||||
QStringList l;
|
||||
l.append(items_[i].label);
|
||||
l.append(items_[i].code);
|
||||
|
||||
|
||||
if (items_[i].checked)
|
||||
l.append("on");
|
||||
|
||||
|
||||
settings.setValue(QString::number(i), l);
|
||||
}
|
||||
}
|
||||
@ -230,13 +230,13 @@ void CheatDialog::resetViewModel(const std::vector<CheatListItem> &items, const
|
||||
void CheatDialog::addCheat() {
|
||||
const scoped_ptr<GetCheatInput> getCheatDialog(new GetCheatInput(QString(), QString(), this));
|
||||
getCheatDialog->setWindowTitle(tr("Add Cheat"));
|
||||
|
||||
|
||||
if (getCheatDialog->exec()) {
|
||||
std::vector<CheatListItem> items = reinterpret_cast<CheatListModel*>(view_->model())->items();
|
||||
const CheatListItem item(getCheatDialog->descText(), getCheatDialog->codeText(), false);
|
||||
const std::vector<CheatListItem>::iterator it =
|
||||
items.insert(std::lower_bound(items.begin(), items.end(), item, CheatItemLess()), item);
|
||||
|
||||
|
||||
resetViewModel(items, it - items.begin());
|
||||
}
|
||||
}
|
||||
@ -244,19 +244,19 @@ void CheatDialog::addCheat() {
|
||||
void CheatDialog::editCheat() {
|
||||
const std::size_t row = view_->selectionModel()->currentIndex().row();
|
||||
std::vector<CheatListItem> items = reinterpret_cast<CheatListModel*>(view_->model())->items();
|
||||
|
||||
|
||||
if (row < items.size()) {
|
||||
const scoped_ptr<GetCheatInput> getCheatDialog(
|
||||
new GetCheatInput(items[row].label, items[row].code, this));
|
||||
getCheatDialog->setWindowTitle(tr("Edit Cheat"));
|
||||
|
||||
|
||||
if (getCheatDialog->exec()) {
|
||||
const CheatListItem item(getCheatDialog->descText(), getCheatDialog->codeText(), items[row].checked);
|
||||
items.erase(items.begin() + row);
|
||||
|
||||
|
||||
const std::vector<CheatListItem>::iterator it =
|
||||
items.insert(std::lower_bound(items.begin(), items.end(), item, CheatItemLess()), item);
|
||||
|
||||
|
||||
resetViewModel(items, it - items.begin());
|
||||
}
|
||||
}
|
||||
@ -266,7 +266,7 @@ void CheatDialog::removeCheat() {
|
||||
if (view_->selectionModel()->currentIndex().isValid()) {
|
||||
const std::size_t row = view_->selectionModel()->currentIndex().row();
|
||||
std::vector<CheatListItem> items = reinterpret_cast<CheatListModel*>(view_->model())->items();
|
||||
|
||||
|
||||
if (row < items.size()) {
|
||||
items.erase(items.begin() + row);
|
||||
resetViewModel(items, row);
|
||||
@ -281,12 +281,12 @@ void CheatDialog::selectionChanged(const QModelIndex ¤t, const QModelIndex
|
||||
|
||||
const QString CheatDialog::cheats() const {
|
||||
QString s;
|
||||
|
||||
|
||||
for (std::size_t i = 0; i < items_.size(); ++i) {
|
||||
if (items_[i].checked)
|
||||
s += items_[i].code + ";";
|
||||
}
|
||||
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
|
@ -27,7 +27,7 @@ struct CheatListItem {
|
||||
QString label;
|
||||
QString code;
|
||||
bool checked;
|
||||
|
||||
|
||||
CheatListItem(const QString &label, const QString &code, const bool checked)
|
||||
: label(label), code(code), checked(checked)
|
||||
{
|
||||
@ -36,14 +36,14 @@ struct CheatListItem {
|
||||
|
||||
class GetCheatInput : public QDialog {
|
||||
Q_OBJECT
|
||||
|
||||
|
||||
class QLineEdit *const codeEdit_;
|
||||
class QLineEdit *const descEdit_;
|
||||
class QPushButton *const okButton_;
|
||||
|
||||
|
||||
private slots:
|
||||
void codeTextEdited(const QString&);
|
||||
|
||||
|
||||
public:
|
||||
explicit GetCheatInput(const QString &desc, const QString &code, QWidget *parent);
|
||||
const QString codeText() const;
|
||||
@ -52,31 +52,31 @@ public:
|
||||
|
||||
class CheatDialog : public QDialog {
|
||||
Q_OBJECT
|
||||
|
||||
|
||||
class QListView *const view_;
|
||||
class QPushButton *const editButton_;
|
||||
class QPushButton *const rmButton_;
|
||||
std::vector<CheatListItem> items_;
|
||||
const QString savefile_;
|
||||
QString gamename_;
|
||||
|
||||
|
||||
void loadFromSettingsFile();
|
||||
void saveToSettingsFile();
|
||||
void resetViewModel(const std::vector<CheatListItem> &items);
|
||||
void resetViewModel(const std::vector<CheatListItem> &items, int newCurRow);
|
||||
|
||||
|
||||
private slots:
|
||||
void addCheat();
|
||||
void editCheat();
|
||||
void removeCheat();
|
||||
void selectionChanged(const class QModelIndex ¤t, const class QModelIndex &last);
|
||||
|
||||
|
||||
public:
|
||||
explicit CheatDialog(const QString &savefile, QWidget *parent = 0);
|
||||
~CheatDialog();
|
||||
const QString cheats() const;
|
||||
void setGameName(const QString &name);
|
||||
|
||||
|
||||
public slots:
|
||||
virtual void accept();
|
||||
virtual void reject();
|
||||
|
@ -27,15 +27,15 @@ static int getCustomIndex(const QComboBox *const comboBox) {
|
||||
|
||||
static void setFps(QComboBox *const comboBox, const QSize &value) {
|
||||
const int valueIndex = comboBox->findData(value);
|
||||
|
||||
|
||||
if (valueIndex < 0) {
|
||||
comboBox->addItem(QString::number(static_cast<double>(value.width()) / value.height()) + " fps", value);
|
||||
|
||||
|
||||
const int customIndex = getCustomIndex(comboBox);
|
||||
|
||||
|
||||
if (customIndex + 4 < comboBox->count())
|
||||
comboBox->removeItem(customIndex + 1);
|
||||
|
||||
|
||||
comboBox->setCurrentIndex(comboBox->count() - 1);
|
||||
} else
|
||||
comboBox->setCurrentIndex(valueIndex);
|
||||
@ -47,11 +47,11 @@ FpsSelector::FpsSelector()
|
||||
{
|
||||
comboBox_->addItem("GB/GBC (" + QString::number(262144.0 / 4389.0) + " fps)", QSize(262144, 4389));
|
||||
comboBox_->addItem(QString("Other..."));
|
||||
|
||||
|
||||
const QSize &loadedValue = QSettings().value("misc/fps", value_).toSize();
|
||||
value_ = loadedValue.width() > 0 && loadedValue.height() > 0
|
||||
&& loadedValue.width() / loadedValue.height() > 0 ? loadedValue : value_;
|
||||
|
||||
|
||||
reject();
|
||||
|
||||
connect(comboBox_, SIGNAL(currentIndexChanged(int)), this, SLOT(indexChanged(int)));
|
||||
@ -77,11 +77,11 @@ QWidget * FpsSelector::widget() const {
|
||||
void FpsSelector::indexChanged(const int index) {
|
||||
if (getCustomIndex(comboBox_) == index) {
|
||||
bool ok = false;
|
||||
|
||||
|
||||
const QSize v(static_cast<int>(
|
||||
QInputDialog::getDouble(comboBox_, tr("Set Frame Rate"), tr("Frame rate (fps):"),
|
||||
static_cast<double>(value_.width()) / value_.height(), 30.0, 120.0, 4, &ok) * 10000 + 0.5), 10000);
|
||||
|
||||
|
||||
setFps(comboBox_, ok ? v : value_);
|
||||
}
|
||||
}
|
||||
|
@ -27,13 +27,13 @@ class QWidget;
|
||||
|
||||
class FpsSelector : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
|
||||
QComboBox *const comboBox_;
|
||||
QSize value_;
|
||||
|
||||
|
||||
private slots:
|
||||
void indexChanged(int index);
|
||||
|
||||
|
||||
public:
|
||||
FpsSelector();
|
||||
~FpsSelector();
|
||||
|
@ -25,27 +25,27 @@ class QWidget;
|
||||
|
||||
class ConstAudioEngineConf {
|
||||
const AudioEngine *const ae;
|
||||
|
||||
|
||||
public:
|
||||
/*explicit */ConstAudioEngineConf(const AudioEngine *const ae) : ae(ae) {}
|
||||
const QString& nameString() const;
|
||||
QWidget* settingsWidget() const;
|
||||
void rejectSettings() const;
|
||||
|
||||
|
||||
bool operator==(ConstAudioEngineConf r) const { return ae == r.ae; }
|
||||
bool operator!=(ConstAudioEngineConf r) const { return ae != r.ae; }
|
||||
};
|
||||
|
||||
class AudioEngineConf {
|
||||
AudioEngine *const ae;
|
||||
|
||||
|
||||
public:
|
||||
/*explicit */AudioEngineConf(AudioEngine *const ae) : ae(ae) {}
|
||||
const QString& nameString() const;
|
||||
QWidget* settingsWidget() const;
|
||||
void acceptSettings() const;
|
||||
void rejectSettings() const;
|
||||
|
||||
|
||||
bool operator==(AudioEngineConf r) const { return ae == r.ae; }
|
||||
bool operator!=(AudioEngineConf r) const { return ae != r.ae; }
|
||||
operator const ConstAudioEngineConf() const { return ConstAudioEngineConf(ae); }
|
||||
|
@ -30,17 +30,17 @@ private:
|
||||
std::vector<T*, Allocator> v;
|
||||
explicit released(const std::vector<T*, Allocator> &v): v(v) {}
|
||||
};
|
||||
|
||||
|
||||
public:
|
||||
typedef typename std::vector<T*, Allocator>::const_iterator const_iterator;
|
||||
typedef typename std::vector<T*, Allocator>::iterator iterator;
|
||||
typedef typename std::vector<T*, Allocator>::size_type size_type;
|
||||
|
||||
|
||||
explicit auto_vector(const Allocator &a = Allocator()) : std::vector<T*, Allocator>(a) {}
|
||||
explicit auto_vector(size_type n, const Allocator &a = Allocator()) : std::vector<T*, Allocator>(n, 0, a) {}
|
||||
auto_vector(auto_vector &v) : std::vector<T*, Allocator>() { swap(v); }
|
||||
auto_vector(const released &v) : std::vector<T*, Allocator>(v.v) {}
|
||||
|
||||
|
||||
template<class InputIterator>
|
||||
auto_vector(InputIterator first, InputIterator last, const Allocator& a = Allocator())
|
||||
: std::vector<T*, Allocator>(first, last, a)
|
||||
@ -48,7 +48,7 @@ public:
|
||||
}
|
||||
|
||||
~auto_vector() { clear(); }
|
||||
|
||||
|
||||
using std::vector<T*, Allocator>::begin;
|
||||
using std::vector<T*, Allocator>::end;
|
||||
using std::vector<T*, Allocator>::rbegin;
|
||||
@ -63,44 +63,44 @@ public:
|
||||
using std::vector<T*, Allocator>::front;
|
||||
using std::vector<T*, Allocator>::back;
|
||||
using std::vector<T*, Allocator>::push_back;
|
||||
|
||||
|
||||
template<class InputIterator>
|
||||
void assign(InputIterator first, InputIterator last) {
|
||||
clear();
|
||||
std::vector<T*, Allocator>::assign(first, last);
|
||||
}
|
||||
|
||||
|
||||
void assign(size_type n) {
|
||||
clear();
|
||||
std::vector<T*, Allocator>::assign(n);
|
||||
}
|
||||
|
||||
|
||||
void pop_back() {
|
||||
if (!empty())
|
||||
defined_delete(back());
|
||||
|
||||
|
||||
std::vector<T*, Allocator>::pop_back();
|
||||
}
|
||||
|
||||
|
||||
iterator insert(iterator position, T *x) { return std::vector<T*, Allocator>::insert(position, x); }
|
||||
|
||||
|
||||
template<class InputIterator>
|
||||
void insert(iterator position, InputIterator first, InputIterator last) {
|
||||
std::vector<T*, Allocator>::insert(position, first, last);
|
||||
}
|
||||
|
||||
|
||||
iterator erase(iterator position) {
|
||||
if (position != end())
|
||||
defined_delete(*position);
|
||||
|
||||
|
||||
return std::vector<T*, Allocator>::erase(position);
|
||||
}
|
||||
|
||||
|
||||
iterator erase(iterator first, iterator last) {
|
||||
std::for_each(first, last, defined_delete<T>);
|
||||
return std::vector<T*, Allocator>::erase(first, last);
|
||||
}
|
||||
|
||||
|
||||
void swap(auto_vector &vec) { std::vector<T*, Allocator>::swap(vec); }
|
||||
void clear() { erase(begin(), end()); }
|
||||
const std::vector<T*,Allocator> get() const { return *this; }
|
||||
|
@ -25,21 +25,21 @@ class QWidget;
|
||||
|
||||
class ConstBlitterConf {
|
||||
const BlitterWidget *const blitter;
|
||||
|
||||
|
||||
public:
|
||||
explicit ConstBlitterConf(const BlitterWidget *const blitter) : blitter(blitter) {}
|
||||
const QString& nameString() const;
|
||||
unsigned maxSwapInterval() const;
|
||||
QWidget* settingsWidget() const;
|
||||
void rejectSettings() const;
|
||||
|
||||
|
||||
bool operator==(ConstBlitterConf r) const { return blitter == r.blitter; }
|
||||
bool operator!=(ConstBlitterConf r) const { return blitter != r.blitter; }
|
||||
};
|
||||
|
||||
class BlitterConf {
|
||||
BlitterWidget *const blitter;
|
||||
|
||||
|
||||
public:
|
||||
explicit BlitterConf(BlitterWidget *const blitter) : blitter(blitter) {}
|
||||
const QString& nameString() const;
|
||||
@ -47,7 +47,7 @@ public:
|
||||
QWidget* settingsWidget() const;
|
||||
void acceptSettings() const;
|
||||
void rejectSettings() const;
|
||||
|
||||
|
||||
bool operator==(BlitterConf r) const { return blitter == r.blitter; }
|
||||
bool operator!=(BlitterConf r) const { return blitter != r.blitter; }
|
||||
operator const ConstBlitterConf() const { return ConstBlitterConf(blitter); }
|
||||
|
@ -38,30 +38,30 @@ class ParamQueue : Uncopyable {
|
||||
char *start;
|
||||
char *end;
|
||||
std::size_t avail;
|
||||
|
||||
|
||||
template<class T> struct PaddedSize { enum { R = ((sizeof(T) + ALIGN - 1) / ALIGN) * ALIGN }; };
|
||||
|
||||
|
||||
public:
|
||||
explicit ParamQueue(const std::size_t sz = ALIGN * 2) :
|
||||
data((char*) std::malloc(sz)), dataend(data + sz), start(data), end(data), avail(sz) {}
|
||||
~ParamQueue() { free(data); }
|
||||
|
||||
|
||||
template<class T> bool hasSpaceFor() {
|
||||
return avail > PaddedSize<T>::R * 2 - 2;
|
||||
}
|
||||
|
||||
|
||||
template<class T> void push(const T &t);
|
||||
|
||||
|
||||
template<class T> T& front() {
|
||||
return *reinterpret_cast<T*>(dataend - start < PaddedSize<T>::R ? data : start);
|
||||
}
|
||||
|
||||
|
||||
template<class T> const T& front() const {
|
||||
return *reinterpret_cast<const T*>(dataend - start < PaddedSize<T>::R ? data : start);
|
||||
}
|
||||
|
||||
|
||||
template<class T> void pop();
|
||||
|
||||
|
||||
std::size_t size() const { return dataend - data; }
|
||||
static void swap(ParamQueue &a, ParamQueue &b);
|
||||
};
|
||||
@ -72,7 +72,7 @@ template<class T> void ParamQueue<ALIGN>::push(const T &t) {
|
||||
avail -= dataend - end;
|
||||
end = data;
|
||||
}
|
||||
|
||||
|
||||
new (end) T(t);
|
||||
end += PaddedSize<T>::R;
|
||||
avail -= PaddedSize<T>::R;
|
||||
@ -84,7 +84,7 @@ template<class T> void ParamQueue<ALIGN>::pop() {
|
||||
avail += dataend - start;
|
||||
start = data;
|
||||
}
|
||||
|
||||
|
||||
reinterpret_cast<T*>(start)->~T();
|
||||
start += PaddedSize<T>::R;
|
||||
avail += PaddedSize<T>::R;
|
||||
@ -102,7 +102,7 @@ void ParamQueue<ALIGN>::swap(ParamQueue<ALIGN> &a, ParamQueue<ALIGN> &b) {
|
||||
template<class T, std::size_t ALIGN> void popto(ParamQueue<ALIGN> &pq, ParamQueue<ALIGN> *const pqout) {
|
||||
if (pqout)
|
||||
pqout->push(pq.template front<T>());
|
||||
|
||||
|
||||
pq.template pop<T>();
|
||||
}
|
||||
|
||||
@ -112,21 +112,21 @@ struct CallQueueBase {
|
||||
Callptr call;
|
||||
void (*popto)(ParamQueue<ALIGN>&, ParamQueue<ALIGN>*);
|
||||
};
|
||||
|
||||
|
||||
ParamQueue<ALIGN> pq;
|
||||
std::deque<const Funptrs*> fq;
|
||||
|
||||
|
||||
void popAllTo(ParamQueue<ALIGN> *const pqout);
|
||||
void incpq();
|
||||
|
||||
|
||||
template<class T> void push(const T &t, const Funptrs *const fptrs) {
|
||||
while (!pq.template hasSpaceFor<T>())
|
||||
incpq();
|
||||
|
||||
|
||||
pq.push(t);
|
||||
fq.push_back(fptrs);
|
||||
}
|
||||
|
||||
|
||||
~CallQueueBase() { popAllTo(0); }
|
||||
};
|
||||
|
||||
@ -148,28 +148,28 @@ class NoParam;
|
||||
template<typename Param = NoParam, std::size_t ALIGN = sizeof(DefaultTypeAlignUnion)>
|
||||
class CallQueue {
|
||||
CallQueueBase<void (*)(ParamQueue<ALIGN>&, Param), ALIGN> base;
|
||||
|
||||
|
||||
template<class T> static void call(ParamQueue<ALIGN> &pq, Param p) {
|
||||
pq.template front<T>()(p);
|
||||
pq.template pop<T>();
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
template<class T> void push(const T &t) {
|
||||
static const typename CallQueueBase<void (*)(ParamQueue<ALIGN>&, Param), ALIGN>::Funptrs fptrs = { call<T>, popto<T,ALIGN> };
|
||||
base.push(t, &fptrs);
|
||||
}
|
||||
|
||||
|
||||
void pop(Param p) {
|
||||
base.fq.front()->call(base.pq, p);
|
||||
base.fq.pop_front();
|
||||
}
|
||||
|
||||
|
||||
void pop_all(Param p) {
|
||||
while (!base.fq.empty())
|
||||
pop(p);
|
||||
}
|
||||
|
||||
|
||||
std::size_t size() const { return base.fq.size(); }
|
||||
bool empty() const { return base.fq.empty(); }
|
||||
};
|
||||
@ -182,23 +182,23 @@ class CallQueue<NoParam, ALIGN> {
|
||||
pq.template front<T>()();
|
||||
pq.template pop<T>();
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
template<class T> void push(const T &t) {
|
||||
static const typename CallQueueBase<void (*)(ParamQueue<ALIGN>&), ALIGN>::Funptrs fptrs = { call<T>, popto<T,ALIGN> };
|
||||
base.push(t, &fptrs);
|
||||
}
|
||||
|
||||
|
||||
void pop() {
|
||||
base.fq.front()->call(base.pq);
|
||||
base.fq.pop_front();
|
||||
}
|
||||
|
||||
|
||||
void pop_all() {
|
||||
while (!base.fq.empty())
|
||||
pop();
|
||||
}
|
||||
|
||||
|
||||
std::size_t size() const { return base.fq.size(); }
|
||||
bool empty() const { return base.fq.empty(); }
|
||||
};
|
||||
|
@ -42,64 +42,64 @@ public:
|
||||
struct Button {
|
||||
// Label used in input settings dialog. If this is empty the button won't be configurable, but will use the defaultKey.
|
||||
QString label;
|
||||
|
||||
|
||||
// Tab label used in input settings dialog.
|
||||
QString category;
|
||||
|
||||
|
||||
// Default Qt::Key. Use Qt::Key_unknown for none.
|
||||
int defaultKey;
|
||||
|
||||
|
||||
// Default alternate Qt::Key. Use Qt::Key_unknown for none.
|
||||
int defaultAltKey;
|
||||
|
||||
|
||||
// called on button press / release
|
||||
struct Action {
|
||||
virtual void buttonPressed() {}
|
||||
virtual void buttonReleased() {}
|
||||
virtual ~Action() {}
|
||||
} *action;
|
||||
|
||||
|
||||
// Default number of frames per auto-repeat press. 0 for auto-repeat disabled.
|
||||
unsigned char defaultFpp;
|
||||
};
|
||||
|
||||
|
||||
private:
|
||||
struct KeyMapped {
|
||||
Button::Action *const action;
|
||||
const unsigned char fpp;
|
||||
KeyMapped(Button::Action *action, int fpp) : action(action), fpp(fpp) {}
|
||||
};
|
||||
|
||||
|
||||
struct JoyMapped {
|
||||
Button::Action *const action;
|
||||
const int mask;
|
||||
const unsigned char fpp;
|
||||
JoyMapped(Button::Action *action, int mask, int fpp) : action(action), mask(mask), fpp(fpp) {}
|
||||
};
|
||||
|
||||
|
||||
struct AutoPress {
|
||||
Button::Action *action;
|
||||
unsigned char fpp;
|
||||
unsigned char fcnt;
|
||||
AutoPress(Button::Action *action, unsigned char fpp, unsigned char fcnt) : action(action), fpp(fpp), fcnt(fcnt) {}
|
||||
};
|
||||
|
||||
|
||||
struct Config {
|
||||
SDL_Event event;
|
||||
unsigned char fpp;
|
||||
};
|
||||
|
||||
|
||||
template<class Map>
|
||||
struct Mapping {
|
||||
Map map;
|
||||
std::vector<AutoPress> rapidvec;
|
||||
};
|
||||
|
||||
|
||||
typedef std::multimap<unsigned,KeyMapped> keymap_t;
|
||||
typedef std::multimap<unsigned,JoyMapped> joymap_t;
|
||||
typedef Mapping<keymap_t> KeyMapping;
|
||||
typedef Mapping<joymap_t> JoyMapping;
|
||||
|
||||
|
||||
const std::vector<Button> buttonInfos;
|
||||
auto_vector<InputBoxPair> inputBoxPairs;
|
||||
auto_vector<QSpinBox> fppBoxes;
|
||||
@ -107,25 +107,25 @@ private:
|
||||
Mutual<KeyMapping> keymapping;
|
||||
Mutual<JoyMapping> joymapping;
|
||||
const bool deleteButtonActions;
|
||||
|
||||
|
||||
void resetMapping();
|
||||
void store();
|
||||
void restore();
|
||||
|
||||
|
||||
public:
|
||||
explicit InputDialog(const std::vector<Button> &buttonInfos,
|
||||
bool deleteButtonActions = true,
|
||||
QWidget *parent = 0);
|
||||
~InputDialog();
|
||||
|
||||
|
||||
// These invoke Button::Actions matching the key pressed/released
|
||||
void keyPressEvent(const QKeyEvent *);
|
||||
void keyReleaseEvent(const QKeyEvent *);
|
||||
void joystickEvent(const SDL_Event&);
|
||||
|
||||
|
||||
// Call once every frame to tick auto-repeat pressing.
|
||||
void consumeAutoPress();
|
||||
|
||||
|
||||
public slots:
|
||||
void accept();
|
||||
void reject();
|
||||
|
@ -54,7 +54,7 @@ public:
|
||||
MediaWidget *const mw;
|
||||
public:
|
||||
explicit FrameBuffer(MainWindow *const mw) : mw(mw->w_) {}
|
||||
|
||||
|
||||
class Locked : Uncopyable {
|
||||
MediaWidget *mw;
|
||||
PixelBuffer pb;
|
||||
@ -66,80 +66,80 @@ public:
|
||||
};
|
||||
|
||||
explicit MainWindow(MediaSource *source);
|
||||
|
||||
|
||||
/** Sets the duration in seconds of each video frame.
|
||||
* Eg. use setFrameTime(1, 60) for 60 fps video.
|
||||
* Can be used to speed things up or slow things down. Audio pitch will change accordingly.
|
||||
*/
|
||||
void setFrameTime(long num, long denom);
|
||||
|
||||
|
||||
/** Sets the mean number of audio samples produced by MediaSource::update for each video frame produced.
|
||||
* So, for instance if you have 60 fps video, and 48 kHz audio, you would use setSamplesPerFrame(48000 / 60);
|
||||
* or setSamplesPerFrame(48000, 60);
|
||||
*/
|
||||
void setSamplesPerFrame(long num, long denom = 1);
|
||||
|
||||
|
||||
/** Advance a single video frame forward. It only makes sense to use this when paused. */
|
||||
void frameStep();
|
||||
|
||||
|
||||
/** Pauses audio/video production. Will set the pause bits given by bitmask. Pauses when pause is not 0. */
|
||||
void pause(unsigned bitmask = 1);
|
||||
|
||||
|
||||
/** Resumes audio/video production. Will unset the pause bits given by bitmask. Unpauses when pause is 0. */
|
||||
void unpause(unsigned bitmask = 1);
|
||||
|
||||
|
||||
/** Pauses audio/video production. Will add inc to pause. Pauses when pause is not 0. */
|
||||
void incPause(unsigned inc);
|
||||
|
||||
|
||||
/** Resumes audio/video production. Will subtract dec from pause. Unpauses when pause is 0. */
|
||||
void decPause(unsigned dec);
|
||||
|
||||
|
||||
/** Pauses audio/video production automatically when the central widget of the MainWindow loses focus.
|
||||
* Calls pause(bitmask) on focusOut, and unpause(bitmask) on focusIn.
|
||||
*/
|
||||
void setPauseOnFocusOut(unsigned bitmask);
|
||||
|
||||
|
||||
/** Run must be called once to initialize resources and start audio/video production. */
|
||||
void run();
|
||||
|
||||
|
||||
/** Stop can be called to release resources and stop audio/video production.
|
||||
* Run will have to be called again to resume. Blocks until stopped.
|
||||
*/
|
||||
void stop();
|
||||
|
||||
|
||||
bool isRunning() const;
|
||||
|
||||
|
||||
/** The video format is the format of the video content produced by MediaSource.
|
||||
* This will set the "frame buffer" to the requested format.
|
||||
*/
|
||||
void setVideoFormat(unsigned w, unsigned h/*, PixelBuffer::PixelFormat pf*/);
|
||||
|
||||
|
||||
void setAspectRatio(const QSize &ar);
|
||||
void setScalingMethod(ScalingMethod smet);
|
||||
|
||||
|
||||
/** Sets the size of the video area of the MainWindow when not full screen.
|
||||
* Should be used in place of methods like QMainWindow::resize, because this one doesn't screw up full screen.
|
||||
* Pass sz = QSize(-1,-1) for a variable size, such that the user may adjust the window size.
|
||||
* Otherwise a fixed window size equal to sz will be used. This window size does not include window borders or menus.
|
||||
*/
|
||||
void setWindowSize(const QSize &sz);
|
||||
|
||||
|
||||
/** Each blitter has some properties that can be accessed through its BlitterConf. */
|
||||
const BlitterConf blitterConf(std::size_t blitterNo);
|
||||
const ConstBlitterConf blitterConf(std::size_t blitterNo) const;
|
||||
std::size_t numBlitters() const;
|
||||
const BlitterConf currentBlitterConf();
|
||||
const ConstBlitterConf currentBlitterConf() const;
|
||||
|
||||
|
||||
/** A video blitter is an engine (DirectDraw, Xv, etc.) responsible for putting video content on the screen. */
|
||||
void setVideoBlitter(std::size_t blitterNo);
|
||||
|
||||
|
||||
void setVideoFormatAndBlitter(unsigned w, unsigned h,
|
||||
/*PixelBuffer::PixelFormat pf, */std::size_t blitterNo);
|
||||
|
||||
|
||||
/** speed = N, gives N times faster than normal when fastForward is enabled. */
|
||||
void setFastForwardSpeed(unsigned speed);
|
||||
|
||||
|
||||
/** Sets the video mode that is used for full screen (see toggleFullScreen).
|
||||
* A screen is basically a monitor. A different full screen mode can be selected for each screen.
|
||||
* Which screen is used for full screen presentation depends on the location of the window.
|
||||
@ -148,50 +148,50 @@ public:
|
||||
* @param rateIndex Index of the selected refresh rate for the selected resolution.
|
||||
*/
|
||||
void setFullScreenMode(std::size_t screenNo, std::size_t resIndex, std::size_t rateIndex);
|
||||
|
||||
|
||||
/** Returns the modes supported by each screen. */
|
||||
const std::vector<ResInfo>& modeVector(std::size_t screen) const;
|
||||
|
||||
|
||||
const QString screenName(std::size_t screen) const;
|
||||
|
||||
|
||||
/** Returns the number of screens. */
|
||||
std::size_t screens() const;
|
||||
|
||||
|
||||
/** Returns the current full screen resolution index selected for a screen. */
|
||||
std::size_t currentResIndex(std::size_t screen) const;
|
||||
|
||||
|
||||
/** Returns the current full screen rate index selected for a screen. */
|
||||
std::size_t currentRateIndex(std::size_t screen) const;
|
||||
|
||||
|
||||
/** Returns the current screen that will be used for full screen. */
|
||||
std::size_t currentScreen() const;
|
||||
|
||||
|
||||
/** Toggle full screen mode on/off. QMainWindow::isFullScreen() can be used to determine the current state.
|
||||
* QMainWindow::setFullScreen should not be used.
|
||||
*/
|
||||
void toggleFullScreen();
|
||||
|
||||
|
||||
/** Each AudioEngine has some properties that can be accessed through its AudioEngineConf. */
|
||||
const AudioEngineConf audioEngineConf(std::size_t aeNo);
|
||||
const ConstAudioEngineConf audioEngineConf(std::size_t aeNo) const;
|
||||
std::size_t numAudioEngines() const;
|
||||
|
||||
|
||||
/** Audio resamplers of different performance can be selected. */
|
||||
std::size_t numResamplers() const;
|
||||
const char* resamplerDesc(std::size_t resamplerNo) const;
|
||||
|
||||
|
||||
/** Sets the AudioEngine (DirectSound, ALSA, etc.) to be used for audio output,
|
||||
* as well as which output sampling rate, buffer size in milliseconds, and resampler to use.
|
||||
* The sampling rate does not need to match the sampling rate of the audio content produced
|
||||
* by the source, as the input will be converted to match the output rate.
|
||||
*/
|
||||
void setAudioOut(std::size_t engineNo, unsigned srateHz, unsigned msecLatency, std::size_t resamplerNo);
|
||||
|
||||
|
||||
/** Pause doesn't take effect immediately. Call this to wait until the worker thread is paused.
|
||||
* Meant as a tool to simplify thread safety.
|
||||
*/
|
||||
void waitUntilPaused();
|
||||
|
||||
|
||||
/** Temporarily pauses the worker thread and calls fun once it has paused. Then unpauses.
|
||||
* Returns before fun is actually called. Fun is called in an event at a later time.
|
||||
* fun should implement operator() and have a copy-constructor.
|
||||
@ -199,7 +199,7 @@ public:
|
||||
*/
|
||||
template<class T>
|
||||
void callWhenPaused(const T &fun);
|
||||
|
||||
|
||||
/** Puts fun into a queue of functors that are called in the worker thread at a later time.
|
||||
* fun should implement operator() and have a copy-constructor.
|
||||
* Meant as a tool to simplify thread safety.
|
||||
@ -219,19 +219,19 @@ public:
|
||||
public slots:
|
||||
void hideCursor();
|
||||
void setFastForward(bool enable);
|
||||
|
||||
|
||||
/** Will synchronize frame rate to vertical retrace if the blitter supports a swapInterval of at least 1.
|
||||
* Picks a swapInterval closest to the current frame rate.
|
||||
* Literally speeds things up or slows things down to match the swapInterval. Audio pitch will change accordingly.
|
||||
*/
|
||||
void setSyncToRefreshRate(bool enable);
|
||||
|
||||
|
||||
signals:
|
||||
void audioEngineFailure();
|
||||
void videoBlitterFailure();
|
||||
void closing();
|
||||
void dwmCompositionChange();
|
||||
|
||||
|
||||
protected:
|
||||
virtual void mouseMoveEvent(QMouseEvent*);
|
||||
virtual void closeEvent(QCloseEvent*);
|
||||
@ -246,12 +246,12 @@ protected:
|
||||
#ifdef Q_WS_WIN
|
||||
virtual bool winEvent(MSG *msg, long *result);
|
||||
#endif
|
||||
|
||||
|
||||
private:
|
||||
void correctFullScreenGeometry();
|
||||
void doSetWindowSize(const QSize &sz);
|
||||
void doShowFullScreen();
|
||||
|
||||
|
||||
MediaWidget *const w_;
|
||||
QSize winSize_;
|
||||
bool fullscreen_;
|
||||
@ -263,7 +263,7 @@ class CallWhenMediaWorkerPaused : Uncopyable {
|
||||
public:
|
||||
explicit CallWhenMediaWorkerPaused(MediaWidget &mw);
|
||||
~CallWhenMediaWorkerPaused();
|
||||
|
||||
|
||||
template<class T>
|
||||
void operator()(const T &function) const { callq_.push(function); }
|
||||
};
|
||||
@ -280,7 +280,7 @@ class PushMediaWorkerCall : Uncopyable {
|
||||
public:
|
||||
explicit PushMediaWorkerCall(MediaWidget &mw);
|
||||
~PushMediaWorkerCall();
|
||||
|
||||
|
||||
template<class T>
|
||||
void operator()(const T &function) const { callq_.push(function); }
|
||||
};
|
||||
|
@ -48,14 +48,14 @@ protected:
|
||||
explicit MediaSource(const unsigned overupdate = 0) : overupdate(overupdate) {}
|
||||
public:
|
||||
const unsigned overupdate;
|
||||
|
||||
|
||||
// Reimplement to get input events. The InputDialog class may be useful.
|
||||
// joystickEvent is called from the worker thread, while keyPress/ReleaseEvent
|
||||
// are called from the GUI thread.
|
||||
virtual void keyPressEvent(const QKeyEvent *) {}
|
||||
virtual void keyReleaseEvent(const QKeyEvent *) {}
|
||||
virtual void joystickEvent(const SDL_Event&) {}
|
||||
|
||||
|
||||
/**
|
||||
* Update until a new frame of video, or 'samples' audio samples have been produced.
|
||||
* May postpone writing to frameBuf until generateVideoFrame is called.
|
||||
@ -73,7 +73,7 @@ public:
|
||||
* @return The number of stereo samples that should be output before the video frame is displayed. Or a negative number if no new video frame should be displayed.
|
||||
*/
|
||||
virtual long update(const PixelBuffer &frameBuf, qint16 *soundBuf, long &samples) = 0;
|
||||
|
||||
|
||||
/**
|
||||
* This is called after update returns, but only when it is clear that the frame won't be skipped.
|
||||
* This gives an opportunity to delay heavy video work until it is clear that it will be used.
|
||||
@ -82,7 +82,7 @@ public:
|
||||
* Heavy post-processing of video is a good candidate for this method.
|
||||
*/
|
||||
virtual void generateVideoFrame(const PixelBuffer &/*fb*/) {}
|
||||
|
||||
|
||||
virtual ~MediaSource() {}
|
||||
};
|
||||
|
||||
|
@ -50,7 +50,7 @@ public:
|
||||
const T* operator->() const { return &lc.t; }
|
||||
const T& get() const { return lc.t; }
|
||||
};
|
||||
|
||||
|
||||
class TryLocked : Uncopyable {
|
||||
Mutual *const lc;
|
||||
public:
|
||||
|
@ -33,7 +33,7 @@ struct PixelBuffer {
|
||||
* umask: 0x000000ff, ymask: 0xff00ff00, vmask: 0x00ff0000 (little endian)
|
||||
*/
|
||||
enum PixelFormat { RGB32, RGB16, UYVY };
|
||||
|
||||
|
||||
void *data;
|
||||
int pitch; // number of pixels (not bytes) between line N and line N+1
|
||||
unsigned width, height;
|
||||
|
@ -32,7 +32,7 @@ class QSpinBox;
|
||||
*/
|
||||
class SoundDialog : public QDialog {
|
||||
Q_OBJECT
|
||||
|
||||
|
||||
const MainWindow *const mw;
|
||||
QVBoxLayout *const topLayout;
|
||||
QComboBox *const engineSelector;
|
||||
@ -44,14 +44,14 @@ class SoundDialog : public QDialog {
|
||||
int resamplerNum;
|
||||
int rate_;
|
||||
int latency_;
|
||||
|
||||
|
||||
void store();
|
||||
void restore();
|
||||
|
||||
|
||||
private slots:
|
||||
void engineChange(int index);
|
||||
void rateIndexChange(int index);
|
||||
|
||||
|
||||
public:
|
||||
explicit SoundDialog(const MainWindow *mw, QWidget *parent = 0);
|
||||
~SoundDialog();
|
||||
@ -59,9 +59,9 @@ public:
|
||||
int resamplerNo() const { return resamplerNum; }
|
||||
int rate() const { return rate_; }
|
||||
int latency() const { return latency_; };
|
||||
|
||||
|
||||
static void applySettings(MainWindow *mw, const SoundDialog *sd);
|
||||
|
||||
|
||||
public slots:
|
||||
void accept();
|
||||
void reject();
|
||||
|
@ -45,11 +45,11 @@ public:
|
||||
struct VideoSourceInfo {
|
||||
// label used in the video dialog combobox.
|
||||
QString label;
|
||||
|
||||
|
||||
unsigned width;
|
||||
unsigned height;
|
||||
};
|
||||
|
||||
|
||||
private:
|
||||
class PersistInt {
|
||||
const QString key_;
|
||||
@ -60,11 +60,11 @@ private:
|
||||
PersistInt & operator=(int i) { i_ = i; return *this; }
|
||||
operator int() const { return i_; }
|
||||
};
|
||||
|
||||
|
||||
class EngineSelector {
|
||||
QComboBox *const comboBox_;
|
||||
PersistInt index_;
|
||||
|
||||
|
||||
public:
|
||||
explicit EngineSelector(const MainWindow *mw);
|
||||
void addToLayout(QBoxLayout *topLayout);
|
||||
@ -73,13 +73,13 @@ private:
|
||||
void restore();
|
||||
int index() const { return index_; }
|
||||
};
|
||||
|
||||
|
||||
class ScalingMethodSelector {
|
||||
QRadioButton *const unrestrictedScalingButton_;
|
||||
QRadioButton *const keepRatioButton_;
|
||||
QRadioButton *const integerScalingButton_;
|
||||
PersistInt scaling_;
|
||||
|
||||
|
||||
public:
|
||||
ScalingMethodSelector();
|
||||
void addToLayout(QLayout *layout);
|
||||
@ -88,12 +88,12 @@ private:
|
||||
void restore();
|
||||
ScalingMethod scalingMethod() const { return static_cast<ScalingMethod>(static_cast<int>(scaling_)); }
|
||||
};
|
||||
|
||||
|
||||
class SourceSelector {
|
||||
QLabel *const label_;
|
||||
QComboBox *const comboBox_;
|
||||
PersistInt index_;
|
||||
|
||||
|
||||
public:
|
||||
SourceSelector(const QString &sourcesLabel, const std::vector<VideoSourceInfo> &sourceInfos);
|
||||
void addToLayout(QBoxLayout *layout);
|
||||
@ -103,12 +103,12 @@ private:
|
||||
void restore();
|
||||
int index() const { return index_; }
|
||||
};
|
||||
|
||||
|
||||
class FullResSelector {
|
||||
QComboBox *const comboBox_;
|
||||
const QString key_;
|
||||
int index_;
|
||||
|
||||
|
||||
void fillComboBox(const QSize &sourceSize, const std::vector<ResInfo> &resVector);
|
||||
public:
|
||||
FullResSelector(const QString &key, int defaultIndex,
|
||||
@ -121,12 +121,12 @@ private:
|
||||
void setSourceSize(const QSize &sourceSize, const std::vector<ResInfo> &resVector);
|
||||
int index() const { return index_; }
|
||||
};
|
||||
|
||||
|
||||
class FullHzSelector {
|
||||
QComboBox *const comboBox_;
|
||||
const QString key_;
|
||||
int index_;
|
||||
|
||||
|
||||
public:
|
||||
FullHzSelector(const QString &key, const std::vector<short> &rates, int defaultIndex);
|
||||
~FullHzSelector();
|
||||
@ -137,7 +137,7 @@ private:
|
||||
void setRates(const std::vector<short> &rates);
|
||||
int index() const { return index_; }
|
||||
};
|
||||
|
||||
|
||||
const MainWindow *const mw;
|
||||
QVBoxLayout *const topLayout;
|
||||
QWidget *engineWidget;
|
||||
@ -146,7 +146,7 @@ private:
|
||||
SourceSelector sourceSelector;
|
||||
const auto_vector<FullResSelector> fullResSelectors;
|
||||
const auto_vector<FullHzSelector> fullHzSelectors;
|
||||
|
||||
|
||||
static auto_vector<FullResSelector> makeFullResSelectors(const QSize &sourceSize, const MainWindow *mw);
|
||||
static auto_vector<FullHzSelector> makeFullHzSelectors(
|
||||
const auto_vector<FullResSelector> &fullResSelectors, const MainWindow *mw);
|
||||
@ -172,7 +172,7 @@ public:
|
||||
void setVideoSources(const std::vector<VideoSourceInfo> &sourceInfos);
|
||||
void setSourceSize(const QSize &sourceSize);
|
||||
ScalingMethod scalingMethod() const { return scalingMethodSelector.scalingMethod(); }
|
||||
|
||||
|
||||
public slots:
|
||||
void accept();
|
||||
void reject();
|
||||
|
@ -33,16 +33,16 @@ typedef struct {
|
||||
uint8_t num;
|
||||
uint8_t zero;
|
||||
};
|
||||
|
||||
|
||||
uint32_t id;
|
||||
};
|
||||
|
||||
|
||||
union {
|
||||
struct {
|
||||
int16_t xrel;
|
||||
int16_t yrel;
|
||||
};
|
||||
|
||||
|
||||
int32_t value;
|
||||
};
|
||||
} SDL_Event;
|
||||
|
@ -46,14 +46,14 @@ void SDL_SetEventFilter(const unsigned int f) {
|
||||
int SDL_PollEvent(SDL_Event *const event) {
|
||||
if (!event || queue.empty())
|
||||
return 0;
|
||||
|
||||
|
||||
{
|
||||
const SDL_Event &front = queue.front();
|
||||
event->id = front.id;
|
||||
event->value = front.value;
|
||||
}
|
||||
|
||||
|
||||
queue.pop_front();
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -35,16 +35,16 @@ struct _SDL_Joystick {
|
||||
|
||||
int nhats; /* Number of hats on the joystick */
|
||||
Uint8 *hats; /* Current hat states */
|
||||
|
||||
|
||||
int nballs; /* Number of trackballs on the joystick */
|
||||
struct balldelta {
|
||||
int dx;
|
||||
int dy;
|
||||
} *balls; /* Current ball motion deltas */
|
||||
|
||||
|
||||
int nbuttons; /* Number of buttons on the joystick */
|
||||
Uint8 *buttons; /* Current button states */
|
||||
|
||||
|
||||
struct joystick_hwdata *hwdata; /* Driver dependent information */
|
||||
|
||||
int ref_count; /* Reference count for multiple opens */
|
||||
|
@ -29,7 +29,7 @@ class AudioEngine {
|
||||
QMutex mut;
|
||||
const QString nameString_;
|
||||
int rate_;
|
||||
|
||||
|
||||
protected:
|
||||
virtual int doInit(int rate, unsigned msLatency) = 0;
|
||||
virtual void doAcceptSettings() {}
|
||||
@ -39,10 +39,10 @@ public:
|
||||
unsigned fromUnderrun;
|
||||
unsigned fromOverflow;
|
||||
};
|
||||
|
||||
|
||||
const QString& nameString() const { return nameString_; }
|
||||
int rate() const { return rate_; }
|
||||
|
||||
|
||||
AudioEngine(const QString &name) : nameString_(name), rate_(0) {}
|
||||
virtual ~AudioEngine() {}
|
||||
int init(int rate, unsigned msLatency) { QMutexLocker l(&mut); return rate_ = doInit(rate, msLatency); }
|
||||
@ -54,14 +54,14 @@ public:
|
||||
|
||||
/** @return success */
|
||||
virtual bool flushPausedBuffers() const { return false; }
|
||||
|
||||
|
||||
virtual int write(void *buffer, unsigned samples, BufferState &preBufState_out, long &rate_out) {
|
||||
preBufState_out = bufferState();
|
||||
const int ret = write(buffer, samples);
|
||||
rate_out = rateEstimate();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
virtual QWidget* settingsWidget() const { return 0; }
|
||||
void acceptSettings() { QMutexLocker l(&mut); doAcceptSettings(); }
|
||||
virtual void rejectSettings() const {}
|
||||
|
@ -34,77 +34,77 @@ AlsaEngine::~AlsaEngine() {
|
||||
|
||||
int AlsaEngine::doInit(const int inrate, const unsigned latency) {
|
||||
unsigned rate = inrate;
|
||||
|
||||
|
||||
if (snd_pcm_open(&pcm_handle, conf.device(), SND_PCM_STREAM_PLAYBACK, 0) < 0) {
|
||||
std::fprintf(stderr, "Error opening PCM device %s\n", conf.device());
|
||||
pcm_handle = 0;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
snd_pcm_hw_params_t *hwparams;
|
||||
snd_pcm_hw_params_alloca(&hwparams);
|
||||
|
||||
|
||||
if (snd_pcm_hw_params_any(pcm_handle, hwparams) < 0) {
|
||||
std::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) {
|
||||
std::fprintf(stderr, "Error setting access.\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
||||
if (snd_pcm_hw_params_set_format(pcm_handle, hwparams, SND_PCM_FORMAT_S16) < 0) {
|
||||
std::fprintf(stderr, "Error setting format.\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
||||
if (snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &rate, 0) < 0) {
|
||||
std::fprintf(stderr, "Error setting rate.\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
||||
if (snd_pcm_hw_params_set_channels(pcm_handle, hwparams, 2) < 0) {
|
||||
std::fprintf(stderr, "Error setting channels.\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
unsigned ulatency = latency * 1000;
|
||||
|
||||
|
||||
if (snd_pcm_hw_params_set_buffer_time_near(pcm_handle, hwparams, &ulatency, 0) < 0) {
|
||||
std::fprintf(stderr, "Error setting buffer latency %u.\n", ulatency);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
unsigned val = 16;
|
||||
snd_pcm_hw_params_set_periods_max(pcm_handle, hwparams, &val, 0);
|
||||
}
|
||||
|
||||
|
||||
if (snd_pcm_hw_params(pcm_handle, hwparams) < 0) {
|
||||
std::fprintf(stderr, "Error setting HW params.\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
snd_pcm_uframes_t bSize = 0;
|
||||
|
||||
|
||||
if (snd_pcm_hw_params_get_buffer_size(hwparams, &bSize) < 0) {
|
||||
std::fprintf(stderr, "Error getting buffer size\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
||||
bufSize = bSize;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
snd_pcm_sw_params_t *swparams;
|
||||
snd_pcm_sw_params_alloca(&swparams);
|
||||
|
||||
|
||||
if (snd_pcm_sw_params_current(pcm_handle, swparams) < 0) {
|
||||
std::fprintf(stderr, "Error getting current swparams\n");
|
||||
} else if (snd_pcm_sw_params_set_start_threshold(pcm_handle, swparams, bufSize) < 0) {
|
||||
@ -113,12 +113,12 @@ int AlsaEngine::doInit(const int inrate, const unsigned latency) {
|
||||
std::fprintf(stderr, "Error setting swparams\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
prevfur = 0;
|
||||
est.init(rate, rate, bufSize);
|
||||
|
||||
|
||||
return rate;
|
||||
|
||||
|
||||
fail:
|
||||
uninit();
|
||||
return -1;
|
||||
@ -127,29 +127,29 @@ fail:
|
||||
void AlsaEngine::uninit() {
|
||||
if (pcm_handle)
|
||||
snd_pcm_close(pcm_handle);
|
||||
|
||||
|
||||
pcm_handle = 0;
|
||||
}
|
||||
|
||||
int AlsaEngine::write(void *const buffer, const unsigned samples, const BufferState &bstate) {
|
||||
bool underrun = false;
|
||||
|
||||
|
||||
if (bstate.fromUnderrun == 0 || snd_pcm_state(pcm_handle) != SND_PCM_STATE_RUNNING) {
|
||||
underrun = true;
|
||||
} else if (prevfur > bstate.fromUnderrun && bstate.fromUnderrun != BufferState::NOT_SUPPORTED) {
|
||||
est.feed(prevfur - bstate.fromUnderrun);
|
||||
}
|
||||
|
||||
|
||||
prevfur = bstate.fromUnderrun + samples;
|
||||
|
||||
|
||||
for (int n = 4; n-- && snd_pcm_writei(pcm_handle, buffer, samples) < 0;) {
|
||||
snd_pcm_prepare(pcm_handle);
|
||||
underrun = true;
|
||||
}
|
||||
|
||||
|
||||
if (underrun)
|
||||
est.reset();
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -166,22 +166,22 @@ int AlsaEngine::write(void *const buffer, const unsigned samples, BufferState &p
|
||||
const AudioEngine::BufferState AlsaEngine::bufferState() const {
|
||||
BufferState s;
|
||||
snd_pcm_sframes_t avail;
|
||||
|
||||
|
||||
snd_pcm_hwsync(pcm_handle);
|
||||
avail = snd_pcm_avail_update(pcm_handle);
|
||||
|
||||
|
||||
if (avail == -EPIPE)
|
||||
avail = bufSize;
|
||||
|
||||
|
||||
if (avail < 0) {
|
||||
s.fromOverflow = s.fromUnderrun = BufferState::NOT_SUPPORTED;
|
||||
} else {
|
||||
if (static_cast<unsigned>(avail) > bufSize)
|
||||
avail = bufSize;
|
||||
|
||||
|
||||
s.fromUnderrun = bufSize - avail;
|
||||
s.fromOverflow = avail;
|
||||
}
|
||||
|
||||
|
||||
return s;
|
||||
}
|
||||
|
@ -30,11 +30,11 @@ class AlsaEngine : public AudioEngine {
|
||||
snd_pcm_t *pcm_handle;
|
||||
unsigned bufSize;
|
||||
unsigned prevfur;
|
||||
|
||||
|
||||
int doInit(int rate, unsigned latency);
|
||||
void doAcceptSettings() { conf.acceptSettings(); }
|
||||
int write(void *buffer, unsigned samples, const BufferState &bstate);
|
||||
|
||||
|
||||
public:
|
||||
AlsaEngine();
|
||||
~AlsaEngine();
|
||||
|
@ -26,22 +26,22 @@ AoEngine::~AoEngine() {
|
||||
|
||||
int AoEngine::doInit(const int rate, unsigned /*latency*/) {
|
||||
ao_initialize();
|
||||
|
||||
|
||||
aoDevice = NULL;
|
||||
|
||||
|
||||
ao_sample_format sampleFormat = { 16, rate, 2, AO_FMT_NATIVE };
|
||||
|
||||
|
||||
int aoDriverId = ao_default_driver_id();
|
||||
|
||||
|
||||
if (aoDriverId != -1) {
|
||||
aoDevice = ao_open_live(aoDriverId, &sampleFormat, NULL);
|
||||
}
|
||||
|
||||
|
||||
if (aoDevice == NULL) {
|
||||
ao_shutdown();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
return sampleFormat.rate;
|
||||
}
|
||||
|
||||
@ -49,7 +49,7 @@ void AoEngine::uninit() {
|
||||
if (aoDevice) {
|
||||
ao_close(aoDevice);
|
||||
aoDevice = NULL;
|
||||
|
||||
|
||||
ao_shutdown();
|
||||
}
|
||||
}
|
||||
@ -57,6 +57,6 @@ void AoEngine::uninit() {
|
||||
int AoEngine::write(void *const buffer, const unsigned samples) {
|
||||
if (ao_play(aoDevice, reinterpret_cast<char*>(buffer), samples * 4) == 0)
|
||||
return -1;
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -25,9 +25,9 @@
|
||||
|
||||
class AoEngine : public AudioEngine {
|
||||
ao_device *aoDevice;
|
||||
|
||||
|
||||
int doInit(int rate, unsigned latency);
|
||||
|
||||
|
||||
public:
|
||||
AoEngine();
|
||||
~AoEngine();
|
||||
|
@ -26,12 +26,12 @@ namespace {
|
||||
static int createMutex(pthread_mutex_t* &mutptr) {
|
||||
mutptr = new pthread_mutex_t;
|
||||
const int ret = pthread_mutex_init(mutptr, 0);
|
||||
|
||||
|
||||
if (ret) {
|
||||
delete mutptr;
|
||||
mutptr = 0;
|
||||
}
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -47,12 +47,12 @@ static void destroyMutex(pthread_mutex_t* &mutptr) {
|
||||
static int createCond(pthread_cond_t* &condptr) {
|
||||
condptr = new pthread_cond_t;
|
||||
const int ret = pthread_cond_init(condptr, 0);
|
||||
|
||||
|
||||
if (ret) {
|
||||
delete condptr;
|
||||
condptr = 0;
|
||||
}
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -66,13 +66,13 @@ static void destroyCond(pthread_cond_t* &condptr) {
|
||||
|
||||
class MutexLocker : Uncopyable {
|
||||
pthread_mutex_t *const mut;
|
||||
|
||||
|
||||
public:
|
||||
const int err;
|
||||
|
||||
|
||||
explicit MutexLocker(pthread_mutex_t *mut) : mut(mut), err(pthread_mutex_lock(mut)) {
|
||||
}
|
||||
|
||||
|
||||
~MutexLocker() {
|
||||
if (!err)
|
||||
pthread_mutex_unlock(mut);
|
||||
@ -98,22 +98,22 @@ CoreAudioEngine::~CoreAudioEngine() {
|
||||
|
||||
unsigned CoreAudioEngine::read(void *const stream, unsigned frames, const Float64 rateScalar) {
|
||||
MutexLocker mutlock(mutex);
|
||||
|
||||
|
||||
if (!mutlock.err) {
|
||||
{
|
||||
const Float64 rateEst = rate() / rateScalar;
|
||||
// rateVar = (rateVar * 15 + std::fabs(rateEst - this->rateEst)) * (1.0 / 16.0);
|
||||
this->rateEst = rateEst;
|
||||
}
|
||||
|
||||
|
||||
if (frames > rbuf.used() / 2)
|
||||
frames = rbuf.used() / 2;
|
||||
|
||||
|
||||
rbuf.read(reinterpret_cast<SInt16*>(stream), frames * 2);
|
||||
|
||||
|
||||
pthread_cond_signal(availCond);
|
||||
}
|
||||
|
||||
|
||||
return frames;
|
||||
}
|
||||
|
||||
@ -122,14 +122,14 @@ OSStatus CoreAudioEngine::renderProc(void *inRefCon, AudioUnitRenderActionFlags
|
||||
{
|
||||
ioData->mBuffers[0].mDataByteSize = reinterpret_cast<CoreAudioEngine*>(
|
||||
inRefCon)->read(ioData->mBuffers[0].mData, inNumFrames, inTimeStamp->mRateScalar) * 4;
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CoreAudioEngine::doInit(const int rate, const unsigned latency) {
|
||||
{
|
||||
Component comp;
|
||||
|
||||
|
||||
{
|
||||
ComponentDescription desc;
|
||||
desc.componentType = kAudioUnitType_Output;
|
||||
@ -137,31 +137,31 @@ int CoreAudioEngine::doInit(const int rate, const unsigned latency) {
|
||||
desc.componentManufacturer = kAudioUnitManufacturer_Apple;
|
||||
desc.componentFlags = 0;
|
||||
desc.componentFlagsMask = 0;
|
||||
|
||||
|
||||
if ((comp = FindNextComponent(0, &desc)) == 0) {
|
||||
std::fprintf(stderr, "Failed to find output unit component\n");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (ComponentResult err = OpenAComponent(comp, &outUnit)) {
|
||||
std::fprintf(stderr, "Failed to open output unit component: %d\n", static_cast<int>(err));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
||||
outUnitState = UNIT_OPENED;
|
||||
}
|
||||
|
||||
|
||||
if (ComponentResult err = AudioUnitInitialize(outUnit)) {
|
||||
std::fprintf(stderr, "Failed to initialize output unit component: %d\n", static_cast<int>(err));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
||||
outUnitState = UNIT_INITED;
|
||||
|
||||
|
||||
{
|
||||
AudioStreamBasicDescription desc;
|
||||
|
||||
|
||||
desc.mSampleRate = rate;
|
||||
desc.mFormatID = kAudioFormatLinearPCM;
|
||||
desc.mChannelsPerFrame = 2;
|
||||
@ -169,59 +169,59 @@ int CoreAudioEngine::doInit(const int rate, const unsigned latency) {
|
||||
desc.mFramesPerPacket = 1;
|
||||
desc.mBytesPerPacket = desc.mBytesPerFrame = 4;
|
||||
desc.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
|
||||
|
||||
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
desc.mFormatFlags |= kAudioFormatFlagIsBigEndian;
|
||||
#endif
|
||||
|
||||
|
||||
if (ComponentResult err = AudioUnitSetProperty(outUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &desc, sizeof desc)) {
|
||||
std::fprintf(stderr, "Failed to set the input format: %d\n", static_cast<int>(err));
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
AURenderCallbackStruct renderCallback;
|
||||
renderCallback.inputProc = renderProc;
|
||||
renderCallback.inputProcRefCon = this;
|
||||
|
||||
|
||||
if (ComponentResult err = AudioUnitSetProperty(outUnit,
|
||||
kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &renderCallback, sizeof renderCallback)) {
|
||||
std::fprintf(stderr, "Failed to set render callback: %d\n", static_cast<int>(err));
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (int err = createMutex(mutex)) {
|
||||
std::fprintf(stderr, "Failed to create mutex: %d\n", err);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
||||
if (int err = createCond(availCond)) {
|
||||
std::fprintf(stderr, "Failed to create condition variable: %d\n", err);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
||||
rbuf.reset(((rate * latency + 500) / 1000) * 2);
|
||||
rbuf.fill(0);
|
||||
rateEst = rate;
|
||||
// rateVar = rate >> 12;
|
||||
|
||||
|
||||
return rate;
|
||||
|
||||
|
||||
fail:
|
||||
uninit();
|
||||
|
||||
return -1;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void CoreAudioEngine::uninit() {
|
||||
if (outUnitState >= UNIT_INITED)
|
||||
AudioUnitUninitialize(outUnit);
|
||||
|
||||
|
||||
if (outUnitState >= UNIT_OPENED)
|
||||
CloseComponent(outUnit);
|
||||
|
||||
|
||||
destroyMutex(mutex);
|
||||
destroyCond(availCond);
|
||||
outUnitState = UNIT_CLOSED;
|
||||
@ -242,15 +242,15 @@ int CoreAudioEngine::doWrite(void *const buffer, unsigned samples) {
|
||||
std::fprintf(stderr, "Failed to start output unit: %d\n", static_cast<int>(err));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
running = true;
|
||||
}
|
||||
|
||||
|
||||
SInt16 *inBuf = reinterpret_cast<SInt16*>(buffer);
|
||||
|
||||
|
||||
{
|
||||
std::size_t avail;
|
||||
|
||||
|
||||
while ((avail = rbuf.avail() / 2) < samples) {
|
||||
rbuf.write(inBuf, avail * 2);
|
||||
inBuf += avail * 2;
|
||||
@ -258,18 +258,18 @@ int CoreAudioEngine::doWrite(void *const buffer, unsigned samples) {
|
||||
pthread_cond_wait(availCond, mutex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
rbuf.write(inBuf, samples * 2);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CoreAudioEngine::write(void *const buffer, const unsigned samples, BufferState &preBufState_out, long &rate_out) {
|
||||
MutexLocker mutlock(mutex);
|
||||
|
||||
|
||||
if (mutlock.err)
|
||||
return -1;
|
||||
|
||||
|
||||
preBufState_out.fromUnderrun = rbuf.used() / 2;
|
||||
preBufState_out.fromOverflow = rbuf.avail() / 2;
|
||||
rate_out = rateEst + 0.5;
|
||||
@ -279,10 +279,10 @@ int CoreAudioEngine::write(void *const buffer, const unsigned samples, BufferSta
|
||||
|
||||
int CoreAudioEngine::write(void *const buffer, const unsigned samples) {
|
||||
MutexLocker mutlock(mutex);
|
||||
|
||||
|
||||
if (mutlock.err)
|
||||
return -1;
|
||||
|
||||
|
||||
return doWrite(buffer, samples);
|
||||
}
|
||||
|
||||
|
@ -35,13 +35,13 @@ class CoreAudioEngine : public AudioEngine, private Uncopyable {
|
||||
pthread_cond_t *availCond;
|
||||
Float64 rateEst;
|
||||
bool running;
|
||||
|
||||
|
||||
static OSStatus renderProc(void *inRefCon, AudioUnitRenderActionFlags *inActionFlags,
|
||||
const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumFrames, AudioBufferList *ioData);
|
||||
unsigned read(void *stream, unsigned frames, Float64 rateScalar);
|
||||
int doInit(int rate, unsigned latency);
|
||||
int doWrite(void *buffer, unsigned frames);
|
||||
|
||||
|
||||
public:
|
||||
CoreAudioEngine();
|
||||
~CoreAudioEngine();
|
||||
|
@ -37,7 +37,7 @@ useCustomDev(false)
|
||||
confWidget->layout()->setMargin(0);
|
||||
confWidget->layout()->addWidget(customDevBox);
|
||||
confWidget->layout()->addWidget(customDevEdit);
|
||||
|
||||
|
||||
{
|
||||
QSettings settings;
|
||||
settings.beginGroup(confgroup);
|
||||
@ -45,7 +45,7 @@ useCustomDev(false)
|
||||
customDevStr = settings.value("customDevStr", customDevStr).toByteArray();
|
||||
settings.endGroup();
|
||||
}
|
||||
|
||||
|
||||
customDevBoxChange(customDevBox->isChecked());
|
||||
connect(customDevBox, SIGNAL(toggled(bool)), this, SLOT(customDevBoxChange(bool)));
|
||||
rejectSettings();
|
||||
|
@ -29,7 +29,7 @@ class QWidget;
|
||||
|
||||
class CustomDevConf : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
|
||||
const char *const defaultstr;
|
||||
const char *const confgroup;
|
||||
const scoped_ptr<QWidget> confWidget;
|
||||
@ -37,10 +37,10 @@ class CustomDevConf : public QObject {
|
||||
QLineEdit *const customDevEdit;
|
||||
QByteArray customDevStr;
|
||||
bool useCustomDev;
|
||||
|
||||
|
||||
private slots:
|
||||
void customDevBoxChange(bool checked);
|
||||
|
||||
|
||||
public:
|
||||
CustomDevConf(const char *desc, const char *defaultstr, const char *confgroup, const char *customdevstr = 0);
|
||||
~CustomDevConf();
|
||||
|
@ -23,7 +23,7 @@
|
||||
|
||||
class NullAudioEngine : public AudioEngine {
|
||||
int doInit(int rate, unsigned /*latency*/) { return rate; }
|
||||
|
||||
|
||||
public:
|
||||
NullAudioEngine() : AudioEngine("Null") {}
|
||||
int write(void */*buffer*/, unsigned /*samples*/) { return 0; }
|
||||
|
@ -35,15 +35,15 @@ static const char* errorToString(ALenum error) {
|
||||
case AL_INVALID_OPERATION: return "invalid operation";
|
||||
case AL_OUT_OF_MEMORY: return "out of memory";
|
||||
}
|
||||
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
static ALint getSourcei(ALuint source, ALenum pname) {
|
||||
ALint value = 0;
|
||||
|
||||
|
||||
alGetSourcei(source, pname, &value);
|
||||
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
@ -66,10 +66,10 @@ OpenAlEngine::~OpenAlEngine() {
|
||||
|
||||
void OpenAlEngine::deleteProcessedBufs() const {
|
||||
ALint processed = getSourcei(source, AL_BUFFERS_PROCESSED);
|
||||
|
||||
|
||||
while (processed--) {
|
||||
ALuint bid = 0;
|
||||
|
||||
|
||||
alSourceUnqueueBuffers(source, 1, &bid);
|
||||
alDeleteBuffers(1, &bid);
|
||||
}
|
||||
@ -78,52 +78,52 @@ void OpenAlEngine::deleteProcessedBufs() const {
|
||||
int OpenAlEngine::doInit(const int rate, unsigned latency) {
|
||||
class FailureCleaner {
|
||||
OpenAlEngine *const engine;
|
||||
|
||||
|
||||
public:
|
||||
bool failed;
|
||||
|
||||
|
||||
FailureCleaner(OpenAlEngine *engine) : engine(engine), failed(true) {}
|
||||
|
||||
|
||||
~FailureCleaner() {
|
||||
if (failed)
|
||||
engine->uninit();
|
||||
}
|
||||
} failureCleaner(this);
|
||||
|
||||
|
||||
ALenum error;
|
||||
|
||||
|
||||
if (!(device = alcOpenDevice(NULL))) {
|
||||
std::fprintf(stderr, "alcOpenDevice error\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
if (!(context = alcCreateContext(device, NULL))) {
|
||||
std::fprintf(stderr, "alcCreateContext error\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
alGetError();
|
||||
alcMakeContextCurrent(context);
|
||||
|
||||
|
||||
if ((error = alGetError()) != AL_NO_ERROR) {
|
||||
std::fprintf(stderr, "alcMakeContextCurrent error: %s\n", errorToString(error));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
alGenSources (1, &source);
|
||||
|
||||
|
||||
if ((error = alGetError()) != AL_NO_ERROR) {
|
||||
std::fprintf(stderr, "alGenSources error: %s\n", errorToString(error));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
failureCleaner.failed = false;
|
||||
buffers = rate * latency / (BUF_SZ * 1000);
|
||||
++buffers;
|
||||
// std::printf("buffers: %u\n", buffers);
|
||||
buf = new qint16[BUF_SZ * 2];
|
||||
bufPos = 0;
|
||||
|
||||
|
||||
return rate;
|
||||
}
|
||||
|
||||
@ -131,28 +131,28 @@ void OpenAlEngine::uninit() {
|
||||
if (context) {
|
||||
if (alIsSource(source)) {
|
||||
alSourceStop(source);
|
||||
|
||||
|
||||
ALint queued = getSourcei(source, AL_BUFFERS_QUEUED);
|
||||
|
||||
|
||||
while (queued--) {
|
||||
ALuint bid = 0;
|
||||
|
||||
|
||||
alSourceUnqueueBuffers(source, 1, &bid);
|
||||
alDeleteBuffers(1, &bid);
|
||||
}
|
||||
|
||||
|
||||
alDeleteSources(1, &source);
|
||||
}
|
||||
|
||||
|
||||
alcMakeContextCurrent(NULL);
|
||||
alcDestroyContext(context);
|
||||
}
|
||||
|
||||
|
||||
if (device)
|
||||
alcCloseDevice(device);
|
||||
|
||||
|
||||
delete []buf;
|
||||
|
||||
|
||||
buf = NULL;
|
||||
context = NULL;
|
||||
device = NULL;
|
||||
@ -163,7 +163,7 @@ int OpenAlEngine::write(void *const data, const unsigned samples) {
|
||||
{
|
||||
unsigned total = samples + bufPos;
|
||||
const qint16 *src = static_cast<const qint16*>(data);
|
||||
|
||||
|
||||
while (total >= BUF_SZ) {
|
||||
if (getSourcei(source, AL_BUFFERS_QUEUED) >= static_cast<int>(buffers)) {
|
||||
while (getSourcei(source, AL_BUFFERS_PROCESSED) < 1 && getSourcei(source, AL_SOURCE_STATE) == AL_PLAYING) {
|
||||
@ -174,17 +174,17 @@ int OpenAlEngine::write(void *const data, const unsigned samples) {
|
||||
nanosleep(&tspec, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
ALuint bid = 0;
|
||||
alSourceUnqueueBuffers(source, 1, &bid);
|
||||
alDeleteBuffers(1, &bid);
|
||||
}
|
||||
|
||||
|
||||
std::memcpy(buf + bufPos * 2, src, (BUF_SZ - bufPos) * 2 * sizeof *buf);
|
||||
src += (BUF_SZ - bufPos) * 2;
|
||||
total -= BUF_SZ;
|
||||
bufPos = 0;
|
||||
|
||||
|
||||
{
|
||||
ALuint bufid = 0;
|
||||
alGenBuffers(1, &bufid);
|
||||
@ -192,40 +192,40 @@ int OpenAlEngine::write(void *const data, const unsigned samples) {
|
||||
alSourceQueueBuffers(source, 1, &bufid);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::memcpy(buf + bufPos * 2, src, (total - bufPos) * 2 * sizeof *buf);
|
||||
|
||||
|
||||
bufPos = total;
|
||||
}
|
||||
|
||||
|
||||
if (getSourcei(source, AL_SOURCE_STATE) != AL_PLAYING) {
|
||||
//std::printf("UNDERRUN!!!!!!!!!!!!!!!!!!!!!!!!!\n");
|
||||
alSourcePlay(source);
|
||||
}
|
||||
|
||||
|
||||
//if (alGetError() != AL_NO_ERROR)
|
||||
// return -1;
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const AudioEngine::BufferState OpenAlEngine::bufferState() const {
|
||||
deleteProcessedBufs();
|
||||
|
||||
|
||||
unsigned fromUnderrun = 0;
|
||||
|
||||
|
||||
{
|
||||
const ALint queued = getSourcei(source, AL_BUFFERS_QUEUED);
|
||||
|
||||
|
||||
if (queued > 0)
|
||||
fromUnderrun = queued * BUF_SZ - (BUF_SZ >> 1);
|
||||
}
|
||||
|
||||
|
||||
fromUnderrun += bufPos;
|
||||
|
||||
|
||||
const BufferState s = { fromUnderrun: fromUnderrun, fromOverflow: fromUnderrun > (buffers + 1) * BUF_SZ ? 0 : (buffers + 1) * BUF_SZ - fromUnderrun };
|
||||
|
||||
|
||||
//std::printf("fromUnderrun: %u\n", s.fromUnderrun);
|
||||
|
||||
|
||||
return s;
|
||||
}
|
||||
|
@ -40,10 +40,10 @@ class OpenAlEngine : public AudioEngine {
|
||||
ALuint source;
|
||||
unsigned buffers;
|
||||
unsigned bufPos;
|
||||
|
||||
|
||||
void deleteProcessedBufs() const;
|
||||
int doInit(int rate, unsigned latency);
|
||||
|
||||
|
||||
public:
|
||||
OpenAlEngine();
|
||||
~OpenAlEngine();
|
||||
|
@ -50,66 +50,66 @@ int OssEngine::doInit(int speed, const unsigned latency) {
|
||||
std::perror(conf.device());
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
int channels = 2;
|
||||
|
||||
|
||||
if (ioctl(audio_fd, SNDCTL_DSP_CHANNELS, &channels) == -1) {
|
||||
std::perror("SNDCTL_DSP_CHANNELS");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
||||
if (channels != 2) {
|
||||
std::fprintf(stderr, "oss: unsupported number of channels\n");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
int format = AFMT_S16_NE;
|
||||
|
||||
|
||||
if (ioctl(audio_fd, SNDCTL_DSP_SETFMT, &format) == -1) {
|
||||
std::perror("SNDCTL_DSP_SETFMT");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
||||
if (format != AFMT_S16_NE) {
|
||||
std::fprintf(stderr, "oss: unsupported format\n");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (ioctl(audio_fd, SNDCTL_DSP_SPEED, &speed) == -1) {
|
||||
std::perror("SNDCTL_DSP_SPEED");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
int arg = 0x60000 | static_cast<int>(std::log(speed * latency * 4 / 6000.0) / std::log(2.0) + 0.5);
|
||||
|
||||
|
||||
if (ioctl(audio_fd, SNDCTL_DSP_SETFRAGMENT, &arg) == -1) {
|
||||
std::perror("SNDCTL_DSP_SETFRAGMENT");
|
||||
// goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
audio_buf_info info;
|
||||
|
||||
|
||||
if (ioctl(audio_fd, SNDCTL_DSP_GETOSPACE, &info) == -1) {
|
||||
std::perror("SNDCTL_DSP_GETOSPACE");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
||||
bufSize = info.bytes >> 2;
|
||||
fragSize = info.fragsize >> 2;
|
||||
}
|
||||
|
||||
|
||||
prevbytes = 0;
|
||||
est.init(speed, speed, bufSize);
|
||||
|
||||
|
||||
return speed;
|
||||
|
||||
|
||||
fail:
|
||||
uninit();
|
||||
return -1;
|
||||
@ -118,14 +118,14 @@ fail:
|
||||
void OssEngine::uninit() {
|
||||
if (audio_fd != -1)
|
||||
close(audio_fd);
|
||||
|
||||
|
||||
audio_fd = -1;
|
||||
}
|
||||
|
||||
int OssEngine::write(void *const buffer, const unsigned samples, const BufferState &bstate) {
|
||||
if (bstate.fromUnderrun != BufferState::NOT_SUPPORTED) {
|
||||
count_info ci;
|
||||
|
||||
|
||||
if (ioctl(audio_fd, SNDCTL_DSP_GETOPTR, &ci) != -1) {
|
||||
if (static_cast<unsigned>(ci.bytes) > prevbytes) {
|
||||
if (bstate.fromUnderrun > fragSize)
|
||||
@ -133,14 +133,14 @@ int OssEngine::write(void *const buffer, const unsigned samples, const BufferSta
|
||||
else
|
||||
est.reset();
|
||||
}
|
||||
|
||||
|
||||
prevbytes = ci.bytes;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (::write(audio_fd, buffer, samples * 4) != static_cast<int>(samples * 4))
|
||||
return -1;
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -157,7 +157,7 @@ int OssEngine::write(void *const buffer, const unsigned samples, BufferState &pr
|
||||
const AudioEngine::BufferState OssEngine::bufferState() const {
|
||||
BufferState s;
|
||||
audio_buf_info info;
|
||||
|
||||
|
||||
if (ioctl(audio_fd, SNDCTL_DSP_GETOSPACE, &info) == -1) {
|
||||
s.fromOverflow = s.fromUnderrun = BufferState::NOT_SUPPORTED;
|
||||
} else {
|
||||
@ -165,10 +165,10 @@ const AudioEngine::BufferState OssEngine::bufferState() const {
|
||||
info.bytes = 0;
|
||||
else if (static_cast<unsigned>(info.bytes >> 2) > bufSize)
|
||||
info.bytes = bufSize << 2;
|
||||
|
||||
|
||||
s.fromUnderrun = bufSize - (info.bytes >> 2);
|
||||
s.fromOverflow = info.bytes >> 2;
|
||||
}
|
||||
|
||||
|
||||
return s;
|
||||
}
|
||||
|
@ -30,11 +30,11 @@ class OssEngine : public AudioEngine {
|
||||
unsigned bufSize;
|
||||
unsigned fragSize;
|
||||
unsigned prevbytes;
|
||||
|
||||
|
||||
int doInit(int rate, unsigned latency);
|
||||
void doAcceptSettings() { conf.acceptSettings(); }
|
||||
int write(void *buffer, unsigned samples, const BufferState &bstate);
|
||||
|
||||
|
||||
public:
|
||||
OssEngine();
|
||||
~OssEngine();
|
||||
|
@ -74,12 +74,12 @@ void BlitterContainer::setBlitter(BlitterWidget *const blitter_in) {
|
||||
if (blitter_ != blitter_in) {
|
||||
// if (blitter_)
|
||||
// blitter_->setParent(0);
|
||||
|
||||
|
||||
blitter_ = blitter_in;
|
||||
|
||||
|
||||
// if (blitter_)
|
||||
// blitter_->setParent(this);
|
||||
|
||||
|
||||
updateLayout();
|
||||
testExclusive();
|
||||
}
|
||||
|
@ -32,15 +32,15 @@ class BlitterContainer : public QWidget {
|
||||
ScalingMethod scalingMethod_;
|
||||
bool parentExclusive;
|
||||
bool cursorHidden_;
|
||||
|
||||
|
||||
void doLayout(int w, int h);
|
||||
void testExclusive();
|
||||
void updateLayout() { doLayout(width(), height()); }
|
||||
|
||||
|
||||
protected:
|
||||
void moveEvent(QMoveEvent *event);
|
||||
void resizeEvent(QResizeEvent *event);
|
||||
|
||||
|
||||
public:
|
||||
explicit BlitterContainer(QWidget *parent = 0);
|
||||
~BlitterContainer();
|
||||
|
@ -51,15 +51,15 @@ class BlitterWidget : public QWidget {
|
||||
const QString nameString_;
|
||||
const unsigned maxSwapInterval_;
|
||||
bool paused;
|
||||
|
||||
|
||||
protected:
|
||||
virtual void privSetPaused(const bool paused) { setUpdatesEnabled(paused); }
|
||||
virtual void setBufferDimensions(unsigned width, unsigned height) = 0;
|
||||
|
||||
|
||||
// use these if modifying pixel buffer in the sync method, or in an event method.
|
||||
void lockPixelBuffer() { vbl.lock(); }
|
||||
void unlockPixelBuffer() { vbl.unlock(); }
|
||||
|
||||
|
||||
void setPixelBuffer(void *pixels, PixelBuffer::PixelFormat format, unsigned pitch) {
|
||||
pixbuf.data = pixels;
|
||||
pixbuf.pitch = pitch;
|
||||
@ -82,24 +82,24 @@ public:
|
||||
virtual void blit() = 0;
|
||||
virtual void draw() {}
|
||||
virtual bool isUnusable() const { return false; }
|
||||
|
||||
|
||||
void setVideoFormat(unsigned width, unsigned height/*, PixelBuffer::PixelFormat pf*/) {
|
||||
pixbuf.width = width;
|
||||
pixbuf.height = height;
|
||||
setBufferDimensions(width, height);
|
||||
// return pf == pixbuf.pixelFormat;
|
||||
}
|
||||
|
||||
|
||||
virtual void setCorrectedGeometry(int w, int h, int new_w, int new_h) {
|
||||
setGeometry((w - new_w) >> 1, (h - new_h) >> 1, new_w, new_h);
|
||||
}
|
||||
|
||||
|
||||
virtual WId hwnd() const { return winId(); }
|
||||
virtual long frameTimeEst() const { return 0; }
|
||||
virtual long sync() { return 0; }
|
||||
virtual void setExclusive(bool) {}
|
||||
virtual void setSwapInterval(unsigned) {}
|
||||
|
||||
|
||||
virtual QWidget* settingsWidget() const { return 0; }
|
||||
virtual void acceptSettings() {}
|
||||
virtual void rejectSettings() const {}
|
||||
|
@ -325,7 +325,7 @@ void QGLBlitter::blit() {
|
||||
void QGLBlitter::draw() {
|
||||
if (buffer)
|
||||
subWidget->updateTexture(inBuffer().data == buffer ? buffer + buffer.size() / 2 : buffer);
|
||||
|
||||
|
||||
if (subWidget->doubleBuffer())
|
||||
subWidget->blit();
|
||||
}
|
||||
|
@ -27,7 +27,7 @@
|
||||
|
||||
class QGLBlitter : public BlitterWidget {
|
||||
class SubWidget;
|
||||
|
||||
|
||||
const DwmControlHwndChange hwndChange_;
|
||||
FtEst ftEst;
|
||||
const scoped_ptr<QWidget> confWidget;
|
||||
@ -37,14 +37,14 @@ class QGLBlitter : public BlitterWidget {
|
||||
unsigned swapInterval_;
|
||||
int dhz;
|
||||
scoped_ptr<SubWidget> subWidget;
|
||||
|
||||
|
||||
void resetSubWidget();
|
||||
void privSetPaused(const bool /*paused*/) {}
|
||||
|
||||
|
||||
protected:
|
||||
void setBufferDimensions(unsigned int width, unsigned int height);
|
||||
void resizeEvent(QResizeEvent *event);
|
||||
|
||||
|
||||
public:
|
||||
explicit QGLBlitter(VideoBufferLocker vbl, DwmControlHwndChange hwndChange, QWidget *parent = 0);
|
||||
~QGLBlitter();
|
||||
@ -57,10 +57,10 @@ public:
|
||||
void draw();
|
||||
long sync();
|
||||
QWidget* settingsWidget() const { return confWidget.get(); }
|
||||
|
||||
|
||||
void acceptSettings();
|
||||
void rejectSettings() const;
|
||||
|
||||
|
||||
void setSwapInterval(unsigned);
|
||||
void rateChange(int dhz);
|
||||
void compositionEnabledChange();
|
||||
|
@ -63,7 +63,7 @@ void QPainterBlitter::draw() {
|
||||
void QPainterBlitter::paintEvent(QPaintEvent *const event) {
|
||||
if (!image.get())
|
||||
return;
|
||||
|
||||
|
||||
QImage *const frontImage = image2.get() && backImage == image.get() ? image2.get() : image.get();
|
||||
QPainter painter(this);
|
||||
painter.setClipRegion(event->region());
|
||||
@ -94,13 +94,13 @@ void QPainterBlitter::setBufferDimensions(const unsigned int w, const unsigned i
|
||||
|
||||
void QPainterBlitter::uninit() {
|
||||
image.reset();
|
||||
|
||||
|
||||
if (image2.get()) {
|
||||
image2.reset();
|
||||
} else {
|
||||
delete[] buffer;
|
||||
}
|
||||
|
||||
|
||||
buffer = NULL;
|
||||
}
|
||||
|
||||
|
@ -33,12 +33,12 @@ class QPainterBlitter : public BlitterWidget {
|
||||
scoped_ptr<QImage> image2;
|
||||
PersistCheckBox bf_;
|
||||
union { quint32 *buffer; QImage *backImage; };
|
||||
|
||||
|
||||
protected:
|
||||
void privSetPaused(bool) {}
|
||||
void paintEvent(QPaintEvent *event);
|
||||
void resizeEvent(QResizeEvent *event);
|
||||
|
||||
|
||||
public:
|
||||
explicit QPainterBlitter(VideoBufferLocker vbl, QWidget *parent = 0);
|
||||
~QPainterBlitter();
|
||||
|
@ -57,7 +57,7 @@ public:
|
||||
X11Blitter::ShmBlitter::ShmBlitter(const unsigned width, const unsigned height, const VisInfo &visInfo, const bool db) : doubleBuffer(db) {
|
||||
shminfo.shmaddr = NULL;
|
||||
ximage = XShmCreateImage(QX11Info::display(), reinterpret_cast<Visual*>(visInfo.visual), visInfo.depth, ZPixmap, NULL, &shminfo, width, height);
|
||||
|
||||
|
||||
if (ximage == NULL) {
|
||||
std::cerr << "failed to create shm ximage\n";
|
||||
} else {
|
||||
@ -75,7 +75,7 @@ X11Blitter::ShmBlitter::~ShmBlitter() {
|
||||
XSync(QX11Info::display(), 0);
|
||||
shmdt(shminfo.shmaddr);
|
||||
shmctl(shminfo.shmid, IPC_RMID, 0);
|
||||
|
||||
|
||||
XFree(ximage);
|
||||
}
|
||||
}
|
||||
@ -98,7 +98,7 @@ bool X11Blitter::ShmBlitter::failed() const {
|
||||
void* X11Blitter::ShmBlitter::pixels() const {
|
||||
if (!ximage)
|
||||
return 0;
|
||||
|
||||
|
||||
if (!doubleBuffer)
|
||||
return ximage->data;
|
||||
|
||||
@ -112,7 +112,7 @@ unsigned X11Blitter::ShmBlitter::pitch() const {
|
||||
class X11Blitter::PlainBlitter : public X11Blitter::SubBlitter, Uncopyable {
|
||||
XImage *const ximage;
|
||||
char *data;
|
||||
|
||||
|
||||
bool doubleBuffer() const { return data; }
|
||||
public:
|
||||
PlainBlitter(unsigned int width, unsigned int height, const VisInfo &visInfo, bool db);
|
||||
@ -131,7 +131,7 @@ X11Blitter::PlainBlitter::PlainBlitter(const unsigned int width, const unsigned
|
||||
{
|
||||
if (ximage) {
|
||||
ximage->data = new char[ximage->bytes_per_line * ximage->height << db];
|
||||
|
||||
|
||||
if (db)
|
||||
data = ximage->data;
|
||||
} else {
|
||||
@ -145,7 +145,7 @@ X11Blitter::PlainBlitter::~PlainBlitter () {
|
||||
delete[] data;
|
||||
} else
|
||||
delete[] ximage->data;
|
||||
|
||||
|
||||
XFree(ximage);
|
||||
}
|
||||
}
|
||||
@ -169,10 +169,10 @@ bool X11Blitter::PlainBlitter::failed() const {
|
||||
void* X11Blitter::PlainBlitter::pixels() const {
|
||||
if (!ximage)
|
||||
return 0;
|
||||
|
||||
|
||||
if (!doubleBuffer())
|
||||
return ximage->data;
|
||||
|
||||
|
||||
return ximage->data == data ? data + ximage->bytes_per_line * ximage->height : data;
|
||||
}
|
||||
|
||||
@ -188,16 +188,16 @@ static XVisualInfo* getVisualPtr(unsigned depth, int c_class, unsigned long rmas
|
||||
vinfo_template.red_mask = rmask;
|
||||
vinfo_template.green_mask = gmask;
|
||||
vinfo_template.blue_mask = bmask;
|
||||
|
||||
|
||||
int nitems = 0;
|
||||
XVisualInfo *vinfos = XGetVisualInfo(QX11Info::display(),
|
||||
VisualScreenMask|(depth ? VisualDepthMask : 0)|VisualClassMask|VisualRedMaskMask|VisualGreenMaskMask|VisualBlueMaskMask,
|
||||
&vinfo_template, &nitems);
|
||||
|
||||
|
||||
if (nitems > 0) {
|
||||
return vinfos;
|
||||
}
|
||||
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -205,38 +205,38 @@ static XVisualInfo* getVisualPtr() {
|
||||
{
|
||||
XVisualInfo vinfo_template;
|
||||
vinfo_template.visualid = XVisualIDFromVisual(XDefaultVisual(QX11Info::display(), QX11Info::appScreen()));
|
||||
|
||||
|
||||
int nitems = 0;
|
||||
XVisualInfo *vinfos = XGetVisualInfo(QX11Info::display(), VisualIDMask, &vinfo_template, &nitems);
|
||||
|
||||
|
||||
if (nitems > 0) {
|
||||
if ((vinfos->depth == 24 && vinfos->red_mask == 0xFF0000 && vinfos->green_mask == 0x00FF00 && vinfos->blue_mask == 0x0000FF) ||
|
||||
(vinfos->depth <= 16 && vinfos->red_mask == 0xF800 && vinfos->green_mask == 0x07E0 && vinfos->blue_mask == 0x001F)) {
|
||||
return vinfos;
|
||||
}
|
||||
|
||||
|
||||
XFree(vinfos);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (XVisualInfo *visual = getVisualPtr(24, TrueColor, 0xFF0000, 0x00FF00, 0x0000FF))
|
||||
return visual;
|
||||
|
||||
|
||||
if (XVisualInfo *visual = getVisualPtr(16, TrueColor, 0xF800, 0x07E0, 0x001F))
|
||||
return visual;
|
||||
|
||||
|
||||
if (XVisualInfo *visual = getVisualPtr(0, TrueColor, 0xFF0000, 0x00FF00, 0x0000FF))
|
||||
return visual;
|
||||
|
||||
|
||||
if (XVisualInfo *visual = getVisualPtr(0, TrueColor, 0xF800, 0x07E0, 0x001F))
|
||||
return visual;
|
||||
|
||||
|
||||
if (XVisualInfo *visual = getVisualPtr(0, DirectColor, 0xFF0000, 0x00FF00, 0x0000FF))
|
||||
return visual;
|
||||
|
||||
|
||||
if (XVisualInfo *visual = getVisualPtr(0, DirectColor, 0xF800, 0x07E0, 0x001F))
|
||||
return visual;
|
||||
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -247,14 +247,14 @@ bf_(new QCheckBox(QString("Semi-bilinear filtering")), "x11blitter/bf", false)
|
||||
{
|
||||
visInfo.visual = NULL;
|
||||
visInfo.depth = 0;
|
||||
|
||||
|
||||
confWidget->setLayout(new QVBoxLayout);
|
||||
confWidget->layout()->setMargin(0);
|
||||
confWidget->layout()->addWidget(bf_.checkBox());
|
||||
|
||||
|
||||
setAttribute(Qt::WA_OpaquePaintEvent, true);
|
||||
setAttribute(Qt::WA_PaintOnScreen, true);
|
||||
|
||||
|
||||
if (XVisualInfo *v = getVisualPtr()) {
|
||||
visInfo.visual = v->visual;
|
||||
visInfo.depth = v->depth;
|
||||
@ -281,10 +281,10 @@ void X11Blitter::uninit() {
|
||||
long X11Blitter::sync() {
|
||||
if (subBlitter->failed())
|
||||
return -1;
|
||||
|
||||
|
||||
subBlitter->blit(winId(), 0, 0, width(), height());
|
||||
XSync(QX11Info::display(), 0);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -310,23 +310,23 @@ void X11Blitter::paintEvent(QPaintEvent *event) {
|
||||
|
||||
void X11Blitter::setBufferDimensions(const unsigned int w, const unsigned int h) {
|
||||
uninit();
|
||||
|
||||
|
||||
const bool scale = width() != static_cast<int>(w) || height() != static_cast<int>(h);
|
||||
bool shm = XShmQueryExtension(QX11Info::display());
|
||||
std::cout << "shm: " << shm << std::endl;
|
||||
|
||||
|
||||
if (shm) {
|
||||
subBlitter.reset(new ShmBlitter(width(), height(), visInfo, !scale));
|
||||
|
||||
|
||||
if (subBlitter->failed()) {
|
||||
shm = false;
|
||||
subBlitter.reset(); // predestruct previous object to ensure resource availability.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!shm)
|
||||
subBlitter.reset(new PlainBlitter(width(), height(), visInfo, !scale));
|
||||
|
||||
|
||||
if (scale) {
|
||||
buffer.reset(w * h * (visInfo.depth <= 16 ? 2 : 4));
|
||||
setPixelBuffer(buffer, visInfo.depth <= 16 ? PixelBuffer::RGB16 : PixelBuffer::RGB32, w);
|
||||
|
@ -28,23 +28,23 @@ class X11Blitter : public BlitterWidget {
|
||||
class SubBlitter;
|
||||
class ShmBlitter;
|
||||
class PlainBlitter;
|
||||
|
||||
|
||||
struct VisInfo {
|
||||
void *visual;
|
||||
unsigned depth;
|
||||
};
|
||||
|
||||
|
||||
const scoped_ptr<QWidget> confWidget;
|
||||
scoped_ptr<SubBlitter> subBlitter;
|
||||
PersistCheckBox bf_;
|
||||
Array<char> buffer;
|
||||
VisInfo visInfo;
|
||||
|
||||
|
||||
protected:
|
||||
void setBufferDimensions(const unsigned width, const unsigned height);
|
||||
void paintEvent(QPaintEvent *event);
|
||||
void resizeEvent(QResizeEvent *event);
|
||||
|
||||
|
||||
public:
|
||||
explicit X11Blitter(VideoBufferLocker vbl, QWidget *parent = 0);
|
||||
~X11Blitter();
|
||||
@ -56,7 +56,7 @@ public:
|
||||
QWidget* settingsWidget() const { return confWidget.get(); }
|
||||
void acceptSettings();
|
||||
void rejectSettings() const;
|
||||
|
||||
|
||||
QPaintEngine* paintEngine() const { return 0; }
|
||||
};
|
||||
|
||||
|
@ -47,7 +47,7 @@ public:
|
||||
class XvBlitter::ShmBlitter : public SubBlitter {
|
||||
XShmSegmentInfo shminfo;
|
||||
XvImage *xvimage;
|
||||
|
||||
|
||||
public:
|
||||
ShmBlitter(XvPortID xvport, int formatid, unsigned int width, unsigned int height);
|
||||
void blit(Drawable drawable, XvPortID xvport, unsigned width, unsigned height);
|
||||
@ -61,7 +61,7 @@ public:
|
||||
XvBlitter::ShmBlitter::ShmBlitter(const XvPortID xvport, const int formatid, const unsigned int width, const unsigned int height) {
|
||||
shminfo.shmaddr = NULL;
|
||||
xvimage = XvShmCreateImage(QX11Info::display(), xvport, formatid, NULL, width << (formatid != 3), height, &shminfo);
|
||||
|
||||
|
||||
if (xvimage == NULL) {
|
||||
std::cerr << "failed to create xvimage\n";
|
||||
} else {
|
||||
@ -80,7 +80,7 @@ XvBlitter::ShmBlitter::~ShmBlitter() {
|
||||
shmdt(shminfo.shmaddr);
|
||||
shmctl(shminfo.shmid, IPC_RMID, 0);
|
||||
}
|
||||
|
||||
|
||||
if (xvimage != NULL)
|
||||
XFree(xvimage);
|
||||
}
|
||||
@ -116,7 +116,7 @@ unsigned XvBlitter::ShmBlitter::pitch() const {
|
||||
class XvBlitter::PlainBlitter : public SubBlitter {
|
||||
XvImage *const xvimage;
|
||||
char *data;
|
||||
|
||||
|
||||
public:
|
||||
PlainBlitter(XvPortID xvport, int formatid, unsigned int width, unsigned int height);
|
||||
void blit(Drawable drawable, XvPortID xvport, unsigned width, unsigned height);
|
||||
@ -128,7 +128,7 @@ public:
|
||||
};
|
||||
|
||||
XvBlitter::PlainBlitter::PlainBlitter(const XvPortID xvport, const int formatid, const unsigned int width, const unsigned int height)
|
||||
: xvimage(XvCreateImage(QX11Info::display(), xvport, formatid, 0, width << (formatid != 3), height)),
|
||||
: xvimage(XvCreateImage(QX11Info::display(), xvport, formatid, 0, width << (formatid != 3), height)),
|
||||
data(0)
|
||||
{
|
||||
if (xvimage) {
|
||||
@ -184,12 +184,12 @@ public:
|
||||
num_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
~XvAdaptorInfos() {
|
||||
if (infos_)
|
||||
XvFreeAdaptorInfo(infos_);
|
||||
}
|
||||
|
||||
|
||||
unsigned len() const { return num_; }
|
||||
operator const XvAdaptorInfo*() const { return infos_; }
|
||||
};
|
||||
@ -197,48 +197,48 @@ public:
|
||||
class XvPortImageFormats : Uncopyable {
|
||||
int num_;
|
||||
XvImageFormatValues *const formats_;
|
||||
|
||||
|
||||
public:
|
||||
explicit XvPortImageFormats(const XvPortID baseId)
|
||||
: num_(0), formats_(XvListImageFormats(QX11Info::display(), baseId, &num_))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
~XvPortImageFormats() {
|
||||
if (formats_)
|
||||
XFree(formats_);
|
||||
}
|
||||
|
||||
|
||||
int len() const { return num_; }
|
||||
operator const XvImageFormatValues*() const { return formats_; }
|
||||
};
|
||||
|
||||
static int findId(const XvPortImageFormats &formats, const int id) {
|
||||
int i = 0;
|
||||
|
||||
|
||||
while (i < formats.len() && formats[i].id != id)
|
||||
++i;
|
||||
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
static void addPorts(QComboBox &portSelector) {
|
||||
XvAdaptorInfos adaptors;
|
||||
|
||||
|
||||
for (unsigned i = 0; i < adaptors.len(); ++i) {
|
||||
if (!(adaptors[i].type & XvImageMask))
|
||||
continue;
|
||||
|
||||
|
||||
const XvPortImageFormats formats(adaptors[i].base_id);
|
||||
|
||||
|
||||
int formatId = 0x3;
|
||||
int j = findId(formats, formatId);
|
||||
|
||||
|
||||
if (j == formats.len()) {
|
||||
formatId = 0x59565955;
|
||||
j = findId(formats, formatId);
|
||||
}
|
||||
|
||||
|
||||
if (j < formats.len()) {
|
||||
QList<QVariant> l;
|
||||
l.append(static_cast<uint>(adaptors[i].base_id));
|
||||
@ -255,12 +255,12 @@ XvBlitter::ConfWidget::ConfWidget()
|
||||
: widget_(new QWidget), portSelector_(new QComboBox(widget_.get())), portIndex_(0)
|
||||
{
|
||||
addPorts(*portSelector_);
|
||||
|
||||
|
||||
if ((portIndex_ = QSettings().value("xvblitter/portIndex", 0).toUInt()) >= static_cast<unsigned>(portSelector_->count()))
|
||||
portIndex_ = 0;
|
||||
|
||||
|
||||
restore();
|
||||
|
||||
|
||||
widget_->setLayout(new QHBoxLayout);
|
||||
widget_->layout()->setMargin(0);
|
||||
widget_->layout()->addWidget(new QLabel(QString(tr("Xv Port:"))));
|
||||
@ -304,14 +304,14 @@ XvBlitter::PortGrabber::~PortGrabber() {
|
||||
|
||||
bool XvBlitter::PortGrabber::grab(const XvPortID basePort, const unsigned numPorts) {
|
||||
ungrab();
|
||||
|
||||
|
||||
for (XvPortID port = basePort; port < basePort + numPorts; ++port) {
|
||||
port_ = port;
|
||||
|
||||
|
||||
if ((grabbed_ = XvGrabPort(QX11Info::display(), port, CurrentTime) == Success))
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -332,10 +332,10 @@ XvBlitter::XvBlitter(VideoBufferLocker vbl, QWidget *parent) :
|
||||
setPalette(pal);
|
||||
setBackgroundRole(QPalette::Window);
|
||||
setAutoFillBackground(true);*/
|
||||
|
||||
|
||||
setAttribute(Qt::WA_NoSystemBackground, true);
|
||||
setAttribute(Qt::WA_PaintOnScreen, true);
|
||||
|
||||
|
||||
{
|
||||
XGCValues gcValues;
|
||||
gcValues.foreground = gcValues.background = 2110;
|
||||
@ -351,23 +351,23 @@ bool XvBlitter::isUnusable() const {
|
||||
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;
|
||||
}*/
|
||||
|
||||
@ -387,11 +387,11 @@ void XvBlitter::init() {
|
||||
yuv_table[i] = (y << 24) | (v << 16) | (y << 8) | u;
|
||||
}
|
||||
}*/
|
||||
|
||||
|
||||
XSync(QX11Info::display(), 0);
|
||||
|
||||
|
||||
initPort();
|
||||
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
@ -408,38 +408,38 @@ XvBlitter::~XvBlitter() {
|
||||
long XvBlitter::sync() {
|
||||
if (!portGrabber.grabbed() || subBlitter->failed())
|
||||
return -1;
|
||||
|
||||
|
||||
subBlitter->blit(winId(), portGrabber.port(), width(), height());
|
||||
XSync(QX11Info::display(), 0);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void XvBlitter::paintEvent(QPaintEvent *event) {
|
||||
const QRect &rect = event->rect();
|
||||
XFillRectangle(QX11Info::display(), winId(), gc, rect.x(), rect.y(), rect.width(), rect.height());
|
||||
|
||||
|
||||
if (isPaused() && portGrabber.grabbed())
|
||||
subBlitter->blit(winId(), portGrabber.port(), width(), height());
|
||||
}
|
||||
|
||||
void XvBlitter::setBufferDimensions(const unsigned width, const unsigned height) {
|
||||
const int formatid = confWidget.formatId();
|
||||
|
||||
|
||||
subBlitter.reset(); // predestruct previous object to ensure resource availability.
|
||||
|
||||
|
||||
bool shm = XShmQueryExtension(QX11Info::display());
|
||||
std::cout << "shm: " << shm << std::endl;
|
||||
|
||||
|
||||
if (shm) {
|
||||
subBlitter.reset(new ShmBlitter(portGrabber.port(), formatid, width, height));
|
||||
|
||||
|
||||
if (subBlitter->failed()) {
|
||||
shm = false;
|
||||
subBlitter.reset();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!shm)
|
||||
subBlitter.reset(new PlainBlitter(portGrabber.port(), formatid, width, height));
|
||||
|
||||
@ -459,30 +459,30 @@ class XvAttributes : Uncopyable {
|
||||
const XvPortID xvport_;
|
||||
int numAttribs_;
|
||||
XvAttribute *const attribs_;
|
||||
|
||||
|
||||
Atom atomOf(const char *const name) const {
|
||||
for (int i = 0; i < numAttribs_; ++i) {
|
||||
if (!strcmp(attribs_[i].name, name))
|
||||
return XInternAtom(QX11Info::display(), name, True);
|
||||
}
|
||||
|
||||
|
||||
return None;
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
explicit XvAttributes(const XvPortID xvport)
|
||||
: xvport_(xvport), numAttribs_(0), attribs_(XvQueryPortAttributes(QX11Info::display(), xvport, &numAttribs_))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
~XvAttributes() {
|
||||
if (attribs_)
|
||||
XFree(attribs_);
|
||||
}
|
||||
|
||||
|
||||
void set(const char *const name, const int value) {
|
||||
const Atom atom = atomOf(name);
|
||||
|
||||
|
||||
if (atom != None)
|
||||
XvSetPortAttribute(QX11Info::display(), xvport_, atom, value);
|
||||
}
|
||||
@ -500,7 +500,7 @@ void XvBlitter::initPort() {
|
||||
|
||||
void XvBlitter::acceptSettings() {
|
||||
confWidget.store();
|
||||
|
||||
|
||||
if (initialized && !(portGrabber.port() >= confWidget.basePortId()
|
||||
&& portGrabber.port() < confWidget.basePortId() + confWidget.numPortIds())) {
|
||||
initPort();
|
||||
|
@ -31,12 +31,12 @@ class XvBlitter : public BlitterWidget {
|
||||
class SubBlitter;
|
||||
class ShmBlitter;
|
||||
class PlainBlitter;
|
||||
|
||||
|
||||
class ConfWidget {
|
||||
const scoped_ptr<QWidget> widget_;
|
||||
QComboBox *const portSelector_;
|
||||
unsigned portIndex_;
|
||||
|
||||
|
||||
public:
|
||||
ConfWidget();
|
||||
~ConfWidget();
|
||||
@ -48,7 +48,7 @@ class XvBlitter : public BlitterWidget {
|
||||
int numAdapters() const;
|
||||
QWidget * qwidget() const { return widget_.get(); }
|
||||
};
|
||||
|
||||
|
||||
class PortGrabber : Uncopyable {
|
||||
XvPortID port_;
|
||||
bool grabbed_;
|
||||
@ -60,13 +60,13 @@ class XvBlitter : public BlitterWidget {
|
||||
bool grabbed() const { return grabbed_; }
|
||||
XvPortID port() const { return port_; }
|
||||
};
|
||||
|
||||
|
||||
ConfWidget confWidget;
|
||||
PortGrabber portGrabber;
|
||||
scoped_ptr<SubBlitter> subBlitter;
|
||||
GC gc;
|
||||
bool initialized;
|
||||
|
||||
|
||||
void initPort();
|
||||
void privSetPaused(const bool /*paused*/) {}
|
||||
|
||||
@ -83,11 +83,11 @@ public:
|
||||
long sync();
|
||||
void setBufferDimensions(const unsigned int width, const unsigned int height);
|
||||
void blit();
|
||||
|
||||
|
||||
QWidget* settingsWidget() const { return confWidget.qwidget(); }
|
||||
void acceptSettings();
|
||||
void rejectSettings() const;
|
||||
|
||||
|
||||
QPaintEngine* paintEngine() const { return NULL; }
|
||||
};
|
||||
|
||||
|
@ -42,7 +42,7 @@ void FrameRateControl::setFrameTime(const Rational frameTime) {
|
||||
void FrameRateControl::setRefreshRate(int refreshRate) {
|
||||
if (refreshRate < 1)
|
||||
refreshRate = 600;
|
||||
|
||||
|
||||
refreshRate_ = refreshRate;
|
||||
blitter_->rateChange(refreshRate);
|
||||
update();
|
||||
|
@ -39,7 +39,7 @@ public:
|
||||
void setFrameTime(Rational frameTime);
|
||||
void setRefreshRate(int refreshRate);
|
||||
void setRefreshRateSync(bool enable) { refreshRateSync_ = enable; update(); }
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -36,24 +36,24 @@ static inline bool operator>(const ResInfo &l, const ResInfo &r) {
|
||||
static void addMode(const DEVMODE &devmode, std::vector<ResInfo> &infoVector, unsigned *resIndex, unsigned *rateIndex) {
|
||||
ResInfo info;
|
||||
short rate;
|
||||
|
||||
|
||||
info.w = devmode.dmPelsWidth;
|
||||
info.h = devmode.dmPelsHeight;
|
||||
rate = devmode.dmDisplayFrequency * 10;
|
||||
|
||||
|
||||
std::vector<ResInfo>::iterator it = std::lower_bound(infoVector.begin(), infoVector.end(), info, std::greater<ResInfo>());
|
||||
|
||||
|
||||
if (it == infoVector.end() || *it != info)
|
||||
it = infoVector.insert(it, info);
|
||||
|
||||
|
||||
std::vector<short>::iterator rateIt = std::lower_bound(it->rates.begin(), it->rates.end(), rate, std::greater<short>());
|
||||
|
||||
|
||||
if (rateIt == it->rates.end() || *rateIt != rate)
|
||||
rateIt = it->rates.insert(rateIt, rate);
|
||||
|
||||
|
||||
if (resIndex)
|
||||
*resIndex = std::distance(infoVector.begin(), it);
|
||||
|
||||
|
||||
if (rateIndex)
|
||||
*rateIndex = std::distance(it->rates.begin(), rateIt);
|
||||
}
|
||||
@ -61,15 +61,15 @@ static void addMode(const DEVMODE &devmode, std::vector<ResInfo> &infoVector, un
|
||||
class GdiToggler::MultiMon : Uncopyable {
|
||||
HMONITOR *devMonitors;
|
||||
unsigned numDevs;
|
||||
|
||||
|
||||
HMONITOR monitor(int screen) const { return devMonitors ? devMonitors[screen] : NULL; }
|
||||
|
||||
|
||||
public:
|
||||
MultiMon() : devMonitors(NULL), numDevs(1) {
|
||||
if (gdiSettings.monitorFromPoint) {
|
||||
numDevs = QApplication::desktop()->numScreens();
|
||||
devMonitors = new HMONITOR[numDevs];
|
||||
|
||||
|
||||
for (unsigned i = 0; i < numDevs; ++i) {
|
||||
const QPoint &qpoint = QApplication::desktop()->screenGeometry(i).center();
|
||||
POINT point = { x: qpoint.x(), y: qpoint.y() };
|
||||
@ -77,17 +77,17 @@ public:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
~MultiMon() {
|
||||
delete []devMonitors;
|
||||
}
|
||||
|
||||
|
||||
unsigned numScreens() const { return numDevs; }
|
||||
|
||||
|
||||
BOOL enumDisplaySettings(unsigned screen, DWORD iModeNum, LPDEVMODE devmode) const {
|
||||
return gdiSettings.enumDisplaySettings(monitor(screen), iModeNum, devmode);
|
||||
}
|
||||
|
||||
|
||||
LONG changeDisplaySettings(unsigned screen, LPDEVMODE devmode, DWORD dwflags) const {
|
||||
return gdiSettings.changeDisplaySettings(monitor(screen), devmode, dwflags);
|
||||
}
|
||||
@ -101,24 +101,24 @@ isFull(false)
|
||||
infoVector.resize(mon->numScreens());
|
||||
fullResIndex.resize(mon->numScreens());
|
||||
fullRateIndex.resize(mon->numScreens());
|
||||
|
||||
|
||||
DEVMODE devmode;
|
||||
devmode.dmSize = sizeof devmode;
|
||||
devmode.dmDriverExtra = 0;
|
||||
|
||||
|
||||
for (unsigned i = 0; i < mon->numScreens(); ++i) {
|
||||
mon->enumDisplaySettings(i, ENUM_CURRENT_SETTINGS, &devmode);
|
||||
|
||||
|
||||
const unsigned bpp = devmode.dmBitsPerPel;
|
||||
|
||||
|
||||
int n = 0;
|
||||
|
||||
|
||||
while (mon->enumDisplaySettings(i, n++, &devmode)) {
|
||||
if (devmode.dmBitsPerPel == bpp)
|
||||
addMode(devmode, infoVector[i], NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (unsigned i = 0; i < mon->numScreens(); ++i) {
|
||||
mon->enumDisplaySettings(i, ENUM_CURRENT_SETTINGS, &devmode);
|
||||
addMode(devmode, infoVector[i], &fullResIndex[i], &fullRateIndex[i]);
|
||||
@ -136,7 +136,7 @@ GdiToggler::~GdiToggler() {
|
||||
|
||||
void GdiToggler::setScreen(const QWidget *widget) {
|
||||
unsigned n = QApplication::desktop()->screenNumber(widget);
|
||||
|
||||
|
||||
if (n != widgetScreen && n < mon->numScreens()) {
|
||||
if (isFullMode()) {
|
||||
setFullMode(false);
|
||||
@ -152,7 +152,7 @@ void GdiToggler::setScreen(const QWidget *widget) {
|
||||
void GdiToggler::setMode(const unsigned screen, const unsigned resIndex, const unsigned rateIndex) {
|
||||
fullResIndex[screen] = resIndex;
|
||||
fullRateIndex[screen] = rateIndex;
|
||||
|
||||
|
||||
if (isFullMode() && screen == widgetScreen)
|
||||
setFullMode(true);
|
||||
}
|
||||
@ -161,12 +161,12 @@ void GdiToggler::setFullMode(const bool enable) {
|
||||
DEVMODE devmode;
|
||||
devmode.dmSize = sizeof devmode;
|
||||
devmode.dmDriverExtra = 0;
|
||||
|
||||
|
||||
mon->enumDisplaySettings(widgetScreen, ENUM_CURRENT_SETTINGS, &devmode);
|
||||
const unsigned currentWidth = devmode.dmPelsWidth;
|
||||
const unsigned currentHeight = devmode.dmPelsHeight;
|
||||
const unsigned currentRate = devmode.dmDisplayFrequency;
|
||||
|
||||
|
||||
if (enable) {
|
||||
const ResInfo &info = infoVector[widgetScreen][fullResIndex[widgetScreen]];
|
||||
devmode.dmPelsWidth = info.w;
|
||||
@ -175,15 +175,15 @@ void GdiToggler::setFullMode(const bool enable) {
|
||||
} else if (isFull) {
|
||||
mon->enumDisplaySettings(widgetScreen, ENUM_REGISTRY_SETTINGS, &devmode);
|
||||
}
|
||||
|
||||
|
||||
if (devmode.dmPelsWidth != currentWidth || devmode.dmPelsHeight != currentHeight || devmode.dmDisplayFrequency != currentRate) {
|
||||
devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY;
|
||||
mon->changeDisplaySettings(widgetScreen, &devmode, enable ? CDS_FULLSCREEN : 0);
|
||||
|
||||
|
||||
if (devmode.dmDisplayFrequency != currentRate)
|
||||
emit rateChange(devmode.dmDisplayFrequency * 10);
|
||||
}
|
||||
|
||||
|
||||
isFull = enable;
|
||||
}
|
||||
|
||||
|
@ -25,16 +25,16 @@
|
||||
|
||||
class GdiToggler : public FullModeToggler, private Uncopyable {
|
||||
Q_OBJECT
|
||||
|
||||
|
||||
class MultiMon;
|
||||
|
||||
|
||||
MultiMon *const mon;
|
||||
std::vector<std::vector<ResInfo> > infoVector;
|
||||
std::vector<unsigned> fullResIndex;
|
||||
std::vector<unsigned> fullRateIndex;
|
||||
unsigned widgetScreen;
|
||||
bool isFull;
|
||||
|
||||
|
||||
public:
|
||||
GdiToggler();
|
||||
~GdiToggler();
|
||||
@ -49,7 +49,7 @@ public:
|
||||
void setScreen(const QWidget *widget);
|
||||
unsigned screen() const { return widgetScreen; }
|
||||
unsigned screens() const { return infoVector.size(); }
|
||||
|
||||
|
||||
signals:
|
||||
void rateChange(int newHz);
|
||||
// void modeChange();
|
||||
|
@ -25,10 +25,10 @@ class QWidget;
|
||||
|
||||
class NullToggler : public FullModeToggler {
|
||||
Q_OBJECT
|
||||
|
||||
|
||||
const std::vector<ResInfo> nullVector;
|
||||
bool fullRes;
|
||||
|
||||
|
||||
public:
|
||||
NullToggler() : fullRes(false) {}
|
||||
unsigned currentResIndex(unsigned /*screen*/) const { return 0; }
|
||||
@ -41,7 +41,7 @@ public:
|
||||
void setScreen(const QWidget */*widget*/) {}
|
||||
unsigned screen() const { return 0; }
|
||||
unsigned screens() const { return 0; }
|
||||
|
||||
|
||||
signals:
|
||||
void rateChange(int newHz);
|
||||
};
|
||||
|
@ -32,34 +32,34 @@ static inline bool operator>(const ResInfo &l, const ResInfo &r) {
|
||||
static void addMode(CFDictionaryRef mode, std::vector<ResInfo> &infoVector, unsigned *resIndex, unsigned *rateIndex) {
|
||||
ResInfo info;
|
||||
short rate = 0;
|
||||
|
||||
|
||||
{
|
||||
int w = 0;
|
||||
int h = 0;
|
||||
double r = 0.0;
|
||||
|
||||
|
||||
CFNumberGetValue(static_cast<CFNumberRef>(CFDictionaryGetValue(mode, kCGDisplayWidth)), kCFNumberIntType, &w);
|
||||
CFNumberGetValue(static_cast<CFNumberRef>(CFDictionaryGetValue(mode, kCGDisplayHeight)), kCFNumberIntType, &h);
|
||||
CFNumberGetValue(static_cast<CFNumberRef>(CFDictionaryGetValue(mode, kCGDisplayRefreshRate)), kCFNumberDoubleType, &r);
|
||||
|
||||
|
||||
info.w = w;
|
||||
info.h = h;
|
||||
rate = static_cast<short>(r * 10.0 + 0.5);
|
||||
}
|
||||
|
||||
|
||||
std::vector<ResInfo>::iterator it = std::lower_bound(infoVector.begin(), infoVector.end(), info, std::greater<ResInfo>());
|
||||
|
||||
|
||||
if (it == infoVector.end() || *it != info)
|
||||
it = infoVector.insert(it, info);
|
||||
|
||||
|
||||
std::vector<short>::iterator rateIt = std::lower_bound(it->rates.begin(), it->rates.end(), rate, std::greater<short>());
|
||||
|
||||
|
||||
if (rateIt == it->rates.end() || *rateIt != rate)
|
||||
rateIt = it->rates.insert(rateIt, rate);
|
||||
|
||||
|
||||
if (resIndex)
|
||||
*resIndex = std::distance(infoVector.begin(), it);
|
||||
|
||||
|
||||
if (rateIndex)
|
||||
*rateIndex = std::distance(it->rates.begin(), rateIt);
|
||||
}
|
||||
@ -72,32 +72,32 @@ isFull(false)
|
||||
{
|
||||
CGDisplayCount dspyCnt = 0;
|
||||
CGGetActiveDisplayList(0, 0, &dspyCnt);
|
||||
|
||||
|
||||
activeDspys = new CGDirectDisplayID[dspyCnt];
|
||||
CGGetActiveDisplayList(dspyCnt, activeDspys, &dspyCnt);
|
||||
|
||||
|
||||
infoVector.resize(dspyCnt);
|
||||
fullResIndex.resize(dspyCnt);
|
||||
fullRateIndex.resize(dspyCnt);
|
||||
|
||||
|
||||
for (CGDisplayCount i = 0; i < dspyCnt; ++i) {
|
||||
CGDirectDisplayID display = activeDspys[i];
|
||||
CFDictionaryRef currentMode = CGDisplayCurrentMode(display);
|
||||
CFArrayRef modesArray = CGDisplayAvailableModes(display);
|
||||
CFIndex numModes = CFArrayGetCount(modesArray);
|
||||
CFNumberRef bpp = static_cast<CFNumberRef>(CFDictionaryGetValue(currentMode, kCGDisplayBitsPerPixel));
|
||||
|
||||
|
||||
for (CFIndex j = 0; j < numModes; ++j) {
|
||||
CFDictionaryRef mode = static_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(modesArray, j));
|
||||
|
||||
|
||||
if (CFNumberCompare(bpp, static_cast<CFNumberRef>(CFDictionaryGetValue(mode, kCGDisplayBitsPerPixel)), NULL) == kCFCompareEqualTo) {
|
||||
addMode(mode, infoVector[i], NULL, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
originalMode = CGDisplayCurrentMode(activeDspys[widgetScreen]);
|
||||
|
||||
|
||||
for (CGDisplayCount i = 0; i < dspyCnt; ++i) {
|
||||
unsigned resIndex = 0;
|
||||
unsigned rateIndex = 0;
|
||||
@ -114,13 +114,13 @@ QuartzToggler::~QuartzToggler() {
|
||||
|
||||
const QRect QuartzToggler::fullScreenRect(const QWidget */*w*/) const {
|
||||
CGRect r = CGDisplayBounds(activeDspys[widgetScreen]);
|
||||
|
||||
|
||||
return QRectF(r.origin.x, r.origin.y, r.size.width, r.size.height).toRect();
|
||||
}
|
||||
|
||||
void QuartzToggler::setScreen(const QWidget *widget) {
|
||||
unsigned n = QApplication::desktop()->screenNumber(widget);
|
||||
|
||||
|
||||
if (n != widgetScreen && n < infoVector.size()) {
|
||||
if (isFullMode()) {
|
||||
setFullMode(false);
|
||||
@ -136,7 +136,7 @@ void QuartzToggler::setScreen(const QWidget *widget) {
|
||||
void QuartzToggler::setMode(const unsigned screen, const unsigned resIndex, const unsigned rateIndex) {
|
||||
fullResIndex[screen] = resIndex;
|
||||
fullRateIndex[screen] = rateIndex;
|
||||
|
||||
|
||||
if (isFullMode() && screen == widgetScreen)
|
||||
setFullMode(true);
|
||||
}
|
||||
@ -144,13 +144,13 @@ void QuartzToggler::setMode(const unsigned screen, const unsigned resIndex, cons
|
||||
void QuartzToggler::setFullMode(const bool enable) {
|
||||
CGDirectDisplayID display = activeDspys[widgetScreen];
|
||||
CFDictionaryRef currentMode = CGDisplayCurrentMode(display);
|
||||
|
||||
|
||||
CFDictionaryRef mode = currentMode;
|
||||
|
||||
|
||||
if (enable) {
|
||||
int bpp = 0;
|
||||
CFNumberGetValue(static_cast<CFNumberRef>(CFDictionaryGetValue(currentMode, kCGDisplayBitsPerPixel)), kCFNumberIntType, &bpp);
|
||||
|
||||
|
||||
mode = CGDisplayBestModeForParametersAndRefreshRate(
|
||||
display,
|
||||
bpp,
|
||||
@ -159,32 +159,32 @@ void QuartzToggler::setFullMode(const bool enable) {
|
||||
infoVector[widgetScreen][fullResIndex[widgetScreen]].rates[fullRateIndex[widgetScreen]] / 10.0,
|
||||
NULL
|
||||
);
|
||||
|
||||
|
||||
if (!isFull)
|
||||
originalMode = currentMode;
|
||||
} else if (isFull)
|
||||
mode = originalMode;
|
||||
|
||||
|
||||
if (mode != currentMode) {
|
||||
CGDisplaySwitchToMode(display, mode);
|
||||
|
||||
|
||||
double oldRate = 0.0;
|
||||
double newRate = 0.0;
|
||||
|
||||
|
||||
CFNumberGetValue(static_cast<CFNumberRef>(CFDictionaryGetValue(currentMode, kCGDisplayRefreshRate)), kCFNumberDoubleType, &oldRate);
|
||||
CFNumberGetValue(static_cast<CFNumberRef>(CFDictionaryGetValue(mode, kCGDisplayRefreshRate)), kCFNumberDoubleType, &newRate);
|
||||
|
||||
|
||||
if (static_cast<int>(oldRate * 10.0 + 0.5) != static_cast<int>(newRate * 10.0 + 0.5))
|
||||
emit rateChange(static_cast<int>(newRate * 10.0 + 0.5));
|
||||
}
|
||||
|
||||
|
||||
isFull = enable;
|
||||
}
|
||||
|
||||
void QuartzToggler::emitRate() {
|
||||
double rate = 0.0;
|
||||
|
||||
|
||||
CFNumberGetValue(static_cast<CFNumberRef>(CFDictionaryGetValue(CGDisplayCurrentMode(activeDspys[widgetScreen]), kCGDisplayRefreshRate)), kCFNumberDoubleType, &rate);
|
||||
|
||||
|
||||
emit rateChange(static_cast<int>(rate * 10.0 + 0.5));
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ class QWidget;
|
||||
|
||||
class QuartzToggler : public FullModeToggler {
|
||||
Q_OBJECT
|
||||
|
||||
|
||||
CFDictionaryRef originalMode;
|
||||
CGDirectDisplayID *activeDspys;
|
||||
std::vector<std::vector<ResInfo> > infoVector;
|
||||
@ -35,7 +35,7 @@ class QuartzToggler : public FullModeToggler {
|
||||
std::vector<unsigned> fullRateIndex;
|
||||
unsigned widgetScreen;
|
||||
bool isFull;
|
||||
|
||||
|
||||
public:
|
||||
QuartzToggler();
|
||||
~QuartzToggler();
|
||||
@ -50,7 +50,7 @@ public:
|
||||
void setScreen(const QWidget *widget);
|
||||
unsigned screen() const { return widgetScreen; }
|
||||
unsigned screens() const { return infoVector.size(); }
|
||||
|
||||
|
||||
signals:
|
||||
void rateChange(int newHz);
|
||||
// void modeChange();
|
||||
|
@ -25,25 +25,25 @@
|
||||
|
||||
bool Xf86VidModeToggler::isUsable() {
|
||||
int unused;
|
||||
|
||||
|
||||
if (XF86VidModeQueryExtension(QX11Info::display(), &unused, &unused)) {
|
||||
XF86VidModeSetClientVersion(QX11Info::display());
|
||||
|
||||
|
||||
if (XF86VidModeQueryVersion(QX11Info::display(), &unused, &unused)) {
|
||||
if (XineramaQueryVersion(QX11Info::display(), &unused, &unused)) {
|
||||
int number = 0;
|
||||
|
||||
|
||||
if (XineramaScreenInfo *info = XineramaQueryScreens(QX11Info::display(), &number))
|
||||
XFree(info);
|
||||
|
||||
|
||||
if (number > 1)
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -58,7 +58,7 @@ static inline bool operator>(const ResInfo &l, const ResInfo &r) {
|
||||
static unsigned getRate(const unsigned dotclock, const unsigned htotal, const unsigned vtotal) {
|
||||
if (unsigned long pixels = htotal * vtotal)
|
||||
return (dotclock * 10000ull + (pixels >> 1)) / pixels;
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -69,24 +69,24 @@ static unsigned getRate(const XF86VidModeModeInfo &mode) {
|
||||
static void addMode(XF86VidModeModeInfo *mode, std::vector<ResInfo> &infoVector, unsigned *resIndex, unsigned *rateIndex) {
|
||||
ResInfo info;
|
||||
short rate;
|
||||
|
||||
|
||||
info.w = mode->hdisplay;
|
||||
info.h = mode->vdisplay;
|
||||
rate = getRate(*mode);
|
||||
|
||||
|
||||
std::vector<ResInfo>::iterator it = std::lower_bound(infoVector.begin(), infoVector.end(), info, std::greater<ResInfo>());
|
||||
|
||||
|
||||
if (it == infoVector.end() || *it != info)
|
||||
it = infoVector.insert(it, info);
|
||||
|
||||
|
||||
std::vector<short>::iterator rateIt = std::lower_bound(it->rates.begin(), it->rates.end(), rate, std::greater<short>());
|
||||
|
||||
|
||||
if (rateIt == it->rates.end() || *rateIt != rate)
|
||||
rateIt = it->rates.insert(rateIt, rate);
|
||||
|
||||
|
||||
if (resIndex)
|
||||
*resIndex = std::distance(infoVector.begin(), it);
|
||||
|
||||
|
||||
if (rateIndex)
|
||||
*rateIndex = std::distance(it->rates.begin(), rateIt);
|
||||
}
|
||||
@ -102,12 +102,12 @@ winId(winId),
|
||||
isFull(false)
|
||||
{
|
||||
XF86VidModeGetAllModeLines(QX11Info::display(), QX11Info::appScreen(), &modecount, &modesinfo);
|
||||
|
||||
|
||||
if (modecount) {
|
||||
for (int i = 1; i < modecount; ++i) {
|
||||
addMode(modesinfo[i], infoVector, NULL, NULL);
|
||||
}
|
||||
|
||||
|
||||
originalMode = *modesinfo[0];
|
||||
addMode(modesinfo[0], infoVector, &fullResIndex, &fullRateIndex);
|
||||
}
|
||||
@ -115,7 +115,7 @@ isFull(false)
|
||||
|
||||
Xf86VidModeToggler::~Xf86VidModeToggler() {
|
||||
setFullMode(false);
|
||||
|
||||
|
||||
if (modesinfo)
|
||||
XFree(modesinfo);
|
||||
}
|
||||
@ -123,23 +123,23 @@ Xf86VidModeToggler::~Xf86VidModeToggler() {
|
||||
const QRect Xf86VidModeToggler::fullScreenRect(const QWidget *wdgt) const {
|
||||
int dotclock = 0;
|
||||
XF86VidModeModeLine modeline;
|
||||
|
||||
|
||||
if (XF86VidModeGetModeLine(QX11Info::display(), QX11Info::appScreen(), &dotclock, &modeline)) {
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
|
||||
|
||||
// XF86VidModeGetViewPort(QX11Info::display(), QX11Info::appScreen(), &x, &y);
|
||||
|
||||
|
||||
return QRect(x, y, modeline.hdisplay, modeline.vdisplay);
|
||||
}
|
||||
|
||||
|
||||
return wdgt->geometry();
|
||||
}
|
||||
|
||||
void Xf86VidModeToggler::setMode(unsigned /*screen*/, const unsigned resIndex, const unsigned rateIndex) {
|
||||
fullResIndex = resIndex;
|
||||
fullRateIndex = rateIndex;
|
||||
|
||||
|
||||
if (isFullMode())
|
||||
setFullMode(true);
|
||||
}
|
||||
@ -147,39 +147,39 @@ void Xf86VidModeToggler::setMode(unsigned /*screen*/, const unsigned resIndex, c
|
||||
void Xf86VidModeToggler::setFullMode(const bool enable) {
|
||||
XF86VidModeModeInfo curMode;
|
||||
bool curModeValid;
|
||||
|
||||
|
||||
{
|
||||
int dotclock = 0;
|
||||
XF86VidModeModeLine modeline;
|
||||
curModeValid = XF86VidModeGetModeLine(QX11Info::display(), QX11Info::appScreen(), &dotclock, &modeline);
|
||||
curMode.dotclock = dotclock;
|
||||
|
||||
|
||||
std::memcpy(reinterpret_cast<char*>(&curMode) + sizeof curMode.dotclock,
|
||||
reinterpret_cast<char*>(&modeline),
|
||||
std::min(sizeof modeline, sizeof curMode - sizeof curMode.dotclock));
|
||||
}
|
||||
|
||||
|
||||
XF86VidModeModeInfo *newMode = NULL;
|
||||
int vportx = 0;
|
||||
int vporty = 0;
|
||||
|
||||
|
||||
if (enable) {
|
||||
if (!isFull) {
|
||||
if (curModeValid)
|
||||
originalMode = curMode;
|
||||
|
||||
|
||||
XF86VidModeGetViewPort(QX11Info::display(), QX11Info::appScreen(), &originalvportx, &originalvporty);
|
||||
}
|
||||
|
||||
|
||||
int i = 0;
|
||||
|
||||
|
||||
while (i < modecount &&
|
||||
modesinfo[i]->hdisplay != infoVector[fullResIndex].w ||
|
||||
modesinfo[i]->vdisplay != infoVector[fullResIndex].h ||
|
||||
getRate(*modesinfo[i]) != static_cast<unsigned>(infoVector[fullResIndex].rates[fullRateIndex])) {
|
||||
++i;
|
||||
}
|
||||
|
||||
|
||||
if (i != modecount) {
|
||||
newMode = modesinfo[i];
|
||||
}
|
||||
@ -187,23 +187,23 @@ void Xf86VidModeToggler::setFullMode(const bool enable) {
|
||||
if (modecount) {
|
||||
newMode = &originalMode;
|
||||
}
|
||||
|
||||
|
||||
vportx = originalvportx;
|
||||
vporty = originalvporty;
|
||||
}
|
||||
|
||||
|
||||
if (newMode) {
|
||||
if (XF86VidModeSwitchToMode(QX11Info::display(), QX11Info::appScreen(), newMode)) {
|
||||
const unsigned newRate = getRate(*newMode);
|
||||
|
||||
|
||||
if (!curModeValid || newRate != getRate(curMode))
|
||||
emit rateChange(newRate);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
XF86VidModeSetViewPort(QX11Info::display(), QX11Info::appScreen(), vportx, vporty);
|
||||
XF86VidModeLockModeSwitch(QX11Info::display(), QX11Info::appScreen(), enable);
|
||||
|
||||
|
||||
if (enable) {
|
||||
XGrabPointer(QX11Info::display(), QX11Info::appRootWindow(), True, 0,
|
||||
GrabModeAsync, GrabModeAsync,
|
||||
@ -213,9 +213,9 @@ void Xf86VidModeToggler::setFullMode(const bool enable) {
|
||||
XUngrabPointer(QX11Info::display(), CurrentTime);
|
||||
QCoreApplication::instance()->removeEventFilter(this);
|
||||
}
|
||||
|
||||
|
||||
// XSync(QX11Info::display(), False);
|
||||
|
||||
|
||||
isFull = enable;
|
||||
}
|
||||
|
||||
@ -229,7 +229,7 @@ bool Xf86VidModeToggler::eventFilter(QObject *obj, QEvent *ev) {
|
||||
} else if (ev->type() == 9)
|
||||
XUngrabPointer(QX11Info::display(), CurrentTime);
|
||||
}*/
|
||||
|
||||
|
||||
if (ev->type() == QEvent::Show || ev->type() == QEvent::Hide) {
|
||||
XGrabPointer(QX11Info::display(), QX11Info::appRootWindow(), True, 0,
|
||||
GrabModeAsync, GrabModeAsync,
|
||||
@ -239,7 +239,7 @@ bool Xf86VidModeToggler::eventFilter(QObject *obj, QEvent *ev) {
|
||||
}/* else if (ev->type() == QEvent::Leave && obj->isWidgetType() && static_cast<QWidget*>(obj)->winId() == winId && !qApp->activeWindow()) {
|
||||
XUngrabPointer(QX11Info::display(), CurrentTime);
|
||||
}*/
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -247,10 +247,10 @@ void Xf86VidModeToggler::emitRate() {
|
||||
int rate = 0;
|
||||
int dotclock = 0;
|
||||
XF86VidModeModeLine modeline;
|
||||
|
||||
|
||||
if (XF86VidModeGetModeLine(QX11Info::display(), QX11Info::appScreen(), &dotclock, &modeline)) {
|
||||
rate = getRate(dotclock, modeline.htotal, modeline.vtotal);
|
||||
}
|
||||
|
||||
|
||||
emit rateChange(rate);
|
||||
}
|
||||
|
@ -26,7 +26,7 @@
|
||||
|
||||
class Xf86VidModeToggler : public FullModeToggler {
|
||||
Q_OBJECT
|
||||
|
||||
|
||||
XF86VidModeModeInfo **modesinfo;
|
||||
XF86VidModeModeInfo originalMode;
|
||||
std::vector<ResInfo> infoVector;
|
||||
@ -37,7 +37,7 @@ class Xf86VidModeToggler : public FullModeToggler {
|
||||
int originalvporty;
|
||||
WId winId;
|
||||
bool isFull;
|
||||
|
||||
|
||||
public:
|
||||
static bool isUsable();
|
||||
Xf86VidModeToggler(WId winId);
|
||||
@ -54,7 +54,7 @@ public:
|
||||
unsigned screen() const { return 0; }
|
||||
unsigned screens() const { return 1; }
|
||||
bool eventFilter(QObject *obj, QEvent *ev);
|
||||
|
||||
|
||||
signals:
|
||||
void rateChange(int newHz);
|
||||
// void modeChange();
|
||||
|
@ -34,7 +34,7 @@ static inline bool operator>(const ResInfo &l, const ResInfo &r) {
|
||||
static unsigned getRate(const unsigned long dotclock, const unsigned htotal, const unsigned vtotal) {
|
||||
if (unsigned long pixels = htotal * vtotal)
|
||||
return (dotclock * 10ull + (pixels >> 1)) / pixels;
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -45,24 +45,24 @@ static unsigned getRate(const XRRModeInfo &mode) {
|
||||
static void addMode(const XRRModeInfo &mode, std::vector<ResInfo> &infoVector, unsigned *resIndex, unsigned *rateIndex) {
|
||||
ResInfo info;
|
||||
short rate;
|
||||
|
||||
|
||||
info.w = mode.width;
|
||||
info.h = mode.height;
|
||||
rate = getRate(mode);
|
||||
|
||||
|
||||
std::vector<ResInfo>::iterator it = std::lower_bound(infoVector.begin(), infoVector.end(), info, std::greater<ResInfo>());
|
||||
|
||||
|
||||
if (it == infoVector.end() || *it != info)
|
||||
it = infoVector.insert(it, info);
|
||||
|
||||
|
||||
std::vector<short>::iterator rateIt = std::lower_bound(it->rates.begin(), it->rates.end(), rate, std::greater<short>());
|
||||
|
||||
|
||||
if (rateIt == it->rates.end() || *rateIt != rate)
|
||||
rateIt = it->rates.insert(rateIt, rate);
|
||||
|
||||
|
||||
if (resIndex)
|
||||
*resIndex = std::distance(infoVector.begin(), it);
|
||||
|
||||
|
||||
if (rateIndex)
|
||||
*rateIndex = std::distance(it->rates.begin(), rateIt);
|
||||
}
|
||||
@ -72,14 +72,14 @@ static XRRModeInfo* getModeInfo(const XRRScreenResources *const resources, const
|
||||
if (resources->modes[m].id == mode)
|
||||
return resources->modes + m;
|
||||
}
|
||||
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool isGood(const RRMode mode, const std::vector<XRROutputInfo*> &outputInfos) {
|
||||
for (std::size_t o = 0; o < outputInfos.size(); ++o) {
|
||||
RRMode *const modesEnd = outputInfos[o]->modes + outputInfos[o]->nmode;
|
||||
|
||||
|
||||
if (std::find(outputInfos[o]->modes, modesEnd, mode) == modesEnd)
|
||||
return false;
|
||||
}
|
||||
@ -102,7 +102,7 @@ OutputInfos::OutputInfos(XRRScreenResources *const resources, const XRRCrtcInfo
|
||||
{
|
||||
for (std::size_t i = 0; i < v.size();) {
|
||||
v[i] = XRRGetOutputInfo(QX11Info::display(), resources, crtcInfo->outputs[i]);
|
||||
|
||||
|
||||
if (v[i])
|
||||
++i;
|
||||
else
|
||||
@ -117,7 +117,7 @@ OutputInfos::~OutputInfos() {
|
||||
|
||||
class CrtcInfoPtr : Uncopyable {
|
||||
XRRCrtcInfo *const crtcInfo;
|
||||
|
||||
|
||||
public:
|
||||
CrtcInfoPtr(XRRScreenResources *const resources, const RRCrtc crtc)
|
||||
: crtcInfo(XRRGetCrtcInfo(QX11Info::display(), resources, crtc)) {}
|
||||
@ -134,21 +134,21 @@ static RRMode getMode(XRRScreenResources *const resources, const XRRCrtcInfo *co
|
||||
if (curMode->width == info.w && curMode->height == info.h && getRate(*curMode) == static_cast<unsigned>(rate))
|
||||
return crtcInfo->mode;
|
||||
}
|
||||
|
||||
|
||||
if (XRRModeInfo *prefMode = getModeInfo(resources, preferred)) {
|
||||
if (prefMode->width == info.w && prefMode->height == info.h && getRate(*prefMode) == static_cast<unsigned>(rate))
|
||||
return preferred;
|
||||
}
|
||||
|
||||
|
||||
OutputInfos outputInfos(resources, crtcInfo);
|
||||
|
||||
|
||||
for (int m = 0; m < resources->nmode; ++m) {
|
||||
if (resources->modes[m].width == info.w && resources->modes[m].height == info.h && getRate(resources->modes[m]) == static_cast<unsigned>(rate)) {
|
||||
if (isGood(resources->modes[m].id, outputInfos.get()))
|
||||
return resources->modes[m].id;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return crtcInfo->mode;
|
||||
}
|
||||
|
||||
@ -158,7 +158,7 @@ bool XRandR12Toggler::isUsable() {
|
||||
int unused = 0;
|
||||
int major = 1;
|
||||
int minor = 1;
|
||||
|
||||
|
||||
return XRRQueryExtension(QX11Info::display(), &unused, &unused) &&
|
||||
XRRQueryVersion(QX11Info::display(), &major, &minor) &&
|
||||
major == 1 && minor >= 2;
|
||||
@ -171,21 +171,21 @@ widgetScreen(0),
|
||||
isFull(false)
|
||||
{
|
||||
resources = XRRGetScreenResources(QX11Info::display(), QX11Info::appRootWindow());
|
||||
|
||||
|
||||
if (resources) {
|
||||
infoVector.resize(resources->ncrtc);
|
||||
fullResIndex.resize(resources->ncrtc);
|
||||
fullRateIndex.resize(resources->ncrtc);
|
||||
|
||||
|
||||
for (int c = 0; c < resources->ncrtc; ++c) {
|
||||
XRRModeInfo *curMode = NULL;
|
||||
|
||||
|
||||
{
|
||||
CrtcInfoPtr crtcInfo(resources, resources->crtcs[c]);
|
||||
|
||||
|
||||
if (crtcInfo && (curMode = getModeInfo(resources, crtcInfo->mode))) {
|
||||
OutputInfos outputInfos(resources, crtcInfo);
|
||||
|
||||
|
||||
for (int m = 0; m < resources->nmode; ++m) {
|
||||
if (resources->modes[m].width <= curMode->width && resources->modes[m].height <= curMode->height) {
|
||||
if (isGood(resources->modes[m].id, outputInfos.get()))
|
||||
@ -194,13 +194,13 @@ isFull(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
unsigned resIndex = 0;
|
||||
unsigned rateIndex = 0;
|
||||
|
||||
|
||||
if (curMode)
|
||||
addMode(*curMode, infoVector[c], &resIndex, &rateIndex);
|
||||
|
||||
|
||||
fullResIndex[c] = resIndex;
|
||||
fullRateIndex[c] = rateIndex;
|
||||
}
|
||||
@ -215,39 +215,39 @@ XRandR12Toggler::~XRandR12Toggler() {
|
||||
const QRect XRandR12Toggler::fullScreenRect(const QWidget *const w) const {
|
||||
if (resources) {
|
||||
CrtcInfoPtr crtcInfo(resources, resources->crtcs[widgetScreen]);
|
||||
|
||||
|
||||
if (crtcInfo)
|
||||
return QRect(crtcInfo->x, crtcInfo->y, crtcInfo->width, crtcInfo->height);
|
||||
}
|
||||
|
||||
|
||||
return FullModeToggler::fullScreenRect(w);
|
||||
}
|
||||
|
||||
void XRandR12Toggler::setScreen(const QWidget *const widget) {
|
||||
unsigned n = widgetScreen;
|
||||
|
||||
|
||||
if (resources) {
|
||||
int maxIntersect = 0;
|
||||
const QRect &wrect = widget->geometry();
|
||||
|
||||
|
||||
for (int c = 0; c < resources->ncrtc; ++c) {
|
||||
CrtcInfoPtr crtcInfo(resources, resources->crtcs[c]);
|
||||
|
||||
|
||||
if (crtcInfo) {
|
||||
const QRect &r = QRect(crtcInfo->x, crtcInfo->y, crtcInfo->width, crtcInfo->height).intersected(wrect);
|
||||
const int area = r.width() * r.height();
|
||||
|
||||
|
||||
if (area > maxIntersect) {
|
||||
maxIntersect = area;
|
||||
n = c;
|
||||
|
||||
|
||||
if (r == wrect)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (n != widgetScreen && n < infoVector.size()) {
|
||||
if (isFullMode()) {
|
||||
setFullMode(false);
|
||||
@ -263,7 +263,7 @@ void XRandR12Toggler::setScreen(const QWidget *const widget) {
|
||||
void XRandR12Toggler::setMode(const unsigned screen, const unsigned resIndex, const unsigned rateIndex) {
|
||||
fullResIndex[screen] = resIndex;
|
||||
fullRateIndex[screen] = rateIndex;
|
||||
|
||||
|
||||
if (isFullMode() && screen == widgetScreen)
|
||||
setFullMode(true);
|
||||
}
|
||||
@ -271,59 +271,59 @@ void XRandR12Toggler::setMode(const unsigned screen, const unsigned resIndex, co
|
||||
void XRandR12Toggler::setFullMode(const bool enable) {
|
||||
if (resources) {
|
||||
CrtcInfoPtr crtcInfo(resources, resources->crtcs[widgetScreen]);
|
||||
|
||||
|
||||
if (crtcInfo) {
|
||||
RRMode mode = crtcInfo->mode;
|
||||
|
||||
|
||||
if (enable) {
|
||||
if (!infoVector[widgetScreen].empty()) {
|
||||
mode = getMode(resources, crtcInfo, isFull ? originalMode : crtcInfo->mode,
|
||||
infoVector[widgetScreen][fullResIndex[widgetScreen]],
|
||||
infoVector[widgetScreen][fullResIndex[widgetScreen]].rates[fullRateIndex[widgetScreen]]);
|
||||
}
|
||||
|
||||
|
||||
if (!isFull)
|
||||
originalMode = crtcInfo->mode;
|
||||
} else if (isFull)
|
||||
mode = originalMode;
|
||||
|
||||
|
||||
if (mode != crtcInfo->mode) {
|
||||
if (XRRSetCrtcConfig(QX11Info::display(), resources, resources->crtcs[widgetScreen],
|
||||
CurrentTime, crtcInfo->x, crtcInfo->y, mode, crtcInfo->rotation,
|
||||
crtcInfo->outputs, crtcInfo->noutput) == Success) {
|
||||
const short rate = infoVector[widgetScreen][fullResIndex[widgetScreen]].rates[fullRateIndex[widgetScreen]];
|
||||
short prevRate = -1;
|
||||
|
||||
|
||||
if (XRRModeInfo *curMode = getModeInfo(resources, crtcInfo->mode))
|
||||
prevRate = getRate(*curMode);
|
||||
|
||||
|
||||
if (rate != prevRate)
|
||||
emit rateChange(rate);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
isFull = enable;
|
||||
}
|
||||
|
||||
void XRandR12Toggler::emitRate() {
|
||||
const CrtcInfoPtr crtcInfo(resources, resources->crtcs[widgetScreen]);
|
||||
short rate = 0;
|
||||
|
||||
|
||||
if (crtcInfo) {
|
||||
if (XRRModeInfo *curMode = getModeInfo(resources, crtcInfo->mode))
|
||||
rate = getRate(*curMode);
|
||||
}
|
||||
|
||||
|
||||
emit rateChange(rate);
|
||||
}
|
||||
|
||||
const QString XRandR12Toggler::screenName(const unsigned screen) const {
|
||||
OutputInfos outputInfos(resources, CrtcInfoPtr(resources, resources->crtcs[screen]));
|
||||
|
||||
|
||||
if (!outputInfos.get().empty())
|
||||
return QString(outputInfos.get()[0]->name);
|
||||
|
||||
|
||||
return FullModeToggler::screenName(screen);
|
||||
}
|
||||
|
@ -26,7 +26,7 @@
|
||||
|
||||
class XRandR12Toggler : public FullModeToggler, Uncopyable {
|
||||
Q_OBJECT
|
||||
|
||||
|
||||
RRMode originalMode;
|
||||
XRRScreenResources *resources;
|
||||
std::vector<std::vector<ResInfo> > infoVector;
|
||||
@ -34,7 +34,7 @@ class XRandR12Toggler : public FullModeToggler, Uncopyable {
|
||||
std::vector<unsigned> fullRateIndex;
|
||||
unsigned widgetScreen;
|
||||
bool isFull;
|
||||
|
||||
|
||||
public:
|
||||
static bool isUsable();
|
||||
XRandR12Toggler();
|
||||
@ -51,11 +51,11 @@ public:
|
||||
unsigned screen() const { return widgetScreen; }
|
||||
unsigned screens() const { return infoVector.size(); }
|
||||
const QString screenName(unsigned screen) const;
|
||||
|
||||
|
||||
signals:
|
||||
void rateChange(int newHz);
|
||||
// void modeChange();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -25,7 +25,7 @@ bool XRandRToggler::isUsable() {
|
||||
int unused = 0;
|
||||
int major = 1;
|
||||
int minor = 1;
|
||||
|
||||
|
||||
return XRRQueryExtension(QX11Info::display(), &unused, &unused) &&
|
||||
XRRQueryVersion(QX11Info::display(), &major, &minor) &&
|
||||
major == 1 && minor >= 1;
|
||||
@ -42,33 +42,33 @@ isFull(false)
|
||||
{
|
||||
fullResIndex = originalResIndex = XRRConfigCurrentConfiguration(config, &rotation);
|
||||
originalRate = 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] * 10);
|
||||
|
||||
|
||||
infoVector.push_back(info);
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
unsigned i = 0;
|
||||
|
||||
|
||||
while (i < infoVector[fullResIndex].rates.size() && infoVector[fullResIndex].rates[i] != originalRate * 10)
|
||||
++i;
|
||||
|
||||
|
||||
if (i == infoVector[fullResIndex].rates.size())
|
||||
infoVector[fullResIndex].rates.push_back(originalRate * 10);
|
||||
|
||||
|
||||
fullRateIndex = i;
|
||||
}
|
||||
}
|
||||
@ -80,14 +80,14 @@ XRandRToggler::~XRandRToggler() {
|
||||
|
||||
const QRect XRandRToggler::fullScreenRect(const QWidget */*wdgt*/) const {
|
||||
int w, h;
|
||||
|
||||
|
||||
{
|
||||
int nSizes = 0;
|
||||
XRRScreenSize *randrSizes = XRRConfigSizes(config, &nSizes);
|
||||
|
||||
|
||||
Rotation rot = rotation;
|
||||
SizeID currentID = XRRConfigCurrentConfiguration(config, &rot);
|
||||
|
||||
|
||||
if (currentID < nSizes) {
|
||||
w = randrSizes[currentID].width;
|
||||
h = randrSizes[currentID].height;
|
||||
@ -96,14 +96,14 @@ const QRect XRandRToggler::fullScreenRect(const QWidget */*wdgt*/) const {
|
||||
h = infoVector[fullResIndex].h;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return QRect(0, 0, w, h);
|
||||
}
|
||||
|
||||
void XRandRToggler::setMode(unsigned /*screen*/, const unsigned resIndex, const unsigned rateIndex) {
|
||||
fullResIndex = resIndex;
|
||||
fullRateIndex = rateIndex;
|
||||
|
||||
|
||||
if (isFullMode())
|
||||
setFullMode(true);
|
||||
}
|
||||
@ -111,14 +111,14 @@ void XRandRToggler::setMode(unsigned /*screen*/, const unsigned resIndex, const
|
||||
void XRandRToggler::setFullMode(const bool enable) {
|
||||
SizeID currentID = XRRConfigCurrentConfiguration(config, &rotation);
|
||||
int currentRate = XRRConfigCurrentRate(config);
|
||||
|
||||
|
||||
SizeID newID;
|
||||
int newRate;
|
||||
|
||||
|
||||
if (enable) {
|
||||
newID = fullResIndex;
|
||||
newRate = infoVector[fullResIndex].rates[fullRateIndex] / 10;
|
||||
|
||||
|
||||
if (!isFull) {
|
||||
originalResIndex = currentID;
|
||||
originalRate = currentRate;
|
||||
@ -127,14 +127,14 @@ void XRandRToggler::setFullMode(const bool enable) {
|
||||
newID = originalResIndex;
|
||||
newRate = originalRate;
|
||||
}
|
||||
|
||||
|
||||
if (newID != currentID || newRate != currentRate) {
|
||||
XRRSetScreenConfigAndRate(QX11Info::display(), config, QX11Info::appRootWindow(), newID, rotation, newRate, CurrentTime);
|
||||
|
||||
|
||||
if (newRate != currentRate)
|
||||
emit rateChange(newRate * 10);
|
||||
}
|
||||
|
||||
|
||||
isFull = enable;
|
||||
}
|
||||
|
||||
|
@ -27,7 +27,7 @@
|
||||
|
||||
class XRandRToggler : public FullModeToggler, Uncopyable {
|
||||
Q_OBJECT
|
||||
|
||||
|
||||
std::vector<ResInfo> infoVector;
|
||||
XRRScreenConfiguration *const config;
|
||||
unsigned originalResIndex;
|
||||
@ -36,7 +36,7 @@ class XRandRToggler : public FullModeToggler, Uncopyable {
|
||||
unsigned fullRateIndex;
|
||||
short originalRate;
|
||||
bool isFull;
|
||||
|
||||
|
||||
public:
|
||||
static bool isUsable();
|
||||
XRandRToggler();
|
||||
@ -52,7 +52,7 @@ public:
|
||||
void setScreen(const QWidget */*widget*/) {}
|
||||
unsigned screen() const { return 0; }
|
||||
unsigned screens() const { return 1; }
|
||||
|
||||
|
||||
signals:
|
||||
void rateChange(int newHz);
|
||||
// void modeChange();
|
||||
|
@ -23,10 +23,10 @@ GdiSettings::GdiSettings() : user32handle(NULL), getMonitorInfo(NULL), changeDis
|
||||
if ((user32handle = LoadLibraryA("user32.dll"))) {
|
||||
QT_WA({getMonitorInfo = (GetMonInfo)GetProcAddress(user32handle, "GetMonitorInfoW");},
|
||||
{getMonitorInfo = (GetMonInfo)GetProcAddress(user32handle, "GetMonitorInfoA");});
|
||||
|
||||
|
||||
QT_WA({changeDisplaySettingsEx = (ChangeGdiSettingsEx)GetProcAddress(user32handle, "ChangeDisplaySettingsExW");},
|
||||
{changeDisplaySettingsEx = (ChangeGdiSettingsEx)GetProcAddress(user32handle, "ChangeDisplaySettingsExA");});
|
||||
|
||||
|
||||
monitorFromWindow = (MonFromWindow)GetProcAddress(user32handle, "MonitorFromWindow");
|
||||
monitorFromPoint = (MonFromPoint)GetProcAddress(user32handle, "MonitorFromPoint");
|
||||
}
|
||||
@ -41,22 +41,22 @@ TCHAR* GdiSettings::getMonitorName(HMONITOR monitor, GdiSettings::MonInfo *minfo
|
||||
if (getMonitorInfo && monitor) {
|
||||
minfo->cbSize = sizeof *minfo;
|
||||
getMonitorInfo(monitor, minfo);
|
||||
|
||||
|
||||
return minfo->szDevice;
|
||||
}
|
||||
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BOOL GdiSettings::enumDisplaySettings(HMONITOR monitor, DWORD iModeNum, LPDEVMODE devmode) const {
|
||||
MonInfo minfo;
|
||||
|
||||
|
||||
return EnumDisplaySettings(getMonitorName(monitor, &minfo), iModeNum, devmode);
|
||||
}
|
||||
|
||||
LONG GdiSettings::changeDisplaySettings(HMONITOR monitor, LPDEVMODE devmode, DWORD dwflags) const {
|
||||
MonInfo minfo;
|
||||
|
||||
|
||||
return changeDisplaySettingsEx ?
|
||||
changeDisplaySettingsEx(getMonitorName(monitor, &minfo), devmode, NULL, dwflags, NULL) :
|
||||
ChangeDisplaySettings(devmode, dwflags);
|
||||
|
@ -23,11 +23,11 @@
|
||||
#include <windows.h>
|
||||
|
||||
class GdiSettings : Uncopyable {
|
||||
struct MonInfo {
|
||||
DWORD cbSize;
|
||||
RECT rcMonitor;
|
||||
RECT rcWork;
|
||||
DWORD dwFlags;
|
||||
struct MonInfo {
|
||||
DWORD cbSize;
|
||||
RECT rcMonitor;
|
||||
RECT rcWork;
|
||||
DWORD dwFlags;
|
||||
TCHAR szDevice[CCHDEVICENAME];
|
||||
};
|
||||
|
||||
@ -35,22 +35,22 @@ class GdiSettings : Uncopyable {
|
||||
typedef HMONITOR (WINAPI *MonFromWindow)(HWND, DWORD);
|
||||
typedef HMONITOR (WINAPI *MonFromPoint)(POINT pt, DWORD dwFlags);
|
||||
typedef LONG (WINAPI *ChangeGdiSettingsEx)(LPCTSTR, LPDEVMODE, HWND, DWORD, LPVOID);
|
||||
|
||||
|
||||
public:
|
||||
enum { MON_DEFAULTTONEAREST = 2 };
|
||||
|
||||
|
||||
private:
|
||||
HMODULE user32handle;
|
||||
GetMonInfo getMonitorInfo;
|
||||
ChangeGdiSettingsEx changeDisplaySettingsEx;
|
||||
|
||||
|
||||
public:
|
||||
MonFromWindow monitorFromWindow;
|
||||
MonFromPoint monitorFromPoint;
|
||||
|
||||
|
||||
private:
|
||||
TCHAR *getMonitorName(HMONITOR monitor, MonInfo *minfo) const;
|
||||
|
||||
|
||||
public:
|
||||
GdiSettings();
|
||||
~GdiSettings();
|
||||
|
@ -25,12 +25,12 @@
|
||||
transfer_ptr<FullModeToggler> getFullModeToggler(WId /*winId*/) {
|
||||
if (XRandR12Toggler::isUsable())
|
||||
return transfer_ptr<FullModeToggler>(new XRandR12Toggler);
|
||||
|
||||
|
||||
if (XRandRToggler::isUsable())
|
||||
return transfer_ptr<FullModeToggler>(new XRandRToggler);
|
||||
|
||||
|
||||
// if (Xf86VidModeToggler::isUsable())
|
||||
// return transfer_ptr<FullModeToggler>(new Xf86VidModeToggler(winId));
|
||||
|
||||
|
||||
return transfer_ptr<FullModeToggler>(new NullToggler);
|
||||
}
|
||||
|
@ -374,7 +374,7 @@ void InputBox::focusInEvent(QFocusEvent *event) {
|
||||
ignoreCnt = 1;
|
||||
timerId = startTimer(100);
|
||||
}
|
||||
|
||||
|
||||
QLineEdit::focusInEvent(event);
|
||||
}
|
||||
|
||||
@ -384,7 +384,7 @@ void InputBox::focusOutEvent(QFocusEvent *event) {
|
||||
killTimer(timerId);
|
||||
timerId = 0;
|
||||
}
|
||||
|
||||
|
||||
QLineEdit::focusOutEvent(event);
|
||||
}
|
||||
|
||||
@ -393,7 +393,7 @@ void InputBox::keyPressEvent(QKeyEvent *e) {
|
||||
QLineEdit::keyPressEvent(e);
|
||||
} else {
|
||||
setData(e->key());
|
||||
|
||||
|
||||
if (nextFocus)
|
||||
nextFocus->setFocus();
|
||||
}
|
||||
@ -404,11 +404,11 @@ void InputBox::timerEvent(QTimerEvent */*event*/) {
|
||||
return;
|
||||
|
||||
SDL_JoystickUpdate();
|
||||
|
||||
|
||||
SDL_Event ev;
|
||||
int value = 0;
|
||||
unsigned id = 0;
|
||||
|
||||
|
||||
if (ignoreCnt) {
|
||||
ignoreCnt--;
|
||||
} else while (pollJsEvent(&ev, 256)) {
|
||||
@ -418,20 +418,20 @@ void InputBox::timerEvent(QTimerEvent */*event*/) {
|
||||
case SDL_JOYBUTTONCHANGE:
|
||||
if (!ev.value)
|
||||
continue;
|
||||
|
||||
|
||||
value = ev.value;
|
||||
break;
|
||||
default: continue;
|
||||
}
|
||||
|
||||
|
||||
id = ev.id;
|
||||
}
|
||||
|
||||
|
||||
SDL_ClearEvents();
|
||||
|
||||
|
||||
if (id) {
|
||||
setData(id, value);
|
||||
|
||||
|
||||
if (nextFocus)
|
||||
nextFocus->setFocus();
|
||||
}
|
||||
@ -440,7 +440,7 @@ void InputBox::timerEvent(QTimerEvent */*event*/) {
|
||||
void InputBox::setData(const unsigned id, const int value) {
|
||||
data.id = id;
|
||||
data.value = value;
|
||||
|
||||
|
||||
if (value == KBD_VALUE) {
|
||||
setText(keyToString(id));
|
||||
} else if (value == NULL_VALUE) {
|
||||
@ -448,7 +448,7 @@ void InputBox::setData(const unsigned id, const int value) {
|
||||
} else {
|
||||
QString str(SDL_JoystickName(data.dev_num));
|
||||
str.append(' ');
|
||||
|
||||
|
||||
switch (data.type) {
|
||||
case SDL_JOYAXISMOTION:
|
||||
str.append("Axis ");
|
||||
@ -460,7 +460,7 @@ void InputBox::setData(const unsigned id, const int value) {
|
||||
str.append("Hat ");
|
||||
str.append(QString::number(data.num));
|
||||
str.append(' ');
|
||||
|
||||
|
||||
if (data.value & SDL_HAT_UP)
|
||||
str.append("Up");
|
||||
if (data.value & SDL_HAT_DOWN)
|
||||
@ -469,14 +469,14 @@ void InputBox::setData(const unsigned id, const int value) {
|
||||
str.append("Left");
|
||||
if (data.value & SDL_HAT_RIGHT)
|
||||
str.append("Right");
|
||||
|
||||
|
||||
break;
|
||||
case SDL_JOYBUTTONCHANGE:
|
||||
str.append("Button ");
|
||||
str.append(QString::number(data.num));
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
setText(str);
|
||||
}
|
||||
}
|
||||
|
@ -29,19 +29,19 @@ class InputBox : public QLineEdit {
|
||||
SDL_Event data;
|
||||
int timerId;
|
||||
int ignoreCnt;
|
||||
|
||||
|
||||
private slots:
|
||||
void textEditedSlot(const QString &) {
|
||||
setData(data);
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
void contextMenuEvent(QContextMenuEvent *event);
|
||||
void focusInEvent(QFocusEvent *event);
|
||||
void focusOutEvent(QFocusEvent *event);
|
||||
void keyPressEvent(QKeyEvent *e);
|
||||
void timerEvent(QTimerEvent */*event*/);
|
||||
|
||||
|
||||
public:
|
||||
enum { NULL_VALUE = 0, KBD_VALUE = 0x7FFFFFFF };
|
||||
explicit InputBox(QWidget *nextFocus = 0);
|
||||
@ -60,9 +60,9 @@ class InputBoxPair : public QObject {
|
||||
public:
|
||||
InputBox *const mainBox;
|
||||
InputBox *const altBox;
|
||||
|
||||
|
||||
InputBoxPair(InputBox *mainBox, InputBox *altBox) : mainBox(mainBox), altBox(altBox) {}
|
||||
|
||||
|
||||
public slots:
|
||||
void clear();
|
||||
};
|
||||
|
@ -48,23 +48,23 @@ InputDialog::InputDialog(const std::vector<Button> &buttonInfos,
|
||||
deleteButtonActions(deleteButtonActions)
|
||||
{
|
||||
setWindowTitle(tr("Input Settings"));
|
||||
|
||||
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||
QPushButton *const okButton = new QPushButton(tr("OK"));
|
||||
QPushButton *const cancelButton = new QPushButton(tr("Cancel"));
|
||||
|
||||
|
||||
{
|
||||
QTabWidget *const tabw = new QTabWidget;
|
||||
|
||||
|
||||
for (std::size_t i = 0; i < buttonInfos.size(); ++i) {
|
||||
if (!buttonInfos[i].label.isEmpty()) {
|
||||
inputBoxPairs[i] = new InputBoxPair(new InputBox, new InputBox);
|
||||
|
||||
|
||||
int j = tabw->count() - 1;
|
||||
|
||||
|
||||
while (j >= 0 && tabw->tabText(j) != buttonInfos[i].category)
|
||||
--j;
|
||||
|
||||
|
||||
if (j < 0) {
|
||||
QWidget *const w = new QWidget;
|
||||
QBoxLayout *const boxl = new QVBoxLayout;
|
||||
@ -73,16 +73,16 @@ InputDialog::InputDialog(const std::vector<Button> &buttonInfos,
|
||||
w->setLayout(boxl);
|
||||
j = tabw->addTab(w, buttonInfos[i].category);
|
||||
}
|
||||
|
||||
|
||||
QGridLayout *const gLayout = (QGridLayout*) tabw->widget(j)->layout()->itemAt(0);
|
||||
gLayout->addWidget(new QLabel(buttonInfos[i].label + ":"), i, 0);
|
||||
|
||||
|
||||
if (buttonInfos[i].defaultFpp) {
|
||||
QHBoxLayout *hLayout = new QHBoxLayout;
|
||||
hLayout->addWidget(inputBoxPairs[i]->mainBox);
|
||||
hLayout->addWidget(fppBoxes[i * 2] = makeFppBox(buttonInfos[i].defaultFpp).release());
|
||||
gLayout->addLayout(hLayout, i, 1);
|
||||
|
||||
|
||||
hLayout = new QHBoxLayout;
|
||||
hLayout->addWidget(inputBoxPairs[i]->altBox);
|
||||
hLayout->addWidget(fppBoxes[i * 2 + 1] = makeFppBox(buttonInfos[i].defaultFpp).release());
|
||||
@ -91,27 +91,27 @@ InputDialog::InputDialog(const std::vector<Button> &buttonInfos,
|
||||
gLayout->addWidget(inputBoxPairs[i]->mainBox, i, 1);
|
||||
gLayout->addWidget(inputBoxPairs[i]->altBox, i, 2);
|
||||
}
|
||||
|
||||
|
||||
QPushButton *const clearButton = new QPushButton(tr("Clear"));
|
||||
gLayout->addWidget(clearButton, i, 3);
|
||||
connect(clearButton, SIGNAL(clicked()), inputBoxPairs[i], SLOT(clear()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (int tabi = 0; tabi < tabw->count(); ++tabi) {
|
||||
QWidget *const w = tabw->widget(tabi);
|
||||
|
||||
|
||||
std::size_t i = 0;
|
||||
|
||||
|
||||
while (i < inputBoxPairs.size() && (!inputBoxPairs[i] || inputBoxPairs[i]->mainBox->parentWidget() != w))
|
||||
++i;
|
||||
|
||||
|
||||
while (i < inputBoxPairs.size()) {
|
||||
std::size_t j = i + 1;
|
||||
|
||||
|
||||
while (j < inputBoxPairs.size() && (!inputBoxPairs[j] || inputBoxPairs[j]->mainBox->parentWidget() != w))
|
||||
++j;
|
||||
|
||||
|
||||
if (j < inputBoxPairs.size()) {
|
||||
inputBoxPairs[i]->mainBox->setNextFocus(inputBoxPairs[j]->mainBox);
|
||||
inputBoxPairs[i]->altBox->setNextFocus(inputBoxPairs[j]->altBox);
|
||||
@ -119,29 +119,29 @@ InputDialog::InputDialog(const std::vector<Button> &buttonInfos,
|
||||
inputBoxPairs[i]->mainBox->setNextFocus(okButton);
|
||||
inputBoxPairs[i]->altBox->setNextFocus(okButton);
|
||||
}
|
||||
|
||||
|
||||
i = j;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
mainLayout->addWidget(tabw);
|
||||
}
|
||||
|
||||
|
||||
QHBoxLayout *const 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");
|
||||
|
||||
|
||||
for (std::size_t i = 0; i < buttonInfos.size(); ++i) {
|
||||
if (!buttonInfos[i].label.isEmpty()) {
|
||||
config[i * 2 ].event.id = settings.value(
|
||||
@ -151,7 +151,7 @@ InputDialog::InputDialog(const std::vector<Button> &buttonInfos,
|
||||
buttonInfos[i].defaultKey == Qt::Key_unknown ? InputBox::NULL_VALUE : InputBox::KBD_VALUE).toInt();
|
||||
config[i * 2 ].fpp = buttonInfos[i].defaultFpp ? settings.value(
|
||||
buttonInfos[i].category + buttonInfos[i].label + "Fpp1", buttonInfos[i].defaultFpp).toInt() : 0;
|
||||
|
||||
|
||||
config[i * 2 + 1].event.id = settings.value(
|
||||
buttonInfos[i].category + buttonInfos[i].label + "Key2", buttonInfos[i].defaultAltKey).toUInt();
|
||||
config[i * 2 + 1].event.value = settings.value(
|
||||
@ -164,16 +164,16 @@ InputDialog::InputDialog(const std::vector<Button> &buttonInfos,
|
||||
config[i * 2 ].event.value =
|
||||
buttonInfos[i].defaultKey == Qt::Key_unknown ? InputBox::NULL_VALUE : InputBox::KBD_VALUE;
|
||||
config[i * 2 ].fpp = buttonInfos[i].defaultFpp;
|
||||
|
||||
|
||||
config[i * 2 + 1].event.id = buttonInfos[i].defaultAltKey;
|
||||
config[i * 2 + 1].event.value =
|
||||
buttonInfos[i].defaultAltKey == Qt::Key_unknown ? InputBox::NULL_VALUE : InputBox::KBD_VALUE;
|
||||
config[i * 2 + 1].fpp = buttonInfos[i].defaultFpp;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
settings.endGroup();
|
||||
|
||||
|
||||
restore();
|
||||
resetMapping();
|
||||
}
|
||||
@ -181,23 +181,23 @@ InputDialog::InputDialog(const std::vector<Button> &buttonInfos,
|
||||
InputDialog::~InputDialog() {
|
||||
QSettings settings;
|
||||
settings.beginGroup("input");
|
||||
|
||||
|
||||
for (std::size_t i = 0; i < buttonInfos.size(); ++i) {
|
||||
if (!buttonInfos[i].label.isEmpty()) {
|
||||
settings.setValue(buttonInfos[i].category + buttonInfos[i].label + "Key1", config[i * 2].event.id);
|
||||
settings.setValue(buttonInfos[i].category + buttonInfos[i].label + "Value1", config[i * 2].event.value);
|
||||
settings.setValue(buttonInfos[i].category + buttonInfos[i].label + "Key2", config[i * 2 + 1].event.id);
|
||||
settings.setValue(buttonInfos[i].category + buttonInfos[i].label + "Value2", config[i * 2 + 1].event.value);
|
||||
|
||||
|
||||
if (buttonInfos[i].defaultFpp) {
|
||||
settings.setValue(buttonInfos[i].category + buttonInfos[i].label + "Fpp1", config[i * 2 ].fpp);
|
||||
settings.setValue(buttonInfos[i].category + buttonInfos[i].label + "Fpp2", config[i * 2 + 1].fpp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
settings.endGroup();
|
||||
|
||||
|
||||
if (deleteButtonActions)
|
||||
for (std::size_t i = 0; i < buttonInfos.size(); ++i)
|
||||
delete buttonInfos[i].action;
|
||||
@ -208,7 +208,7 @@ void InputDialog::resetMapping() {
|
||||
Mutual<KeyMapping>::Locked lkm(keymapping);
|
||||
lkm->map.clear();
|
||||
lkm->rapidvec.clear();
|
||||
|
||||
|
||||
for (std::size_t i = 0; i < config.size(); ++i) {
|
||||
if (config[i].event.value != InputBox::NULL_VALUE && config[i].event.value == InputBox::KBD_VALUE) {
|
||||
lkm->map.insert(std::make_pair(config[i].event.id,
|
||||
@ -216,12 +216,12 @@ void InputDialog::resetMapping() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
Mutual<JoyMapping>::Locked ljm(joymapping);
|
||||
ljm->map.clear();
|
||||
ljm->rapidvec.clear();
|
||||
|
||||
|
||||
for (std::size_t i = 0; i < config.size(); ++i) {
|
||||
if (config[i].event.value != InputBox::NULL_VALUE && config[i].event.value != InputBox::KBD_VALUE) {
|
||||
ljm->map.insert(std::make_pair(config[i].event.id,
|
||||
@ -238,12 +238,12 @@ void InputDialog::store() {
|
||||
config[i * 2 + 1].event = inputBoxPairs[i]->altBox->getData();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (std::size_t i = 0; i < fppBoxes.size(); ++i) {
|
||||
if (fppBoxes[i])
|
||||
config[i].fpp = fppBoxes[i]->value();
|
||||
}
|
||||
|
||||
|
||||
resetMapping();
|
||||
}
|
||||
|
||||
@ -254,7 +254,7 @@ void InputDialog::restore() {
|
||||
inputBoxPairs[i]->altBox->setData( config[i * 2 + 1].event);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (std::size_t i = 0; i < fppBoxes.size(); ++i) {
|
||||
if (fppBoxes[i])
|
||||
fppBoxes[i]->setValue(config[i].fpp);
|
||||
@ -269,10 +269,10 @@ static void setButtonPressed(AutoPressVec &v, InputDialog::Button::Action *const
|
||||
if (it->action == action && it->fpp == fpp)
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
v.push_back(typename AutoPressVec::value_type(action, fpp, 0));
|
||||
}
|
||||
|
||||
|
||||
action->buttonPressed();
|
||||
}
|
||||
|
||||
@ -287,7 +287,7 @@ static void unsetButtonPressed(AutoPressVec &v, InputDialog::Button::Action *con
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
action->buttonReleased();
|
||||
}
|
||||
|
||||
@ -336,7 +336,7 @@ static void doConsumeAutoPress(AutoPressVec &v) {
|
||||
void InputDialog::consumeAutoPress() {
|
||||
if (const Mutual<KeyMapping>::TryLocked &lm = keymapping)
|
||||
doConsumeAutoPress(lm->rapidvec);
|
||||
|
||||
|
||||
if (const Mutual<JoyMapping>::TryLocked &lm = joymapping)
|
||||
doConsumeAutoPress(lm->rapidvec);
|
||||
}
|
||||
|
@ -27,14 +27,14 @@ int pollJsEvent(SDL_Event *const ev, const int insensitivity) {
|
||||
static map_t axisState;
|
||||
|
||||
int evValid;
|
||||
|
||||
|
||||
do {
|
||||
evValid = SDL_PollEvent(ev);
|
||||
|
||||
|
||||
if (evValid && ev->type == SDL_JOYAXISMOTION) {
|
||||
enum { THRESHOLD = 8192 };
|
||||
const map_t::iterator it = axisState.insert(map_t::value_type(ev->id, 0)).first;
|
||||
|
||||
|
||||
switch (it->second) {
|
||||
case 0:
|
||||
if (ev->value >= THRESHOLD + insensitivity)
|
||||
@ -62,6 +62,6 @@ int pollJsEvent(SDL_Event *const ev, const int insensitivity) {
|
||||
it->second = ev->value;
|
||||
}
|
||||
} while (false);
|
||||
|
||||
|
||||
return evValid;
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ MainWindow::MainWindow(MediaSource *const source)
|
||||
setCentralWidget(w_->widget());
|
||||
setMouseTracking(true);
|
||||
setFocus();
|
||||
|
||||
|
||||
connect(w_, SIGNAL( audioEngineFailure()), this, SIGNAL( audioEngineFailure()));
|
||||
connect(w_, SIGNAL(videoBlitterFailure()), this, SIGNAL(videoBlitterFailure()));
|
||||
}
|
||||
@ -50,7 +50,7 @@ void MainWindow::stop() { w_->stop(); }
|
||||
|
||||
void MainWindow::setWindowSize(const QSize &sz) {
|
||||
winSize_ = sz;
|
||||
|
||||
|
||||
if (!fullscreen_ && isVisible())
|
||||
doSetWindowSize(sz);
|
||||
}
|
||||
@ -61,14 +61,14 @@ void MainWindow::toggleFullScreen() {
|
||||
w_->parentExclusiveEvent(false);
|
||||
w_->setFullMode(false);
|
||||
showNormal();
|
||||
|
||||
|
||||
if (isVisible())
|
||||
doSetWindowSize(winSize_);
|
||||
|
||||
|
||||
activateWindow();
|
||||
} else {
|
||||
fullscreen_ = true;
|
||||
|
||||
|
||||
if (isVisible())
|
||||
doShowFullScreen();
|
||||
}
|
||||
@ -76,14 +76,14 @@ void MainWindow::toggleFullScreen() {
|
||||
|
||||
void MainWindow::setVideoFormat(unsigned w, unsigned h) {
|
||||
w_->setVideoFormat(w, h);
|
||||
|
||||
|
||||
if (winSize_ == QSize(-1, -1))
|
||||
centralWidget()->setMinimumSize(w_->videoSize());
|
||||
}
|
||||
|
||||
void MainWindow::setVideoFormatAndBlitter(unsigned w, unsigned h, std::size_t blitterNo) {
|
||||
w_->setVideoFormatAndBlitter(w, h, blitterNo);
|
||||
|
||||
|
||||
if (winSize_ == QSize(-1, -1))
|
||||
centralWidget()->setMinimumSize(w_->videoSize());
|
||||
}
|
||||
@ -162,7 +162,7 @@ void MainWindow::showEvent(QShowEvent *) {
|
||||
// some window managers get pissed (xfwm4 breaks, metacity complains) if fixed window size is set too early.
|
||||
if (!fullscreen_)
|
||||
doSetWindowSize(winSize_);
|
||||
|
||||
|
||||
w_->showEvent(this);
|
||||
}
|
||||
|
||||
@ -174,7 +174,7 @@ void MainWindow::focusOutEvent(QFocusEvent *) {
|
||||
void MainWindow::focusInEvent(QFocusEvent *) {
|
||||
w_->focusInEvent();
|
||||
w_->parentExclusiveEvent(isFullScreen());
|
||||
|
||||
|
||||
// urk, delay full screen until getting focus if not visible to avoid WMs screwing up.
|
||||
if (fullscreen_ && !w_->isFullMode())
|
||||
doShowFullScreen();
|
||||
@ -200,7 +200,7 @@ void MainWindow::doShowFullScreen() {
|
||||
const int screen = QApplication::desktop()->screenNumber(this);
|
||||
|
||||
w_->setFullMode(true);
|
||||
doSetWindowSize(QSize(-1, -1));
|
||||
doSetWindowSize(QSize(-1, -1));
|
||||
|
||||
// If the window is outside the screen it will be moved to the primary screen by Qt.
|
||||
{
|
||||
|
@ -69,7 +69,7 @@ struct CustomEvent : QEvent {
|
||||
struct MediaWidget::Pauser::DoPause {
|
||||
MediaWidget &mw;
|
||||
explicit DoPause(MediaWidget &mw) : mw(mw) {}
|
||||
|
||||
|
||||
void operator()() const {
|
||||
if (mw.running) {
|
||||
mw.worker->pause();
|
||||
@ -83,7 +83,7 @@ struct MediaWidget::Pauser::DoPause {
|
||||
struct MediaWidget::Pauser::DoUnpause {
|
||||
MediaWidget &mw;
|
||||
explicit DoUnpause(MediaWidget &mw) : mw(mw) {}
|
||||
|
||||
|
||||
void operator()() const {
|
||||
if (mw.running) {
|
||||
mw.jsTimer->stop();
|
||||
@ -131,16 +131,16 @@ public:
|
||||
bool cancelBlit();
|
||||
void paused();
|
||||
void audioEngineFailure();
|
||||
|
||||
|
||||
bool tryLockVideoBuffer(PixelBuffer &pb) {
|
||||
if (mw.vbmut.tryLock()) {
|
||||
pb = mw.blitterContainer->blitter()->inBuffer();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void unlockVideoBuffer() { mw.vbmut.unlock(); }
|
||||
|
||||
void consumeBlitRequest();
|
||||
@ -232,11 +232,11 @@ void MediaWidget::WorkerCallback::consumeBlitRequest() {
|
||||
|
||||
static auto_vector<BlitterWidget> makeBlitterWidgets(const VideoBufferLocker vbl, const DwmControlHwndChange hwndc) {
|
||||
auto_vector<BlitterWidget> blitters;
|
||||
|
||||
|
||||
addBlitterWidgets(blitters, vbl);
|
||||
blitters.push_back(new QGLBlitter(vbl, hwndc));
|
||||
blitters.push_back(new QPainterBlitter(vbl));
|
||||
|
||||
|
||||
for (auto_vector<BlitterWidget>::iterator it = blitters.begin(); it != blitters.end();) {
|
||||
if ((*it)->isUnusable()) {
|
||||
it = blitters.erase(it);
|
||||
@ -249,10 +249,10 @@ static auto_vector<BlitterWidget> makeBlitterWidgets(const VideoBufferLocker vbl
|
||||
|
||||
static auto_vector<AudioEngine> makeAudioEngines(const WId winId) {
|
||||
auto_vector<AudioEngine> audioEngines;
|
||||
|
||||
|
||||
addAudioEngines(audioEngines, winId);
|
||||
audioEngines.push_back(new NullAudioEngine);
|
||||
|
||||
|
||||
return audioEngines;
|
||||
}
|
||||
|
||||
@ -378,7 +378,7 @@ void MediaWidget::setVideo(const unsigned w, const unsigned h, BlitterWidget *co
|
||||
if (running)
|
||||
blitterContainer->blitter()->setVideoFormat(w, h);
|
||||
}
|
||||
|
||||
|
||||
blitterContainer->setSourceSize(QSize(w, h));
|
||||
}
|
||||
}
|
||||
@ -466,7 +466,7 @@ void MediaWidget::setFrameTime(long num, long denom) {
|
||||
num = 0xFFFF;
|
||||
denom = 1;
|
||||
}
|
||||
|
||||
|
||||
frameRateControl.setFrameTime(Rational(num, denom));
|
||||
}
|
||||
|
||||
@ -486,7 +486,7 @@ void MediaWidget::updateJoysticks() {
|
||||
struct MediaWidget::FrameStepFun {
|
||||
MediaWidget &mw;
|
||||
explicit FrameStepFun(MediaWidget &mw) : mw(mw) {}
|
||||
|
||||
|
||||
void operator()() const {
|
||||
if (mw.running && mw.worker->frameStep()) {
|
||||
BlitterWidget *const blitter = mw.blitterContainer->blitter();
|
||||
|
@ -44,13 +44,13 @@ class QMainWindow;
|
||||
|
||||
class MediaWidget : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
|
||||
class Pauser {
|
||||
struct DoPause;
|
||||
struct DoUnpause;
|
||||
|
||||
|
||||
unsigned paused;
|
||||
|
||||
|
||||
void modifyPaused(unsigned newPaused, MediaWidget &mw);
|
||||
public:
|
||||
Pauser() : paused(0) {}
|
||||
@ -60,17 +60,17 @@ class MediaWidget : public QObject {
|
||||
void set(unsigned bm, MediaWidget &mw) { modifyPaused(paused | bm, mw); }
|
||||
void unset(unsigned bm, MediaWidget &mw) { modifyPaused(paused & ~bm, mw); }
|
||||
};
|
||||
|
||||
|
||||
const class JoystickIniter : Uncopyable {
|
||||
std::vector<SDL_Joystick*> joysticks;
|
||||
public:
|
||||
JoystickIniter();
|
||||
~JoystickIniter();
|
||||
} jsInit_;
|
||||
|
||||
|
||||
class WorkerCallback;
|
||||
struct FrameStepFun;
|
||||
|
||||
|
||||
QMutex vbmut;
|
||||
BlitterContainer *const blitterContainer;
|
||||
const auto_vector<AudioEngine> audioEngines;
|
||||
@ -86,7 +86,7 @@ class MediaWidget : public QObject {
|
||||
DwmControl dwmControl_;
|
||||
unsigned focusPauseBit;
|
||||
bool running;
|
||||
|
||||
|
||||
friend class CallWhenMediaWorkerPaused;
|
||||
friend class PushMediaWorkerCall;
|
||||
virtual void customEvent(QEvent*);
|
||||
@ -96,17 +96,17 @@ class MediaWidget : public QObject {
|
||||
void updateSwapInterval();
|
||||
void emitVideoBlitterFailure() { emit videoBlitterFailure(); }
|
||||
void emitAudioEngineFailure();
|
||||
|
||||
|
||||
private slots:
|
||||
void refreshRateChange(int refreshRate);
|
||||
void updateJoysticks();
|
||||
|
||||
|
||||
public:
|
||||
MediaWidget(MediaSource *source, QWidget &parent);
|
||||
~MediaWidget();
|
||||
|
||||
|
||||
QWidget* widget() const { return blitterContainer; }
|
||||
|
||||
|
||||
/** @return compositionChange */
|
||||
bool winEvent(const void *message) { return dwmControl_.winEvent(message); }
|
||||
void hideEvent() { dwmControl_.hideEvent(); }
|
||||
@ -118,57 +118,57 @@ public:
|
||||
void focusInEvent();
|
||||
void keyPressEvent(QKeyEvent*);
|
||||
void keyReleaseEvent(QKeyEvent*);
|
||||
|
||||
|
||||
bool tryLockFrameBuf(PixelBuffer &pb) {
|
||||
if (vbmut.tryLock()) {
|
||||
pb = running ? blitterContainer->blitter()->inBuffer() : PixelBuffer();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void unlockFrameBuf() { vbmut.unlock(); }
|
||||
|
||||
|
||||
const QSize& videoSize() const { return blitterContainer->sourceSize(); }
|
||||
|
||||
|
||||
void setFrameTime(long num, long denom);
|
||||
void setSamplesPerFrame(long num, long denom = 1) { worker->setSamplesPerFrame(Rational(num, denom)); }
|
||||
|
||||
|
||||
void frameStep();
|
||||
void pause(unsigned bitmask = 1) { pauser.set(bitmask, *this); }
|
||||
void unpause(unsigned bitmask = 1) { pauser.unset(bitmask, *this); }
|
||||
void incPause(unsigned inc) { pauser.inc(inc, *this); }
|
||||
void decPause(unsigned dec) { pauser.dec(dec, *this); }
|
||||
void setPauseOnFocusOut(unsigned bitmask, bool hasFocus);
|
||||
|
||||
|
||||
void run();
|
||||
void stop();
|
||||
bool isRunning() const { return running; }
|
||||
|
||||
|
||||
void setAspectRatio(const QSize &ar) { blitterContainer->setAspectRatio(ar); }
|
||||
void setScalingMethod(ScalingMethod smet) { blitterContainer->setScalingMethod(smet); }
|
||||
|
||||
|
||||
const BlitterConf blitterConf(std::size_t blitterNo) { return BlitterConf(blitters[blitterNo]); }
|
||||
const ConstBlitterConf blitterConf(std::size_t blitterNo) const { return ConstBlitterConf(blitters[blitterNo]); }
|
||||
std::size_t numBlitters() const { return blitters.size(); }
|
||||
const BlitterConf currentBlitterConf() { return BlitterConf(blitterContainer->blitter()); }
|
||||
const ConstBlitterConf currentBlitterConf() const { return ConstBlitterConf(blitterContainer->blitter()); }
|
||||
|
||||
|
||||
void setVideoBlitter(std::size_t blitterNo) {
|
||||
setVideoFormatAndBlitter(blitterContainer->sourceSize().width(),
|
||||
blitterContainer->sourceSize().height(), blitterNo);
|
||||
}
|
||||
|
||||
|
||||
void setVideoFormat(unsigned w, unsigned h/*, PixelBuffer::PixelFormat pf*/) {
|
||||
setVideo(w, h, /*pf, */blitterContainer->blitter());
|
||||
}
|
||||
|
||||
|
||||
void setVideoFormatAndBlitter(unsigned w, unsigned h,
|
||||
/*PixelBuffer::PixelFormat pf, */std::size_t blitterNo) {
|
||||
setVideo(w, h,/* pf,*/ blitters[blitterNo]);
|
||||
}
|
||||
|
||||
|
||||
void setFastForwardSpeed(unsigned speed) { worker->setFastForwardSpeed(speed); }
|
||||
void setMode(std::size_t screenNo, std::size_t resIndex, std::size_t rateIndex) { fullModeToggler->setMode(screenNo, resIndex, rateIndex); }
|
||||
const std::vector<ResInfo>& modeVector(std::size_t screen) const { return fullModeToggler->modeVector(screen); }
|
||||
@ -181,20 +181,20 @@ public:
|
||||
void setFullMode(bool fullscreen) { fullModeToggler->setFullMode(fullscreen); }
|
||||
bool isFullMode() const { return fullModeToggler->isFullMode(); }
|
||||
void parentExclusiveEvent(bool exclusive) { blitterContainer->parentExclusiveEvent(exclusive); }
|
||||
|
||||
|
||||
const AudioEngineConf audioEngineConf(std::size_t aeNo) { return AudioEngineConf(audioEngines[aeNo]); }
|
||||
const ConstAudioEngineConf audioEngineConf(std::size_t aeNo) const { return ConstAudioEngineConf(audioEngines[aeNo]); }
|
||||
std::size_t numAudioEngines() const { return audioEngines.size(); }
|
||||
|
||||
|
||||
void setAudioOut(std::size_t engineNo, unsigned srateHz, unsigned msecLatency, std::size_t resamplerNo) {
|
||||
worker->setAudioOut(audioEngines[engineNo], srateHz, msecLatency, resamplerNo);
|
||||
}
|
||||
|
||||
|
||||
std::size_t numResamplers() const { return ResamplerInfo::num(); }
|
||||
const char* resamplerDesc(std::size_t resamplerNo) const { return ResamplerInfo::get(resamplerNo).desc; }
|
||||
|
||||
|
||||
void waitUntilPaused();
|
||||
|
||||
|
||||
template<class T>
|
||||
void callWhenPaused(const T &fun) {
|
||||
worker->qPause();
|
||||
@ -206,10 +206,10 @@ public:
|
||||
void setDwmTripleBuffer(bool enable) { dwmControl_.setDwmTripleBuffer(enable); }
|
||||
void setFastForward(bool enable) { worker->setFastForward(enable); }
|
||||
void setSyncToRefreshRate(bool on) { frameRateControl.setRefreshRateSync(on); }
|
||||
|
||||
|
||||
public slots:
|
||||
void hideCursor();
|
||||
|
||||
|
||||
signals:
|
||||
void audioEngineFailure();
|
||||
void videoBlitterFailure();
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user