Skip to content

Commit

Permalink
implementing the soundwave functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
wwmm committed Jun 8, 2024
1 parent f50282c commit 08860eb
Show file tree
Hide file tree
Showing 11 changed files with 509 additions and 190 deletions.
1 change: 1 addition & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ kde_target_enable_exceptions(eyeofsauron PRIVATE)
target_sources(eyeofsauron PRIVATE
frame_source.cpp
main.cpp
sound_wave.cpp
tracker.cpp
util.cpp
resources.qrc
Expand Down
15 changes: 15 additions & 0 deletions src/contents/ui/SoundWave.qml
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import EoSSoundBackend
import EoSdb
import EosSoundSourceModel
import QtCharts
import QtQuick
import QtQuick.Controls as Controls
Expand All @@ -10,6 +12,11 @@ Kirigami.ScrollablePage {

title: i18n("Sound Wave")
actions: [
Kirigami.Action {
text: i18n("Audio Source")
icon.name: "emblem-music-symbolic"
onTriggered: sourceMenu.open()
},
Kirigami.Action {
icon.name: "media-playback-start-symbolic"
text: i18nc("@action:button", "Play")
Expand All @@ -24,6 +31,14 @@ Kirigami.ScrollablePage {
}
]

SourceMenu {
id: sourceMenu

backend: EoSSoundBackend
model: EosSoundSourceModel
backendName: "sound_wave"
}

ColumnLayout {
anchors.fill: parent

Expand Down
7 changes: 4 additions & 3 deletions src/contents/ui/SourceMenu.qml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Kirigami.OverlaySheet {

property var backend: null
property var model: null
property string backendName

showCloseButton: false
implicitWidth: Kirigami.Units.gridUnit * 30
Expand Down Expand Up @@ -123,7 +124,7 @@ Kirigami.OverlaySheet {

fileMode: FileDialog.OpenFile
currentFolder: StandardPaths.standardLocations(StandardPaths.MoviesLocation)[0]
nameFilters: ["Video files (*.*)"]
nameFilters: backendName === "tracker" ? ["Video files (*.*)"] : ["Audio files (*.*)"]
onAccepted: {
backend.append(fileDialog.selectedFile);
}
Expand All @@ -133,8 +134,8 @@ Kirigami.OverlaySheet {
alignment: Qt.AlignCenter
actions: [
Kirigami.Action {
text: i18n("Add Video File")
icon.name: "video-symbolic"
text: backendName === "tracker" ? i18n("Add Video File") : i18n("Add Audio File")
icon.name: backendName === "tracker" ? "video-symbolic" : "emblem-music-symbolic"
onTriggered: {
fileDialog.open();
}
Expand Down
3 changes: 2 additions & 1 deletion src/contents/ui/Tracker.qml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Kirigami.ScrollablePage {
actions: [
Kirigami.Action {
text: i18n("Video Source")
icon.name: "camera-web-symbolic"
icon.name: "video-symbolic"
onTriggered: sourceMenu.open()
},
Kirigami.Action {
Expand Down Expand Up @@ -54,6 +54,7 @@ Kirigami.ScrollablePage {

backend: EoSTrackerBackend
model: EosTrackerSourceModel
backendName: "tracker"
}

FileDialog {
Expand Down
190 changes: 189 additions & 1 deletion src/frame_source.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
#include "frame_source.hpp"
#include <qabstractitemmodel.h>
#include <qbytearray.h>
#include <qdebug.h>
#include <qhash.h>
#include <qlist.h>
#include <qlogging.h>
#include <qtmetamacros.h>
#include <qvariant.h>
#include <cmath>
#include <format>
#include <iterator>
#include <memory>
#include <string>
#include <utility>
#define _UNICODE
Expand Down Expand Up @@ -58,4 +66,184 @@ MediaFileSource::MediaFileSource(QUrl file_url) : Source(SourceType::MediaFile),
util::warning("failed to get media information");
}
}
}
}

int SourceModel::rowCount(const QModelIndex& /*parent*/) const {
return list.size();
}

QHash<int, QByteArray> SourceModel::roleNames() const {
return {
{Roles::SourceType, "sourceType"}, {Roles::Name, "name"}, {Roles::Subtitle, "subtitle"}, {Roles::Icon, "icon"}};
}

QVariant SourceModel::data(const QModelIndex& index, int role) const {
if (list.empty()) {
return "";
}

const auto it = std::next(list.begin(), index.row());

switch (role) {
case Roles::SourceType: {
QString value;

switch (it->get()->source_type) {
case Camera: {
value = "camera";

break;
}
case MediaFile: {
value = "media_file";

break;
}
case Microphone: {
value = "microphone";

break;
}
}

return value;
}
case Roles::Name: {
QString value;

switch (it->get()->source_type) {
case Camera: {
value = dynamic_cast<const CameraSource*>(it->get())->device.description();

break;
}
case MediaFile: {
value = dynamic_cast<const MediaFileSource*>(it->get())->url.fileName();

break;
}
case Microphone: {
value = dynamic_cast<const MicSource*>(it->get())->device.description();

break;
}
}

return value;
}
case Roles::Subtitle: {
QString value;

switch (it->get()->source_type) {
case Camera: {
auto format = dynamic_cast<const CameraSource*>(it->get())->format;

if (!format.isNull()) {
auto resolution = util::to_string(format.resolution().width()) + "x" +
util::to_string(format.resolution().height()) + " " +
util::to_string(format.maxFrameRate()) + " fps";

value = QString::fromStdString(resolution);
}

break;
}
case MediaFile: {
auto file_size_mb = dynamic_cast<const MediaFileSource*>(it->get())->file_size_mb;
auto duration = dynamic_cast<const MediaFileSource*>(it->get())->duration;
auto frame_rate = dynamic_cast<const MediaFileSource*>(it->get())->frame_rate;

value = frame_rate + " fps" + ", " + file_size_mb + " MiB" + ", " + duration;

break;
}
case Microphone: {
auto format = dynamic_cast<const MicSource*>(it->get())->format;

if (format.isValid()) {
auto resolution = util::to_string(format.sampleRate()) + " Hz, " + util::to_string(format.sampleFormat());

value = QString::fromStdString(resolution);
}

break;
}
}

return value;
}
case Roles::Icon: {
QString name;

switch (it->get()->source_type) {
case Camera: {
name = "camera-web-symbolic";

break;
}
case MediaFile: {
name = "video-symbolic";

break;
}
case Microphone: {
name = "audio-input-microphone-symbolic";

break;
}
}

return name;
}
default:
return {};
}
}

auto SourceModel::getList() -> QList<std::shared_ptr<Source>> {
return list;
}

auto SourceModel::get_source(const int& rowIndex) -> std::shared_ptr<Source> {
return list[rowIndex];
}

void SourceModel::append(std::shared_ptr<Source> source) {
int pos = list.empty() ? 0 : list.size() - 1;

beginInsertRows(QModelIndex(), pos, pos);

switch (source->source_type) {
case Camera:
list.insert(0, source);
break;
case MediaFile:
list.append(source);
break;
case Microphone:
list.append(source);
break;
}

endInsertRows();

emit dataChanged(index(0), index(list.size() - 1));
}

void SourceModel::reset() {
beginResetModel();

list.clear();

endResetModel();
}

void SourceModel::removeSource(const int& rowIndex) {
beginRemoveRows(QModelIndex(), rowIndex, rowIndex);

list.remove(rowIndex);

endRemoveRows();

emit dataChanged(index(0), index(list.size() - 1));
}
49 changes: 47 additions & 2 deletions src/frame_source.hpp
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
#pragma once

#include <qabstractitemmodel.h>
#include <qaudioformat.h>
#include <qbytearray.h>
#include <qcameradevice.h>
#include <qhash.h>
#include <qlist.h>
#include <qnamespace.h>
#include <qstring.h>
#include <qtmetamacros.h>
#include <qurl.h>
#include <qvariant.h>
#include <QAudioDevice>
#include <memory>

enum SourceType { Camera, MediaFile };
enum SourceType { Camera, MediaFile, Microphone };

class Source {
public:
Expand Down Expand Up @@ -36,4 +46,39 @@ class MediaFileSource : public Source {
QString duration;

QString frame_rate;
};
};

class MicSource : public Source {
public:
MicSource(QAudioDevice dev, QAudioFormat fmt);

QAudioDevice device;

QAudioFormat format;
};

class SourceModel : public QAbstractListModel {
Q_OBJECT;

public:
enum Roles { SourceType = Qt::UserRole, Name, Subtitle, Icon = Qt::DecorationRole };

[[nodiscard]] int rowCount(const QModelIndex& /*parent*/) const override;

[[nodiscard]] QHash<int, QByteArray> roleNames() const override;

[[nodiscard]] QVariant data(const QModelIndex& index, int role) const override;

auto getList() -> QList<std::shared_ptr<Source>>;

auto get_source(const int& rowIndex) -> std::shared_ptr<Source>;

void reset();

void append(std::shared_ptr<Source> source);

Q_INVOKABLE void removeSource(const int& rowIndex);

private:
QList<std::shared_ptr<Source>> list;
};
2 changes: 2 additions & 0 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <memory>
#include "config.h"
#include "eyeofsauron_db.h"
#include "sound_wave.hpp"
#include "tracker.hpp"
#include "util.hpp"

Expand Down Expand Up @@ -99,6 +100,7 @@ int main(int argc, char* argv[]) {
// loading classes

tracker::Backend tracker;
sound::Backend sound;

QQmlApplicationEngine engine;

Expand Down
Loading

0 comments on commit 08860eb

Please sign in to comment.