mirror of https://github.com/odrling/Aegisub
Use signals in AudioController and AudioTimingController
Originally committed to SVN as r4907.
This commit is contained in:
parent
3bb1f590d7
commit
3345797ff6
|
@ -39,7 +39,6 @@
|
|||
#include "ass_export_filter.h"
|
||||
#include "ass_exporter.h"
|
||||
#include "ass_file.h"
|
||||
#include "audio_controller.h"
|
||||
#include "frame_main.h"
|
||||
|
||||
/// @brief Constructor
|
||||
|
|
|
@ -255,7 +255,7 @@ AudioBox::AudioBox(wxWindow *parent, AudioController *_controller, SelectionCont
|
|||
SetSizer(MainSizer);
|
||||
|
||||
SetKaraokeButtons(); // Decide which one to show or hide.
|
||||
|
||||
|
||||
timing_controller_dialogue = CreateDialogueTimingController(controller, selection_controller);
|
||||
controller->SetTimingController(timing_controller_dialogue);
|
||||
}
|
||||
|
@ -425,8 +425,8 @@ void AudioBox::OnPrev(wxCommandEvent &event) {
|
|||
/// @param event
|
||||
///
|
||||
void AudioBox::OnPlay500Before(wxCommandEvent &event) {
|
||||
AudioController::SampleRange times(controller->GetPrimaryPlaybackRange());
|
||||
controller->PlayRange(AudioController::SampleRange(
|
||||
SampleRange times(controller->GetPrimaryPlaybackRange());
|
||||
controller->PlayRange(SampleRange(
|
||||
times.begin() - controller->SamplesFromMilliseconds(500),
|
||||
times.begin()));
|
||||
}
|
||||
|
@ -437,8 +437,8 @@ void AudioBox::OnPlay500Before(wxCommandEvent &event) {
|
|||
/// @param event
|
||||
///
|
||||
void AudioBox::OnPlay500After(wxCommandEvent &event) {
|
||||
AudioController::SampleRange times(controller->GetPrimaryPlaybackRange());
|
||||
controller->PlayRange(AudioController::SampleRange(
|
||||
SampleRange times(controller->GetPrimaryPlaybackRange());
|
||||
controller->PlayRange(SampleRange(
|
||||
times.end(),
|
||||
times.end() + controller->SamplesFromMilliseconds(500)));
|
||||
}
|
||||
|
@ -449,8 +449,8 @@ void AudioBox::OnPlay500After(wxCommandEvent &event) {
|
|||
/// @param event
|
||||
///
|
||||
void AudioBox::OnPlay500First(wxCommandEvent &event) {
|
||||
AudioController::SampleRange times(controller->GetPrimaryPlaybackRange());
|
||||
controller->PlayRange(AudioController::SampleRange(
|
||||
SampleRange times(controller->GetPrimaryPlaybackRange());
|
||||
controller->PlayRange(SampleRange(
|
||||
times.begin(),
|
||||
times.begin() + std::min(
|
||||
controller->SamplesFromMilliseconds(500),
|
||||
|
@ -463,8 +463,8 @@ void AudioBox::OnPlay500First(wxCommandEvent &event) {
|
|||
/// @param event
|
||||
///
|
||||
void AudioBox::OnPlay500Last(wxCommandEvent &event) {
|
||||
AudioController::SampleRange times(controller->GetPrimaryPlaybackRange());
|
||||
controller->PlayRange(AudioController::SampleRange(
|
||||
SampleRange times(controller->GetPrimaryPlaybackRange());
|
||||
controller->PlayRange(SampleRange(
|
||||
times.end() - std::min(
|
||||
controller->SamplesFromMilliseconds(500),
|
||||
times.length()),
|
||||
|
|
|
@ -54,14 +54,11 @@
|
|||
#include <wx/tglbtn.h>
|
||||
#endif
|
||||
|
||||
#ifndef AGI_AUDIO_CONTROLLER_INCLUDED
|
||||
#error You must include "audio_controller.h" before "audio_box.h"
|
||||
#endif
|
||||
|
||||
|
||||
//////////////
|
||||
// Prototypes
|
||||
class AudioController;
|
||||
class AssDialogue;
|
||||
class AudioTimingController;
|
||||
class AudioDisplay;
|
||||
class AudioKaraoke;
|
||||
class FrameMain;
|
||||
|
@ -80,7 +77,7 @@ class AudioBox : public wxPanel {
|
|||
/// Selection controller used for timing controllers
|
||||
SelectionController<AssDialogue> *selection_controller;
|
||||
|
||||
/// The regular dalogue timing controller
|
||||
/// The regular dialogue timing controller
|
||||
AudioTimingController *timing_controller_dialogue;
|
||||
|
||||
/// DOCME
|
||||
|
|
|
@ -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; }
|
||||
wxPen AudioMarkerKeyframe::style;
|
||||
|
||||
class AudioMarkerProviderKeyframes : public AudioMarkerProvider, private AudioControllerAudioEventListener {
|
||||
// GetMarkers needs to be const but still needs to modify this state, which is really
|
||||
// just a cache... use the mutable "hack".
|
||||
mutable int last_keyframes_revision;
|
||||
mutable std::vector<AudioMarkerKeyframe> keyframe_samples;
|
||||
AudioController *controller;
|
||||
int64_t samplerate;
|
||||
class AudioMarkerProviderKeyframes : public AudioMarkerProvider {
|
||||
VideoContext *vc;
|
||||
|
||||
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();
|
||||
|
||||
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());
|
||||
for (size_t i = 0; i < raw_keyframes.size(); ++i)
|
||||
{
|
||||
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());
|
||||
AnnounceMarkerMoved();
|
||||
}
|
||||
|
||||
private:
|
||||
// AudioControllerAudioEventListener implementation
|
||||
virtual void OnAudioOpen(AudioProvider *provider)
|
||||
void OnAudioOpen(AudioProvider *)
|
||||
{
|
||||
samplerate = provider->GetSampleRate();
|
||||
ReloadKeyframes();
|
||||
OnKeyframesOpen(vc->GetKeyFrames());
|
||||
}
|
||||
virtual void OnAudioClose() { }
|
||||
virtual void OnPlaybackPosition(int64_t sample_position) { }
|
||||
virtual void OnPlaybackStop() { }
|
||||
|
||||
public:
|
||||
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
|
||||
last_keyframes_revision = 0;
|
||||
samplerate = 44100;
|
||||
controller->AddAudioListener(this);
|
||||
OnKeyframesOpen(vc->GetKeyFrames());
|
||||
}
|
||||
|
||||
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
|
||||
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());
|
||||
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());
|
||||
|
||||
// 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()
|
||||
: player(0)
|
||||
, provider(0)
|
||||
, timing_controller(0)
|
||||
, keyframes_marker_provider(new AudioMarkerProviderKeyframes(this))
|
||||
, playback_mode(PM_NotPlaying)
|
||||
, playback_timer(this)
|
||||
|
@ -195,10 +162,7 @@ void AudioController::OnPlaybackTimer(wxTimerEvent &event)
|
|||
}
|
||||
else
|
||||
{
|
||||
AUDIO_LISTENERS(l)
|
||||
{
|
||||
(*l)->OnPlaybackPosition(pos);
|
||||
}
|
||||
AnnouncePlaybackPosition(pos);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -312,10 +276,7 @@ void AudioController::OpenAudio(const wxString &url)
|
|||
}
|
||||
|
||||
// Tell listeners about this.
|
||||
AUDIO_LISTENERS(l)
|
||||
{
|
||||
(*l)->OnAudioOpen(provider);
|
||||
}
|
||||
AnnounceAudioOpen(provider);
|
||||
}
|
||||
|
||||
|
||||
|
@ -328,10 +289,7 @@ void AudioController::CloseAudio()
|
|||
player = 0;
|
||||
provider = 0;
|
||||
|
||||
AUDIO_LISTENERS(l)
|
||||
{
|
||||
(*l)->OnAudioClose();
|
||||
}
|
||||
AnnounceAudioClose();
|
||||
}
|
||||
|
||||
|
||||
|
@ -347,90 +305,37 @@ wxString AudioController::GetAudioURL() const
|
|||
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)
|
||||
{
|
||||
delete timing_controller;
|
||||
timing_controller = new_controller;
|
||||
|
||||
TIMING_LISTENERS(l)
|
||||
{
|
||||
(*l)->OnTimingControllerChanged();
|
||||
if (timing_controller.get() != new_controller) {
|
||||
timing_controller.reset(new_controller);
|
||||
timing_controller->AddMarkerMovedListener(std::tr1::bind(std::tr1::ref(AnnounceMarkerMoved)));
|
||||
timing_controller->AddUpdatedPrimaryRangeListener(&AudioController::OnTimingControllerUpdatedPrimaryRange, this);
|
||||
timing_controller->AddUpdatedStyleRangesListener(&AudioController::OnTimingControllerUpdatedStyleRanges, this);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
player->SetEndPosition(timing_controller->GetPrimaryPlaybackRange().end());
|
||||
}
|
||||
|
||||
TIMING_LISTENERS(l)
|
||||
{
|
||||
(*l)->OnSelectionChanged();
|
||||
}
|
||||
AnnounceSelectionChanged();
|
||||
}
|
||||
|
||||
|
||||
void AudioController::OnTimingControllerUpdatedStyleRanges(AudioTimingController *sending_controller)
|
||||
void AudioController::OnTimingControllerUpdatedStyleRanges()
|
||||
{
|
||||
assert(sending_controller != 0);
|
||||
if (sending_controller != timing_controller)
|
||||
return;
|
||||
|
||||
/// @todo redraw and stuff, probably
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
void AudioController::PlayRange(const SampleRange &range)
|
||||
{
|
||||
if (!IsAudioOpen()) return;
|
||||
|
||||
|
@ -438,10 +343,7 @@ void AudioController::PlayRange(const AudioController::SampleRange &range)
|
|||
playback_mode = PM_Range;
|
||||
playback_timer.Start(20);
|
||||
|
||||
AUDIO_LISTENERS(l)
|
||||
{
|
||||
(*l)->OnPlaybackPosition(range.begin());
|
||||
}
|
||||
AnnouncePlaybackPosition(range.begin());
|
||||
}
|
||||
|
||||
|
||||
|
@ -461,10 +363,7 @@ void AudioController::PlayToEnd(int64_t start_sample)
|
|||
playback_mode = PM_ToEnd;
|
||||
playback_timer.Start(20);
|
||||
|
||||
AUDIO_LISTENERS(l)
|
||||
{
|
||||
(*l)->OnPlaybackPosition(start_sample);
|
||||
}
|
||||
AnnouncePlaybackPosition(start_sample);
|
||||
}
|
||||
|
||||
|
||||
|
@ -476,10 +375,7 @@ void AudioController::Stop()
|
|||
playback_mode = PM_NotPlaying;
|
||||
playback_timer.Stop();
|
||||
|
||||
AUDIO_LISTENERS(l)
|
||||
{
|
||||
(*l)->OnPlaybackStop();
|
||||
}
|
||||
AnnouncePlaybackStop();
|
||||
}
|
||||
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -522,6 +418,7 @@ void AudioController::GetMarkers(const SampleRange &range, AudioMarkerVector &ma
|
|||
{
|
||||
/// @todo Find all sources of 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -48,9 +48,8 @@
|
|||
#endif
|
||||
|
||||
#include <libaegisub/exception.h>
|
||||
|
||||
#define AGI_AUDIO_CONTROLLER_INCLUDED 1
|
||||
|
||||
#include <libaegisub/scoped_ptr.h>
|
||||
#include <libaegisub/signals.h>
|
||||
|
||||
class AudioPlayer;
|
||||
class AudioProvider;
|
||||
|
@ -62,15 +61,78 @@ class AudioTimingController;
|
|||
class AudioMarker;
|
||||
class AudioMarkerProvider;
|
||||
|
||||
|
||||
typedef std::vector<const AudioMarker*> AudioMarkerVector;
|
||||
|
||||
|
||||
/// @class SampleRange
|
||||
/// @brief Represents an immutable range of audio samples
|
||||
class SampleRange {
|
||||
int64_t _begin;
|
||||
int64_t _end;
|
||||
|
||||
public:
|
||||
/// @brief Constructor
|
||||
/// @param begin Index of the first sample to include in the range
|
||||
/// @param end Index of one past the last sample to include in the range
|
||||
SampleRange(int64_t begin, int64_t 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 samples to add to the start of the range
|
||||
/// @param end_adjust Number of samples to add to the end of the range
|
||||
SampleRange(const SampleRange &src, int64_t begin_adjust = 0, int64_t end_adjust = 0)
|
||||
{
|
||||
_begin = src._begin + begin_adjust;
|
||||
_end = src._end + end_adjust;
|
||||
assert(_end >= _begin);
|
||||
}
|
||||
|
||||
/// Get the number of samples in the range
|
||||
int64_t length() const { return _end - _begin; }
|
||||
/// Get the index of the first sample in the range
|
||||
int64_t begin() const { return _begin; }
|
||||
/// Get the index of one past the last sample in the range
|
||||
int64_t end() const { return _end; }
|
||||
|
||||
/// Determine whether the range contains a given sample index
|
||||
bool contains(int64_t sample) const { return sample >= begin() && sample < end(); }
|
||||
|
||||
/// Determine whether there is an overlap between two ranges
|
||||
bool overlaps(const SampleRange &other) const
|
||||
{
|
||||
return other.contains(_begin)
|
||||
|| other.contains(_end)
|
||||
|| contains(other._begin)
|
||||
|| contains(other._end);
|
||||
}
|
||||
};
|
||||
|
||||
/// @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 moveable markers are on the audio, and any secondary non-moveable markers
|
||||
/// 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
|
||||
|
@ -85,65 +147,25 @@ typedef std::vector<const AudioMarker*> AudioMarkerVector;
|
|||
/// 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
|
||||
/// @brief Represents an immutable range of audio samples
|
||||
class SampleRange {
|
||||
int64_t _begin;
|
||||
int64_t _end;
|
||||
|
||||
public:
|
||||
/// @brief Constructor
|
||||
/// @param begin Index of the first sample to include in the range
|
||||
/// @param end Index of one past the last sample to include in the range
|
||||
SampleRange(int64_t begin, int64_t 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 samples to add to the start of the range
|
||||
/// @param end_adjust Number of samples to add to the end of the range
|
||||
SampleRange(const SampleRange &src, int64_t begin_adjust = 0, int64_t end_adjust = 0)
|
||||
{
|
||||
_begin = src._begin + begin_adjust;
|
||||
_end = src._end + end_adjust;
|
||||
assert(_end >= _begin);
|
||||
}
|
||||
|
||||
/// Get the number of samples in the range
|
||||
int64_t length() const { return _end - _begin; }
|
||||
/// Get the index of the first sample in the range
|
||||
int64_t begin() const { return _begin; }
|
||||
/// Get the index of one past the last sample in the range
|
||||
int64_t end() const { return _end; }
|
||||
|
||||
/// Determine whether the range contains a given sample index
|
||||
bool contains(int64_t sample) const { return sample >= begin() && sample < end(); }
|
||||
|
||||
/// Determine whether there is an overlap between two ranges
|
||||
bool overlaps(const SampleRange &other) const
|
||||
{
|
||||
return other.contains(_begin)
|
||||
|| other.contains(_end)
|
||||
|| contains(other._begin)
|
||||
|| contains(other._end);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class AudioController : public wxEvtHandler, public AudioMarkerProvider {
|
||||
private:
|
||||
/// A new audio stream was opened (and any previously open was closed)
|
||||
agi::signal::Signal<AudioProvider*> AnnounceAudioOpen;
|
||||
|
||||
/// Listeners for audio-related events
|
||||
std::set<AudioControllerAudioEventListener *> audio_event_listeners;
|
||||
/// The current audio stream was closed
|
||||
agi::signal::Signal<> AnnounceAudioClose;
|
||||
|
||||
/// Listeners for timing-related events
|
||||
std::set<AudioControllerTimingEventListener *> timing_event_listeners;
|
||||
/// Playback is in progress and the current position was updated
|
||||
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
|
||||
AudioPlayer *player;
|
||||
|
@ -152,10 +174,10 @@ private:
|
|||
AudioProvider *provider;
|
||||
|
||||
/// 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
|
||||
std::auto_ptr<AudioMarkerProvider> keyframes_marker_provider;
|
||||
agi::scoped_ptr<AudioMarkerProvider> keyframes_marker_provider;
|
||||
|
||||
|
||||
enum PlaybackMode {
|
||||
|
@ -174,6 +196,11 @@ private:
|
|||
/// Event handler for the playback timer
|
||||
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
|
||||
/// Handle computer going into suspend mode by stopping audio and closing device
|
||||
|
@ -182,7 +209,6 @@ private:
|
|||
void OnComputerResuming(wxPowerEvent &event);
|
||||
#endif
|
||||
|
||||
|
||||
public:
|
||||
|
||||
/// @brief Constructor
|
||||
|
@ -213,23 +239,6 @@ public:
|
|||
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
|
||||
/// @param range The range of audio to play back
|
||||
///
|
||||
|
@ -279,12 +288,9 @@ public:
|
|||
/// @return An immutable SampleRange object
|
||||
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 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;
|
||||
|
||||
|
||||
|
@ -304,7 +310,7 @@ public:
|
|||
|
||||
/// @brief Return the current timing controller
|
||||
/// @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
|
||||
/// @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.
|
||||
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
|
||||
/// @param samples Sample count to convert
|
||||
/// @return The number of milliseconds equivalent to the sample-count, rounded down
|
||||
|
@ -346,57 +327,15 @@ public:
|
|||
/// @param ms Time in milliseconds to convert
|
||||
/// @return The index of the first sample that is wholly inside the millisecond
|
||||
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
|
||||
/// @brief A marker on the audio display
|
||||
class AudioMarker {
|
||||
|
@ -431,8 +370,6 @@ public:
|
|||
virtual bool CanSnap() const = 0;
|
||||
};
|
||||
|
||||
|
||||
|
||||
namespace agi {
|
||||
DEFINE_BASE_EXCEPTION(AudioControllerError, Exception);
|
||||
DEFINE_SIMPLE_EXCEPTION(AudioOpenError, AudioControllerError, "audio_controller/open_failed");
|
||||
|
|
|
@ -496,7 +496,7 @@ public:
|
|||
|
||||
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));
|
||||
const AudioMarker *snap_marker = 0;
|
||||
|
@ -546,8 +546,13 @@ AudioDisplay::AudioDisplay(wxWindow *parent, AudioController *controller)
|
|||
|
||||
track_cursor_pos = -1;
|
||||
|
||||
controller->AddAudioListener(this);
|
||||
controller->AddTimingListener(this);
|
||||
slots.push_back(controller->AddAudioOpenListener(&AudioDisplay::OnAudioOpen, 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);
|
||||
|
||||
|
@ -564,8 +569,6 @@ AudioDisplay::AudioDisplay(wxWindow *parent, AudioController *controller)
|
|||
|
||||
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 range_begin = AbsoluteXFromSamples(range.begin());
|
||||
|
@ -810,7 +813,7 @@ void AudioDisplay::OnPaint(wxPaintEvent& event)
|
|||
bool redraw_timeline = false;
|
||||
|
||||
/// @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_end = AbsoluteXFromSamples(sel_samples.end());
|
||||
|
||||
|
@ -856,12 +859,10 @@ void AudioDisplay::OnPaint(wxPaintEvent& event)
|
|||
// Draw markers on top of it all
|
||||
AudioMarkerVector markers;
|
||||
const int foot_size = 6;
|
||||
AudioController::SampleRange updrectsamples(
|
||||
SampleRange updrectsamples(
|
||||
SamplesFromRelativeX(updrect.x - foot_size),
|
||||
SamplesFromRelativeX(updrect.x + updrect.width + foot_size));
|
||||
controller->GetMarkers(updrectsamples, markers);
|
||||
if (controller->GetTimingController())
|
||||
controller->GetTimingController()->GetMarkers(updrectsamples, markers);
|
||||
wxDCPenChanger pen_retainer(dc, wxPen());
|
||||
wxDCBrushChanger brush_retainer(dc, wxBrush());
|
||||
for (AudioMarkerVector::iterator marker_i = markers.begin(); marker_i != markers.end(); ++marker_i)
|
||||
|
@ -1184,35 +1185,15 @@ void AudioDisplay::OnAudioOpen(AudioProvider *_provider)
|
|||
Refresh();
|
||||
}
|
||||
|
||||
|
||||
void AudioDisplay::OnAudioClose()
|
||||
{
|
||||
OnAudioOpen(0);
|
||||
}
|
||||
|
||||
|
||||
void AudioDisplay::OnPlaybackPosition(int64_t sample_position)
|
||||
{
|
||||
SetTrackCursor(AbsoluteXFromSamples(sample_position), false);
|
||||
}
|
||||
|
||||
|
||||
void AudioDisplay::OnPlaybackStop()
|
||||
{
|
||||
RemoveTrackCursor();
|
||||
}
|
||||
|
||||
|
||||
void AudioDisplay::OnMarkersMoved()
|
||||
{
|
||||
Refresh();
|
||||
}
|
||||
|
||||
|
||||
void AudioDisplay::OnSelectionChanged()
|
||||
{
|
||||
/// @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()));
|
||||
|
||||
if (sel.overlaps(old_selection))
|
||||
|
@ -1242,11 +1223,3 @@ void AudioDisplay::OnSelectionChanged()
|
|||
|
||||
old_selection = sel;
|
||||
}
|
||||
|
||||
|
||||
void AudioDisplay::OnTimingControllerChanged()
|
||||
{
|
||||
Refresh();
|
||||
/// @todo Do something more about the new timing controller?
|
||||
}
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#pragma once
|
||||
|
||||
#ifndef AGI_PRE
|
||||
#include <list>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <wx/bitmap.h>
|
||||
|
@ -47,6 +48,7 @@
|
|||
#endif
|
||||
|
||||
#include <libaegisub/scoped_ptr.h>
|
||||
#include <libaegisub/signals.h>
|
||||
|
||||
|
||||
class AudioRenderer;
|
||||
|
@ -108,8 +110,9 @@ public:
|
|||
/// 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
|
||||
/// and the timing controller, using an audio renderer instance.
|
||||
class AudioDisplay: public wxWindow, private AudioControllerAudioEventListener, private AudioControllerTimingEventListener {
|
||||
class AudioDisplay: public wxWindow {
|
||||
private:
|
||||
std::list<agi::signal::Connection> slots;
|
||||
|
||||
/// The audio renderer manager
|
||||
agi::scoped_ptr<AudioRenderer> audio_renderer;
|
||||
|
@ -178,9 +181,8 @@ private:
|
|||
/// @brief Remove the tracking cursor from the display
|
||||
void RemoveTrackCursor();
|
||||
|
||||
|
||||
/// Previous audio selection for optimising redraw when selection changes
|
||||
AudioController::SampleRange old_selection;
|
||||
/// Previous audio selection for optimizing redraw when selection changes
|
||||
SampleRange old_selection;
|
||||
|
||||
/// @brief Reload all rendering settings from Options and reset caches
|
||||
///
|
||||
|
@ -197,19 +199,10 @@ private:
|
|||
/// wxWidgets input focus changed event
|
||||
void OnFocus(wxFocusEvent &event);
|
||||
|
||||
|
||||
private:
|
||||
// AudioControllerAudioEventListener implementation
|
||||
virtual void OnAudioOpen(AudioProvider *provider);
|
||||
virtual void OnAudioClose();
|
||||
virtual void OnPlaybackPosition(int64_t sample_position);
|
||||
virtual void OnPlaybackStop();
|
||||
|
||||
// AudioControllerTimingEventListener implementation
|
||||
virtual void OnMarkersMoved();
|
||||
virtual void OnSelectionChanged();
|
||||
virtual void OnTimingControllerChanged();
|
||||
|
||||
|
||||
public:
|
||||
|
||||
|
@ -261,7 +254,7 @@ public:
|
|||
/// 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
|
||||
/// margin.
|
||||
void ScrollSampleRangeInView(const AudioController::SampleRange &range);
|
||||
void ScrollSampleRangeInView(const SampleRange &range);
|
||||
|
||||
|
||||
/// @brief Change the zoom level
|
||||
|
|
|
@ -40,7 +40,6 @@
|
|||
|
||||
#include <libaegisub/log.h>
|
||||
|
||||
#include "audio_controller.h"
|
||||
#include "audio_player_alsa.h"
|
||||
#include "main.h"
|
||||
#include "compat.h"
|
||||
|
|
|
@ -40,7 +40,6 @@
|
|||
|
||||
#include <libaegisub/log.h>
|
||||
|
||||
#include "audio_controller.h"
|
||||
#include "audio_player_dsound.h"
|
||||
#include "frame_main.h"
|
||||
#include "main.h"
|
||||
|
|
|
@ -40,7 +40,6 @@
|
|||
|
||||
#include <libaegisub/log.h>
|
||||
|
||||
#include "audio_controller.h"
|
||||
#include "audio_player_openal.h"
|
||||
#include "frame_main.h"
|
||||
#include "utils.h"
|
||||
|
|
|
@ -38,7 +38,6 @@
|
|||
|
||||
#include <libaegisub/log.h>
|
||||
|
||||
#include "audio_controller.h"
|
||||
#include "audio_player_oss.h"
|
||||
#include "frame_main.h"
|
||||
#include "compat.h"
|
||||
|
|
|
@ -41,7 +41,6 @@
|
|||
#include <wx/filename.h>
|
||||
#endif
|
||||
|
||||
#include "audio_controller.h"
|
||||
#include "audio_provider_hd.h"
|
||||
#include "compat.h"
|
||||
#include "dialog_progress.h"
|
||||
|
|
|
@ -36,7 +36,6 @@
|
|||
|
||||
#include "config.h"
|
||||
|
||||
#include "audio_controller.h"
|
||||
#include "audio_provider_ram.h"
|
||||
#include "dialog_progress.h"
|
||||
#include "frame_main.h"
|
||||
|
|
|
@ -38,17 +38,27 @@
|
|||
class AssDialogue;
|
||||
class AudioController;
|
||||
|
||||
#include <libaegisub/signals.h>
|
||||
|
||||
/// @class AudioTimingController
|
||||
/// @brief Base class for objects controlling audio timing
|
||||
///
|
||||
/// 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
|
||||
/// 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
|
||||
/// in empty areas of the audio display.
|
||||
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:
|
||||
/// @brief Get any warning message to show in the audio display
|
||||
/// @return The warning message to show, may be empty if there is none
|
||||
|
@ -58,13 +68,13 @@ public:
|
|||
/// @return A sample range
|
||||
///
|
||||
/// 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
|
||||
/// @return A sample range
|
||||
///
|
||||
/// 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?
|
||||
/// @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;
|
||||
|
||||
/// @brief Destructor
|
||||
///
|
||||
/// Does nothing in the base class, only present for virtual destruction.
|
||||
virtual ~AudioTimingController() { }
|
||||
|
||||
DEFINE_SIGNAL_ADDERS(AnnounceUpdatedPrimaryRange, AddUpdatedPrimaryRangeListener)
|
||||
DEFINE_SIGNAL_ADDERS(AnnounceUpdatedStyleRanges, AddUpdatedStyleRangesListener)
|
||||
DEFINE_SIGNAL_ADDERS(AnnounceMarkerMoved, AddMarkerMovedListener)
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -143,12 +143,12 @@ private:
|
|||
|
||||
public:
|
||||
// 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
|
||||
virtual wxString GetWarningMessage() const;
|
||||
virtual AudioController::SampleRange GetIdealVisibleSampleRange() const;
|
||||
virtual AudioController::SampleRange GetPrimaryPlaybackRange() const;
|
||||
virtual SampleRange GetIdealVisibleSampleRange() const;
|
||||
virtual SampleRange GetPrimaryPlaybackRange() const;
|
||||
virtual bool HasLabels() const;
|
||||
virtual void Next();
|
||||
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()))
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
|
||||
AudioController::SampleRange AudioTimingControllerDialogue::GetPrimaryPlaybackRange() const
|
||||
SampleRange AudioTimingControllerDialogue::GetPrimaryPlaybackRange() const
|
||||
{
|
||||
return AudioController::SampleRange(
|
||||
return SampleRange(
|
||||
GetLeftMarker()->GetPosition(),
|
||||
GetRightMarker()->GetPosition());
|
||||
}
|
||||
|
@ -396,7 +396,7 @@ void AudioTimingControllerDialogue::Revert()
|
|||
|
||||
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());
|
||||
}
|
||||
|
@ -419,7 +419,7 @@ AudioMarker * AudioTimingControllerDialogue::OnLeftClick(int64_t sample, int sen
|
|||
// Clicked near the left marker:
|
||||
// Insta-move it and start dragging it
|
||||
left->SetPosition(sample);
|
||||
audio_controller->OnTimingControllerMarkerMoved(this, left);
|
||||
AnnounceMarkerMoved(left);
|
||||
timing_modified = true;
|
||||
UpdateSelection();
|
||||
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,
|
||||
// such that if the user does start dragging, he will create a new selection from scratch
|
||||
left->SetPosition(sample);
|
||||
audio_controller->OnTimingControllerMarkerMoved(this, left);
|
||||
AnnounceMarkerMoved(left);
|
||||
timing_modified = true;
|
||||
UpdateSelection();
|
||||
return right;
|
||||
|
@ -449,7 +449,7 @@ AudioMarker * AudioTimingControllerDialogue::OnRightClick(int64_t sample, int se
|
|||
AudioMarkerDialogueTiming *right = GetRightMarker();
|
||||
|
||||
right->SetPosition(sample);
|
||||
audio_controller->OnTimingControllerMarkerMoved(this, right);
|
||||
AnnounceMarkerMoved(right);
|
||||
timing_modified = true;
|
||||
UpdateSelection();
|
||||
return right;
|
||||
|
@ -462,7 +462,7 @@ void AudioTimingControllerDialogue::OnMarkerDrag(AudioMarker *marker, int64_t ne
|
|||
assert(marker == &markers[0] || marker == &markers[1]);
|
||||
|
||||
static_cast<AudioMarkerDialogueTiming*>(marker)->SetPosition(new_position);
|
||||
audio_controller->OnTimingControllerMarkerMoved(this, marker);
|
||||
AnnounceMarkerMoved(marker);
|
||||
timing_modified = true;
|
||||
|
||||
UpdateSelection();
|
||||
|
@ -472,7 +472,7 @@ void AudioTimingControllerDialogue::OnMarkerDrag(AudioMarker *marker, int64_t ne
|
|||
|
||||
void AudioTimingControllerDialogue::UpdateSelection()
|
||||
{
|
||||
audio_controller->OnTimingControllerUpdatedPrimaryRange(this);
|
||||
AnnounceUpdatedPrimaryRange();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -50,7 +50,6 @@
|
|||
#include "ass_dialogue.h"
|
||||
#include "ass_file.h"
|
||||
#include "ass_style.h"
|
||||
#include "audio_controller.h"
|
||||
#include "selection_controller.h"
|
||||
#include "compat.h"
|
||||
#include "frame_main.h"
|
||||
|
|
|
@ -42,7 +42,6 @@
|
|||
#include <wx/display.h> /// Must be included last.
|
||||
#endif
|
||||
|
||||
#include "audio_controller.h"
|
||||
#include "dialog_detached_video.h"
|
||||
#include "frame_main.h"
|
||||
#include "main.h"
|
||||
|
|
|
@ -51,7 +51,6 @@
|
|||
#include "ass_file.h"
|
||||
#include "ass_override.h"
|
||||
#include "ass_style.h"
|
||||
#include "audio_controller.h"
|
||||
#include "compat.h"
|
||||
#include "dialog_fonts_collector.h"
|
||||
#include "font_file_lister.h"
|
||||
|
|
|
@ -47,7 +47,6 @@
|
|||
#include "compat.h"
|
||||
#include "ass_dialogue.h"
|
||||
#include "ass_file.h"
|
||||
#include "audio_controller.h"
|
||||
#include "dialog_search_replace.h"
|
||||
#include "frame_main.h"
|
||||
#include "main.h"
|
||||
|
|
|
@ -44,7 +44,6 @@
|
|||
|
||||
#include "ass_dialogue.h"
|
||||
#include "ass_file.h"
|
||||
#include "audio_controller.h"
|
||||
#include "compat.h"
|
||||
#include "dialog_spellchecker.h"
|
||||
#include "frame_main.h"
|
||||
|
|
|
@ -379,7 +379,7 @@ void DialogStyling::OnPlayVideoButton(wxCommandEvent &event) {
|
|||
/// @param event
|
||||
///
|
||||
void DialogStyling::OnPlayAudioButton(wxCommandEvent &event) {
|
||||
audio->PlayRange(AudioController::SampleRange(
|
||||
audio->PlayRange(SampleRange(
|
||||
audio->SamplesFromMilliseconds(line->Start.GetMS()),
|
||||
audio->SamplesFromMilliseconds(line->End.GetMS())));
|
||||
TypeBox->SetFocus();
|
||||
|
|
|
@ -444,7 +444,7 @@ void DialogTranslation::OnPlayVideoButton(wxCommandEvent &event) {
|
|||
/// @param event
|
||||
///
|
||||
void DialogTranslation::OnPlayAudioButton(wxCommandEvent &event) {
|
||||
audio->PlayRange(AudioController::SampleRange(
|
||||
audio->PlayRange(SampleRange(
|
||||
audio->SamplesFromMilliseconds(current->Start.GetMS()),
|
||||
audio->SamplesFromMilliseconds(current->End.GetMS())));
|
||||
TransText->SetFocus();
|
||||
|
|
|
@ -43,7 +43,6 @@
|
|||
#include <wx/filename.h>
|
||||
#endif
|
||||
|
||||
#include "audio_controller.h"
|
||||
#include "drop.h"
|
||||
#include "frame_main.h"
|
||||
|
||||
|
|
|
@ -48,7 +48,6 @@
|
|||
|
||||
#include <libaegisub/log.h>
|
||||
|
||||
#include "audio_controller.h"
|
||||
#include "compat.h"
|
||||
#include "ffmpegsource_common.h"
|
||||
#include "frame_main.h"
|
||||
|
|
|
@ -132,7 +132,8 @@ FrameMain::FrameMain (wxArrayString args)
|
|||
|
||||
// Contexts and controllers
|
||||
audioController = new AudioController;
|
||||
audioController->AddAudioListener(this);
|
||||
audioController->AddAudioOpenListener(&FrameMain::OnAudioOpen, this);
|
||||
audioController->AddAudioCloseListener(&FrameMain::OnAudioClose, this);
|
||||
|
||||
// Create menu and tool bars
|
||||
StartupLog(_T("Apply saved Maximized state"));
|
||||
|
|
|
@ -47,10 +47,6 @@
|
|||
#include <wx/timer.h>
|
||||
#endif
|
||||
|
||||
#ifndef AGI_AUDIO_CONTROLLER_INCLUDED
|
||||
#error You must include "audio_controller.h" before "frame_main.h"
|
||||
#endif
|
||||
|
||||
class AssFile;
|
||||
class VideoDisplay;
|
||||
class VideoSlider;
|
||||
|
@ -63,6 +59,7 @@ class DialogDetachedVideo;
|
|||
class DialogStyling;
|
||||
class AegisubFileDropTarget;
|
||||
class AudioController;
|
||||
class AudioProvider;
|
||||
|
||||
namespace Automation4 { class FeatureMacro; class ScriptManager; }
|
||||
|
||||
|
@ -73,7 +70,7 @@ namespace Automation4 { class FeatureMacro; class ScriptManager; }
|
|||
/// @brief DOCME
|
||||
///
|
||||
/// DOCME
|
||||
class FrameMain: public wxFrame, private AudioControllerAudioEventListener {
|
||||
class FrameMain: public wxFrame {
|
||||
friend class AegisubFileDropTarget;
|
||||
friend class AegisubApp;
|
||||
friend class SubtitlesGrid;
|
||||
|
@ -327,13 +324,9 @@ private:
|
|||
void RebuildRecentList(wxString listName,wxMenu *menu,int startID);
|
||||
void SynchronizeProject(bool FromSubs=false);
|
||||
|
||||
|
||||
private:
|
||||
// AudioControllerAudioEventListener implementation
|
||||
virtual void OnAudioOpen(AudioProvider *provider);
|
||||
virtual void OnAudioClose();
|
||||
virtual void OnPlaybackPosition(int64_t sample_position);
|
||||
virtual void OnPlaybackStop();
|
||||
void OnAudioOpen(AudioProvider *provider);
|
||||
void OnAudioClose();
|
||||
|
||||
|
||||
void OnSubtitlesFileChanged();
|
||||
|
|
|
@ -1517,8 +1517,8 @@ void FrameMain::OnMedusaStop(wxCommandEvent &) {
|
|||
|
||||
// Otherwise, play the last 500 ms
|
||||
else {
|
||||
AudioController::SampleRange sel(audioController->GetPrimaryPlaybackRange());
|
||||
audioController->PlayRange(AudioController::SampleRange(
|
||||
SampleRange sel(audioController->GetPrimaryPlaybackRange());
|
||||
audioController->PlayRange(SampleRange(
|
||||
sel.end() - audioController->SamplesFromMilliseconds(500),
|
||||
sel.end()));;
|
||||
}
|
||||
|
@ -1526,7 +1526,7 @@ void FrameMain::OnMedusaStop(wxCommandEvent &) {
|
|||
|
||||
/// @brief DOCME
|
||||
void FrameMain::OnMedusaShiftStartForward(wxCommandEvent &) {
|
||||
AudioController::SampleRange newsel(
|
||||
SampleRange newsel(
|
||||
audioController->GetPrimaryPlaybackRange(),
|
||||
audioController->SamplesFromMilliseconds(10),
|
||||
0);
|
||||
|
@ -1536,7 +1536,7 @@ void FrameMain::OnMedusaShiftStartForward(wxCommandEvent &) {
|
|||
|
||||
/// @brief DOCME
|
||||
void FrameMain::OnMedusaShiftStartBack(wxCommandEvent &) {
|
||||
AudioController::SampleRange newsel(
|
||||
SampleRange newsel(
|
||||
audioController->GetPrimaryPlaybackRange(),
|
||||
-audioController->SamplesFromMilliseconds(10),
|
||||
0);
|
||||
|
@ -1546,7 +1546,7 @@ void FrameMain::OnMedusaShiftStartBack(wxCommandEvent &) {
|
|||
|
||||
/// @brief DOCME
|
||||
void FrameMain::OnMedusaShiftEndForward(wxCommandEvent &) {
|
||||
AudioController::SampleRange newsel(
|
||||
SampleRange newsel(
|
||||
audioController->GetPrimaryPlaybackRange(),
|
||||
0,
|
||||
audioController->SamplesFromMilliseconds(10));
|
||||
|
@ -1556,7 +1556,7 @@ void FrameMain::OnMedusaShiftEndForward(wxCommandEvent &) {
|
|||
|
||||
/// @brief DOCME
|
||||
void FrameMain::OnMedusaShiftEndBack(wxCommandEvent &) {
|
||||
AudioController::SampleRange newsel(
|
||||
SampleRange newsel(
|
||||
audioController->GetPrimaryPlaybackRange(),
|
||||
0,
|
||||
-audioController->SamplesFromMilliseconds(10));
|
||||
|
@ -1566,16 +1566,16 @@ void FrameMain::OnMedusaShiftEndBack(wxCommandEvent &) {
|
|||
|
||||
/// @brief DOCME
|
||||
void FrameMain::OnMedusaPlayBefore(wxCommandEvent &) {
|
||||
AudioController::SampleRange sel(audioController->GetPrimaryPlaybackRange());
|
||||
audioController->PlayRange(AudioController::SampleRange(
|
||||
SampleRange sel(audioController->GetPrimaryPlaybackRange());
|
||||
audioController->PlayRange(SampleRange(
|
||||
sel.begin() - audioController->SamplesFromMilliseconds(500),
|
||||
sel.begin()));;
|
||||
}
|
||||
|
||||
/// @brief DOCME
|
||||
void FrameMain::OnMedusaPlayAfter(wxCommandEvent &) {
|
||||
AudioController::SampleRange sel(audioController->GetPrimaryPlaybackRange());
|
||||
audioController->PlayRange(AudioController::SampleRange(
|
||||
SampleRange sel(audioController->GetPrimaryPlaybackRange());
|
||||
audioController->PlayRange(SampleRange(
|
||||
sel.end(),
|
||||
sel.end() + audioController->SamplesFromMilliseconds(500)));;
|
||||
}
|
||||
|
@ -1623,16 +1623,6 @@ void FrameMain::OnAudioClose()
|
|||
SetDisplayMode(-1, 0);
|
||||
}
|
||||
|
||||
void FrameMain::OnPlaybackPosition(int64_t sample_position)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
void FrameMain::OnPlaybackStop()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
void FrameMain::OnSubtitlesFileChanged() {
|
||||
if (OPT_GET("App/Auto/Save on Every Change")->GetBool()) {
|
||||
if (ass->IsModified() && !ass->filename.empty()) SaveSubtitles(false);
|
||||
|
@ -1640,4 +1630,3 @@ void FrameMain::OnSubtitlesFileChanged() {
|
|||
|
||||
UpdateTitle();
|
||||
}
|
||||
|
||||
|
|
|
@ -55,7 +55,6 @@
|
|||
#include "ass_file.h"
|
||||
#include "ass_time.h"
|
||||
#include "selection_controller.h"
|
||||
#include "audio_controller.h"
|
||||
#include "audio_box.h"
|
||||
#ifdef WITH_AUTOMATION
|
||||
#include "auto4_base.h"
|
||||
|
|
|
@ -50,7 +50,6 @@
|
|||
|
||||
#include <libaegisub/log.h>
|
||||
|
||||
#include "audio_controller.h"
|
||||
#include "ass_file.h"
|
||||
#include "dialog_progress.h"
|
||||
#include "frame_main.h"
|
||||
|
|
|
@ -45,7 +45,6 @@
|
|||
|
||||
#include "ass_dialogue.h"
|
||||
#include "ass_file.h"
|
||||
#include "audio_controller.h"
|
||||
#include "frame_main.h"
|
||||
#include "help_button.h"
|
||||
#include "libresrc/libresrc.h"
|
||||
|
|
|
@ -308,7 +308,7 @@ void VideoContext::PlayNextFrame() {
|
|||
JumpToFrame(frame_n + 1);
|
||||
// Start playing audio
|
||||
if (playAudioOnStep->GetBool()) {
|
||||
audio->PlayRange(AudioController::SampleRange(
|
||||
audio->PlayRange(SampleRange(
|
||||
audio->SamplesFromMilliseconds(TimeAtFrame(thisFrame)),
|
||||
audio->SamplesFromMilliseconds(TimeAtFrame(thisFrame + 1))));
|
||||
}
|
||||
|
@ -322,7 +322,7 @@ void VideoContext::PlayPrevFrame() {
|
|||
JumpToFrame(frame_n -1);
|
||||
// Start playing audio
|
||||
if (playAudioOnStep->GetBool()) {
|
||||
audio->PlayRange(AudioController::SampleRange(
|
||||
audio->PlayRange(SampleRange(
|
||||
audio->SamplesFromMilliseconds(TimeAtFrame(thisFrame - 1)),
|
||||
audio->SamplesFromMilliseconds(TimeAtFrame(thisFrame))));
|
||||
}
|
||||
|
@ -355,7 +355,7 @@ void VideoContext::PlayLine() {
|
|||
if (!curline) return;
|
||||
|
||||
// Start playing audio
|
||||
audio->PlayRange(AudioController::SampleRange(
|
||||
audio->PlayRange(SampleRange(
|
||||
audio->SamplesFromMilliseconds(curline->Start.GetMS()),
|
||||
audio->SamplesFromMilliseconds(curline->End.GetMS())));
|
||||
|
||||
|
|
Loading…
Reference in New Issue