Barely working basic playback
This commit is contained in:
parent
98a443e298
commit
9b5198a6ce
19 changed files with 406 additions and 24 deletions
80
lib/wModel/file/audio.cpp
Normal file
80
lib/wModel/file/audio.cpp
Normal file
|
@ -0,0 +1,80 @@
|
|||
#include "audio.h"
|
||||
|
||||
#include <mad.h>
|
||||
|
||||
M::Audio::Audio(W::Blob* p_file, const W::Address& addr, QObject* parent):
|
||||
File(p_file, addr, parent),
|
||||
frames()
|
||||
{
|
||||
W::Handler* requestFrames = W::Handler::create(address + W::Address({u"requestFrames"}), this, &M::Audio::_h_requestFrames);
|
||||
|
||||
addHandler(requestFrames);
|
||||
}
|
||||
|
||||
M::Audio::~Audio()
|
||||
{}
|
||||
|
||||
M::Model::ModelType M::Audio::getType() const
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
void M::Audio::initAdditional(const W::String& p_mime)
|
||||
{
|
||||
File::initAdditional(p_mime); //TODO handle other than mp3 formats
|
||||
|
||||
mad_stream stream;
|
||||
mad_header header;
|
||||
mad_stream_init(&stream);
|
||||
mad_header_init(&header);
|
||||
|
||||
mad_stream_buffer(&stream, file->uchar(), file->size());
|
||||
|
||||
uint64_t length = 0;
|
||||
uint64_t tBits = 0;
|
||||
while(stream.error != MAD_ERROR_BUFLEN) { //TODO handle other errors;
|
||||
|
||||
int success = mad_header_decode(&header, &stream);
|
||||
if (success == 0) {
|
||||
frames.emplace_back(stream.this_frame - stream.buffer, stream.next_frame - stream.this_frame);
|
||||
|
||||
length += header.duration.seconds * MAD_TIMER_RESOLUTION + header.duration.fraction;
|
||||
tBits += header.bitrate;
|
||||
}
|
||||
}
|
||||
|
||||
additional.insert(u"duration", new W::Uint64(length / MAD_TIMER_RESOLUTION));
|
||||
additional.insert(u"bitrate", new W::Uint64(tBits / frames.size()));
|
||||
additional.insert(u"framesAmount", new W::Uint64(frames.size()));
|
||||
}
|
||||
|
||||
void M::Audio::h_requestFrames(const W::Event& ev)
|
||||
{
|
||||
const W::Vocabulary& vc = static_cast<const W::Vocabulary&>(ev.getData());
|
||||
const W::Uint64& index = static_cast<const W::Uint64&>(vc.at(u"index"));
|
||||
const W::Uint64& amount = static_cast<const W::Uint64&>(vc.at(u"amount"));
|
||||
|
||||
W::Vocabulary* evc = new W::Vocabulary();
|
||||
if (index + amount > frames.size()) {
|
||||
evc->insert(u"result", new W::Uint64(1));
|
||||
} else {
|
||||
evc->insert(u"result", new W::Uint64(0));
|
||||
uint64_t start = 0;
|
||||
uint64_t size = 0;
|
||||
bool first = true;
|
||||
for (int i = 0; i < amount; ++i) {
|
||||
const std::pair<uint64_t, uint64_t>& pair = frames[index + i];
|
||||
if (first) {
|
||||
start = pair.first;
|
||||
first = false;
|
||||
}
|
||||
size += pair.second;
|
||||
}
|
||||
|
||||
evc->insert(u"data", file->slice(start, size));
|
||||
evc->insert(u"amount", new W::Uint64(amount));
|
||||
|
||||
}
|
||||
|
||||
response(evc, W::Address{u"responseFrames"}, ev);
|
||||
}
|
36
lib/wModel/file/audio.h
Normal file
36
lib/wModel/file/audio.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
#ifndef M_AUDIO_H
|
||||
#define M_AUDIO_H
|
||||
|
||||
#include <wModel/file/file.h>
|
||||
|
||||
#include <wType/blob.h>
|
||||
#include <deque>
|
||||
|
||||
namespace M {
|
||||
|
||||
/**
|
||||
* @todo write docs
|
||||
*/
|
||||
class Audio : public File {
|
||||
friend class File;
|
||||
protected:
|
||||
Audio(W::Blob* p_file, const W::Address& addr, QObject* parent = 0);
|
||||
|
||||
public:
|
||||
~Audio();
|
||||
|
||||
M::Model::ModelType getType() const override;
|
||||
static const M::Model::ModelType type = audio;
|
||||
|
||||
protected:
|
||||
void initAdditional(const W::String& p_mime) override;
|
||||
|
||||
handler(requestFrames);
|
||||
|
||||
private:
|
||||
std::deque<std::pair<uint64_t, uint64_t>> frames;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // M_AUDIO_H
|
|
@ -1,7 +1,13 @@
|
|||
#include "file.h"
|
||||
#include <iostream>
|
||||
|
||||
#include "audio.h"
|
||||
|
||||
QMimeDatabase M::File::mimeDB;
|
||||
const std::map<QString, M::Model::ModelType> M::File::mimeMap = {
|
||||
{"image/jpeg", M::Model::file},
|
||||
{"audio/mpeg", M::Model::audio}
|
||||
};
|
||||
|
||||
M::File::File(W::Blob* p_file, const W::Address& addr, QObject* parent):
|
||||
M::Model(addr, parent),
|
||||
|
@ -79,8 +85,24 @@ M::File * M::File::create(W::Blob* blob, const W::Address& addr, QObject* parent
|
|||
M::File* out;
|
||||
|
||||
QMimeType mt = mimeDB.mimeTypeForData(blob->byteArray());
|
||||
out = new File(blob, addr, parent);
|
||||
|
||||
out->initAdditional(W::String(mt.name().toStdString()));
|
||||
const QString& mime = mt.name();
|
||||
std::map<QString, M::Model::ModelType>::const_iterator itr = mimeMap.find(mime);
|
||||
|
||||
M::Model::ModelType modelType = M::Model::file;
|
||||
if (itr != mimeMap.end()) {
|
||||
modelType = itr->second;
|
||||
}
|
||||
|
||||
switch (modelType) {
|
||||
case Model::audio:
|
||||
out = new Audio(blob, addr, parent);
|
||||
break;
|
||||
default:
|
||||
out = new File(blob, addr, parent);
|
||||
break;
|
||||
}
|
||||
|
||||
out->initAdditional(W::String(mime.toStdString()));
|
||||
return out;
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@ namespace M {
|
|||
W::Blob* file;
|
||||
|
||||
static QMimeDatabase mimeDB;
|
||||
static const std::map<QString, M::Model::ModelType> mimeMap;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue