diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt
index 8abc90033..dbc42a041 100644
--- a/app/CMakeLists.txt
+++ b/app/CMakeLists.txt
@@ -19,6 +19,8 @@ set(OLIVE_SOURCES
core.h
core.cpp
main.cpp
+ rational.h
+ rational.cpp
)
#add_subdirectory(decoder)
diff --git a/app/project/CMakeLists.txt b/app/project/CMakeLists.txt
index bceeb1898..1b9763aba 100644
--- a/app/project/CMakeLists.txt
+++ b/app/project/CMakeLists.txt
@@ -14,12 +14,10 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
+add_subdirectory(item)
+
set(OLIVE_SOURCES
${OLIVE_SOURCES}
- project/folder.h
- project/folder.cpp
- project/item.h
- project/item.cpp
project/project.h
project/project.cpp
project/projectviewmodel.h
diff --git a/app/project/item/CMakeLists.txt b/app/project/item/CMakeLists.txt
new file mode 100644
index 000000000..457197f1b
--- /dev/null
+++ b/app/project/item/CMakeLists.txt
@@ -0,0 +1,25 @@
+# Olive - Non-Linear Video Editor
+# Copyright (C) 2019 Olive Team
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+add_subdirectory(folder)
+add_subdirectory(footage)
+
+set(OLIVE_SOURCES
+ ${OLIVE_SOURCES}
+ project/item/item.h
+ project/item/item.cpp
+ PARENT_SCOPE
+)
diff --git a/app/project/item/folder/CMakeLists.txt b/app/project/item/folder/CMakeLists.txt
new file mode 100644
index 000000000..b055fbeb5
--- /dev/null
+++ b/app/project/item/folder/CMakeLists.txt
@@ -0,0 +1,23 @@
+# Olive - Non-Linear Video Editor
+# Copyright (C) 2019 Olive Team
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+
+set(OLIVE_SOURCES
+ ${OLIVE_SOURCES}
+ project/item/folder/folder.h
+ project/item/folder/folder.cpp
+ PARENT_SCOPE
+)
diff --git a/app/project/folder.cpp b/app/project/item/folder/folder.cpp
similarity index 100%
rename from app/project/folder.cpp
rename to app/project/item/folder/folder.cpp
diff --git a/app/project/folder.h b/app/project/item/folder/folder.h
similarity index 83%
rename from app/project/folder.h
rename to app/project/item/folder/folder.h
index 24daf2da1..7a8bc07df 100644
--- a/app/project/folder.h
+++ b/app/project/item/folder/folder.h
@@ -1,7 +1,7 @@
#ifndef FOLDER_H
#define FOLDER_H
-#include "item.h"
+#include "project/item/item.h"
class Folder : public Item
{
diff --git a/app/project/item/footage/CMakeLists.txt b/app/project/item/footage/CMakeLists.txt
new file mode 100644
index 000000000..a6972cbd0
--- /dev/null
+++ b/app/project/item/footage/CMakeLists.txt
@@ -0,0 +1,27 @@
+# Olive - Non-Linear Video Editor
+# Copyright (C) 2019 Olive Team
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+
+set(OLIVE_SOURCES
+ ${OLIVE_SOURCES}
+ project/item/footage/audiostream.h
+ project/item/footage/audiostream.cpp
+ project/item/footage/footage.h
+ project/item/footage/footage.cpp
+ project/item/footage/videostream.h
+ project/item/footage/videostream.cpp
+ PARENT_SCOPE
+)
diff --git a/app/project/item/footage/audiostream.cpp b/app/project/item/footage/audiostream.cpp
new file mode 100644
index 000000000..7174491e3
--- /dev/null
+++ b/app/project/item/footage/audiostream.cpp
@@ -0,0 +1,53 @@
+#include "audiostream.h"
+
+AudioStream::AudioStream(Footage* footage,
+ const int& channels,
+ const int& layout,
+ const int& sample_rate) :
+ footage_(footage),
+ channels_(channels),
+ layout_(layout),
+ sample_rate_(sample_rate)
+{
+
+}
+
+Footage *AudioStream::footage()
+{
+ return footage_;
+}
+
+void AudioStream::set_footage(Footage *f)
+{
+ footage_ = f;
+}
+
+const int &AudioStream::channels()
+{
+ return channels_;
+}
+
+void AudioStream::set_channels(const int &channels)
+{
+ channels_ = channels;
+}
+
+const int &AudioStream::layout()
+{
+ return layout_;
+}
+
+void AudioStream::set_layout(const int &layout)
+{
+ layout_ = layout;
+}
+
+const int &AudioStream::sample_rate()
+{
+ return sample_rate_;
+}
+
+void AudioStream::set_sample_rate(const int &sample_rate)
+{
+ sample_rate_ = sample_rate;
+}
diff --git a/app/project/item/footage/audiostream.h b/app/project/item/footage/audiostream.h
new file mode 100644
index 000000000..7c886f9b5
--- /dev/null
+++ b/app/project/item/footage/audiostream.h
@@ -0,0 +1,33 @@
+#ifndef AUDIOSTREAM_H
+#define AUDIOSTREAM_H
+
+#include "rational.h"
+
+class Footage;
+
+class AudioStream
+{
+public:
+ AudioStream(Footage* footage, const int& channels, const int& layout, const int& sample_rate);
+
+ Footage* footage();
+ void set_footage(Footage* f);
+
+ const int& channels();
+ void set_channels(const int& channels);
+
+ const int& layout();
+ void set_layout(const int& layout);
+
+ const int& sample_rate();
+ void set_sample_rate(const int& sample_rate);
+
+private:
+ Footage* footage_;
+
+ int channels_;
+ int layout_;
+ int sample_rate_;
+};
+
+#endif // AUDIOSTREAM_H
diff --git a/app/project/item/footage/footage.cpp b/app/project/item/footage/footage.cpp
new file mode 100644
index 000000000..b83449d98
--- /dev/null
+++ b/app/project/item/footage/footage.cpp
@@ -0,0 +1,21 @@
+#include "footage.h"
+
+Footage::Footage()
+{
+
+}
+
+const QString &Footage::filename()
+{
+ return filename_;
+}
+
+void Footage::set_filename(const QString &s)
+{
+ filename_ = s;
+}
+
+Item::Type Footage::type() const
+{
+ return kFootage;
+}
diff --git a/app/project/item/footage/footage.h b/app/project/item/footage/footage.h
new file mode 100644
index 000000000..9e169c04f
--- /dev/null
+++ b/app/project/item/footage/footage.h
@@ -0,0 +1,27 @@
+#ifndef FOOTAGE_H
+#define FOOTAGE_H
+
+#include "project/item/item.h"
+#include "project/item/footage/audiostream.h"
+#include "project/item/footage/videostream.h"
+
+#include
+
+class Footage : public Item
+{
+public:
+ Footage();
+
+ const QString& filename();
+ void set_filename(const QString& s);
+
+ virtual Type type() const override;
+
+private:
+ QString filename_;
+
+ QList video_streams_;
+ QList audio_streams_;
+};
+
+#endif // FOOTAGE_H
diff --git a/app/project/item/footage/videostream.cpp b/app/project/item/footage/videostream.cpp
new file mode 100644
index 000000000..ada80cff8
--- /dev/null
+++ b/app/project/item/footage/videostream.cpp
@@ -0,0 +1,64 @@
+#include "videostream.h"
+
+VideoStream::VideoStream(Footage *footage,
+ const int &index,
+ const int &width,
+ const int &height,
+ const rational &timebase) :
+ footage_(footage),
+ index_(index),
+ width_(width),
+ height_(height),
+ timebase_(timebase)
+{
+}
+
+Footage *VideoStream::footage()
+{
+ return footage_;
+}
+
+void VideoStream::set_footage(Footage *f)
+{
+ footage_ = f;
+}
+
+const int &VideoStream::index()
+{
+ return index_;
+}
+
+void VideoStream::set_index(const int &index)
+{
+ index_ = index;
+}
+
+const int &VideoStream::width()
+{
+ return width_;
+}
+
+void VideoStream::set_width(const int &width)
+{
+ width_ = width;
+}
+
+const int &VideoStream::height()
+{
+ return height_;
+}
+
+void VideoStream::set_height(const int &height)
+{
+ height_ = height;
+}
+
+const rational &VideoStream::timebase()
+{
+ return timebase_;
+}
+
+void VideoStream::set_timebase(const rational &timebase)
+{
+ timebase_ = timebase;
+}
diff --git a/app/project/item/footage/videostream.h b/app/project/item/footage/videostream.h
new file mode 100644
index 000000000..e5a57ca61
--- /dev/null
+++ b/app/project/item/footage/videostream.h
@@ -0,0 +1,37 @@
+#ifndef VIDEOSTREAM_H
+#define VIDEOSTREAM_H
+
+#include "rational.h"
+
+class Footage;
+
+class VideoStream
+{
+public:
+ VideoStream(Footage* footage, const int& index, const int& width, const int& height, const rational& timebase);
+
+ Footage* footage();
+ void set_footage(Footage* f);
+
+ const int& index();
+ void set_index(const int& index);
+
+ const int& width();
+ void set_width(const int& width);
+
+ const int& height();
+ void set_height(const int& height);
+
+ const rational& timebase();
+ void set_timebase(const rational& timebase);
+
+private:
+ Footage* footage_;
+
+ int index_;
+ int width_;
+ int height_;
+ rational timebase_;
+};
+
+#endif // VIDEOSTREAM_H
diff --git a/app/project/item.cpp b/app/project/item/item.cpp
similarity index 88%
rename from app/project/item.cpp
rename to app/project/item/item.cpp
index 4814b0f95..2b82cf023 100644
--- a/app/project/item.cpp
+++ b/app/project/item/item.cpp
@@ -7,6 +7,10 @@ Item::Item() :
Item::~Item()
{
+ // Delete all children
+ for (int i=0;i
#include
-#include "folder.h"
+#include "project/item/folder/folder.h"
class Project : public QObject
{
diff --git a/app/rational.cpp b/app/rational.cpp
new file mode 100644
index 000000000..e6df7a871
--- /dev/null
+++ b/app/rational.cpp
@@ -0,0 +1,377 @@
+#include "rational.h"
+
+rational::rational(const int64_t &numerator) :
+ numerator_(numerator),
+ denominator_(1)
+{
+ if (numerator_ == 0) {
+ denominator_ = 0;
+ }
+}
+
+rational::rational(const int64_t &numerator, const int64_t &denominator) :
+ numerator_(numerator),
+ denominator_(denominator)
+{
+ if (denominator_ != 0) {
+
+ if (numerator_ != 0) {
+ FixSigns();
+ Reduce();
+ } else {
+ denominator_ = 0;
+ }
+
+ } else {
+ numerator_ = 0;
+ }
+}
+
+rational::rational(const AVRational &r) :
+ numerator_(r.num),
+ denominator_(r.den)
+{
+}
+
+rational::rational(const rational &r) :
+ numerator_(r.numerator_),
+ denominator_(r.denominator_)
+{
+}
+
+const rational &rational::operator=(const rational &r)
+{
+ if (this != &r) {
+ numerator_ = r.numerator_;
+ denominator_ = r.denominator_;
+ }
+
+ return *this;
+}
+
+const rational &rational::operator+=(const rational &r)
+{
+ if (numerator_ * denominator_ == 0 && r.numerator_ * r.denominator_ == 0) {
+ numerator_ = 0;
+ denominator_ = 0;
+ } else {
+ if(numerator_ * denominator_ != 0 && r.numerator_ * r.denominator_ == 0) {
+ // The other rational == 0, no addition needs to be done
+ } else {
+ if(numerator_ * denominator_ == 0 && r.numerator_ * r.denominator_ != 0)
+ {
+ numerator_ = r.numerator_;
+ denominator_ = r.denominator_;
+ }
+ else
+ {
+ numerator_ = (numerator_ * r.denominator_) + (r.numerator_ * denominator_);
+ denominator_ = denominator_ * r.denominator_;
+ FixSigns();
+ Reduce();
+ }
+ }
+ }
+ return *this;
+}
+
+const rational &rational::operator-=(const rational &r)
+{
+ if(numerator_ * denominator_ == 0 && r.numerator_ * r.numerator_ == 0) {
+ numerator_ = 0;
+ denominator_ = 0;
+ } else {
+ if(numerator_ * denominator_ != 0 && r.numerator_ * r.denominator_ == 0) {
+
+ } else {
+ if(numerator_ * denominator_ == 0 && r.numerator_ * r.denominator_ != 0) {
+ numerator_ = -(r.numerator_);
+ denominator_ = r.denominator_;
+ } else {
+ numerator_ = (numerator_ * r.denominator_) - (r.numerator_ * denominator_);
+ numerator_ = denominator_ * r.denominator_;
+ FixSigns();
+ Reduce();
+ }
+ }
+ }
+ return *this;
+}
+
+const rational &rational::operator/=(const rational &r)
+{
+ numerator_ = numerator_ * r.denominator_;
+ denominator_ = denominator_ * r.numerator_;
+ FixSigns();
+ Reduce();
+ return *this;
+}
+
+const rational &rational::operator*=(const rational &r)
+{
+ numerator_ = numerator_ * r.numerator_;
+ denominator_ = denominator_ * r.denominator_;
+ FixSigns();
+ Reduce();
+ return *this;
+}
+
+rational rational::operator+(const rational &r) const
+{
+ rational result(*this);
+ result += r;
+ return result;
+}
+
+rational rational::operator-(const rational &r) const
+{
+ rational result(*this);
+ result -= r;
+ return result;
+}
+
+rational rational::operator/(const rational &r) const
+{
+ rational result(*this);
+ result /= r;
+ return result;
+}
+
+rational rational::operator*(const rational &r) const
+{
+ rational result(*this);
+ result *= r;
+ return result;
+}
+
+bool rational::operator<(const rational &r) const
+{
+ if (numerator_ * denominator_ == 0 && r.numerator_ * r.denominator_ == 0) {
+ return false;
+ } else {
+ if (numerator_ * denominator_ != 0 && r.numerator_ * r.denominator_ == 0) {
+ if(numerator_ * denominator_ < 0)
+ return true;
+ else
+ return false;
+ }
+ else {
+ if (numerator_ * denominator_ == 0 && r.numerator_ * r.denominator_ != 0) {
+ if (r.numerator_ * r.denominator_ < 0) {
+ return false;
+ } else {
+ return true;
+ }
+ } else {
+ return ((numerator_ * r.denominator_) < (denominator_ * r.numerator_));
+ }
+ }
+ }
+}
+
+bool rational::operator<=(const rational &r) const
+{
+ if(numerator_ * denominator_ == 0 && r.numerator_ * r.denominator_ == 0) {
+ return true;
+ } else {
+ if(numerator_ * denominator_ != 0 && r.numerator_ * r.denominator_ == 0) {
+ if(numerator_ * denominator_ < 0) {
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ if(numerator_ * denominator_ == 0 && r.numerator_ * r.denominator_ != 0) {
+ if(r.numerator_ * r.denominator_ < 0) {
+ return false;
+ } else {
+ return true;
+ }
+ } else {
+ return ((numerator_ * r.denominator_) <= (denominator_ * r.numerator_));
+ }
+ }
+ }
+}
+
+bool rational::operator>(const rational &r) const
+{
+ if(numerator_ * denominator_ == 0 && r.numerator_ * r.denominator_ == 0) {
+ return false;
+ } else {
+ if(numerator_ * denominator_ != 0 && r.numerator_ * r.denominator_ == 0) {
+ if(numerator_ * denominator_ > 0) {
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ if(numerator_ * denominator_ == 0 && r.numerator_ * r.denominator_ != 0) {
+ if(r.numerator_ * r.denominator_ > 0) {
+ return false;
+ } else {
+ return true;
+ }
+ } else {
+ return ((numerator_ * r.denominator_) > (denominator_ * r.numerator_));
+ }
+ }
+ }
+}
+
+bool rational::operator>=(const rational &r) const
+{
+ if(numerator_ * denominator_ == 0 && r.numerator_ * r.denominator_ == 0) {
+ return true;
+ } else {
+ if(numerator_ * denominator_ != 0 && r.numerator_ * r.denominator_ == 0) {
+ if(numerator_ * denominator_ > 0) {
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ if(numerator_ * denominator_ == 0 && r.numerator_ * r.denominator_ != 0) {
+ if(r.numerator_ * r.denominator_ > 0) {
+ return false;
+ } else {
+ return true;
+ }
+ } else {
+ return ((numerator_ * r.denominator_) >= (denominator_ * r.numerator_));
+ }
+ }
+ }
+}
+
+bool rational::operator==(const rational &r) const
+{
+ return (numerator_ == r.numerator_ && denominator_ == r.denominator_);
+}
+
+bool rational::operator!=(const rational &r) const
+{
+ return (numerator_ != r.numerator_) || (denominator_ != r.denominator_);
+}
+
+const rational &rational::operator++()
+{
+ numerator_ += denominator_;
+ return *this;
+}
+
+rational rational::operator++(int)
+{
+ rational tmp = *this;
+ numerator_ += denominator_;
+ return tmp;
+}
+
+const rational &rational::operator--()
+{
+ numerator_ -= denominator_;
+ return *this;
+}
+
+rational rational::operator--(int)
+{
+ rational tmp;
+ numerator_ -= denominator_;
+ return tmp;
+}
+
+const rational &rational::operator+() const
+{
+ return *this;
+}
+
+rational rational::operator-() const
+{
+ return rational(numerator_, -denominator_);
+}
+
+bool rational::operator!() const
+{
+ return !numerator_;
+}
+
+double rational::ToDouble() const
+{
+ if (denominator_ == 0) {
+ return 0;
+ } else {
+ return static_cast(numerator_)/static_cast(denominator_);
+ }
+}
+
+void rational::FixSigns()
+{
+ // Ensures denominator is always positive (while numerator can be positive or negative)
+ if(denominator_ < 0) {
+ denominator_ = -denominator_;
+ numerator_ = -numerator_;
+ }
+
+ // Ensures if either are zero, they're both zero
+ if(numerator_ == 0 || denominator_ == 0) {
+ numerator_ = 0;
+ denominator_ = 0;
+ }
+}
+
+void rational::Reduce()
+{
+ int64_t d = 1;
+
+ if(denominator_ != 0 && numerator_ != 0) {
+ d = GreatestCommonDenominator(numerator_, denominator_);
+ }
+
+ if(d > 1) {
+ numerator_ /= d;
+ denominator_ /= d;
+ }
+}
+
+int64_t rational::GreatestCommonDenominator(const int64_t& x, const int64_t& y)
+{
+ if (y == 0) {
+ return x;
+ } else {
+ int64_t tmp = x % y;
+ return GreatestCommonDenominator(y, tmp);
+ }
+}
+
+std::ostream &operator<<(std::ostream &out, const rational &value)
+{
+ out << value.numerator_;
+ if(value.denominator_ != 1)
+ {
+ out << '/' << value.denominator_;
+ return out;
+ }
+ return out;
+}
+
+std::istream &operator>>(std::istream &in, rational &value)
+{
+ in >> value.numerator_;
+ value.denominator_ = 1;
+
+ char ch;
+ in.get(ch);
+
+ if(!in.eof())
+ {
+ if(ch == '/')
+ {
+ in >> value.denominator_;
+ value.FixSigns();
+ value.Reduce();
+ }
+ else
+ in.putback(ch);
+ }
+ return in;
+}
diff --git a/app/rational.h b/app/rational.h
new file mode 100644
index 000000000..4a314757c
--- /dev/null
+++ b/app/rational.h
@@ -0,0 +1,65 @@
+#ifndef RATIONAL_H
+#define RATIONAL_H
+
+// Adapted from https://github.com/angularadam/Qt-Class-rational used in compliance with the GNU General Public License
+
+#include
+
+extern "C" {
+ #include
+}
+
+class rational {
+public:
+ // Constructors
+ rational(const int64_t& numerator = 0);
+ rational(const int64_t& numerator, const int64_t& denominator);
+ rational(const AVRational& r); // Auto-convert from an FFmpeg AVRational
+ rational(const rational& r);
+
+ // Assignment Operators
+ const rational& operator=(const rational& r);
+ const rational& operator+=(const rational& r);
+ const rational& operator-=(const rational& r);
+ const rational& operator/=(const rational& r);
+ const rational& operator*=(const rational& r);
+
+ // Math Operators
+ rational operator+(const rational& r) const;
+ rational operator-(const rational& r) const;
+ rational operator/(const rational& r) const;
+ rational operator*(const rational& r) const;
+
+ // Relational and Equality Operators
+ bool operator<(const rational &r) const;
+ bool operator<=(const rational &r) const;
+ bool operator>(const rational &r) const;
+ bool operator>=(const rational &r) const;
+ bool operator==(const rational &r) const;
+ bool operator!=(const rational &r) const;
+
+ //Unary operators
+ const rational& operator++(); //prefix
+ rational operator++(int); //postfix
+ const rational& operator--(); //prefix
+ rational operator--(int); //postfix
+ const rational& operator+() const;
+ rational operator-() const;
+ bool operator!() const;
+
+ // IO
+ friend std::ostream& operator<<(std::ostream &out, const rational& value);
+ friend std::istream& operator>>(std::istream &in, rational& value);
+
+ // Convert to double
+ double ToDouble() const;
+private:
+ int64_t numerator_;
+ int64_t denominator_;
+
+ void FixSigns();
+ void Reduce();
+ int64_t GreatestCommonDenominator(const int64_t &x, const int64_t &y);
+};
+
+#endif // RATIONAL_H