diff --git a/aegisub/build/aegisub_vs2008/aegisub_vs2008.vcproj b/aegisub/build/aegisub_vs2008/aegisub_vs2008.vcproj
index f8bfacfa2..9dd938748 100644
--- a/aegisub/build/aegisub_vs2008/aegisub_vs2008.vcproj
+++ b/aegisub/build/aegisub_vs2008/aegisub_vs2008.vcproj
@@ -1700,11 +1700,11 @@
>
+
+
TimeAtFrame(frame_number));
- }
- AnnounceMarkerMoved();
- }
-
- void OptChanged(agi::OptionValue const& opt)
- {
- if (opt.GetBool())
- {
- video_seek_slot.Unblock();
- Update(vc->GetFrameN());
- }
- else
- {
- video_seek_slot.Block();
- Update(-1);
- }
- }
-
-public:
- VideoPositionMarkerProvider(agi::Context *c)
- : vc(c->videoController)
- , video_seek_slot(vc->AddSeekListener(&VideoPositionMarkerProvider::Update, this))
- , enable_opt_changed_slot(OPT_SUB("Audio/Display/Draw/Video Position", &VideoPositionMarkerProvider::OptChanged, this))
- {
- OptChanged(*OPT_GET("Audio/Display/Draw/Video Position"));
- }
-
- void GetMarkers(const TimeRange &range, AudioMarkerVector &out) const
- {
- if (range.contains(marker))
- {
- out.push_back(&marker);
- }
- }
-};
-
AudioController::AudioController(agi::Context *context)
: context(context)
, subtitle_save_slot(context->ass->AddFileSaveListener(&AudioController::OnSubtitlesSave, this))
@@ -318,12 +245,6 @@ void AudioController::OpenAudio(const wxString &url)
config::mru->Add("Audio", STD_STR(url));
- if (!video_position_marker_provider.get())
- {
- video_position_marker_provider.reset(new VideoPositionMarkerProvider(context));
- video_position_marker_provider->AddMarkerMovedListener(std::tr1::bind(std::tr1::ref(AnnounceMarkerMoved)));
- }
-
try
{
// Tell listeners about this.
@@ -371,10 +292,7 @@ void AudioController::SetTimingController(AudioTimingController *new_controller)
timing_controller.reset(new_controller);
if (timing_controller)
{
- timing_controller->AddMarkerMovedListener(bind(std::tr1::ref(AnnounceMarkerMoved)));
- timing_controller->AddLabelChangedListener(bind(std::tr1::ref(AnnounceLabelChanged)));
timing_controller->AddUpdatedPrimaryRangeListener(&AudioController::OnTimingControllerUpdatedPrimaryRange, this);
- timing_controller->AddUpdatedStyleRangesListener(bind(std::tr1::ref(AnnounceStyleRangesChanged)));
}
}
@@ -387,8 +305,6 @@ void AudioController::OnTimingControllerUpdatedPrimaryRange()
{
player->SetEndPosition(timing_controller->GetPrimaryPlaybackRange().end());
}
-
- AnnounceSelectionChanged();
}
void AudioController::OnSubtitlesSave()
@@ -497,26 +413,12 @@ TimeRange AudioController::GetPrimaryPlaybackRange() const
}
}
-
-void AudioController::GetMarkers(const TimeRange &range, AudioMarkerVector &markers) const
-{
- /// @todo Find all sources of markers
- if (timing_controller) timing_controller->GetMarkers(range, markers);
- if (video_position_marker_provider.get()) video_position_marker_provider->GetMarkers(range, markers);
-}
-
-void AudioController::GetLabels(const TimeRange &range, std::vector &labels) const
-{
- if (timing_controller) timing_controller->GetLabels(range, labels);
-}
-
double AudioController::GetVolume() const
{
if (!IsAudioOpen()) return 1.0;
return player->GetVolume();
}
-
void AudioController::SetVolume(double volume)
{
if (!IsAudioOpen()) return;
diff --git a/aegisub/src/audio_controller.h b/aegisub/src/audio_controller.h
index 1a90af7fb..6f6d02789 100644
--- a/aegisub/src/audio_controller.h
+++ b/aegisub/src/audio_controller.h
@@ -54,115 +54,12 @@
class AudioPlayer;
class AudioProvider;
-namespace agi { struct Context; }
-
-// Declared below
-class AudioControllerAudioEventListener;
-class AudioControllerTimingEventListener;
class AudioTimingController;
-class AudioMarker;
-class AudioMarkerProvider;
-
-typedef std::vector AudioMarkerVector;
-
-/// @class TimeRange
-/// @brief Represents an immutable range of time
-class TimeRange {
- int _begin;
- int _end;
-
-public:
- /// @brief Constructor
- /// @param begin Index of the first millisecond to include in the range
- /// @param end Index of one past the last millisecond to include in the range
- TimeRange(int begin, int end) : _begin(begin), _end(end)
- {
- assert(end >= begin);
- }
-
- /// @brief Copy constructor, optionally adjusting the range
- /// @param src The range to duplicate
- /// @param begin_adjust Number of milliseconds to add to the start of the range
- /// @param end_adjust Number of milliseconds to add to the end of the range
- TimeRange(const TimeRange &src, int begin_adjust = 0, int end_adjust = 0)
- {
- _begin = src._begin + begin_adjust;
- _end = src._end + end_adjust;
- assert(_end >= _begin);
- }
-
- /// Get the length of the range in milliseconds
- int length() const { return _end - _begin; }
- /// Get the start time of the range in milliseconds
- int begin() const { return _begin; }
- /// Get the exclusive end time of the range in milliseconds
- int end() const { return _end; }
-
- /// Determine whether the range contains a given time in milliseconds
- bool contains(int ms) const { return ms >= begin() && ms < end(); }
-
- /// Determine whether there is an overlap between two ranges
- bool overlaps(const TimeRange &other) const
- {
- return other.contains(_begin) || contains(other._begin);
- }
-};
-
-/// @class AudioMarkerProvider
-/// @brief Abstract interface for audio marker providers
-class AudioMarkerProvider {
-protected:
- /// One or more of the markers provided by this object have changed
- agi::signal::Signal<> AnnounceMarkerMoved;
-public:
- /// Virtual destructor, does nothing
- virtual ~AudioMarkerProvider() { }
-
- /// @brief Return markers in a time range
- virtual void GetMarkers(const TimeRange &range, AudioMarkerVector &out) const = 0;
-
- DEFINE_SIGNAL_ADDERS(AnnounceMarkerMoved, AddMarkerMovedListener)
-};
-
-/// @class AudioLabelProvider
-/// @brief Abstract interface for audio label providers
-class AudioLabelProvider {
-protected:
- /// One or more of the labels provided by this object have changed
- agi::signal::Signal<> AnnounceLabelChanged;
-public:
- /// A label for a range of time on the audio display
- struct AudioLabel {
- /// Text of the label
- wxString text;
- /// Range which this label applies to
- TimeRange range;
- AudioLabel(wxString const& text, TimeRange const& range) : text(text), range(range) { }
- };
-
- /// Virtual destructor, does nothing
- virtual ~AudioLabelProvider() { }
-
- /// @brief Get labels in a time range
- /// @param range Range of times to get labels for
- /// @param[out] out Vector which should be filled with the labels
- virtual void GetLabels(TimeRange const& range, std::vector &out) const = 0;
-
- DEFINE_SIGNAL_ADDERS(AnnounceLabelChanged, AddLabelChangedListener)
-};
+namespace agi { struct Context; }
+class TimeRange;
/// @class AudioController
-/// @brief Manage an open audio stream and UI state for it
-///
-/// Keeps track of the UI interaction state of the open audio for a project,
-/// i.e. what the current selection is, what movable markers are on the audio,
-/// and any secondary non-movable markers that are present.
-///
-/// Changes in interaction are broadcast to all managed audio displays so they
-/// can redraw, and the audio displays report all interactions back to the
-/// controller. There is a one to many relationship between controller and
-/// audio displays. There is at most one audio controller for an open
-/// subtitling project.
+/// @brief Manage an open audio stream
///
/// Creates and destroys audio providers and players. This behaviour should at
/// some point be moved to a separate class, as it adds too many
@@ -173,7 +70,7 @@ public:
/// providers or players owned by a controller. If some operation that isn't
/// possible in the existing design is needed, the controller should be
/// extended in some way to allow it.
-class AudioController : public wxEvtHandler, public AudioMarkerProvider, public AudioLabelProvider {
+class AudioController : public wxEvtHandler {
/// Project context this controller belongs to
agi::Context *context;
@@ -195,12 +92,6 @@ class AudioController : public wxEvtHandler, public AudioMarkerProvider, public
/// The timing controller was replaced
agi::signal::Signal<> AnnounceTimingControllerChanged;
- /// The selected time range changed
- agi::signal::Signal<> AnnounceSelectionChanged;
-
- /// The styling ranges have been updated by the timing controller
- agi::signal::Signal<> AnnounceStyleRangesChanged;
-
/// The audio output object
AudioPlayer *player;
@@ -210,9 +101,6 @@ class AudioController : public wxEvtHandler, public AudioMarkerProvider, public
/// The current timing mode, if any; owned by the audio controller
agi::scoped_ptr timing_controller;
- /// Provider current video position data for audio display
- agi::scoped_ptr video_position_marker_provider;
-
/// The URL of the currently open audio, if any
wxString audio_url;
@@ -356,17 +244,6 @@ public:
/// @return An immutable TimeRange object
TimeRange GetPrimaryPlaybackRange() const;
- /// @brief Get all markers inside a range
- /// @param range The time range to retrieve markers for
- /// @param markers Vector to fill found markers into
- void GetMarkers(const TimeRange &range, AudioMarkerVector &markers) const;
-
- /// @brief Get all labels inside a range
- /// @param range The time range to retrieve labels for
- /// @param labels Vector to fill found labels into
- void GetLabels(const TimeRange &range, std::vector &labels) const;
-
-
/// @brief Get the playback audio volume
/// @return The amplification factor for the audio
double GetVolume() const;
@@ -396,43 +273,6 @@ public:
DEFINE_SIGNAL_ADDERS(AnnouncePlaybackPosition, AddPlaybackPositionListener)
DEFINE_SIGNAL_ADDERS(AnnouncePlaybackStop, AddPlaybackStopListener)
DEFINE_SIGNAL_ADDERS(AnnounceTimingControllerChanged, AddTimingControllerListener)
- DEFINE_SIGNAL_ADDERS(AnnounceSelectionChanged, AddSelectionChangedListener)
- DEFINE_SIGNAL_ADDERS(AnnounceStyleRangesChanged, AddStyleRangesChangedListener)
-};
-
-/// @class AudioMarker
-/// @brief A marker on the audio display
-class AudioMarker {
-public:
-
- /// Describe which directions a marker has feet in
- enum FeetStyle {
- Feet_None = 0,
- Feet_Left,
- Feet_Right,
- Feet_Both // Conveniently Feet_Left|Feet_Right
- };
-
- /// @brief Get the marker's position
- /// @return The marker's position in milliseconds
- virtual int GetPosition() const = 0;
-
- /// @brief Get the marker's drawing style
- /// @return A pen object describing the marker's drawing style
- virtual wxPen GetStyle() const = 0;
-
- /// @brief Get the marker's feet style
- /// @return The marker's feet style
- virtual FeetStyle GetFeet() const = 0;
-
- /// @brief Retrieve whether this marker participates in snapping
- /// @return True if this marker may snap to other snappable markers
- ///
- /// If a marker being dragged returns true from this method, and another
- /// marker which also returns true from this method is within range, the
- /// marker being dragged will be positioned at the position of the other
- /// marker if it is released while it is inside snapping range.
- virtual bool CanSnap() const = 0;
};
namespace agi {
diff --git a/aegisub/src/audio_display.cpp b/aegisub/src/audio_display.cpp
index 334923464..126277a5e 100644
--- a/aegisub/src/audio_display.cpp
+++ b/aegisub/src/audio_display.cpp
@@ -37,6 +37,8 @@
#include "config.h"
+#include "audio_display.h"
+
#ifndef AGI_PRE
#include
@@ -48,7 +50,6 @@
#include "ass_time.h"
#include "audio_colorscheme.h"
#include "audio_controller.h"
-#include "audio_display.h"
#include "audio_renderer.h"
#include "audio_renderer_spectrum.h"
#include "audio_renderer_waveform.h"
@@ -848,7 +849,7 @@ void AudioDisplay::PaintAudio(wxDC &dc, TimeRange updtime, wxRect updrect)
void AudioDisplay::PaintMarkers(wxDC &dc, TimeRange updtime)
{
AudioMarkerVector markers;
- controller->GetMarkers(updtime, markers);
+ controller->GetTimingController()->GetMarkers(updtime, markers);
if (markers.empty()) return;
wxDCPenChanger pen_retainer(dc, wxPen());
@@ -884,7 +885,7 @@ void AudioDisplay::PaintFoot(wxDC &dc, int marker_x, int dir)
void AudioDisplay::PaintLabels(wxDC &dc, TimeRange updtime)
{
std::vector labels;
- controller->GetLabels(updtime, labels);
+ controller->GetTimingController()->GetLabels(updtime, labels);
if (labels.empty()) return;
wxDCFontChanger fc(dc);
@@ -1166,10 +1167,7 @@ void AudioDisplay::OnAudioOpen(AudioProvider *provider)
connections.push_back(controller->AddAudioCloseListener(&AudioDisplay::OnAudioOpen, this, (AudioProvider*)0));
connections.push_back(controller->AddPlaybackPositionListener(&AudioDisplay::OnPlaybackPosition, this));
connections.push_back(controller->AddPlaybackStopListener(&AudioDisplay::RemoveTrackCursor, this));
- connections.push_back(controller->AddTimingControllerListener(&AudioDisplay::OnStyleRangesChanged, this));
- connections.push_back(controller->AddMarkerMovedListener(&AudioDisplay::OnMarkerMoved, this));
- connections.push_back(controller->AddSelectionChangedListener(&AudioDisplay::OnSelectionChanged, this));
- connections.push_back(controller->AddStyleRangesChangedListener(&AudioDisplay::OnStyleRangesChanged, this));
+ connections.push_back(controller->AddTimingControllerListener(&AudioDisplay::OnTimingController, this));
connections.push_back(OPT_SUB("Audio/Spectrum", &AudioDisplay::ReloadRenderingSettings, this));
connections.push_back(OPT_SUB("Audio/Display/Waveform Style", &AudioDisplay::ReloadRenderingSettings, this));
connections.push_back(OPT_SUB("Colour/Audio Display/Spectrum", &AudioDisplay::ReloadRenderingSettings, this));
@@ -1183,6 +1181,20 @@ void AudioDisplay::OnAudioOpen(AudioProvider *provider)
}
}
+void AudioDisplay::OnTimingController()
+{
+ AudioTimingController *timing_controller = controller->GetTimingController();
+ if (timing_controller)
+ {
+ timing_controller->AddMarkerMovedListener(&AudioDisplay::OnMarkerMoved, this);
+ timing_controller->AddUpdatedPrimaryRangeListener(&AudioDisplay::OnSelectionChanged, this);
+ timing_controller->AddUpdatedStyleRangesListener(&AudioDisplay::OnStyleRangesChanged, this);
+
+ OnStyleRangesChanged();
+ OnMarkerMoved();
+ }
+}
+
void AudioDisplay::OnPlaybackPosition(int ms)
{
int pixel_position = AbsoluteXFromTime(ms);
diff --git a/aegisub/src/audio_display.h b/aegisub/src/audio_display.h
index 07e47e5a4..d9ec7c069 100644
--- a/aegisub/src/audio_display.h
+++ b/aegisub/src/audio_display.h
@@ -49,10 +49,12 @@
namespace agi { struct Context; }
+class AudioController;
class AudioRenderer;
class AudioRendererBitmapProvider;
class AudioKaraoke;
class AudioProvider;
+class TimeRange;
// Helper classes used in implementation of the audio display
class AudioDisplayScrollbar;
@@ -113,7 +115,6 @@ class AudioDisplay: public wxWindow {
/// The controller managing us
AudioController *controller;
-
/// Scrollbar helper object
agi::scoped_ptr scrollbar;
@@ -223,6 +224,7 @@ class AudioDisplay: public wxWindow {
void OnPlaybackPosition(int ms_position);
void OnSelectionChanged();
void OnStyleRangesChanged();
+ void OnTimingController();
void OnMarkerMoved();
public:
diff --git a/aegisub/src/audio_karaoke.cpp b/aegisub/src/audio_karaoke.cpp
index 51bd762e4..2d84a350e 100644
--- a/aegisub/src/audio_karaoke.cpp
+++ b/aegisub/src/audio_karaoke.cpp
@@ -47,6 +47,7 @@
#include "ass_karaoke.h"
#include "ass_override.h"
#include "audio_box.h"
+#include "audio_controller.h"
#include "audio_timing.h"
#include "libresrc/libresrc.h"
#include "main.h"
diff --git a/aegisub/src/audio_marker_provider_keyframes.cpp b/aegisub/src/audio_marker.cpp
similarity index 64%
rename from aegisub/src/audio_marker_provider_keyframes.cpp
rename to aegisub/src/audio_marker.cpp
index d2eb6ba1b..46e709d89 100644
--- a/aegisub/src/audio_marker_provider_keyframes.cpp
+++ b/aegisub/src/audio_marker.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011, Thomas Goyne
+// Copyright (c) 2012, 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
@@ -16,14 +16,14 @@
//
// $Id$
-/// @file audio_marker_provider_keyframes.cpp
-/// @see audio_marker_provider_keyframes.h
+/// @file audio_marker.cpp
+/// @see audio_marker.h
/// @ingroup audio_ui
///
#include "config.h"
-#include "audio_marker_provider_keyframes.h"
+#include "audio_marker.h"
#include "include/aegisub/context.h"
#include "main.h"
@@ -49,7 +49,6 @@ public:
AudioMarkerProviderKeyframes::AudioMarkerProviderKeyframes(agi::Context *c, const char *opt_name)
: vc(c->videoController)
, keyframe_slot(vc->AddKeyframesListener(&AudioMarkerProviderKeyframes::Update, this))
-, audio_open_slot(c->audioController->AddAudioOpenListener(&AudioMarkerProviderKeyframes::Update, this))
, timecode_slot(vc->AddTimecodesListener(&AudioMarkerProviderKeyframes::Update, this))
, enabled_slot(OPT_SUB(opt_name, &AudioMarkerProviderKeyframes::Update, this))
, enabled_opt(OPT_GET(opt_name))
@@ -90,3 +89,55 @@ void AudioMarkerProviderKeyframes::GetMarkers(TimeRange const& range, AudioMarke
for (; a != b; ++a)
out.push_back(&*a);
}
+
+class VideoPositionMarker : public AudioMarker {
+ Pen style;
+ int position;
+
+public:
+ VideoPositionMarker()
+ : style("Colour/Audio Display/Play Cursor")
+ , position(-1)
+ {
+ }
+
+ void SetPosition(int new_pos) { position = new_pos; }
+
+ int GetPosition() const { return position; }
+ FeetStyle GetFeet() const { return Feet_None; }
+ bool CanSnap() const { return true; }
+ wxPen GetStyle() const { return style; }
+ operator int() const { return position; }
+};
+
+VideoPositionMarkerProvider::VideoPositionMarkerProvider(agi::Context *c)
+: vc(c->videoController)
+, video_seek_slot(vc->AddSeekListener(&VideoPositionMarkerProvider::Update, this))
+, enable_opt_changed_slot(OPT_SUB("Audio/Display/Draw/Video Position", &VideoPositionMarkerProvider::OptChanged, this))
+{
+ OptChanged(*OPT_GET("Audio/Display/Draw/Video Position"));
+}
+
+VideoPositionMarkerProvider::~VideoPositionMarkerProvider() { }
+
+void VideoPositionMarkerProvider::Update(int frame_number) {
+ marker->SetPosition(vc->TimeAtFrame(frame_number));
+ AnnounceMarkerMoved();
+}
+
+void VideoPositionMarkerProvider::OptChanged(agi::OptionValue const& opt) {
+ if (opt.GetBool()) {
+ video_seek_slot.Unblock();
+ marker.reset(new VideoPositionMarker);
+ marker->SetPosition(vc->GetFrameN());
+ }
+ else {
+ video_seek_slot.Block();
+ marker.reset();
+ }
+}
+
+void VideoPositionMarkerProvider::GetMarkers(const TimeRange &range, AudioMarkerVector &out) const {
+ if (marker && range.contains(*marker))
+ out.push_back(marker.get());
+}
diff --git a/aegisub/src/audio_marker.h b/aegisub/src/audio_marker.h
new file mode 100644
index 000000000..792476098
--- /dev/null
+++ b/aegisub/src/audio_marker.h
@@ -0,0 +1,175 @@
+// Copyright (c) 2012, 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/
+//
+// $Id$
+
+/// @file audio_marker.h
+/// @see audio_marker.cpp
+/// @ingroup audio_ui
+///
+
+#pragma once
+
+#include
+#include
+
+#ifndef AGI_PRE
+#include
+#endif
+
+class AudioMarkerKeyframe;
+class Pen;
+class VideoContext;
+class TimeRange;
+class VideoPositionMarker;
+
+#include "time_range.h"
+
+namespace agi {
+ class OptionValue;
+ struct Context;
+}
+
+/// @class AudioMarker
+/// @brief A marker on the audio display
+class AudioMarker {
+public:
+ /// Describe which directions a marker has feet in
+ enum FeetStyle {
+ Feet_None = 0,
+ Feet_Left,
+ Feet_Right,
+ Feet_Both // Conveniently Feet_Left|Feet_Right
+ };
+
+ /// @brief Get the marker's position
+ /// @return The marker's position in milliseconds
+ virtual int GetPosition() const = 0;
+
+ /// @brief Get the marker's drawing style
+ /// @return A pen object describing the marker's drawing style
+ virtual wxPen GetStyle() const = 0;
+
+ /// @brief Get the marker's feet style
+ /// @return The marker's feet style
+ virtual FeetStyle GetFeet() const = 0;
+
+ /// @brief Retrieve whether this marker participates in snapping
+ /// @return True if this marker may snap to other snappable markers
+ ///
+ /// If a marker being dragged returns true from this method, and another
+ /// marker which also returns true from this method is within range, the
+ /// marker being dragged will be positioned at the position of the other
+ /// marker if it is released while it is inside snapping range.
+ virtual bool CanSnap() const = 0;
+};
+
+typedef std::vector AudioMarkerVector;
+
+/// Abstract interface for audio marker providers
+class AudioMarkerProvider {
+protected:
+ /// One or more of the markers provided by this object have changed
+ agi::signal::Signal<> AnnounceMarkerMoved;
+public:
+ /// Virtual destructor, does nothing
+ virtual ~AudioMarkerProvider() { }
+
+ /// @brief Return markers in a time range
+ virtual void GetMarkers(const TimeRange &range, AudioMarkerVector &out) const = 0;
+
+ DEFINE_SIGNAL_ADDERS(AnnounceMarkerMoved, AddMarkerMovedListener)
+};
+
+/// @class AudioLabelProvider
+/// @brief Abstract interface for audio label providers
+class AudioLabelProvider {
+protected:
+ /// One or more of the labels provided by this object have changed
+ agi::signal::Signal<> AnnounceLabelChanged;
+public:
+ /// A label for a range of time on the audio display
+ struct AudioLabel {
+ /// Text of the label
+ wxString text;
+ /// Range which this label applies to
+ TimeRange range;
+ AudioLabel(wxString const& text, TimeRange const& range) : text(text), range(range) { }
+ };
+
+ /// Virtual destructor, does nothing
+ virtual ~AudioLabelProvider() { }
+
+ /// @brief Get labels in a time range
+ /// @param range Range of times to get labels for
+ /// @param[out] out Vector which should be filled with the labels
+ virtual void GetLabels(TimeRange const& range, std::vector &out) const = 0;
+
+ DEFINE_SIGNAL_ADDERS(AnnounceLabelChanged, AddLabelChangedListener)
+};
+
+
+/// Marker provider for video keyframes
+class AudioMarkerProviderKeyframes : public AudioMarkerProvider {
+ /// Video controller to get keyframes from
+ VideoContext *vc;
+
+ agi::signal::Connection keyframe_slot;
+ agi::signal::Connection timecode_slot;
+ agi::signal::Connection enabled_slot;
+ const agi::OptionValue *enabled_opt;
+
+ /// Current set of markers for the keyframes
+ std::vector markers;
+
+ /// Pen used for all keyframe markers, stored here for performance reasons
+ agi::scoped_ptr style;
+
+ /// Regenerate the list of markers
+ void Update();
+
+public:
+ /// Constructor
+ /// @param c Project context; must have audio and video controllers initialized
+ /// @param opt_name Name of the option to use to decide whether or not this provider is enabled
+ AudioMarkerProviderKeyframes(agi::Context *c, const char *opt_name);
+ /// Explicit destructor needed due to members with incomplete types
+ ~AudioMarkerProviderKeyframes();
+
+ /// Get all keyframe markers within a range
+ /// @param range Time range to get markers for
+ /// @param[out] out Vector to fill with markers in the range
+ void GetMarkers(TimeRange const& range, AudioMarkerVector &out) const;
+};
+
+/// Marker provider for the current video playback position
+class VideoPositionMarkerProvider : public AudioMarkerProvider {
+ VideoContext *vc;
+
+ agi::scoped_ptr marker;
+
+ agi::signal::Connection video_seek_slot;
+ agi::signal::Connection enable_opt_changed_slot;
+
+ void Update(int frame_number);
+ void OptChanged(agi::OptionValue const& opt);
+
+public:
+ VideoPositionMarkerProvider(agi::Context *c);
+ ~VideoPositionMarkerProvider();
+
+ void GetMarkers(const TimeRange &range, AudioMarkerVector &out) const;
+};
diff --git a/aegisub/src/audio_marker_provider_keyframes.h b/aegisub/src/audio_marker_provider_keyframes.h
deleted file mode 100644
index bc2fd5a12..000000000
--- a/aegisub/src/audio_marker_provider_keyframes.h
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright (c) 2011, 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/
-//
-// $Id$
-
-/// @file audio_marker_provider_keyframes.h
-/// @see audio_marker_provider_keyframes.cpp
-/// @ingroup audio_ui
-///
-
-#include "audio_controller.h"
-
-#include
-#include
-
-#ifndef AGI_PRE
-#include
-#endif
-
-class AudioMarkerKeyframe;
-class Pen;
-class VideoContext;
-namespace agi {
- class OptionValue;
- struct Context;
-}
-
-/// Marker provider for video keyframes
-class AudioMarkerProviderKeyframes : public AudioMarkerProvider {
- /// Video controller to get keyframes from
- VideoContext *vc;
-
- agi::signal::Connection keyframe_slot;
- agi::signal::Connection audio_open_slot;
- agi::signal::Connection timecode_slot;
- agi::signal::Connection enabled_slot;
- const agi::OptionValue *enabled_opt;
-
- /// Current set of markers for the keyframes
- std::vector markers;
-
- /// Pen used for all keyframe markers, stored here for performance reasons
- agi::scoped_ptr style;
-
- /// Regenerate the list of markers
- void Update();
-
-public:
- /// Constructor
- /// @param c Project context; must have audio and video controllers initialized
- /// @param opt_name Name of the option to use to decide whether or not this provider is enabled
- AudioMarkerProviderKeyframes(agi::Context *c, const char *opt_name);
- /// Explicit destructor needed due to members with incomplete types
- ~AudioMarkerProviderKeyframes();
-
- /// Get all keyframe markers within a range
- /// @param range Range of samples to get markers for
- /// @param[out] out Vector to fill with markers in the range
- void GetMarkers(TimeRange const& range, AudioMarkerVector &out) const;
-};
diff --git a/aegisub/src/audio_timing.h b/aegisub/src/audio_timing.h
index c3ce1d237..730300f40 100644
--- a/aegisub/src/audio_timing.h
+++ b/aegisub/src/audio_timing.h
@@ -39,11 +39,9 @@ class AssKaraoke;
class AudioRenderingStyleRanges;
namespace agi { struct Context; }
-#include "audio_controller.h"
+#include "audio_marker.h"
#include "selection_controller.h"
-#include
-
/// @class AudioTimingController
/// @brief Base class for objects controlling audio timing
///
diff --git a/aegisub/src/audio_timing_dialogue.cpp b/aegisub/src/audio_timing_dialogue.cpp
index c1d36de08..86ea88c16 100644
--- a/aegisub/src/audio_timing_dialogue.cpp
+++ b/aegisub/src/audio_timing_dialogue.cpp
@@ -42,7 +42,6 @@
#include "ass_dialogue.h"
#include "ass_file.h"
#include "ass_time.h"
-#include "audio_marker_provider_keyframes.h"
#include "audio_renderer.h"
#include "audio_timing.h"
#include "include/aegisub/context.h"
@@ -158,6 +157,9 @@ class AudioTimingControllerDialogue : public AudioTimingController, private Sele
/// Marker provider for video keyframes
AudioMarkerProviderKeyframes keyframes_provider;
+ /// Marker provider for video playback position
+ VideoPositionMarkerProvider video_position_provider;
+
/// Has the timing been modified by the user?
/// If auto commit is enabled this will only be true very briefly following
/// changes
@@ -294,6 +296,7 @@ void AudioMarkerDialogueTiming::InitPair(AudioMarkerDialogueTiming *marker1, Aud
AudioTimingControllerDialogue::AudioTimingControllerDialogue(agi::Context *c)
: keyframes_provider(c, "Audio/Display/Draw/Keyframes in Dialogue Mode")
+, video_position_provider(c)
, timing_modified(false)
, commit_id(-1)
, context(c)
@@ -308,6 +311,7 @@ AudioTimingControllerDialogue::AudioTimingControllerDialogue(agi::Context *c)
c->selectionController->AddSelectionListener(this);
keyframes_provider.AddMarkerMovedListener(std::tr1::bind(std::tr1::ref(AnnounceMarkerMoved)));
+ video_position_provider.AddMarkerMovedListener(std::tr1::bind(std::tr1::ref(AnnounceMarkerMoved)));
Revert();
}
@@ -357,6 +361,7 @@ void AudioTimingControllerDialogue::GetMarkers(const TimeRange &range, AudioMark
out_markers.push_back(&active_markers[1]);
keyframes_provider.GetMarkers(range, out_markers);
+ video_position_provider.GetMarkers(range, out_markers);
}
void AudioTimingControllerDialogue::OnActiveLineChanged(AssDialogue *new_line)
diff --git a/aegisub/src/audio_timing_karaoke.cpp b/aegisub/src/audio_timing_karaoke.cpp
index 9020adb5e..9d46245da 100644
--- a/aegisub/src/audio_timing_karaoke.cpp
+++ b/aegisub/src/audio_timing_karaoke.cpp
@@ -28,7 +28,7 @@
#include "ass_dialogue.h"
#include "ass_file.h"
#include "ass_karaoke.h"
-#include "audio_marker_provider_keyframes.h"
+#include "audio_controller.h"
#include "audio_renderer.h"
#include "audio_timing.h"
#include "include/aegisub/context.h"
@@ -101,6 +101,9 @@ class AudioTimingControllerKaraoke : public AudioTimingController {
/// Marker provider for video keyframes
AudioMarkerProviderKeyframes keyframes_provider;
+ /// Marker provider for video playback position
+ VideoPositionMarkerProvider video_position_provider;
+
/// Labels containing the stripped text of each syllable
std::vector labels;
@@ -150,6 +153,7 @@ AudioTimingControllerKaraoke::AudioTimingControllerKaraoke(agi::Context *c, AssK
, start_marker(active_line->Start, &start_pen, AudioMarker::Feet_Right)
, end_marker(active_line->End, &end_pen, AudioMarker::Feet_Left)
, keyframes_provider(c, "Audio/Display/Draw/Keyframes in Karaoke Mode")
+, video_position_provider(c)
, auto_commit(OPT_GET("Audio/Auto/Commit")->GetBool())
, auto_next(OPT_GET("Audio/Next Line on Commit")->GetBool())
, commit_id(-1)
@@ -159,6 +163,7 @@ AudioTimingControllerKaraoke::AudioTimingControllerKaraoke(agi::Context *c, AssK
slots.push_back(OPT_SUB("Audio/Next Line on Commit", &AudioTimingControllerKaraoke::OnAutoNextChange, this));
keyframes_provider.AddMarkerMovedListener(std::tr1::bind(std::tr1::ref(AnnounceMarkerMoved)));
+ video_position_provider.AddMarkerMovedListener(std::tr1::bind(std::tr1::ref(AnnounceMarkerMoved)));
Revert();
@@ -231,6 +236,7 @@ void AudioTimingControllerKaraoke::GetMarkers(TimeRange const& range, AudioMarke
if (range.contains(end_marker)) out.push_back(&end_marker);
keyframes_provider.GetMarkers(range, out);
+ video_position_provider.GetMarkers(range, out);
}
void AudioTimingControllerKaraoke::DoCommit() {
diff --git a/aegisub/src/time_range.h b/aegisub/src/time_range.h
new file mode 100644
index 000000000..a77705311
--- /dev/null
+++ b/aegisub/src/time_range.h
@@ -0,0 +1,76 @@
+// Copyright (c) 2010, Niels Martin Hansen
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name of the Aegisub Group nor the names of its contributors
+// may be used to endorse or promote products derived from this software
+// without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+// Aegisub Project http://www.aegisub.org/
+//
+// $Id$
+
+/// @file time_range.h
+/// @ingroup audio_ui
+
+/// @class TimeRange
+/// @brief Represents an immutable range of time
+class TimeRange {
+ int _begin;
+ int _end;
+
+public:
+ /// @brief Constructor
+ /// @param begin Index of the first millisecond to include in the range
+ /// @param end Index of one past the last millisecond to include in the range
+ TimeRange(int begin, int end) : _begin(begin), _end(end)
+ {
+ assert(end >= begin);
+ }
+
+ /// @brief Copy constructor, optionally adjusting the range
+ /// @param src The range to duplicate
+ /// @param begin_adjust Number of milliseconds to add to the start of the range
+ /// @param end_adjust Number of milliseconds to add to the end of the range
+ TimeRange(const TimeRange &src, int begin_adjust = 0, int end_adjust = 0)
+ {
+ _begin = src._begin + begin_adjust;
+ _end = src._end + end_adjust;
+ assert(_end >= _begin);
+ }
+
+ /// Get the length of the range in milliseconds
+ int length() const { return _end - _begin; }
+ /// Get the start time of the range in milliseconds
+ int begin() const { return _begin; }
+ /// Get the exclusive end time of the range in milliseconds
+ int end() const { return _end; }
+
+ /// Determine whether the range contains a given time in milliseconds
+ bool contains(int ms) const { return ms >= begin() && ms < end(); }
+
+ /// Determine whether there is an overlap between two ranges
+ bool overlaps(const TimeRange &other) const
+ {
+ return other.contains(_begin) || contains(other._begin);
+ }
+};
diff --git a/aegisub/src/video_context.cpp b/aegisub/src/video_context.cpp
index bcc1d6ede..51d3cfd5e 100644
--- a/aegisub/src/video_context.cpp
+++ b/aegisub/src/video_context.cpp
@@ -61,6 +61,7 @@
#include "mkv_wrap.h"
#include "selection_controller.h"
#include "standard_paths.h"
+#include "time_range.h"
#include "threaded_frame_source.h"
#include "utils.h"
#include "video_context.h"