Use signals in AudioController and AudioTimingController

Originally committed to SVN as r4907.
This commit is contained in:
Thomas Goyne 2010-12-08 08:09:16 +00:00
parent 3bb1f590d7
commit 3345797ff6
31 changed files with 222 additions and 448 deletions

View file

@ -39,7 +39,6 @@
#include "ass_export_filter.h" #include "ass_export_filter.h"
#include "ass_exporter.h" #include "ass_exporter.h"
#include "ass_file.h" #include "ass_file.h"
#include "audio_controller.h"
#include "frame_main.h" #include "frame_main.h"
/// @brief Constructor /// @brief Constructor

View file

@ -425,8 +425,8 @@ void AudioBox::OnPrev(wxCommandEvent &event) {
/// @param event /// @param event
/// ///
void AudioBox::OnPlay500Before(wxCommandEvent &event) { void AudioBox::OnPlay500Before(wxCommandEvent &event) {
AudioController::SampleRange times(controller->GetPrimaryPlaybackRange()); SampleRange times(controller->GetPrimaryPlaybackRange());
controller->PlayRange(AudioController::SampleRange( controller->PlayRange(SampleRange(
times.begin() - controller->SamplesFromMilliseconds(500), times.begin() - controller->SamplesFromMilliseconds(500),
times.begin())); times.begin()));
} }
@ -437,8 +437,8 @@ void AudioBox::OnPlay500Before(wxCommandEvent &event) {
/// @param event /// @param event
/// ///
void AudioBox::OnPlay500After(wxCommandEvent &event) { void AudioBox::OnPlay500After(wxCommandEvent &event) {
AudioController::SampleRange times(controller->GetPrimaryPlaybackRange()); SampleRange times(controller->GetPrimaryPlaybackRange());
controller->PlayRange(AudioController::SampleRange( controller->PlayRange(SampleRange(
times.end(), times.end(),
times.end() + controller->SamplesFromMilliseconds(500))); times.end() + controller->SamplesFromMilliseconds(500)));
} }
@ -449,8 +449,8 @@ void AudioBox::OnPlay500After(wxCommandEvent &event) {
/// @param event /// @param event
/// ///
void AudioBox::OnPlay500First(wxCommandEvent &event) { void AudioBox::OnPlay500First(wxCommandEvent &event) {
AudioController::SampleRange times(controller->GetPrimaryPlaybackRange()); SampleRange times(controller->GetPrimaryPlaybackRange());
controller->PlayRange(AudioController::SampleRange( controller->PlayRange(SampleRange(
times.begin(), times.begin(),
times.begin() + std::min( times.begin() + std::min(
controller->SamplesFromMilliseconds(500), controller->SamplesFromMilliseconds(500),
@ -463,8 +463,8 @@ void AudioBox::OnPlay500First(wxCommandEvent &event) {
/// @param event /// @param event
/// ///
void AudioBox::OnPlay500Last(wxCommandEvent &event) { void AudioBox::OnPlay500Last(wxCommandEvent &event) {
AudioController::SampleRange times(controller->GetPrimaryPlaybackRange()); SampleRange times(controller->GetPrimaryPlaybackRange());
controller->PlayRange(AudioController::SampleRange( controller->PlayRange(SampleRange(
times.end() - std::min( times.end() - std::min(
controller->SamplesFromMilliseconds(500), controller->SamplesFromMilliseconds(500),
times.length()), times.length()),

View file

@ -54,14 +54,11 @@
#include <wx/tglbtn.h> #include <wx/tglbtn.h>
#endif #endif
#ifndef AGI_AUDIO_CONTROLLER_INCLUDED
#error You must include "audio_controller.h" before "audio_box.h"
#endif
////////////// //////////////
// Prototypes // Prototypes
class AudioController;
class AssDialogue; class AssDialogue;
class AudioTimingController;
class AudioDisplay; class AudioDisplay;
class AudioKaraoke; class AudioKaraoke;
class FrameMain; class FrameMain;
@ -80,7 +77,7 @@ class AudioBox : public wxPanel {
/// Selection controller used for timing controllers /// Selection controller used for timing controllers
SelectionController<AssDialogue> *selection_controller; SelectionController<AssDialogue> *selection_controller;
/// The regular dalogue timing controller /// The regular dialogue timing controller
AudioTimingController *timing_controller_dialogue; AudioTimingController *timing_controller_dialogue;
/// DOCME /// DOCME

View file

@ -74,71 +74,51 @@ bool operator < (int64_t a, const AudioMarkerKeyframe &b) { return a < b.GetPosi
bool operator < (const AudioMarkerKeyframe &a, int64_t b) { return a.GetPosition() < b; } bool operator < (const AudioMarkerKeyframe &a, int64_t b) { return a.GetPosition() < b; }
wxPen AudioMarkerKeyframe::style; wxPen AudioMarkerKeyframe::style;
class AudioMarkerProviderKeyframes : public AudioMarkerProvider, private AudioControllerAudioEventListener { class AudioMarkerProviderKeyframes : public AudioMarkerProvider {
// GetMarkers needs to be const but still needs to modify this state, which is really VideoContext *vc;
// just a cache... use the mutable "hack".
mutable int last_keyframes_revision;
mutable std::vector<AudioMarkerKeyframe> keyframe_samples;
AudioController *controller;
int64_t samplerate;
void ReloadKeyframes() const agi::signal::Connection keyframe_slot;
agi::signal::Connection audio_open_slot;
std::vector<AudioMarkerKeyframe> keyframe_samples;
AudioController *controller;
void OnKeyframesOpen(std::vector<int> const& raw_keyframes)
{ {
keyframe_samples.clear(); keyframe_samples.clear();
VideoContext *vc = VideoContext::Get();
if (!vc) return;
last_keyframes_revision = vc->GetKeyframesRevision();
const std::vector<int> &raw_keyframes = vc->GetKeyFrames();
keyframe_samples.reserve(raw_keyframes.size()); keyframe_samples.reserve(raw_keyframes.size());
for (size_t i = 0; i < raw_keyframes.size(); ++i) for (size_t i = 0; i < raw_keyframes.size(); ++i)
{ {
keyframe_samples.push_back(AudioMarkerKeyframe( keyframe_samples.push_back(AudioMarkerKeyframe(
vc->TimeAtFrame(raw_keyframes[i]) * samplerate / 1000)); controller->SamplesFromMilliseconds(vc->TimeAtFrame(raw_keyframes[i]))));
} }
std::sort(keyframe_samples.begin(), keyframe_samples.end()); std::sort(keyframe_samples.begin(), keyframe_samples.end());
AnnounceMarkerMoved();
} }
private: private:
// AudioControllerAudioEventListener implementation // AudioControllerAudioEventListener implementation
virtual void OnAudioOpen(AudioProvider *provider) void OnAudioOpen(AudioProvider *)
{ {
samplerate = provider->GetSampleRate(); OnKeyframesOpen(vc->GetKeyFrames());
ReloadKeyframes();
} }
virtual void OnAudioClose() { }
virtual void OnPlaybackPosition(int64_t sample_position) { }
virtual void OnPlaybackStop() { }
public: public:
AudioMarkerProviderKeyframes(AudioController *controller) AudioMarkerProviderKeyframes(AudioController *controller)
: controller(controller) : vc(VideoContext::Get())
, keyframe_slot(vc->AddKeyframesOpenListener(&AudioMarkerProviderKeyframes::OnKeyframesOpen, this))
, audio_open_slot(controller->AddAudioOpenListener(&AudioMarkerProviderKeyframes::OnAudioOpen, this))
, controller(controller)
{ {
// Assume that a video context with keyframes revision 0 never has keyframes loaded OnKeyframesOpen(vc->GetKeyFrames());
last_keyframes_revision = 0;
samplerate = 44100;
controller->AddAudioListener(this);
} }
virtual ~AudioMarkerProviderKeyframes() void GetMarkers(const SampleRange &range, AudioMarkerVector &out) const
{ {
controller->RemoveAudioListener(this);
}
void GetMarkers(const AudioController::SampleRange &range, AudioMarkerVector &out) const
{
VideoContext *vc = VideoContext::Get();
if (!vc) return;
// Re-read keyframe data if the revision number changed, the keyframe data probably did too
if (vc->GetKeyframesRevision() != last_keyframes_revision)
ReloadKeyframes();
// Find first and last keyframes inside the range // Find first and last keyframes inside the range
std::vector<AudioMarkerKeyframe>::iterator a = std::lower_bound( std::vector<AudioMarkerKeyframe>::const_iterator a = std::lower_bound(
keyframe_samples.begin(), keyframe_samples.end(), range.begin()); keyframe_samples.begin(), keyframe_samples.end(), range.begin());
std::vector<AudioMarkerKeyframe>::iterator b = std::upper_bound( std::vector<AudioMarkerKeyframe>::const_iterator b = std::upper_bound(
keyframe_samples.begin(), keyframe_samples.end(), range.end()); keyframe_samples.begin(), keyframe_samples.end(), range.end());
// Place pointers to the markers in the output vector // Place pointers to the markers in the output vector
@ -147,22 +127,9 @@ public:
} }
}; };
/// Type of the audio event listener container in AudioController
typedef std::set<AudioControllerAudioEventListener *> AudioEventListenerSet;
/// Type of the timing event listener container in AudioController
typedef std::set<AudioControllerTimingEventListener *> TimingEventListenerSet;
/// Macro to iterate audio event listeners in AudioController implementation
#define AUDIO_LISTENERS(listener) for (AudioEventListenerSet::iterator listener = audio_event_listeners.begin(); listener != audio_event_listeners.end(); ++listener)
/// Macro to iterate audio event listeners in AudioController implementation
#define TIMING_LISTENERS(listener) for (TimingEventListenerSet::iterator listener = timing_event_listeners.begin(); listener != timing_event_listeners.end(); ++listener)
AudioController::AudioController() AudioController::AudioController()
: player(0) : player(0)
, provider(0) , provider(0)
, timing_controller(0)
, keyframes_marker_provider(new AudioMarkerProviderKeyframes(this)) , keyframes_marker_provider(new AudioMarkerProviderKeyframes(this))
, playback_mode(PM_NotPlaying) , playback_mode(PM_NotPlaying)
, playback_timer(this) , playback_timer(this)
@ -195,10 +162,7 @@ void AudioController::OnPlaybackTimer(wxTimerEvent &event)
} }
else else
{ {
AUDIO_LISTENERS(l) AnnouncePlaybackPosition(pos);
{
(*l)->OnPlaybackPosition(pos);
}
} }
} }
@ -312,10 +276,7 @@ void AudioController::OpenAudio(const wxString &url)
} }
// Tell listeners about this. // Tell listeners about this.
AUDIO_LISTENERS(l) AnnounceAudioOpen(provider);
{
(*l)->OnAudioOpen(provider);
}
} }
@ -328,10 +289,7 @@ void AudioController::CloseAudio()
player = 0; player = 0;
provider = 0; provider = 0;
AUDIO_LISTENERS(l) AnnounceAudioClose();
{
(*l)->OnAudioClose();
}
} }
@ -347,90 +305,37 @@ wxString AudioController::GetAudioURL() const
return _T(""); return _T("");
} }
void AudioController::AddAudioListener(AudioControllerAudioEventListener *listener)
{
audio_event_listeners.insert(listener);
}
void AudioController::RemoveAudioListener(AudioControllerAudioEventListener *listener)
{
audio_event_listeners.erase(listener);
}
void AudioController::AddTimingListener(AudioControllerTimingEventListener *listener)
{
timing_event_listeners.insert(listener);
}
void AudioController::RemoveTimingListener(AudioControllerTimingEventListener *listener)
{
timing_event_listeners.erase(listener);
}
void AudioController::SetTimingController(AudioTimingController *new_controller) void AudioController::SetTimingController(AudioTimingController *new_controller)
{ {
delete timing_controller; if (timing_controller.get() != new_controller) {
timing_controller = new_controller; timing_controller.reset(new_controller);
timing_controller->AddMarkerMovedListener(std::tr1::bind(std::tr1::ref(AnnounceMarkerMoved)));
TIMING_LISTENERS(l) timing_controller->AddUpdatedPrimaryRangeListener(&AudioController::OnTimingControllerUpdatedPrimaryRange, this);
{ timing_controller->AddUpdatedStyleRangesListener(&AudioController::OnTimingControllerUpdatedStyleRanges, this);
(*l)->OnTimingControllerChanged();
} }
AnnounceTimingControllerChanged();
} }
void AudioController::OnTimingControllerUpdatedPrimaryRange(AudioTimingController *sending_controller) void AudioController::OnTimingControllerUpdatedPrimaryRange()
{ {
assert(sending_controller != 0);
if (sending_controller != timing_controller)
return;
if (playback_mode == PM_PrimaryRange) if (playback_mode == PM_PrimaryRange)
{ {
player->SetEndPosition(timing_controller->GetPrimaryPlaybackRange().end()); player->SetEndPosition(timing_controller->GetPrimaryPlaybackRange().end());
} }
TIMING_LISTENERS(l) AnnounceSelectionChanged();
{
(*l)->OnSelectionChanged();
}
} }
void AudioController::OnTimingControllerUpdatedStyleRanges(AudioTimingController *sending_controller) void AudioController::OnTimingControllerUpdatedStyleRanges()
{ {
assert(sending_controller != 0);
if (sending_controller != timing_controller)
return;
/// @todo redraw and stuff, probably /// @todo redraw and stuff, probably
} }
void AudioController::PlayRange(const SampleRange &range)
void AudioController::OnTimingControllerMarkerMoved(AudioTimingController *sending_controller, AudioMarker *marker)
{
assert(sending_controller != 0);
if (sending_controller != timing_controller)
return;
/// @todo shouldn't this be more detailed?
TIMING_LISTENERS(l)
{
(*l)->OnMarkersMoved();
}
}
void AudioController::PlayRange(const AudioController::SampleRange &range)
{ {
if (!IsAudioOpen()) return; if (!IsAudioOpen()) return;
@ -438,10 +343,7 @@ void AudioController::PlayRange(const AudioController::SampleRange &range)
playback_mode = PM_Range; playback_mode = PM_Range;
playback_timer.Start(20); playback_timer.Start(20);
AUDIO_LISTENERS(l) AnnouncePlaybackPosition(range.begin());
{
(*l)->OnPlaybackPosition(range.begin());
}
} }
@ -461,10 +363,7 @@ void AudioController::PlayToEnd(int64_t start_sample)
playback_mode = PM_ToEnd; playback_mode = PM_ToEnd;
playback_timer.Start(20); playback_timer.Start(20);
AUDIO_LISTENERS(l) AnnouncePlaybackPosition(start_sample);
{
(*l)->OnPlaybackPosition(start_sample);
}
} }
@ -476,10 +375,7 @@ void AudioController::Stop()
playback_mode = PM_NotPlaying; playback_mode = PM_NotPlaying;
playback_timer.Stop(); playback_timer.Stop();
AUDIO_LISTENERS(l) AnnouncePlaybackStop();
{
(*l)->OnPlaybackStop();
}
} }
@ -505,9 +401,9 @@ void AudioController::ResyncPlaybackPosition(int64_t new_position)
} }
AudioController::SampleRange AudioController::GetPrimaryPlaybackRange() const SampleRange AudioController::GetPrimaryPlaybackRange() const
{ {
if (timing_controller != 0) if (timing_controller.get())
{ {
return timing_controller->GetPrimaryPlaybackRange(); return timing_controller->GetPrimaryPlaybackRange();
} }
@ -522,6 +418,7 @@ void AudioController::GetMarkers(const SampleRange &range, AudioMarkerVector &ma
{ {
/// @todo Find all sources of markers /// @todo Find all sources of markers
keyframes_marker_provider->GetMarkers(range, markers); keyframes_marker_provider->GetMarkers(range, markers);
if (timing_controller.get()) timing_controller->GetMarkers(range, markers);
} }
@ -565,4 +462,3 @@ int64_t AudioController::MillisecondsFromSamples(int64_t samples) const
return millisamples / sr; return millisamples / sr;
} }

View file

@ -48,9 +48,8 @@
#endif #endif
#include <libaegisub/exception.h> #include <libaegisub/exception.h>
#include <libaegisub/scoped_ptr.h>
#define AGI_AUDIO_CONTROLLER_INCLUDED 1 #include <libaegisub/signals.h>
class AudioPlayer; class AudioPlayer;
class AudioProvider; class AudioProvider;
@ -62,32 +61,9 @@ class AudioTimingController;
class AudioMarker; class AudioMarker;
class AudioMarkerProvider; class AudioMarkerProvider;
typedef std::vector<const AudioMarker*> AudioMarkerVector; typedef std::vector<const AudioMarker*> AudioMarkerVector;
/// @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, ie. what the current
/// selection is, what moveable markers are on the audio, and any secondary non-moveable 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.
///
/// Creates and destroys audio providers and players. This behaviour should at some point be moved
/// to a separate class, as it adds too many responsibilities to this class, but at the time of
/// writing, it would extend the scope of reworking components too much.
///
/// There is not supposed to be a way to get direct access to the audio 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:
/// @class SampleRange /// @class SampleRange
/// @brief Represents an immutable range of audio samples /// @brief Represents an immutable range of audio samples
class SampleRange { class SampleRange {
@ -136,14 +112,60 @@ public:
} }
}; };
/// @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 sample range
virtual void GetMarkers(const SampleRange &range, AudioMarkerVector &out) const = 0;
DEFINE_SIGNAL_ADDERS(AnnounceMarkerMoved, AddMarkerMovedListener)
};
/// @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, ie. 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.
///
/// Creates and destroys audio providers and players. This behaviour should at some point be moved
/// to a separate class, as it adds too many responsibilities to this class, but at the time of
/// writing, it would extend the scope of reworking components too much.
///
/// There is not supposed to be a way to get direct access to the audio 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 {
private: private:
/// A new audio stream was opened (and any previously open was closed)
agi::signal::Signal<AudioProvider*> AnnounceAudioOpen;
/// Listeners for audio-related events /// The current audio stream was closed
std::set<AudioControllerAudioEventListener *> audio_event_listeners; agi::signal::Signal<> AnnounceAudioClose;
/// Listeners for timing-related events /// Playback is in progress and the current position was updated
std::set<AudioControllerTimingEventListener *> timing_event_listeners; agi::signal::Signal<int64_t> AnnouncePlaybackPosition;
/// Playback has stopped
agi::signal::Signal<> AnnouncePlaybackStop;
/// The timing controller was replaced
agi::signal::Signal<> AnnounceTimingControllerChanged;
/// The selected time range changed
agi::signal::Signal<> AnnounceSelectionChanged;
/// The audio output object /// The audio output object
AudioPlayer *player; AudioPlayer *player;
@ -152,10 +174,10 @@ private:
AudioProvider *provider; AudioProvider *provider;
/// The current timing mode, if any; owned by the audio controller /// The current timing mode, if any; owned by the audio controller
AudioTimingController *timing_controller; agi::scoped_ptr<AudioTimingController> timing_controller;
/// Provide keyframe data for audio displays /// Provide keyframe data for audio displays
std::auto_ptr<AudioMarkerProvider> keyframes_marker_provider; agi::scoped_ptr<AudioMarkerProvider> keyframes_marker_provider;
enum PlaybackMode { enum PlaybackMode {
@ -174,6 +196,11 @@ private:
/// Event handler for the playback timer /// Event handler for the playback timer
void OnPlaybackTimer(wxTimerEvent &event); void OnPlaybackTimer(wxTimerEvent &event);
/// @brief Timing controller signals primary playback range changed
void OnTimingControllerUpdatedPrimaryRange();
/// @brief Timing controller signals that the rendering style ranges have changed
void OnTimingControllerUpdatedStyleRanges();
#ifdef wxHAS_POWER_EVENTS #ifdef wxHAS_POWER_EVENTS
/// Handle computer going into suspend mode by stopping audio and closing device /// Handle computer going into suspend mode by stopping audio and closing device
@ -182,7 +209,6 @@ private:
void OnComputerResuming(wxPowerEvent &event); void OnComputerResuming(wxPowerEvent &event);
#endif #endif
public: public:
/// @brief Constructor /// @brief Constructor
@ -213,23 +239,6 @@ public:
wxString GetAudioURL() const; wxString GetAudioURL() const;
/// @brief Add an audio event listener
/// @param listener The listener to add
void AddAudioListener(AudioControllerAudioEventListener *listener);
/// @brief Remove an audio event listener
/// @param listener The listener to remove
void RemoveAudioListener(AudioControllerAudioEventListener *listener);
/// @brief Add a timing event listener
/// @param listener The listener to add
void AddTimingListener(AudioControllerTimingEventListener *listener);
/// @brief Remove a timing event listener
/// @param listener The listener to remove
void RemoveTimingListener(AudioControllerTimingEventListener *listener);
/// @brief Start or restart audio playback, playing a range /// @brief Start or restart audio playback, playing a range
/// @param range The range of audio to play back /// @param range The range of audio to play back
/// ///
@ -279,12 +288,9 @@ public:
/// @return An immutable SampleRange object /// @return An immutable SampleRange object
SampleRange GetPrimaryPlaybackRange() const; SampleRange GetPrimaryPlaybackRange() const;
/// @brief Get all static markers inside a range /// @brief Get all markers inside a range
/// @param range The sample range to retrieve markers for /// @param range The sample range to retrieve markers for
/// @param markers Vector to fill found markers into /// @param markers Vector to fill found markers into
///
/// The markers retrieved are static markers the user can't interact with.
/// Markers for user interaction are obtained through the timing controller.
void GetMarkers(const SampleRange &range, AudioMarkerVector &markers) const; void GetMarkers(const SampleRange &range, AudioMarkerVector &markers) const;
@ -304,7 +310,7 @@ public:
/// @brief Return the current timing controller /// @brief Return the current timing controller
/// @return The current timing controller or 0 /// @return The current timing controller or 0
AudioTimingController * GetTimingController() const { return timing_controller; } AudioTimingController * GetTimingController() const { return timing_controller.get(); }
/// @brief Change the current timing controller /// @brief Change the current timing controller
/// @param new_mode The new timing controller or 0. This may be the same object as /// @param new_mode The new timing controller or 0. This may be the same object as
@ -312,31 +318,6 @@ public:
/// the object being timed, eg. changed to a new dialogue line. /// the object being timed, eg. changed to a new dialogue line.
void SetTimingController(AudioTimingController *new_controller); void SetTimingController(AudioTimingController *new_controller);
/// @brief Timing controller signals primary playback range changed
/// @param timing_controller The timing controller sending this notification
///
/// Only timing controllers should call this function. This function must be called
/// when the primary playback range is changed in the timing controller, usually
/// as a result of user interaction.
void OnTimingControllerUpdatedPrimaryRange(AudioTimingController *timing_controller);
/// @brief Timing controller signals that the rendering style ranges have changed
/// @param timing_controller The timing controller sending this notification
///
/// Only timing controllers should call this function. This function must be called
/// when one or more rendering style ranges have changed in the timing controller.
void OnTimingControllerUpdatedStyleRanges(AudioTimingController *timing_controller);
/// @brief Timing controller signals that an audio marker has moved
/// @param timing_controller The timing controller sending this notification
/// @param marker The marker that was moved
///
/// Only timing controllers should call this function. This function must be called
/// when a marker owned by the timing controller has been updated in some way.
void OnTimingControllerMarkerMoved(AudioTimingController *timing_controller, AudioMarker *marker);
/// @brief Convert a count of audio samples to a time in milliseconds /// @brief Convert a count of audio samples to a time in milliseconds
/// @param samples Sample count to convert /// @param samples Sample count to convert
/// @return The number of milliseconds equivalent to the sample-count, rounded down /// @return The number of milliseconds equivalent to the sample-count, rounded down
@ -346,57 +327,15 @@ public:
/// @param ms Time in milliseconds to convert /// @param ms Time in milliseconds to convert
/// @return The index of the first sample that is wholly inside the millisecond /// @return The index of the first sample that is wholly inside the millisecond
int64_t SamplesFromMilliseconds(int64_t ms) const; int64_t SamplesFromMilliseconds(int64_t ms) const;
DEFINE_SIGNAL_ADDERS(AnnounceAudioOpen, AddAudioOpenListener)
DEFINE_SIGNAL_ADDERS(AnnounceAudioClose, AddAudioCloseListener)
DEFINE_SIGNAL_ADDERS(AnnouncePlaybackPosition, AddPlaybackPositionListener)
DEFINE_SIGNAL_ADDERS(AnnouncePlaybackStop, AddPlaybackStopListener)
DEFINE_SIGNAL_ADDERS(AnnounceTimingControllerChanged, AddTimingControllerListener)
DEFINE_SIGNAL_ADDERS(AnnounceSelectionChanged, AddSelectionChangedListener)
}; };
/// @class AudioControllerAudioEventListener
/// @brief Abstract interface for objects that want audio events
class AudioControllerAudioEventListener {
public:
/// A new audio stream was opened (and any previously open was closed)
virtual void OnAudioOpen(AudioProvider *) = 0;
/// The current audio stream was closed
virtual void OnAudioClose() = 0;
/// Playback is in progress and ths current position was updated
virtual void OnPlaybackPosition(int64_t sample_position) = 0;
/// Playback has stopped
virtual void OnPlaybackStop() = 0;
};
/// @class AudioControllerTimingEventListener
/// @brief Abstract interface for objects that want audio timing events
class AudioControllerTimingEventListener {
public:
/// One or more moveable markers were moved
virtual void OnMarkersMoved() = 0;
/// The selection was changed
virtual void OnSelectionChanged() = 0;
/// The timing controller was replaced
virtual void OnTimingControllerChanged() = 0;
};
/// @class AudioMarkerProvider
/// @brief Abstract interface for audio marker providers
class AudioMarkerProvider {
public:
/// Virtual destructor, does nothing
virtual ~AudioMarkerProvider() { }
/// @brief Return markers in a sample range
virtual void GetMarkers(const AudioController::SampleRange &range, AudioMarkerVector &out) const = 0;
};
/// @class AudioMarker /// @class AudioMarker
/// @brief A marker on the audio display /// @brief A marker on the audio display
class AudioMarker { class AudioMarker {
@ -431,8 +370,6 @@ public:
virtual bool CanSnap() const = 0; virtual bool CanSnap() const = 0;
}; };
namespace agi { namespace agi {
DEFINE_BASE_EXCEPTION(AudioControllerError, Exception); DEFINE_BASE_EXCEPTION(AudioControllerError, Exception);
DEFINE_SIMPLE_EXCEPTION(AudioOpenError, AudioControllerError, "audio_controller/open_failed"); DEFINE_SIMPLE_EXCEPTION(AudioOpenError, AudioControllerError, "audio_controller/open_failed");

View file

@ -496,7 +496,7 @@ public:
if (marker->CanSnap() && (default_snap != event.ShiftDown())) if (marker->CanSnap() && (default_snap != event.ShiftDown()))
{ {
AudioController::SampleRange snap_sample_range( SampleRange snap_sample_range(
display->SamplesFromRelativeX(event.GetPosition().x - snap_range), display->SamplesFromRelativeX(event.GetPosition().x - snap_range),
display->SamplesFromRelativeX(event.GetPosition().x + snap_range)); display->SamplesFromRelativeX(event.GetPosition().x + snap_range));
const AudioMarker *snap_marker = 0; const AudioMarker *snap_marker = 0;
@ -546,8 +546,13 @@ AudioDisplay::AudioDisplay(wxWindow *parent, AudioController *controller)
track_cursor_pos = -1; track_cursor_pos = -1;
controller->AddAudioListener(this); slots.push_back(controller->AddAudioOpenListener(&AudioDisplay::OnAudioOpen, this));
controller->AddTimingListener(this); slots.push_back(controller->AddAudioCloseListener(&AudioDisplay::OnAudioOpen, this, (AudioProvider*)0));
slots.push_back(controller->AddPlaybackPositionListener(&AudioDisplay::OnPlaybackPosition, this));
slots.push_back(controller->AddPlaybackStopListener(&AudioDisplay::RemoveTrackCursor, this));
slots.push_back(controller->AddTimingControllerListener(&AudioDisplay::Refresh, this, true, (const wxRect*)0));
slots.push_back(controller->AddMarkerMovedListener(&AudioDisplay::Refresh, this, true, (const wxRect*)0));
slots.push_back(controller->AddSelectionChangedListener(&AudioDisplay::OnSelectionChanged, this));
OPT_SUB("Audio/Spectrum", &AudioDisplay::ReloadRenderingSettings, this); OPT_SUB("Audio/Spectrum", &AudioDisplay::ReloadRenderingSettings, this);
@ -564,8 +569,6 @@ AudioDisplay::AudioDisplay(wxWindow *parent, AudioController *controller)
AudioDisplay::~AudioDisplay() AudioDisplay::~AudioDisplay()
{ {
controller->RemoveAudioListener(this);
controller->RemoveTimingListener(this);
} }
@ -614,7 +617,7 @@ void AudioDisplay::ScrollSampleToCenter(int64_t sample_position)
} }
void AudioDisplay::ScrollSampleRangeInView(const AudioController::SampleRange &range) void AudioDisplay::ScrollSampleRangeInView(const SampleRange &range)
{ {
int client_width = GetClientRect().GetWidth(); int client_width = GetClientRect().GetWidth();
int range_begin = AbsoluteXFromSamples(range.begin()); int range_begin = AbsoluteXFromSamples(range.begin());
@ -810,7 +813,7 @@ void AudioDisplay::OnPaint(wxPaintEvent& event)
bool redraw_timeline = false; bool redraw_timeline = false;
/// @todo Get rendering style ranges from timing controller instead /// @todo Get rendering style ranges from timing controller instead
AudioController::SampleRange sel_samples(controller->GetPrimaryPlaybackRange()); SampleRange sel_samples(controller->GetPrimaryPlaybackRange());
int selection_start = AbsoluteXFromSamples(sel_samples.begin()); int selection_start = AbsoluteXFromSamples(sel_samples.begin());
int selection_end = AbsoluteXFromSamples(sel_samples.end()); int selection_end = AbsoluteXFromSamples(sel_samples.end());
@ -856,12 +859,10 @@ void AudioDisplay::OnPaint(wxPaintEvent& event)
// Draw markers on top of it all // Draw markers on top of it all
AudioMarkerVector markers; AudioMarkerVector markers;
const int foot_size = 6; const int foot_size = 6;
AudioController::SampleRange updrectsamples( SampleRange updrectsamples(
SamplesFromRelativeX(updrect.x - foot_size), SamplesFromRelativeX(updrect.x - foot_size),
SamplesFromRelativeX(updrect.x + updrect.width + foot_size)); SamplesFromRelativeX(updrect.x + updrect.width + foot_size));
controller->GetMarkers(updrectsamples, markers); controller->GetMarkers(updrectsamples, markers);
if (controller->GetTimingController())
controller->GetTimingController()->GetMarkers(updrectsamples, markers);
wxDCPenChanger pen_retainer(dc, wxPen()); wxDCPenChanger pen_retainer(dc, wxPen());
wxDCBrushChanger brush_retainer(dc, wxBrush()); wxDCBrushChanger brush_retainer(dc, wxBrush());
for (AudioMarkerVector::iterator marker_i = markers.begin(); marker_i != markers.end(); ++marker_i) for (AudioMarkerVector::iterator marker_i = markers.begin(); marker_i != markers.end(); ++marker_i)
@ -1184,35 +1185,15 @@ void AudioDisplay::OnAudioOpen(AudioProvider *_provider)
Refresh(); Refresh();
} }
void AudioDisplay::OnAudioClose()
{
OnAudioOpen(0);
}
void AudioDisplay::OnPlaybackPosition(int64_t sample_position) void AudioDisplay::OnPlaybackPosition(int64_t sample_position)
{ {
SetTrackCursor(AbsoluteXFromSamples(sample_position), false); SetTrackCursor(AbsoluteXFromSamples(sample_position), false);
} }
void AudioDisplay::OnPlaybackStop()
{
RemoveTrackCursor();
}
void AudioDisplay::OnMarkersMoved()
{
Refresh();
}
void AudioDisplay::OnSelectionChanged() void AudioDisplay::OnSelectionChanged()
{ {
/// @todo Handle rendering style ranges from timing controller instead /// @todo Handle rendering style ranges from timing controller instead
AudioController::SampleRange sel(controller->GetPrimaryPlaybackRange()); SampleRange sel(controller->GetPrimaryPlaybackRange());
scrollbar->SetSelection(AbsoluteXFromSamples(sel.begin()), AbsoluteXFromSamples(sel.length())); scrollbar->SetSelection(AbsoluteXFromSamples(sel.begin()), AbsoluteXFromSamples(sel.length()));
if (sel.overlaps(old_selection)) if (sel.overlaps(old_selection))
@ -1242,11 +1223,3 @@ void AudioDisplay::OnSelectionChanged()
old_selection = sel; old_selection = sel;
} }
void AudioDisplay::OnTimingControllerChanged()
{
Refresh();
/// @todo Do something more about the new timing controller?
}

View file

@ -38,6 +38,7 @@
#pragma once #pragma once
#ifndef AGI_PRE #ifndef AGI_PRE
#include <list>
#include <stdint.h> #include <stdint.h>
#include <wx/bitmap.h> #include <wx/bitmap.h>
@ -47,6 +48,7 @@
#endif #endif
#include <libaegisub/scoped_ptr.h> #include <libaegisub/scoped_ptr.h>
#include <libaegisub/signals.h>
class AudioRenderer; class AudioRenderer;
@ -108,8 +110,9 @@ public:
/// The audio display is the common view that allows the user to interact with the active /// The audio display is the common view that allows the user to interact with the active
/// timing controller. The audio display also renders audio according to the audio controller /// timing controller. The audio display also renders audio according to the audio controller
/// and the timing controller, using an audio renderer instance. /// and the timing controller, using an audio renderer instance.
class AudioDisplay: public wxWindow, private AudioControllerAudioEventListener, private AudioControllerTimingEventListener { class AudioDisplay: public wxWindow {
private: private:
std::list<agi::signal::Connection> slots;
/// The audio renderer manager /// The audio renderer manager
agi::scoped_ptr<AudioRenderer> audio_renderer; agi::scoped_ptr<AudioRenderer> audio_renderer;
@ -178,9 +181,8 @@ private:
/// @brief Remove the tracking cursor from the display /// @brief Remove the tracking cursor from the display
void RemoveTrackCursor(); void RemoveTrackCursor();
/// Previous audio selection for optimizing redraw when selection changes
/// Previous audio selection for optimising redraw when selection changes SampleRange old_selection;
AudioController::SampleRange old_selection;
/// @brief Reload all rendering settings from Options and reset caches /// @brief Reload all rendering settings from Options and reset caches
/// ///
@ -197,19 +199,10 @@ private:
/// wxWidgets input focus changed event /// wxWidgets input focus changed event
void OnFocus(wxFocusEvent &event); void OnFocus(wxFocusEvent &event);
private:
// AudioControllerAudioEventListener implementation // AudioControllerAudioEventListener implementation
virtual void OnAudioOpen(AudioProvider *provider); virtual void OnAudioOpen(AudioProvider *provider);
virtual void OnAudioClose();
virtual void OnPlaybackPosition(int64_t sample_position); virtual void OnPlaybackPosition(int64_t sample_position);
virtual void OnPlaybackStop();
// AudioControllerTimingEventListener implementation
virtual void OnMarkersMoved();
virtual void OnSelectionChanged(); virtual void OnSelectionChanged();
virtual void OnTimingControllerChanged();
public: public:
@ -261,7 +254,7 @@ public:
/// closer to the edge of the display than the margin. The edge that is not ensured to /// closer to the edge of the display than the margin. The edge that is not ensured to
/// be in view might be outside of view or might be closer to the display edge than the /// be in view might be outside of view or might be closer to the display edge than the
/// margin. /// margin.
void ScrollSampleRangeInView(const AudioController::SampleRange &range); void ScrollSampleRangeInView(const SampleRange &range);
/// @brief Change the zoom level /// @brief Change the zoom level

View file

@ -40,7 +40,6 @@
#include <libaegisub/log.h> #include <libaegisub/log.h>
#include "audio_controller.h"
#include "audio_player_alsa.h" #include "audio_player_alsa.h"
#include "main.h" #include "main.h"
#include "compat.h" #include "compat.h"

View file

@ -40,7 +40,6 @@
#include <libaegisub/log.h> #include <libaegisub/log.h>
#include "audio_controller.h"
#include "audio_player_dsound.h" #include "audio_player_dsound.h"
#include "frame_main.h" #include "frame_main.h"
#include "main.h" #include "main.h"

View file

@ -40,7 +40,6 @@
#include <libaegisub/log.h> #include <libaegisub/log.h>
#include "audio_controller.h"
#include "audio_player_openal.h" #include "audio_player_openal.h"
#include "frame_main.h" #include "frame_main.h"
#include "utils.h" #include "utils.h"

View file

@ -38,7 +38,6 @@
#include <libaegisub/log.h> #include <libaegisub/log.h>
#include "audio_controller.h"
#include "audio_player_oss.h" #include "audio_player_oss.h"
#include "frame_main.h" #include "frame_main.h"
#include "compat.h" #include "compat.h"

View file

@ -41,7 +41,6 @@
#include <wx/filename.h> #include <wx/filename.h>
#endif #endif
#include "audio_controller.h"
#include "audio_provider_hd.h" #include "audio_provider_hd.h"
#include "compat.h" #include "compat.h"
#include "dialog_progress.h" #include "dialog_progress.h"

View file

@ -36,7 +36,6 @@
#include "config.h" #include "config.h"
#include "audio_controller.h"
#include "audio_provider_ram.h" #include "audio_provider_ram.h"
#include "dialog_progress.h" #include "dialog_progress.h"
#include "frame_main.h" #include "frame_main.h"

View file

@ -38,17 +38,27 @@
class AssDialogue; class AssDialogue;
class AudioController; class AudioController;
#include <libaegisub/signals.h>
/// @class AudioTimingController /// @class AudioTimingController
/// @brief Base class for objects controlling audio timing /// @brief Base class for objects controlling audio timing
/// ///
/// There is just one active audio timing controller at a time per audio controller. /// There is just one active audio timing controller at a time per audio controller.
/// The timing controller manages the timing mode and supplies markers that can be /// The timing controller manages the timing mode and supplies markers that can be
/// manupulated to the audio display, as well as the current selection. /// manipulated to the audio display, as well as the current selection.
/// ///
/// The timing controller must then be sent the marker drag events as well as clicks /// The timing controller must then be sent the marker drag events as well as clicks
/// in empty areas of the audio display. /// in empty areas of the audio display.
class AudioTimingController : public AudioMarkerProvider { class AudioTimingController : public AudioMarkerProvider {
protected:
/// The primary playback range has changed, usually as a result of user interaction.
agi::signal::Signal<> AnnounceUpdatedPrimaryRange;
/// One or more rendering style ranges have changed in the timing controller.
agi::signal::Signal<> AnnounceUpdatedStyleRanges;
/// A marker has been updated in some way.
agi::signal::Signal<AudioMarker*> AnnounceMarkerMoved;
public: public:
/// @brief Get any warning message to show in the audio display /// @brief Get any warning message to show in the audio display
/// @return The warning message to show, may be empty if there is none /// @return The warning message to show, may be empty if there is none
@ -58,13 +68,13 @@ public:
/// @return A sample range /// @return A sample range
/// ///
/// This is used for "bring working area into view" operations. /// This is used for "bring working area into view" operations.
virtual AudioController::SampleRange GetIdealVisibleSampleRange() const = 0; virtual SampleRange GetIdealVisibleSampleRange() const = 0;
/// @brief Get the primary playback range /// @brief Get the primary playback range
/// @return A sample range /// @return A sample range
/// ///
/// Get the sample range the user is most likely to want to play back currently. /// Get the sample range the user is most likely to want to play back currently.
virtual AudioController::SampleRange GetPrimaryPlaybackRange() const = 0; virtual SampleRange GetPrimaryPlaybackRange() const = 0;
/// @brief Does this timing mode have labels on the audio display? /// @brief Does this timing mode have labels on the audio display?
/// @return True if this timing mode needs labels on the audio display. /// @return True if this timing mode needs labels on the audio display.
@ -122,9 +132,11 @@ public:
virtual void OnMarkerDrag(AudioMarker *marker, int64_t new_position) = 0; virtual void OnMarkerDrag(AudioMarker *marker, int64_t new_position) = 0;
/// @brief Destructor /// @brief Destructor
///
/// Does nothing in the base class, only present for virtual destruction.
virtual ~AudioTimingController() { } virtual ~AudioTimingController() { }
DEFINE_SIGNAL_ADDERS(AnnounceUpdatedPrimaryRange, AddUpdatedPrimaryRangeListener)
DEFINE_SIGNAL_ADDERS(AnnounceUpdatedStyleRanges, AddUpdatedStyleRangesListener)
DEFINE_SIGNAL_ADDERS(AnnounceMarkerMoved, AddMarkerMovedListener)
}; };

View file

@ -143,12 +143,12 @@ private:
public: public:
// AudioMarkerProvider interface // AudioMarkerProvider interface
virtual void GetMarkers(const AudioController::SampleRange &range, AudioMarkerVector &out_markers) const; virtual void GetMarkers(const SampleRange &range, AudioMarkerVector &out_markers) const;
// AudioTimingController interface // AudioTimingController interface
virtual wxString GetWarningMessage() const; virtual wxString GetWarningMessage() const;
virtual AudioController::SampleRange GetIdealVisibleSampleRange() const; virtual SampleRange GetIdealVisibleSampleRange() const;
virtual AudioController::SampleRange GetPrimaryPlaybackRange() const; virtual SampleRange GetPrimaryPlaybackRange() const;
virtual bool HasLabels() const; virtual bool HasLabels() const;
virtual void Next(); virtual void Next();
virtual void Prev(); virtual void Prev();
@ -270,7 +270,7 @@ const AudioMarkerDialogueTiming *AudioTimingControllerDialogue::GetRightMarker()
void AudioTimingControllerDialogue::GetMarkers(const AudioController::SampleRange &range, AudioMarkerVector &out_markers) const void AudioTimingControllerDialogue::GetMarkers(const SampleRange &range, AudioMarkerVector &out_markers) const
{ {
if (range.contains(markers[0].GetPosition())) if (range.contains(markers[0].GetPosition()))
out_markers.push_back(&markers[0]); out_markers.push_back(&markers[0]);
@ -303,16 +303,16 @@ wxString AudioTimingControllerDialogue::GetWarningMessage() const
AudioController::SampleRange AudioTimingControllerDialogue::GetIdealVisibleSampleRange() const SampleRange AudioTimingControllerDialogue::GetIdealVisibleSampleRange() const
{ {
return GetPrimaryPlaybackRange(); return GetPrimaryPlaybackRange();
} }
AudioController::SampleRange AudioTimingControllerDialogue::GetPrimaryPlaybackRange() const SampleRange AudioTimingControllerDialogue::GetPrimaryPlaybackRange() const
{ {
return AudioController::SampleRange( return SampleRange(
GetLeftMarker()->GetPosition(), GetLeftMarker()->GetPosition(),
GetRightMarker()->GetPosition()); GetRightMarker()->GetPosition());
} }
@ -396,7 +396,7 @@ void AudioTimingControllerDialogue::Revert()
bool AudioTimingControllerDialogue::IsNearbyMarker(int64_t sample, int sensitivity) const bool AudioTimingControllerDialogue::IsNearbyMarker(int64_t sample, int sensitivity) const
{ {
AudioController::SampleRange range(sample-sensitivity, sample+sensitivity); SampleRange range(sample-sensitivity, sample+sensitivity);
return range.contains(markers[0].GetPosition()) || range.contains(markers[1].GetPosition()); return range.contains(markers[0].GetPosition()) || range.contains(markers[1].GetPosition());
} }
@ -419,7 +419,7 @@ AudioMarker * AudioTimingControllerDialogue::OnLeftClick(int64_t sample, int sen
// Clicked near the left marker: // Clicked near the left marker:
// Insta-move it and start dragging it // Insta-move it and start dragging it
left->SetPosition(sample); left->SetPosition(sample);
audio_controller->OnTimingControllerMarkerMoved(this, left); AnnounceMarkerMoved(left);
timing_modified = true; timing_modified = true;
UpdateSelection(); UpdateSelection();
return left; return left;
@ -436,7 +436,7 @@ AudioMarker * AudioTimingControllerDialogue::OnLeftClick(int64_t sample, int sen
// Insta-set the left marker to the clicked position and return the right as the dragged one, // Insta-set the left marker to the clicked position and return the right as the dragged one,
// such that if the user does start dragging, he will create a new selection from scratch // such that if the user does start dragging, he will create a new selection from scratch
left->SetPosition(sample); left->SetPosition(sample);
audio_controller->OnTimingControllerMarkerMoved(this, left); AnnounceMarkerMoved(left);
timing_modified = true; timing_modified = true;
UpdateSelection(); UpdateSelection();
return right; return right;
@ -449,7 +449,7 @@ AudioMarker * AudioTimingControllerDialogue::OnRightClick(int64_t sample, int se
AudioMarkerDialogueTiming *right = GetRightMarker(); AudioMarkerDialogueTiming *right = GetRightMarker();
right->SetPosition(sample); right->SetPosition(sample);
audio_controller->OnTimingControllerMarkerMoved(this, right); AnnounceMarkerMoved(right);
timing_modified = true; timing_modified = true;
UpdateSelection(); UpdateSelection();
return right; return right;
@ -462,7 +462,7 @@ void AudioTimingControllerDialogue::OnMarkerDrag(AudioMarker *marker, int64_t ne
assert(marker == &markers[0] || marker == &markers[1]); assert(marker == &markers[0] || marker == &markers[1]);
static_cast<AudioMarkerDialogueTiming*>(marker)->SetPosition(new_position); static_cast<AudioMarkerDialogueTiming*>(marker)->SetPosition(new_position);
audio_controller->OnTimingControllerMarkerMoved(this, marker); AnnounceMarkerMoved(marker);
timing_modified = true; timing_modified = true;
UpdateSelection(); UpdateSelection();
@ -472,7 +472,7 @@ void AudioTimingControllerDialogue::OnMarkerDrag(AudioMarker *marker, int64_t ne
void AudioTimingControllerDialogue::UpdateSelection() void AudioTimingControllerDialogue::UpdateSelection()
{ {
audio_controller->OnTimingControllerUpdatedPrimaryRange(this); AnnounceUpdatedPrimaryRange();
} }

View file

@ -50,7 +50,6 @@
#include "ass_dialogue.h" #include "ass_dialogue.h"
#include "ass_file.h" #include "ass_file.h"
#include "ass_style.h" #include "ass_style.h"
#include "audio_controller.h"
#include "selection_controller.h" #include "selection_controller.h"
#include "compat.h" #include "compat.h"
#include "frame_main.h" #include "frame_main.h"

View file

@ -42,7 +42,6 @@
#include <wx/display.h> /// Must be included last. #include <wx/display.h> /// Must be included last.
#endif #endif
#include "audio_controller.h"
#include "dialog_detached_video.h" #include "dialog_detached_video.h"
#include "frame_main.h" #include "frame_main.h"
#include "main.h" #include "main.h"

View file

@ -51,7 +51,6 @@
#include "ass_file.h" #include "ass_file.h"
#include "ass_override.h" #include "ass_override.h"
#include "ass_style.h" #include "ass_style.h"
#include "audio_controller.h"
#include "compat.h" #include "compat.h"
#include "dialog_fonts_collector.h" #include "dialog_fonts_collector.h"
#include "font_file_lister.h" #include "font_file_lister.h"

View file

@ -47,7 +47,6 @@
#include "compat.h" #include "compat.h"
#include "ass_dialogue.h" #include "ass_dialogue.h"
#include "ass_file.h" #include "ass_file.h"
#include "audio_controller.h"
#include "dialog_search_replace.h" #include "dialog_search_replace.h"
#include "frame_main.h" #include "frame_main.h"
#include "main.h" #include "main.h"

View file

@ -44,7 +44,6 @@
#include "ass_dialogue.h" #include "ass_dialogue.h"
#include "ass_file.h" #include "ass_file.h"
#include "audio_controller.h"
#include "compat.h" #include "compat.h"
#include "dialog_spellchecker.h" #include "dialog_spellchecker.h"
#include "frame_main.h" #include "frame_main.h"

View file

@ -379,7 +379,7 @@ void DialogStyling::OnPlayVideoButton(wxCommandEvent &event) {
/// @param event /// @param event
/// ///
void DialogStyling::OnPlayAudioButton(wxCommandEvent &event) { void DialogStyling::OnPlayAudioButton(wxCommandEvent &event) {
audio->PlayRange(AudioController::SampleRange( audio->PlayRange(SampleRange(
audio->SamplesFromMilliseconds(line->Start.GetMS()), audio->SamplesFromMilliseconds(line->Start.GetMS()),
audio->SamplesFromMilliseconds(line->End.GetMS()))); audio->SamplesFromMilliseconds(line->End.GetMS())));
TypeBox->SetFocus(); TypeBox->SetFocus();

View file

@ -444,7 +444,7 @@ void DialogTranslation::OnPlayVideoButton(wxCommandEvent &event) {
/// @param event /// @param event
/// ///
void DialogTranslation::OnPlayAudioButton(wxCommandEvent &event) { void DialogTranslation::OnPlayAudioButton(wxCommandEvent &event) {
audio->PlayRange(AudioController::SampleRange( audio->PlayRange(SampleRange(
audio->SamplesFromMilliseconds(current->Start.GetMS()), audio->SamplesFromMilliseconds(current->Start.GetMS()),
audio->SamplesFromMilliseconds(current->End.GetMS()))); audio->SamplesFromMilliseconds(current->End.GetMS())));
TransText->SetFocus(); TransText->SetFocus();

View file

@ -43,7 +43,6 @@
#include <wx/filename.h> #include <wx/filename.h>
#endif #endif
#include "audio_controller.h"
#include "drop.h" #include "drop.h"
#include "frame_main.h" #include "frame_main.h"

View file

@ -48,7 +48,6 @@
#include <libaegisub/log.h> #include <libaegisub/log.h>
#include "audio_controller.h"
#include "compat.h" #include "compat.h"
#include "ffmpegsource_common.h" #include "ffmpegsource_common.h"
#include "frame_main.h" #include "frame_main.h"

View file

@ -132,7 +132,8 @@ FrameMain::FrameMain (wxArrayString args)
// Contexts and controllers // Contexts and controllers
audioController = new AudioController; audioController = new AudioController;
audioController->AddAudioListener(this); audioController->AddAudioOpenListener(&FrameMain::OnAudioOpen, this);
audioController->AddAudioCloseListener(&FrameMain::OnAudioClose, this);
// Create menu and tool bars // Create menu and tool bars
StartupLog(_T("Apply saved Maximized state")); StartupLog(_T("Apply saved Maximized state"));

View file

@ -47,10 +47,6 @@
#include <wx/timer.h> #include <wx/timer.h>
#endif #endif
#ifndef AGI_AUDIO_CONTROLLER_INCLUDED
#error You must include "audio_controller.h" before "frame_main.h"
#endif
class AssFile; class AssFile;
class VideoDisplay; class VideoDisplay;
class VideoSlider; class VideoSlider;
@ -63,6 +59,7 @@ class DialogDetachedVideo;
class DialogStyling; class DialogStyling;
class AegisubFileDropTarget; class AegisubFileDropTarget;
class AudioController; class AudioController;
class AudioProvider;
namespace Automation4 { class FeatureMacro; class ScriptManager; } namespace Automation4 { class FeatureMacro; class ScriptManager; }
@ -73,7 +70,7 @@ namespace Automation4 { class FeatureMacro; class ScriptManager; }
/// @brief DOCME /// @brief DOCME
/// ///
/// DOCME /// DOCME
class FrameMain: public wxFrame, private AudioControllerAudioEventListener { class FrameMain: public wxFrame {
friend class AegisubFileDropTarget; friend class AegisubFileDropTarget;
friend class AegisubApp; friend class AegisubApp;
friend class SubtitlesGrid; friend class SubtitlesGrid;
@ -327,13 +324,9 @@ private:
void RebuildRecentList(wxString listName,wxMenu *menu,int startID); void RebuildRecentList(wxString listName,wxMenu *menu,int startID);
void SynchronizeProject(bool FromSubs=false); void SynchronizeProject(bool FromSubs=false);
private:
// AudioControllerAudioEventListener implementation // AudioControllerAudioEventListener implementation
virtual void OnAudioOpen(AudioProvider *provider); void OnAudioOpen(AudioProvider *provider);
virtual void OnAudioClose(); void OnAudioClose();
virtual void OnPlaybackPosition(int64_t sample_position);
virtual void OnPlaybackStop();
void OnSubtitlesFileChanged(); void OnSubtitlesFileChanged();

View file

@ -1517,8 +1517,8 @@ void FrameMain::OnMedusaStop(wxCommandEvent &) {
// Otherwise, play the last 500 ms // Otherwise, play the last 500 ms
else { else {
AudioController::SampleRange sel(audioController->GetPrimaryPlaybackRange()); SampleRange sel(audioController->GetPrimaryPlaybackRange());
audioController->PlayRange(AudioController::SampleRange( audioController->PlayRange(SampleRange(
sel.end() - audioController->SamplesFromMilliseconds(500), sel.end() - audioController->SamplesFromMilliseconds(500),
sel.end()));; sel.end()));;
} }
@ -1526,7 +1526,7 @@ void FrameMain::OnMedusaStop(wxCommandEvent &) {
/// @brief DOCME /// @brief DOCME
void FrameMain::OnMedusaShiftStartForward(wxCommandEvent &) { void FrameMain::OnMedusaShiftStartForward(wxCommandEvent &) {
AudioController::SampleRange newsel( SampleRange newsel(
audioController->GetPrimaryPlaybackRange(), audioController->GetPrimaryPlaybackRange(),
audioController->SamplesFromMilliseconds(10), audioController->SamplesFromMilliseconds(10),
0); 0);
@ -1536,7 +1536,7 @@ void FrameMain::OnMedusaShiftStartForward(wxCommandEvent &) {
/// @brief DOCME /// @brief DOCME
void FrameMain::OnMedusaShiftStartBack(wxCommandEvent &) { void FrameMain::OnMedusaShiftStartBack(wxCommandEvent &) {
AudioController::SampleRange newsel( SampleRange newsel(
audioController->GetPrimaryPlaybackRange(), audioController->GetPrimaryPlaybackRange(),
-audioController->SamplesFromMilliseconds(10), -audioController->SamplesFromMilliseconds(10),
0); 0);
@ -1546,7 +1546,7 @@ void FrameMain::OnMedusaShiftStartBack(wxCommandEvent &) {
/// @brief DOCME /// @brief DOCME
void FrameMain::OnMedusaShiftEndForward(wxCommandEvent &) { void FrameMain::OnMedusaShiftEndForward(wxCommandEvent &) {
AudioController::SampleRange newsel( SampleRange newsel(
audioController->GetPrimaryPlaybackRange(), audioController->GetPrimaryPlaybackRange(),
0, 0,
audioController->SamplesFromMilliseconds(10)); audioController->SamplesFromMilliseconds(10));
@ -1556,7 +1556,7 @@ void FrameMain::OnMedusaShiftEndForward(wxCommandEvent &) {
/// @brief DOCME /// @brief DOCME
void FrameMain::OnMedusaShiftEndBack(wxCommandEvent &) { void FrameMain::OnMedusaShiftEndBack(wxCommandEvent &) {
AudioController::SampleRange newsel( SampleRange newsel(
audioController->GetPrimaryPlaybackRange(), audioController->GetPrimaryPlaybackRange(),
0, 0,
-audioController->SamplesFromMilliseconds(10)); -audioController->SamplesFromMilliseconds(10));
@ -1566,16 +1566,16 @@ void FrameMain::OnMedusaShiftEndBack(wxCommandEvent &) {
/// @brief DOCME /// @brief DOCME
void FrameMain::OnMedusaPlayBefore(wxCommandEvent &) { void FrameMain::OnMedusaPlayBefore(wxCommandEvent &) {
AudioController::SampleRange sel(audioController->GetPrimaryPlaybackRange()); SampleRange sel(audioController->GetPrimaryPlaybackRange());
audioController->PlayRange(AudioController::SampleRange( audioController->PlayRange(SampleRange(
sel.begin() - audioController->SamplesFromMilliseconds(500), sel.begin() - audioController->SamplesFromMilliseconds(500),
sel.begin()));; sel.begin()));;
} }
/// @brief DOCME /// @brief DOCME
void FrameMain::OnMedusaPlayAfter(wxCommandEvent &) { void FrameMain::OnMedusaPlayAfter(wxCommandEvent &) {
AudioController::SampleRange sel(audioController->GetPrimaryPlaybackRange()); SampleRange sel(audioController->GetPrimaryPlaybackRange());
audioController->PlayRange(AudioController::SampleRange( audioController->PlayRange(SampleRange(
sel.end(), sel.end(),
sel.end() + audioController->SamplesFromMilliseconds(500)));; sel.end() + audioController->SamplesFromMilliseconds(500)));;
} }
@ -1623,16 +1623,6 @@ void FrameMain::OnAudioClose()
SetDisplayMode(-1, 0); SetDisplayMode(-1, 0);
} }
void FrameMain::OnPlaybackPosition(int64_t sample_position)
{
// do nothing
}
void FrameMain::OnPlaybackStop()
{
// do nothing
}
void FrameMain::OnSubtitlesFileChanged() { void FrameMain::OnSubtitlesFileChanged() {
if (OPT_GET("App/Auto/Save on Every Change")->GetBool()) { if (OPT_GET("App/Auto/Save on Every Change")->GetBool()) {
if (ass->IsModified() && !ass->filename.empty()) SaveSubtitles(false); if (ass->IsModified() && !ass->filename.empty()) SaveSubtitles(false);
@ -1640,4 +1630,3 @@ void FrameMain::OnSubtitlesFileChanged() {
UpdateTitle(); UpdateTitle();
} }

View file

@ -55,7 +55,6 @@
#include "ass_file.h" #include "ass_file.h"
#include "ass_time.h" #include "ass_time.h"
#include "selection_controller.h" #include "selection_controller.h"
#include "audio_controller.h"
#include "audio_box.h" #include "audio_box.h"
#ifdef WITH_AUTOMATION #ifdef WITH_AUTOMATION
#include "auto4_base.h" #include "auto4_base.h"

View file

@ -50,7 +50,6 @@
#include <libaegisub/log.h> #include <libaegisub/log.h>
#include "audio_controller.h"
#include "ass_file.h" #include "ass_file.h"
#include "dialog_progress.h" #include "dialog_progress.h"
#include "frame_main.h" #include "frame_main.h"

View file

@ -45,7 +45,6 @@
#include "ass_dialogue.h" #include "ass_dialogue.h"
#include "ass_file.h" #include "ass_file.h"
#include "audio_controller.h"
#include "frame_main.h" #include "frame_main.h"
#include "help_button.h" #include "help_button.h"
#include "libresrc/libresrc.h" #include "libresrc/libresrc.h"

View file

@ -308,7 +308,7 @@ void VideoContext::PlayNextFrame() {
JumpToFrame(frame_n + 1); JumpToFrame(frame_n + 1);
// Start playing audio // Start playing audio
if (playAudioOnStep->GetBool()) { if (playAudioOnStep->GetBool()) {
audio->PlayRange(AudioController::SampleRange( audio->PlayRange(SampleRange(
audio->SamplesFromMilliseconds(TimeAtFrame(thisFrame)), audio->SamplesFromMilliseconds(TimeAtFrame(thisFrame)),
audio->SamplesFromMilliseconds(TimeAtFrame(thisFrame + 1)))); audio->SamplesFromMilliseconds(TimeAtFrame(thisFrame + 1))));
} }
@ -322,7 +322,7 @@ void VideoContext::PlayPrevFrame() {
JumpToFrame(frame_n -1); JumpToFrame(frame_n -1);
// Start playing audio // Start playing audio
if (playAudioOnStep->GetBool()) { if (playAudioOnStep->GetBool()) {
audio->PlayRange(AudioController::SampleRange( audio->PlayRange(SampleRange(
audio->SamplesFromMilliseconds(TimeAtFrame(thisFrame - 1)), audio->SamplesFromMilliseconds(TimeAtFrame(thisFrame - 1)),
audio->SamplesFromMilliseconds(TimeAtFrame(thisFrame)))); audio->SamplesFromMilliseconds(TimeAtFrame(thisFrame))));
} }
@ -355,7 +355,7 @@ void VideoContext::PlayLine() {
if (!curline) return; if (!curline) return;
// Start playing audio // Start playing audio
audio->PlayRange(AudioController::SampleRange( audio->PlayRange(SampleRange(
audio->SamplesFromMilliseconds(curline->Start.GetMS()), audio->SamplesFromMilliseconds(curline->Start.GetMS()),
audio->SamplesFromMilliseconds(curline->End.GetMS()))); audio->SamplesFromMilliseconds(curline->End.GetMS())));