diff --git a/build/Aegisub/Aegisub.vcxproj b/build/Aegisub/Aegisub.vcxproj
index 7a8fce47f..69909ccaa 100644
--- a/build/Aegisub/Aegisub.vcxproj
+++ b/build/Aegisub/Aegisub.vcxproj
@@ -117,7 +117,6 @@
-
@@ -257,7 +256,6 @@
-
diff --git a/build/Aegisub/Aegisub.vcxproj.filters b/build/Aegisub/Aegisub.vcxproj.filters
index 1ea6273f1..9e8c86650 100644
--- a/build/Aegisub/Aegisub.vcxproj.filters
+++ b/build/Aegisub/Aegisub.vcxproj.filters
@@ -150,9 +150,6 @@
-
- ASS
-
ASS
@@ -578,9 +575,6 @@
ASS
-
- ASS
-
Audio\Providers
diff --git a/build/libaegisub/libaegisub.vcxproj b/build/libaegisub/libaegisub.vcxproj
index a5e51e28b..d46c88919 100644
--- a/build/libaegisub/libaegisub.vcxproj
+++ b/build/libaegisub/libaegisub.vcxproj
@@ -61,6 +61,8 @@
+
+
@@ -118,6 +120,7 @@
lagi_pre.h
+
diff --git a/build/libaegisub/libaegisub.vcxproj.filters b/build/libaegisub/libaegisub.vcxproj.filters
index a9dfeba9c..5dee77b43 100644
--- a/build/libaegisub/libaegisub.vcxproj.filters
+++ b/build/libaegisub/libaegisub.vcxproj.filters
@@ -125,6 +125,12 @@
ASS
+
+ ASS
+
+
+ ASS
+
Header Files
@@ -265,6 +271,9 @@
ASS
+
+ ASS
+
Source Files\Common
diff --git a/build/tests/tests.vcxproj b/build/tests/tests.vcxproj
index 30895e7ac..7a60299d0 100644
--- a/build/tests/tests.vcxproj
+++ b/build/tests/tests.vcxproj
@@ -57,6 +57,7 @@
+
diff --git a/build/tests/tests.vcxproj.filters b/build/tests/tests.vcxproj.filters
index b5a4d942c..c25a592f9 100644
--- a/build/tests/tests.vcxproj.filters
+++ b/build/tests/tests.vcxproj.filters
@@ -65,6 +65,9 @@
Tests
+
+ Tests
+
Tests
diff --git a/libaegisub/Makefile b/libaegisub/Makefile
index 52c55290c..1492a6f79 100644
--- a/libaegisub/Makefile
+++ b/libaegisub/Makefile
@@ -3,6 +3,7 @@ include $(dir $(lastword $(MAKEFILE_LIST)))../header.mk
aegisub_OBJ := \
$(d)common/parser.o \
$(d)ass/dialogue_parser.o \
+ $(d)ass/time.o \
$(subst .cpp,.o,$(wildcard $(d)common/cajun/*.cpp)) \
$(subst .cpp,.o,$(wildcard $(d)lua/modules/*.cpp)) \
$(subst .c,.o,$(wildcard $(d)lua/modules/*.c)) \
diff --git a/src/ass_time.cpp b/libaegisub/ass/time.cpp
similarity index 66%
rename from src/ass_time.cpp
rename to libaegisub/ass/time.cpp
index 585fa7cf7..0d05cd4c8 100644
--- a/src/ass_time.cpp
+++ b/libaegisub/ass/time.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2013, Thomas Goyne
+// Copyright (c) 2014, Thomas Goyne
//
// Permission to use, copy, modify, and distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
@@ -14,14 +14,8 @@
//
// Aegisub Project http://www.aegisub.org/
-/// @file ass_time.cpp
-/// @brief Class for managing timestamps in subtitles
-/// @ingroup subs_storage
-///
-
-#include "ass_time.h"
-
-#include "utils.h"
+#include
+#include
#include
#include
@@ -31,9 +25,10 @@
#include
#include
-AssTime::AssTime(int time) : time(mid(0, time, 10 * 60 * 60 * 1000 - 1)) { }
+namespace agi {
+Time::Time(int time) : time(util::mid(0, time, 10 * 60 * 60 * 1000 - 1)) { }
-AssTime::AssTime(std::string const& text) {
+Time::Time(std::string const& text) {
int after_decimal = -1;
int current = 0;
for (char c : text | boost::adaptors::filtered(boost::is_any_of(",.0123456789:"))) {
@@ -61,10 +56,10 @@ AssTime::AssTime(std::string const& text) {
time = (time * 60 + current) * 1000;
// Limit to the valid range
- time = mid(0, time, 10 * 60 * 60 * 1000 - 1);
+ time = util::mid(0, time, 10 * 60 * 60 * 1000 - 1);
}
-std::string AssTime::GetAssFormated(bool msPrecision) const {
+std::string Time::GetAssFormatted(bool msPrecision) const {
std::string ret(10 + msPrecision, ':');
ret[0] = '0' + GetTimeHours();
ret[2] = '0' + (time % (60 * 60 * 1000)) / (60 * 1000 * 10);
@@ -79,33 +74,34 @@ std::string AssTime::GetAssFormated(bool msPrecision) const {
return ret;
}
-int AssTime::GetTimeHours() const { return time / 3600000; }
-int AssTime::GetTimeMinutes() const { return (time % 3600000) / 60000; }
-int AssTime::GetTimeSeconds() const { return (time % 60000) / 1000; }
-int AssTime::GetTimeMiliseconds() const { return (time % 1000); }
-int AssTime::GetTimeCentiseconds() const { return (time % 1000) / 10; }
+int Time::GetTimeHours() const { return time / 3600000; }
+int Time::GetTimeMinutes() const { return (time % 3600000) / 60000; }
+int Time::GetTimeSeconds() const { return (time % 60000) / 1000; }
+int Time::GetTimeMiliseconds() const { return (time % 1000); }
+int Time::GetTimeCentiseconds() const { return (time % 1000) / 10; }
-SmpteFormatter::SmpteFormatter(agi::vfr::Framerate fps, std::string sep)
+SmpteFormatter::SmpteFormatter(vfr::Framerate fps, std::string sep)
: fps(std::move(fps))
, sep(std::move(sep))
{
}
-std::string SmpteFormatter::ToSMPTE(AssTime time) const {
+std::string SmpteFormatter::ToSMPTE(Time time) const {
int h=0, m=0, s=0, f=0;
fps.SmpteAtTime(time, &h, &m, &s, &f);
- return agi::format("%02d%s%02d%s%02d%c%02d", h, sep, m, sep, s, sep, f);
+ return format("%02d%s%02d%s%02d%s%02d", h, sep, m, sep, s, sep, f);
}
-AssTime SmpteFormatter::FromSMPTE(std::string const& str) const {
+Time SmpteFormatter::FromSMPTE(std::string const& str) const {
std::vector toks;
boost::split(toks, str, boost::is_any_of(sep));
if (toks.size() != 4) return 0;
int h, m, s, f;
- agi::util::try_parse(toks[0], &h);
- agi::util::try_parse(toks[1], &m);
- agi::util::try_parse(toks[2], &s);
- agi::util::try_parse(toks[3], &f);
+ util::try_parse(toks[0], &h);
+ util::try_parse(toks[1], &m);
+ util::try_parse(toks[2], &s);
+ util::try_parse(toks[3], &f);
return fps.TimeAtSmpte(h, m, s, f);
}
+}
diff --git a/libaegisub/include/libaegisub/ass/smpte.h b/libaegisub/include/libaegisub/ass/smpte.h
new file mode 100644
index 000000000..c6bed8034
--- /dev/null
+++ b/libaegisub/include/libaegisub/ass/smpte.h
@@ -0,0 +1,40 @@
+// Copyright (c) 2014, Thomas Goyne
+//
+// Permission to use, copy, modify, and distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+//
+// Aegisub Project http://www.aegisub.org/
+
+#include
+
+#include
+
+namespace agi {
+class Time;
+
+/// @class SmpteFormatter
+/// @brief Convert times to and from SMPTE timecodes
+class SmpteFormatter {
+ /// Frame rate to use
+ vfr::Framerate fps;
+ /// Separator character
+ std::string sep;
+
+public:
+ SmpteFormatter(vfr::Framerate fps, std::string sep=":");
+
+ /// Convert an Time to a SMPTE timecode
+ std::string ToSMPTE(Time time) const;
+ /// Convert a SMPTE timecode to an Time
+ Time FromSMPTE(std::string const& str) const;
+};
+}
diff --git a/src/ass_time.h b/libaegisub/include/libaegisub/ass/time.h
similarity index 66%
rename from src/ass_time.h
rename to libaegisub/include/libaegisub/ass/time.h
index 2e04a7f66..018b5b94a 100644
--- a/src/ass_time.h
+++ b/libaegisub/include/libaegisub/ass/time.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2013, Thomas Goyne
+// Copyright (c) 2014, Thomas Goyne
//
// Permission to use, copy, modify, and distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
@@ -14,24 +14,18 @@
//
// Aegisub Project http://www.aegisub.org/
-/// @file ass_time.h
-/// @see ass_time.cpp
-/// @ingroup subs_storage
-///
-
#pragma once
#include
-#include
-
-class AssTime {
+namespace agi {
+class Time {
/// Time in milliseconds
int time = 0;
public:
- AssTime(int ms = 0);
- AssTime(std::string const& text);
+ Time(int ms = 0);
+ Time(std::string const& text);
/// Get millisecond, rounded to centisecond precision
operator int() const { return time / 10 * 10; }
@@ -44,22 +38,6 @@ public:
/// Return the time as a string
/// @param ms Use milliseconds precision, for non-ASS formats
- std::string GetAssFormated(bool ms=false) const;
-};
-
-/// @class SmpteFormatter
-/// @brief Convert times to and from SMPTE timecodes
-class SmpteFormatter {
- /// Frame rate to use
- agi::vfr::Framerate fps;
- /// Separator character
- std::string sep;
-
-public:
- SmpteFormatter(agi::vfr::Framerate fps, std::string sep=":");
-
- /// Convert an AssTime to a SMPTE timecode
- std::string ToSMPTE(AssTime time) const;
- /// Convert a SMPTE timecode to an AssTime
- AssTime FromSMPTE(std::string const& str) const;
+ std::string GetAssFormatted(bool ms=false) const;
};
+}
diff --git a/src/Makefile b/src/Makefile
index 7914944c9..76bf2127d 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -28,7 +28,6 @@ src_OBJ := \
$(d)ass_parser.o \
$(d)ass_style.o \
$(d)ass_style_storage.o \
- $(d)ass_time.o \
$(d)async_video_provider.o \
$(d)audio_box.o \
$(d)audio_colorscheme.o \
diff --git a/src/ass_dialogue.cpp b/src/ass_dialogue.cpp
index 80fe5618d..40d2599fa 100644
--- a/src/ass_dialogue.cpp
+++ b/src/ass_dialogue.cpp
@@ -168,8 +168,8 @@ std::string AssDialogue::GetEntryData() const {
str.reserve(51 + Style.get().size() + Actor.get().size() + Effect.get().size() + Text.get().size());
append_int(str, Layer);
- append_str(str, Start.GetAssFormated());
- append_str(str, End.GetAssFormated());
+ append_str(str, Start.GetAssFormatted());
+ append_str(str, End.GetAssFormatted());
append_unsafe_str(str, Style);
append_unsafe_str(str, Actor);
for (auto margin : Margin)
diff --git a/src/ass_dialogue.h b/src/ass_dialogue.h
index a008b1516..e47466ed1 100644
--- a/src/ass_dialogue.h
+++ b/src/ass_dialogue.h
@@ -27,14 +27,10 @@
//
// Aegisub Project http://www.aegisub.org/
-/// @file ass_dialogue.h
-/// @see ass_dialogue.cpp
-/// @ingroup subs_storage
-///
-
#include "ass_entry.h"
#include "ass_override.h"
-#include "ass_time.h"
+
+#include
#include
#include
@@ -135,9 +131,9 @@ struct AssDialogueBase {
/// Margins: 0 = Left, 1 = Right, 2 = Top (Vertical)
std::array Margin = {{0, 0, 0}};
/// Starting time
- AssTime Start = 0;
+ agi::Time Start = 0;
/// Ending time
- AssTime End = 5000;
+ agi::Time End = 5000;
/// Style name
boost::flyweight Style{ "Default" };
/// Actor name
diff --git a/src/ass_override.cpp b/src/ass_override.cpp
index ad11d0728..94cc5ccf3 100644
--- a/src/ass_override.cpp
+++ b/src/ass_override.cpp
@@ -28,16 +28,12 @@
//
// Aegisub Project http://www.aegisub.org/
-/// @file ass_override.cpp
-/// @brief Parse and modify ASSA style overrides
-/// @ingroup subs_storage
-///
-
#include "ass_dialogue.h"
#include "utils.h"
#include
+#include
#include
#include
diff --git a/src/audio_display.cpp b/src/audio_display.cpp
index 5c9135143..dfb6cb9ad 100644
--- a/src/audio_display.cpp
+++ b/src/audio_display.cpp
@@ -30,7 +30,6 @@
#include "audio_display.h"
-#include "ass_time.h"
#include "audio_controller.h"
#include "audio_renderer.h"
#include "audio_renderer_spectrum.h"
@@ -46,6 +45,7 @@
#include "utils.h"
#include "video_controller.h"
+#include
#include
#include
@@ -977,8 +977,8 @@ void AudioDisplay::SetTrackCursor(int new_pos, bool show_time)
if (show_time)
{
- AssTime new_label_time = TimeFromAbsoluteX(track_cursor_pos);
- track_cursor_label = to_wx(new_label_time.GetAssFormated());
+ agi::Time new_label_time = TimeFromAbsoluteX(track_cursor_pos);
+ track_cursor_label = to_wx(new_label_time.GetAssFormatted());
track_cursor_label_rect.x += new_pos - old_pos;
RefreshRect(track_cursor_label_rect, false);
}
diff --git a/src/audio_timing_dialogue.cpp b/src/audio_timing_dialogue.cpp
index 6a1bf2197..c211e8e92 100644
--- a/src/audio_timing_dialogue.cpp
+++ b/src/audio_timing_dialogue.cpp
@@ -29,7 +29,6 @@
#include "ass_dialogue.h"
#include "ass_file.h"
-#include "ass_time.h"
#include "audio_marker.h"
#include "audio_rendering_style.h"
#include "audio_timing.h"
@@ -40,6 +39,7 @@
#include "selection_controller.h"
#include "utils.h"
+#include
#include
#include
diff --git a/src/command/audio.cpp b/src/command/audio.cpp
index 2f8bbe173..cc5e2f7bd 100644
--- a/src/command/audio.cpp
+++ b/src/command/audio.cpp
@@ -200,7 +200,7 @@ struct audio_save_clip final : public Command {
auto filename = SaveFileSelector(_("Save audio clip"), "", "", "wav", "", c->parent);
if (filename.empty()) return;
- AssTime start = INT_MAX, end = 0;
+ agi::Time start = INT_MAX, end = 0;
for (auto line : sel) {
start = std::min(start, line->Start);
end = std::max(end, line->End);
diff --git a/src/command/video.cpp b/src/command/video.cpp
index 04ec49b5c..a7600176d 100644
--- a/src/command/video.cpp
+++ b/src/command/video.cpp
@@ -32,7 +32,6 @@
#include "command.h"
#include "../ass_dialogue.h"
-#include "../ass_time.h"
#include "../async_video_provider.h"
#include "../compat.h"
#include "../dialog_detached_video.h"
@@ -51,6 +50,7 @@
#include "../video_display.h"
#include "../video_frame.h"
+#include
#include
#include
#include
diff --git a/src/dialog_dummy_video.cpp b/src/dialog_dummy_video.cpp
index 9338a54a9..90023864b 100644
--- a/src/dialog_dummy_video.cpp
+++ b/src/dialog_dummy_video.cpp
@@ -14,7 +14,6 @@
//
// Aegisub Project http://www.aegisub.org/
-#include "ass_time.h"
#include "colour_button.h"
#include "format.h"
#include "help_button.h"
@@ -23,6 +22,7 @@
#include "validators.h"
#include "video_provider_dummy.h"
+#include
#include
#include
@@ -161,7 +161,7 @@ void DialogDummyVideo::OnResolutionShortcut(wxCommandEvent &e) {
}
void DialogDummyVideo::UpdateLengthDisplay() {
- length_display->SetLabel(fmt_tl("Resulting duration: %s", AssTime(length / fps * 1000).GetAssFormated(true)));
+ length_display->SetLabel(fmt_tl("Resulting duration: %s", agi::Time(length / fps * 1000).GetAssFormatted(true)));
}
}
diff --git a/src/dialog_jumpto.cpp b/src/dialog_jumpto.cpp
index 4f8e7bcf1..8503240f8 100644
--- a/src/dialog_jumpto.cpp
+++ b/src/dialog_jumpto.cpp
@@ -27,7 +27,6 @@
//
// Aegisub Project http://www.aegisub.org/
-#include "ass_time.h"
#include "async_video_provider.h"
#include "format.h"
#include "include/aegisub/context.h"
@@ -37,6 +36,8 @@
#include "validators.h"
#include "video_controller.h"
+#include
+
#include
#include
#include
@@ -74,7 +75,7 @@ DialogJumpTo::DialogJumpTo(agi::Context *c)
JumpFrame = new wxTextCtrl(&d,-1,"",wxDefaultPosition,wxSize(-1,-1),wxTE_PROCESS_ENTER, IntValidator((int)jumpframe));
JumpFrame->SetMaxLength(std::to_string(c->project->VideoProvider()->GetFrameCount() - 1).size());
- JumpTime = new TimeEdit(&d, -1, c, AssTime(c->videoController->TimeAtFrame(jumpframe)).GetAssFormated(), wxSize(-1,-1));
+ JumpTime = new TimeEdit(&d, -1, c, agi::Time(c->videoController->TimeAtFrame(jumpframe)).GetAssFormatted(), wxSize(-1,-1));
auto TimesSizer = new wxGridSizer(2, 5, 5);
diff --git a/src/dialog_shift_times.cpp b/src/dialog_shift_times.cpp
index c30c86f6a..ae0bf242a 100644
--- a/src/dialog_shift_times.cpp
+++ b/src/dialog_shift_times.cpp
@@ -16,7 +16,6 @@
#include "ass_dialogue.h"
#include "ass_file.h"
-#include "ass_time.h"
#include "compat.h"
#include "dialog_manager.h"
#include "format.h"
@@ -29,6 +28,7 @@
#include "subs_controller.h"
#include "timeedit_ctrl.h"
+#include
#include
#include
#include
@@ -286,7 +286,7 @@ void DialogShiftTimes::OnHistoryClick(wxCommandEvent &evt) {
json::Object& obj = history[entry];
if (obj["is by time"]) {
- shift_time->SetTime(AssTime((std::string)obj["amount"]));
+ shift_time->SetTime(agi::Time((std::string)obj["amount"]));
shift_by_time->SetValue(true);
OnByTime(evt);
}
diff --git a/src/dialog_style_manager.cpp b/src/dialog_style_manager.cpp
index 6231b4c4f..4a60ac086 100644
--- a/src/dialog_style_manager.cpp
+++ b/src/dialog_style_manager.cpp
@@ -46,10 +46,11 @@
#include "subtitle_format.h"
#include
+#include
#include
#include
#include
-#include
+#include
#include
#include
diff --git a/src/dialog_timing_processor.cpp b/src/dialog_timing_processor.cpp
index e03c4b34a..00719c51c 100644
--- a/src/dialog_timing_processor.cpp
+++ b/src/dialog_timing_processor.cpp
@@ -29,7 +29,6 @@
#include "ass_dialogue.h"
#include "ass_file.h"
-#include "ass_time.h"
#include "async_video_provider.h"
#include "compat.h"
#include "format.h"
@@ -42,6 +41,7 @@
#include "utils.h"
#include
+#include
#include
#include
diff --git a/src/dialog_video_details.cpp b/src/dialog_video_details.cpp
index 277928dd8..84dab5462 100644
--- a/src/dialog_video_details.cpp
+++ b/src/dialog_video_details.cpp
@@ -27,13 +27,14 @@
//
// Aegisub Project http://www.aegisub.org/
-#include "ass_time.h"
#include "async_video_provider.h"
#include "compat.h"
#include "format.h"
#include "include/aegisub/context.h"
#include "project.h"
+#include
+
#include
#include
#include
@@ -59,7 +60,7 @@ void ShowVideoDetailsDialog(agi::Context *c) {
make_field(_("FPS:"), fmt_wx("%.3f", fps.FPS()));
make_field(_("Resolution:"), fmt_wx("%dx%d (%d:%d)", width, height, ar.numerator(), ar.denominator()));
make_field(_("Length:"), fmt_plural(framecount, "1 frame", "%d frames (%s)",
- framecount, AssTime(fps.TimeAtFrame(framecount - 1)).GetAssFormated(true)));
+ framecount, agi::Time(fps.TimeAtFrame(framecount - 1)).GetAssFormatted(true)));
make_field(_("Decoder:"), to_wx(provider->GetDecoderName()));
auto video_sizer = new wxStaticBoxSizer(wxVERTICAL, &d, _("Video"));
diff --git a/src/grid_column.cpp b/src/grid_column.cpp
index db52ce1a2..0cdec482b 100644
--- a/src/grid_column.cpp
+++ b/src/grid_column.cpp
@@ -131,7 +131,7 @@ struct GridColumnStartTime final : GridColumnTime {
wxString Value(const AssDialogue *d, const agi::Context *c) const override {
if (by_frame)
return std::to_wstring(c->videoController->FrameAtTime(d->Start, agi::vfr::START));
- return to_wx(d->Start.GetAssFormated());
+ return to_wx(d->Start.GetAssFormatted());
}
int Width(const agi::Context *c, WidthHelper &helper) const override {
@@ -149,7 +149,7 @@ struct GridColumnEndTime final : GridColumnTime {
wxString Value(const AssDialogue *d, const agi::Context *c) const override {
if (by_frame)
return std::to_wstring(c->videoController->FrameAtTime(d->End, agi::vfr::END));
- return to_wx(d->End.GetAssFormated());
+ return to_wx(d->End.GetAssFormatted());
}
int Width(const agi::Context *c, WidthHelper &helper) const override {
diff --git a/src/mkv_wrap.cpp b/src/mkv_wrap.cpp
index 2085bcddc..38bc1aac4 100644
--- a/src/mkv_wrap.cpp
+++ b/src/mkv_wrap.cpp
@@ -36,12 +36,12 @@
#include "ass_file.h"
#include "ass_parser.h"
-#include "ass_time.h"
#include "compat.h"
#include "dialog_progress.h"
#include "MatroskaParser.h"
#include "options.h"
+#include
#include
#include
#include
@@ -130,8 +130,8 @@ static void read_subtitles(agi::ProgressSink *ps, MatroskaFile *file, MkvStdIO *
// Get start and end times
int64_t timecodeScaleLow = 1000000;
- AssTime subStart = startTime / timecodeScaleLow;
- AssTime subEnd = endTime / timecodeScaleLow;
+ agi::Time subStart = startTime / timecodeScaleLow;
+ agi::Time subEnd = endTime / timecodeScaleLow;
using str_range = boost::iterator_range;
@@ -146,15 +146,15 @@ static void read_subtitles(agi::ProgressSink *ps, MatroskaFile *file, MkvStdIO *
boost::lexical_cast(str_range(readBuf, first)),
agi::format("Dialogue: %d,%s,%s,%s"
, boost::lexical_cast(str_range(first + 1, second))
- , subStart.GetAssFormated()
- , subEnd.GetAssFormated()
+ , subStart.GetAssFormatted()
+ , subEnd.GetAssFormatted()
, str_range(second + 1, readBufEnd)));
}
// Process SRT
else {
auto line = agi::format("Dialogue: 0,%s,%s,Default,,0,0,0,,%s"
- , subStart.GetAssFormated()
- , subEnd.GetAssFormated()
+ , subStart.GetAssFormatted()
+ , subEnd.GetAssFormatted()
, str_range(readBuf, readBufEnd));
boost::replace_all(line, "\r\n", "\\N");
boost::replace_all(line, "\r", "\\N");
diff --git a/src/resolution_resampler.cpp b/src/resolution_resampler.cpp
index 2f79be4a2..9e3c49b66 100644
--- a/src/resolution_resampler.cpp
+++ b/src/resolution_resampler.cpp
@@ -21,6 +21,7 @@
#include "ass_style.h"
#include "utils.h"
+#include
#include
#include
#include
diff --git a/src/search_replace_engine.cpp b/src/search_replace_engine.cpp
index e0e2066b4..d345bfbb1 100644
--- a/src/search_replace_engine.cpp
+++ b/src/search_replace_engine.cpp
@@ -23,6 +23,7 @@
#include "selection_controller.h"
#include "text_selection_controller.h"
+#include
#include
#include
diff --git a/src/subs_edit_box.h b/src/subs_edit_box.h
index 71e92cdd4..81b82aed6 100644
--- a/src/subs_edit_box.h
+++ b/src/subs_edit_box.h
@@ -40,9 +40,9 @@
namespace agi { namespace vfr { class Framerate; } }
namespace agi { struct Context; }
+namespace agi { class Time; }
class AssDialogue;
class AssStyle;
-class AssTime;
class SubsTextEditCtrl;
class TimeEdit;
class wxButton;
@@ -126,7 +126,7 @@ class SubsEditBox final : public wxPanel {
/// The start and end times of the selected lines without changes made to
/// avoid negative durations, so that they can be restored if future changes
/// eliminate the negative durations
- boost::container::map> initial_times;
+ boost::container::map> initial_times;
// Constructor helpers
wxTextCtrl *MakeMarginCtrl(wxString const& tooltip, int margin, wxString const& commit_msg);
diff --git a/src/subtitle_format.cpp b/src/subtitle_format.cpp
index 11fe3b19a..d2d1573da 100644
--- a/src/subtitle_format.cpp
+++ b/src/subtitle_format.cpp
@@ -50,6 +50,7 @@
#include
#include
+#include
#include
#include
diff --git a/src/subtitle_format_encore.cpp b/src/subtitle_format_encore.cpp
index 865dda902..51843180a 100644
--- a/src/subtitle_format_encore.cpp
+++ b/src/subtitle_format_encore.cpp
@@ -38,6 +38,7 @@
#include "ass_file.h"
#include "text_file_writer.h"
+#include
#include
EncoreSubtitleFormat::EncoreSubtitleFormat()
@@ -64,7 +65,7 @@ void EncoreSubtitleFormat::WriteFile(const AssFile *src, agi::fs::path const& fi
// Encore wants ; for NTSC and : for PAL
// The manual suggests no other frame rates are supported
- SmpteFormatter ft(fps, fps.NeedsDropFrames() ? ";" : ":");
+ agi::SmpteFormatter ft(fps, fps.NeedsDropFrames() ? ";" : ":");
// Write lines
int i = 0;
diff --git a/src/subtitle_format_microdvd.cpp b/src/subtitle_format_microdvd.cpp
index d2e981bc1..6c3991718 100644
--- a/src/subtitle_format_microdvd.cpp
+++ b/src/subtitle_format_microdvd.cpp
@@ -36,14 +36,15 @@
#include "ass_dialogue.h"
#include "ass_file.h"
-#include "ass_time.h"
#include "options.h"
#include "text_file_reader.h"
#include "text_file_writer.h"
+#include
#include
#include
#include
+#include
#include
#include
diff --git a/src/subtitle_format_srt.cpp b/src/subtitle_format_srt.cpp
index 56c89f547..011f6c7a1 100644
--- a/src/subtitle_format_srt.cpp
+++ b/src/subtitle_format_srt.cpp
@@ -277,7 +277,7 @@ public:
}
};
-std::string WriteSRTTime(AssTime const& ts)
+std::string WriteSRTTime(agi::Time const& ts)
{
return agi::format("%02d:%02d:%02d,%03d", ts.GetTimeHours(), ts.GetTimeMinutes(), ts.GetTimeSeconds(), ts.GetTimeMiliseconds());
}
diff --git a/src/subtitle_format_ssa.cpp b/src/subtitle_format_ssa.cpp
index 3a66f2856..623fbbc67 100644
--- a/src/subtitle_format_ssa.cpp
+++ b/src/subtitle_format_ssa.cpp
@@ -84,7 +84,7 @@ void SsaSubtitleFormat::WriteFile(const AssFile *src, agi::fs::path const& filen
for (auto const& line : src->Events)
file.WriteLineToFile(agi::format("%s: Marked=0,%s,%s,%s,%s,%d,%d,%d,%s,%s"
, (line.Comment ? "Comment" : "Dialogue")
- , line.Start.GetAssFormated(), line.End.GetAssFormated()
+ , line.Start.GetAssFormatted(), line.End.GetAssFormatted()
, replace_commas(line.Style), replace_commas(line.Actor)
, line.Margin[0], line.Margin[1], line.Margin[2]
, replace_commas(line.Effect)
diff --git a/src/subtitle_format_transtation.cpp b/src/subtitle_format_transtation.cpp
index 8ac2c7ba7..66196764a 100644
--- a/src/subtitle_format_transtation.cpp
+++ b/src/subtitle_format_transtation.cpp
@@ -27,19 +27,15 @@
//
// Aegisub Project http://www.aegisub.org/
-/// @file subtitle_format_transtation.cpp
-/// @brief Reading/writing Transtation-compatible subtitles
-/// @ingroup subtitle_io
-///
-
#include "subtitle_format_transtation.h"
#include "ass_dialogue.h"
#include "ass_file.h"
#include "ass_style.h"
-#include "ass_time.h"
#include "text_file_writer.h"
+#include
+#include
#include
TranStationSubtitleFormat::TranStationSubtitleFormat()
@@ -52,7 +48,7 @@ std::vector TranStationSubtitleFormat::GetWriteWildcards() const {
}
void TranStationSubtitleFormat::WriteFile(const AssFile *src, agi::fs::path const& filename, agi::vfr::Framerate const& vfps, std::string const& encoding) const {
- agi::vfr::Framerate fps = AskForFPS(false, true, vfps);
+ auto fps = AskForFPS(false, true, vfps);
if (!fps.IsLoaded()) return;
// Convert to TranStation
@@ -64,7 +60,7 @@ void TranStationSubtitleFormat::WriteFile(const AssFile *src, agi::fs::path cons
StripTags(copy);
ConvertNewlines(copy, "\r\n");
- SmpteFormatter ft(fps);
+ agi::SmpteFormatter ft(fps);
TextFileWriter file(filename, encoding);
const AssDialogue *prev = nullptr;
for (auto const& cur : copy.Events) {
@@ -84,7 +80,7 @@ void TranStationSubtitleFormat::WriteFile(const AssFile *src, agi::fs::path cons
file.WriteLineToFile("SUB[");
}
-std::string TranStationSubtitleFormat::ConvertLine(AssFile *file, const AssDialogue *current, agi::vfr::Framerate const& fps, SmpteFormatter const& ft, int nextl_start) const {
+std::string TranStationSubtitleFormat::ConvertLine(AssFile *file, const AssDialogue *current, agi::vfr::Framerate const& fps, agi::SmpteFormatter const& ft, int nextl_start) const {
int valign = 0;
const char *halign = " "; // default is centered
const char *type = "N"; // no special style
@@ -101,7 +97,7 @@ std::string TranStationSubtitleFormat::ConvertLine(AssFile *file, const AssDialo
if (current->Text.get().find("\\i1") != std::string::npos) type = "I";
// Write header
- AssTime end = current->End;
+ agi::Time end = current->End;
// Subtract one frame if the end time of the current line is equal to the
// start of next one, since the end timestamp is inclusive and the lines
diff --git a/src/subtitle_format_transtation.h b/src/subtitle_format_transtation.h
index 02e51ceb5..da4390b29 100644
--- a/src/subtitle_format_transtation.h
+++ b/src/subtitle_format_transtation.h
@@ -27,18 +27,13 @@
//
// Aegisub Project http://www.aegisub.org/
-/// @file subtitle_format_transtation.h
-/// @see subtitle_format_transtation.cpp
-/// @ingroup subtitle_io
-///
-
#include "subtitle_format.h"
class AssDialogue;
-class SmpteFormatter;
+namespace agi { class SmpteFormatter; }
class TranStationSubtitleFormat final : public SubtitleFormat {
- std::string ConvertLine(AssFile *file, const AssDialogue *line, agi::vfr::Framerate const& fps, SmpteFormatter const& ft, int nextl_start) const;
+ std::string ConvertLine(AssFile *file, const AssDialogue *line, agi::vfr::Framerate const& fps, agi::SmpteFormatter const& ft, int nextl_start) const;
public:
TranStationSubtitleFormat();
diff --git a/src/subtitle_format_ttxt.cpp b/src/subtitle_format_ttxt.cpp
index d2af0a6d3..609f51bba 100644
--- a/src/subtitle_format_ttxt.cpp
+++ b/src/subtitle_format_ttxt.cpp
@@ -36,10 +36,11 @@
#include "ass_dialogue.h"
#include "ass_file.h"
-#include "ass_time.h"
#include "compat.h"
#include "options.h"
+#include
+
#include
DEFINE_EXCEPTION(TTXTParseError, SubtitleFormatParseError);
@@ -102,7 +103,7 @@ void TTXTSubtitleFormat::ReadFile(AssFile *target, agi::fs::path const& filename
AssDialogue *TTXTSubtitleFormat::ProcessLine(wxXmlNode *node, AssDialogue *prev, int version) const {
// Get time
wxString sampleTime = node->GetAttribute("sampleTime", "00:00:00.000");
- AssTime time(from_wx(sampleTime));
+ agi::Time time(from_wx(sampleTime));
// Set end time of last line
if (prev)
@@ -233,7 +234,7 @@ void TTXTSubtitleFormat::WriteLine(wxXmlNode *root, const AssDialogue *prev, con
// If it doesn't start at the end of previous, add blank
if (prev && prev->End != line->Start) {
wxXmlNode *node = new wxXmlNode(wxXML_ELEMENT_NODE, "TextSample");
- node->AddAttribute("sampleTime", to_wx("0" + prev->End.GetAssFormated(true)));
+ node->AddAttribute("sampleTime", to_wx("0" + prev->End.GetAssFormatted(true)));
node->AddAttribute("xml:space", "preserve");
root->AddChild(node);
node->AddChild(new wxXmlNode(wxXML_TEXT_NODE, "", ""));
@@ -241,7 +242,7 @@ void TTXTSubtitleFormat::WriteLine(wxXmlNode *root, const AssDialogue *prev, con
// Generate and insert node
wxXmlNode *node = new wxXmlNode(wxXML_ELEMENT_NODE, "TextSample");
- node->AddAttribute("sampleTime", to_wx("0" + line->Start.GetAssFormated(true)));
+ node->AddAttribute("sampleTime", to_wx("0" + line->Start.GetAssFormatted(true)));
node->AddAttribute("xml:space", "preserve");
root->AddChild(node);
node->AddChild(new wxXmlNode(wxXML_TEXT_NODE, "", to_wx(line->Text)));
@@ -256,7 +257,7 @@ void TTXTSubtitleFormat::ConvertToTTXT(AssFile &file) const {
ConvertNewlines(file, "\r\n");
// Find last line
- AssTime lastTime;
+ agi::Time lastTime;
if (!file.Events.empty())
lastTime = file.Events.back().End;
diff --git a/src/subtitles_provider_libass.cpp b/src/subtitles_provider_libass.cpp
index 0d2bfdd01..3dc047e71 100644
--- a/src/subtitles_provider_libass.cpp
+++ b/src/subtitles_provider_libass.cpp
@@ -44,6 +44,7 @@
#include
#include
+#include
#include
#include
#include
diff --git a/src/timeedit_ctrl.cpp b/src/timeedit_ctrl.cpp
index 20aed53e8..4ccb454d3 100644
--- a/src/timeedit_ctrl.cpp
+++ b/src/timeedit_ctrl.cpp
@@ -34,15 +34,15 @@
#include "timeedit_ctrl.h"
-#include
-
-#include "ass_time.h"
#include "compat.h"
#include "include/aegisub/context.h"
#include "options.h"
#include "project.h"
#include "utils.h"
+#include
+
+#include
#include
#include
@@ -67,7 +67,7 @@ TimeEdit::TimeEdit(wxWindow* parent, wxWindowID id, agi::Context *c, const std::
SetValidator(val);
// Other stuff
- if (value.empty()) SetValue(to_wx(time.GetAssFormated()));
+ if (value.empty()) SetValue(to_wx(time.GetAssFormatted()));
Bind(wxEVT_MENU, std::bind(&TimeEdit::CopyTime, this), Time_Edit_Copy);
Bind(wxEVT_MENU, std::bind(&TimeEdit::PasteTime, this), Time_Edit_Paste);
@@ -78,7 +78,7 @@ TimeEdit::TimeEdit(wxWindow* parent, wxWindowID id, agi::Context *c, const std::
Bind(wxEVT_KILL_FOCUS, &TimeEdit::OnFocusLost, this);
}
-void TimeEdit::SetTime(AssTime new_time) {
+void TimeEdit::SetTime(agi::Time new_time) {
if (time != new_time) {
time = new_time;
UpdateText();
@@ -115,7 +115,7 @@ void TimeEdit::UpdateText() {
if (byFrame)
ChangeValue(std::to_wstring(c->project->Timecodes().FrameAtTime(time, isEnd ? agi::vfr::END : agi::vfr::START)));
else
- ChangeValue(to_wx(time.GetAssFormated()));
+ ChangeValue(to_wx(time.GetAssFormatted()));
}
void TimeEdit::OnKeyDown(wxKeyEvent &event) {
@@ -190,7 +190,7 @@ void TimeEdit::OnChar(wxKeyEvent &event) {
// Overwrite the digit
text[start] = (char)key;
time = text;
- SetValue(to_wx(time.GetAssFormated()));
+ SetValue(to_wx(time.GetAssFormatted()));
SetInsertionPoint(start + 1);
}
@@ -229,8 +229,8 @@ void TimeEdit::PasteTime() {
std::string text(GetClipboard());
if (text.empty()) return;
- AssTime tempTime(text);
- if (tempTime.GetAssFormated() == text) {
+ agi::Time tempTime(text);
+ if (tempTime.GetAssFormatted() == text) {
SetTime(tempTime);
SetSelection(0, GetValue().size());
diff --git a/src/timeedit_ctrl.h b/src/timeedit_ctrl.h
index 925270223..a056a1181 100644
--- a/src/timeedit_ctrl.h
+++ b/src/timeedit_ctrl.h
@@ -27,23 +27,17 @@
//
// Aegisub Project http://www.aegisub.org/
-/// @file timeedit_ctrl.h
-/// @see timeedit_ctrl.cpp
-/// @ingroup custom_control
-///
+#include
+#include
#include
-#include "ass_time.h"
-
-#include
-
namespace agi {
class OptionValue;
struct Context;
}
-/// @brief A text edit control for editing AssTime objects
+/// @brief A text edit control for editing agi::Time objects
///
/// This control constrains values to valid times, and can display the time
/// being edited as either a h:mm:ss.cc formatted time, or a frame number
@@ -51,7 +45,7 @@ class TimeEdit final : public wxTextCtrl {
bool byFrame = false; ///< Is the time displayed as a frame number?
agi::Context *c; ///< Project context
bool isEnd; ///< Should the time be treated as an end time for time <-> frame conversions?
- AssTime time; ///< The time, which may be displayed as either a frame number or time
+ agi::Time time; ///< The time, which may be displayed as either a frame number or time
bool insert; ///< If true, disable overwriting behavior in time mode
agi::signal::Connection insert_opt;
@@ -78,10 +72,10 @@ class TimeEdit final : public wxTextCtrl {
#endif
public:
- /// Get the current time as an AssTime object
- AssTime GetTime() const { return time; }
+ /// Get the current time as an agi::Time object
+ agi::Time GetTime() const { return time; }
/// Set the time
- void SetTime(AssTime time);
+ void SetTime(agi::Time time);
/// Get the current time as a frame number, or 0 if timecodes are unavailable
int GetFrame() const;
diff --git a/src/video_box.cpp b/src/video_box.cpp
index 96a1d5948..49fff80aa 100644
--- a/src/video_box.cpp
+++ b/src/video_box.cpp
@@ -115,7 +115,7 @@ void VideoBox::UpdateTimeBoxes() {
int time = context->videoController->TimeAtFrame(frame, agi::vfr::EXACT);
// Set the text box for frame number and time
- VideoPosition->SetValue(fmt_wx("%s - %d", AssTime(time).GetAssFormated(true), frame));
+ VideoPosition->SetValue(fmt_wx("%s - %d", agi::Time(time).GetAssFormatted(true), frame));
if (boost::binary_search(context->project->Keyframes(), frame)) {
// Set the background color to indicate this is a keyframe
VideoPosition->SetBackgroundColour(to_wx(OPT_GET("Colour/Subtitle Grid/Background/Selection")->GetColor()));
diff --git a/src/video_controller.cpp b/src/video_controller.cpp
index 1ea315a50..ae78fb2b4 100644
--- a/src/video_controller.cpp
+++ b/src/video_controller.cpp
@@ -31,7 +31,6 @@
#include "ass_dialogue.h"
#include "ass_file.h"
-#include "ass_time.h"
#include "audio_controller.h"
#include "compat.h"
#include "include/aegisub/context.h"
@@ -42,6 +41,8 @@
#include "async_video_provider.h"
#include "utils.h"
+#include
+
#include
VideoController::VideoController(agi::Context *c)
diff --git a/src/visual_tool.cpp b/src/visual_tool.cpp
index 049286291..bec098dd5 100644
--- a/src/visual_tool.cpp
+++ b/src/visual_tool.cpp
@@ -23,7 +23,6 @@
#include "ass_dialogue.h"
#include "ass_file.h"
#include "ass_style.h"
-#include "ass_time.h"
#include "include/aegisub/context.h"
#include "selection_controller.h"
#include "video_controller.h"
@@ -32,6 +31,7 @@
#include "visual_tool_drag.h"
#include "visual_tool_vector_clip.h"
+#include
#include
#include
diff --git a/tests/tests/time.cpp b/tests/tests/time.cpp
new file mode 100644
index 000000000..74ea7558f
--- /dev/null
+++ b/tests/tests/time.cpp
@@ -0,0 +1,84 @@
+// Copyright (c) 2014, Thomas Goyne
+//
+// Permission to use, copy, modify, and distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+//
+// Aegisub Project http://www.aegisub.org/
+
+#include
+
+#include
+#include
+
+using agi::Time;
+
+TEST(lagi_time, out_of_range_times) {
+ EXPECT_EQ(0, (int)Time(-1));
+ EXPECT_EQ(10 * 60 * 60 * 1000 - 10, (int)Time(10 * 60 * 60 * 1000));
+}
+
+TEST(lagi_time, rounds_to_cs) {
+ EXPECT_EQ(10, (int)Time(14));
+}
+
+TEST(lagi_time, cs_formatting) {
+ EXPECT_STREQ("1:23:45.67", Time((((1 * 60) + 23) * 60 + 45) * 1000 + 670).GetAssFormatted().c_str());
+}
+
+TEST(lagi_time, ms_formatting) {
+ EXPECT_STREQ("1:23:45.678", Time((((1 * 60) + 23) * 60 + 45) * 1000 + 678).GetAssFormatted(true).c_str());
+}
+
+TEST(lagi_time, well_formed_ass_time_parse) {
+ EXPECT_STREQ("1:23:45.67", Time("1:23:45.67").GetAssFormatted().c_str());
+}
+
+TEST(lagi_time, missing_components) {
+ EXPECT_STREQ("0:23:45.67", Time("23:45.67").GetAssFormatted().c_str());
+ EXPECT_STREQ("0:00:45.67", Time("45.67").GetAssFormatted().c_str());
+ EXPECT_STREQ("0:00:45.60", Time("45.6").GetAssFormatted().c_str());
+ EXPECT_STREQ("0:00:45.00", Time("45").GetAssFormatted().c_str());
+}
+
+TEST(lagi_time, out_of_range_compontents) {
+ EXPECT_STREQ("1:23:45.67", Time("0:83:45.67").GetAssFormatted().c_str());
+ EXPECT_STREQ("0:01:40.00", Time("100").GetAssFormatted().c_str());
+}
+
+TEST(lagi_time, comma_decimal) {
+ EXPECT_STREQ("1:23:45.67", Time("1:23:45,67").GetAssFormatted().c_str());
+}
+
+TEST(lagi_time, component_getters) {
+ Time t("1:23:45.67");
+ EXPECT_EQ(1, t.GetTimeHours());
+ EXPECT_EQ(23, t.GetTimeMinutes());
+ EXPECT_EQ(45, t.GetTimeSeconds());
+ EXPECT_EQ(67, t.GetTimeCentiseconds());
+ EXPECT_EQ(670, t.GetTimeMiliseconds());
+}
+
+TEST(lagi_time, srt_time) {
+ EXPECT_STREQ("1:23:45.678", Time("1:23:45,678").GetAssFormatted(true).c_str());
+}
+
+TEST(lagi_time, smpte_parse_valid) {
+ EXPECT_STREQ("1:23:45.44", agi::SmpteFormatter(25).FromSMPTE("1:23:45:11").GetAssFormatted().c_str());
+}
+
+TEST(lagi_time, smpte_parse_invalid) {
+ EXPECT_EQ(0, (int)agi::SmpteFormatter(25).FromSMPTE("1:23:45.11"));
+}
+
+TEST(lagi_time, to_smpte) {
+ EXPECT_STREQ("01:23:45:11", agi::SmpteFormatter(25).ToSMPTE(Time("1:23:45.44")).c_str());
+}