JustAudio/io/idm.cpp
Maurice O'Neal 73a8c03fa1 Added a logo to the project and changed the "settings" button to "menu"
and added some options to the menu that changes the behaviour of the
app. such as turning on/off the auto playing of files and the directory
and volume control. this is all kept persistent using an IDM formated
file in the app's config directory. still having issues with it not
calculating the durations properly but i now know why. it's because
QMediaPlayer can't calculate the durations of VBR files (variable bit-
rate) properly. other than that, everything seems to be working
perfectly. i'll add more feasures such as a next/previous file button
and a stop button.
2016-10-16 17:04:21 -04:00

433 lines
8.3 KiB
C++

#include "idm.h"
const QByteArray Idm::TAG = "IDM";
const int Idm::MAX_MAJOR = 1;
const int Idm::MAX_MINOR = 0;
int Idm::DEFAULT_INT_SIZE = 3;
int Idm::DEFAULT_FLAGS = 1; // FIXED_KEY_LEN
int Idm::DEFAULT_KEY_LEN = 1;
int Idm::CURRENT_MAJOR = Idm::MAX_MAJOR;
int Idm::CURRENT_MINOR = Idm::MAX_MINOR;
Idm::Idm(const QByteArray &data, QObject *parent) : QObject(parent)
{
buffPtr = data;
init();
}
Idm::Idm(QObject *parent) : QObject(parent)
{
init();
}
void Idm::init()
{
header = 0;
intSize = DEFAULT_INT_SIZE;
keyLen = DEFAULT_KEY_LEN;
flags = DEFAULT_FLAGS;
}
void Idm::loadData(const QByteArray &data)
{
op(RELOAD, data);
}
QByteArray &Idm::getBuff()
{
op(GET_BUFF, QByteArray(), QByteArray(), new QByteArray());
return buffPtr;
}
bool Idm::rdHeader()
{
return rdExHeader(buffPtr);
}
bool Idm::rdExHeader(const QByteArray &data)
{
bool ret;
op(RD_HEADER, data, QByteArray(), 0, 0, 0, &ret);
return ret;
}
bool Idm::rdExHeader(const QByteArray &data, int &major, int &minor, int &intSz, int &flgs, int &keyLen)
{
bool ret = false;
if (data.startsWith(TAG))
{
int pos = TAG.size();
major = rdInt(data.mid(pos++, 1));
minor = rdInt(data.mid(pos++, 1));
intSz = rdInt(data.mid(pos++, 1));
keyLen = rdInt(data.mid(pos++, 1));
flgs = rdInt(data.mid(pos, 4));
if ((major <= MAX_MAJOR) && (minor <= MAX_MINOR))
{
ret = true;
}
}
return ret;
}
bool Idm::verifyExHeader(const QByteArray &data, int major, int minor)
{
bool ret = false;
if (data.startsWith(TAG) && (data.size() == 11))
{
int pos = TAG.size();
int ma = rdInt(data.mid(pos++, 1));
int mi = rdInt(data.mid(pos++, 1));
ret = ((ma <= major) && (mi <= minor));
}
return ret;
}
QByteArray Idm::buildHeader(int major, int minor, int intSz, int flgs, int keyLen)
{
QByteArray ret = TAG;
ret.append(wrInt(major, 1));
ret.append(wrInt(minor, 1));
ret.append(wrInt(intSz, 1));
ret.append(wrInt(keyLen, 1));
ret.append(wrInt(flgs, 4));
return ret;
}
void Idm::setKeyLen(int len)
{
op(SET_KEY_LEN, QByteArray(), QByteArray(), 0, len);
}
void Idm::setFlags(int flgs)
{
op(SET_FLAGS, QByteArray(), QByteArray(), 0, flgs);
}
void Idm::wrHeader()
{
op(WR_HEADER);
}
void Idm::setIntSize(int bytes)
{
op(SET_INT_SIZE, QByteArray(), QByteArray(), 0, bytes);
}
void Idm::setVersion(int major, int minor)
{
op(SET_VERSION, QByteArray(), QByteArray(), 0, major, minor);
}
QByteArray Idm::rdData(int addr, int len, bool *ret)
{
bool ok = false;
if ((addr < buffPtr.size()) && (addr >= 0))
{
if ((len + addr) <= buffPtr.size())
{
ok = true;
}
}
if (ret) *ret = ok;
if (ok)
{
return QByteArray::fromRawData(buffPtr.data() + addr, len);
}
else
{
return QByteArray();
}
}
bool Idm::findKey(int &addr, int &dataLen, const QByteArray &key)
{
bool ok = true;
bool found = false;
while(addr < buffPtr.size() && ok)
{
int keySize;
if (flags & FIXED_KEY_LEN)
{
keySize = keyLen;
}
else
{
keySize = rdInt(rdData(addr, intSize, &ok));
addr += intSize;
}
if (ok)
{
if (key == rdData(addr, keySize, &ok))
{
found = true;
}
addr += keySize;
if (ok)
{
dataLen = rdInt(rdData(addr, intSize, &ok));
addr += intSize;
if (found && ok)
{
break;
}
else
{
addr += dataLen;
}
}
}
}
return found;
}
QByteArray Idm::value(const QByteArray &key)
{
QByteArray ret;
op(RD_VALUE, key, QByteArray(), &ret);
return ret;
}
QByteArray Idm::value(quint64 key)
{
int keySize;
if (flags & FIXED_KEY_LEN) keySize = keyLen;
else keySize = intSize;
return value(wrInt(key, keySize));
}
quint64 Idm::intValue(const QByteArray &key)
{
return rdInt(value(key));
}
quint64 Idm::intValue(quint64 key)
{
return rdInt(value(key));
}
bool Idm::remove(const QByteArray &key)
{
bool ret;
op(RM_VALUE, key, QByteArray(), 0, 0, 0, &ret);
return ret;
}
bool Idm::remove(quint64 key)
{
int keySize;
if (flags & FIXED_KEY_LEN) keySize = keyLen;
else keySize = intSize;
return remove(wrInt(key, keySize));
}
bool Idm::insert(const QByteArray &key, const QByteArray &data)
{
bool ret;
op(WR_VALUE, key, data, 0, 0, 0, &ret);
return ret;
}
bool Idm::insert(quint64 key, quint64 num)
{
int keySize;
if (flags & FIXED_KEY_LEN) keySize = keyLen;
else keySize = intSize;
return insert(wrInt(key, keySize), wrInt(num, intSize));
}
bool Idm::insert(quint64 key, const QByteArray &data)
{
int keySize;
if (flags & FIXED_KEY_LEN) keySize = keyLen;
else keySize = intSize;
return insert(wrInt(key, keySize), data);
}
void Idm::op(Operation opr,
const QByteArray &inA,
const QByteArray &inB,
QByteArray *out,
int intA,
int intB,
bool *ok)
{
QMutex m;
m.lock();
switch(opr)
{
case SET_KEY_LEN:
{
keyLen = intA; break;
}
case SET_FLAGS:
{
flags = intA; break;
}
case GET_BUFF:
{
out = &buffPtr; break;
}
case RELOAD:
{
buffPtr = inA; break;
}
case SET_INT_SIZE:
{
intSize = intA; break;
}
case SET_VERSION:
{
CURRENT_MAJOR = intA;
CURRENT_MINOR = intB;
break;
}
case WR_HEADER:
{
if (buffPtr.startsWith(TAG))
{
int pos = TAG.size();
buffPtr.replace(pos++, 1, wrInt(CURRENT_MAJOR, 1));
buffPtr.replace(pos++, 1, wrInt(CURRENT_MINOR, 1));
buffPtr.replace(pos++, 1, wrInt(intSize, 1));
buffPtr.replace(pos++, 1, wrInt(keyLen, 1));
buffPtr.replace(pos++, 4, wrInt(flags, 4));
}
else
{
buffPtr.insert(0, wrInt(flags, 4));
buffPtr.insert(0, wrInt(keyLen, 1));
buffPtr.insert(0, wrInt(intSize, 1));
buffPtr.insert(0, wrInt(CURRENT_MINOR, 1));
buffPtr.insert(0, wrInt(CURRENT_MAJOR, 1));
buffPtr.insert(0, TAG);
}
header = 8 + TAG.size();
break;
}
case RD_HEADER:
{
*ok = rdExHeader(inA, CURRENT_MAJOR, CURRENT_MINOR, intSize, flags, keyLen);
if (*ok) header = 8 + TAG.size();
break;
}
case RD_VALUE:
{
int pos = header;
int len = 0;
if (findKey(pos, len, inA))
{
out->clear();
out->append(buffPtr.mid(pos, len));
}
break;
}
case RM_VALUE:
{
int pos = header;
int len = 0;
*ok = false;
if (findKey(pos, len, inA))
{
if (flags & FIXED_KEY_LEN)
{
pos -= keyLen + intSize;
len += keyLen + intSize;
}
else
{
pos -= inA.size() + (intSize * 2);
len += inA.size() + (intSize * 2);
}
buffPtr.remove(pos, len);
*ok = true;
}
break;
}
case WR_VALUE:
{
*ok = false;
remove(inA);
if (flags & FIXED_KEY_LEN)
{
if (inA.size() == keyLen)
{
buffPtr.append(inA + wrInt(inB.size(), intSize) + inB);
*ok = true;
}
}
else
{
if (!inA.isEmpty())
{
buffPtr.append(wrInt(inA.size(), intSize) + inA);
buffPtr.append(wrInt(inB.size(), intSize) + inB);
*ok = true;
}
}
break;
}
}
m.unlock();
}